xref: /illumos-gate/usr/src/lib/libdtrace/common/dt_grammar.y (revision 201ceb75ab95f9bf1f42ea1dc9ab363b43ba47cf)
1 %{
2 /*
3  * CDDL HEADER START
4  *
5  * The contents of this file are subject to the terms of the
6  * Common Development and Distribution License, Version 1.0 only
7  * (the "License").  You may not use this file except in compliance
8  * with the License.
9  *
10  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11  * or http://www.opensolaris.org/os/licensing.
12  * See the License for the specific language governing permissions
13  * and limitations under the License.
14  *
15  * When distributing Covered Code, include this CDDL HEADER in each
16  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17  * If applicable, add the following below this CDDL HEADER, with the
18  * fields enclosed by brackets "[]" replaced with your own identifying
19  * information: Portions Copyright [yyyy] [name of copyright owner]
20  *
21  * CDDL HEADER END
22  *
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Copyright (c) 2014, 2016 by Delphix. All rights reserved.
29  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
30  */
31 
32 #include <dt_impl.h>
33 
34 #define	OP1(op, c)	dt_node_op1(op, c)
35 #define	OP2(op, l, r)	dt_node_op2(op, l, r)
36 #define	OP3(x, y, z)	dt_node_op3(x, y, z)
37 #define	LINK(l, r)	dt_node_link(l, r)
38 #define	DUP(s)		strdup(s)
39 
40 %}
41 
42 %union {
43 	dt_node_t *l_node;
44 	dt_decl_t *l_decl;
45 	char *l_str;
46 	uintmax_t l_int;
47 	int l_tok;
48 }
49 
50 %token	DT_TOK_COMMA DT_TOK_ELLIPSIS
51 %token	DT_TOK_ASGN DT_TOK_ADD_EQ DT_TOK_SUB_EQ DT_TOK_MUL_EQ
52 %token	DT_TOK_DIV_EQ DT_TOK_MOD_EQ DT_TOK_AND_EQ DT_TOK_XOR_EQ DT_TOK_OR_EQ
53 %token	DT_TOK_LSH_EQ DT_TOK_RSH_EQ DT_TOK_QUESTION DT_TOK_COLON
54 %token	DT_TOK_LOR DT_TOK_LXOR DT_TOK_LAND
55 %token	DT_TOK_BOR DT_TOK_XOR DT_TOK_BAND DT_TOK_EQU DT_TOK_NEQ
56 %token	DT_TOK_LT DT_TOK_LE DT_TOK_GT DT_TOK_GE DT_TOK_LSH DT_TOK_RSH
57 %token	DT_TOK_ADD DT_TOK_SUB DT_TOK_MUL DT_TOK_DIV DT_TOK_MOD
58 %token	DT_TOK_LNEG DT_TOK_BNEG DT_TOK_ADDADD DT_TOK_SUBSUB
59 %token	DT_TOK_PREINC DT_TOK_POSTINC DT_TOK_PREDEC DT_TOK_POSTDEC
60 %token	DT_TOK_IPOS DT_TOK_INEG DT_TOK_DEREF DT_TOK_ADDROF
61 %token	DT_TOK_OFFSETOF DT_TOK_SIZEOF DT_TOK_STRINGOF DT_TOK_XLATE
62 %token	DT_TOK_LPAR DT_TOK_RPAR DT_TOK_LBRAC DT_TOK_RBRAC DT_TOK_PTR DT_TOK_DOT
63 
64 %token <l_str>	DT_TOK_STRING
65 %token <l_str>	DT_TOK_IDENT
66 %token <l_str>	DT_TOK_PSPEC
67 %token <l_str>	DT_TOK_AGG
68 %token <l_str>	DT_TOK_TNAME
69 %token <l_int>	DT_TOK_INT
70 
71 %token	DT_KEY_AUTO
72 %token	DT_KEY_BREAK
73 %token	DT_KEY_CASE
74 %token	DT_KEY_CHAR
75 %token	DT_KEY_CONST
76 %token	DT_KEY_CONTINUE
77 %token	DT_KEY_COUNTER
78 %token	DT_KEY_DEFAULT
79 %token	DT_KEY_DO
80 %token	DT_KEY_DOUBLE
81 %token	DT_KEY_ELSE
82 %token	DT_KEY_ENUM
83 %token	DT_KEY_EXTERN
84 %token	DT_KEY_FLOAT
85 %token	DT_KEY_FOR
86 %token	DT_KEY_GOTO
87 %token	DT_KEY_IF
88 %token	DT_KEY_IMPORT
89 %token	DT_KEY_INLINE
90 %token	DT_KEY_INT
91 %token	DT_KEY_LONG
92 %token	DT_KEY_PROBE
93 %token	DT_KEY_PROVIDER
94 %token	DT_KEY_REGISTER
95 %token	DT_KEY_RESTRICT
96 %token	DT_KEY_RETURN
97 %token	DT_KEY_SELF
98 %token	DT_KEY_SHORT
99 %token	DT_KEY_SIGNED
100 %token	DT_KEY_STATIC
101 %token	DT_KEY_STRING
102 %token	DT_KEY_STRUCT
103 %token	DT_KEY_SWITCH
104 %token	DT_KEY_THIS
105 %token	DT_KEY_TYPEDEF
106 %token	DT_KEY_UNION
107 %token	DT_KEY_UNSIGNED
108 %token	DT_KEY_USERLAND
109 %token	DT_KEY_VOID
110 %token	DT_KEY_VOLATILE
111 %token	DT_KEY_WHILE
112 %token	DT_KEY_XLATOR
113 
114 %token	DT_TOK_EPRED
115 %token	DT_CTX_DEXPR
116 %token	DT_CTX_DPROG
117 %token	DT_CTX_DTYPE
118 %token	DT_TOK_EOF	0
119 
120 %left	DT_TOK_COMMA
121 %right	DT_TOK_ASGN DT_TOK_ADD_EQ DT_TOK_SUB_EQ DT_TOK_MUL_EQ DT_TOK_DIV_EQ
122 	DT_TOK_MOD_EQ DT_TOK_AND_EQ DT_TOK_XOR_EQ DT_TOK_OR_EQ DT_TOK_LSH_EQ
123 	DT_TOK_RSH_EQ
124 %left	DT_TOK_QUESTION DT_TOK_COLON
125 %left	DT_TOK_LOR
126 %left	DT_TOK_LXOR
127 %left	DT_TOK_LAND
128 %left	DT_TOK_BOR
129 %left	DT_TOK_XOR
130 %left	DT_TOK_BAND
131 %left	DT_TOK_EQU DT_TOK_NEQ
132 %left	DT_TOK_LT DT_TOK_LE DT_TOK_GT DT_TOK_GE
133 %left	DT_TOK_LSH DT_TOK_RSH
134 %left	DT_TOK_ADD DT_TOK_SUB
135 %left	DT_TOK_MUL DT_TOK_DIV DT_TOK_MOD
136 %right	DT_TOK_LNEG DT_TOK_BNEG DT_TOK_ADDADD DT_TOK_SUBSUB
137 	DT_TOK_IPOS DT_TOK_INEG
138 %right	DT_TOK_DEREF DT_TOK_ADDROF DT_TOK_SIZEOF DT_TOK_STRINGOF DT_TOK_XLATE
139 %left	DT_TOK_LPAR DT_TOK_RPAR DT_TOK_LBRAC DT_TOK_RBRAC DT_TOK_PTR DT_TOK_DOT
140 
141 %type	<l_node>	d_expression
142 %type	<l_node>	d_program
143 %type	<l_node>	d_type
144 
145 %type	<l_node>	translation_unit
146 %type	<l_node>	external_declaration
147 %type	<l_node>	inline_definition
148 %type	<l_node>	translator_definition
149 %type	<l_node>	translator_member_list
150 %type	<l_node>	translator_member
151 %type	<l_node>	provider_definition
152 %type	<l_node>	provider_probe_list
153 %type	<l_node>	provider_probe
154 %type	<l_node>	probe_definition
155 %type	<l_node>	probe_specifiers
156 %type	<l_node>	probe_specifier_list
157 %type	<l_node>	probe_specifier
158 %type	<l_node>	statement_list
159 %type	<l_node>	statement_list_impl
160 %type	<l_node>	statement_or_block
161 %type	<l_node>	statement
162 %type	<l_node>	declaration
163 %type	<l_node>	init_declarator_list
164 %type	<l_node>	init_declarator
165 
166 %type	<l_decl>	type_specifier
167 %type	<l_decl>	type_qualifier
168 %type	<l_decl>	struct_or_union_specifier
169 %type	<l_decl>	specifier_qualifier_list
170 %type	<l_decl>	enum_specifier
171 %type	<l_decl>	declarator
172 %type	<l_decl>	direct_declarator
173 %type	<l_decl>	pointer
174 %type	<l_decl>	type_qualifier_list
175 %type	<l_decl>	type_name
176 %type	<l_decl>	abstract_declarator
177 %type	<l_decl>	direct_abstract_declarator
178 
179 %type	<l_node>	parameter_type_list
180 %type	<l_node>	parameter_list
181 %type	<l_node>	parameter_declaration
182 
183 %type	<l_node>	array
184 %type	<l_node>	array_parameters
185 %type	<l_node>	function
186 %type	<l_node>	function_parameters
187 
188 %type	<l_node>	expression
189 %type	<l_node>	assignment_expression
190 %type	<l_node>	conditional_expression
191 %type	<l_node>	constant_expression
192 %type	<l_node>	logical_or_expression
193 %type	<l_node>	logical_xor_expression
194 %type	<l_node>	logical_and_expression
195 %type	<l_node>	inclusive_or_expression
196 %type	<l_node>	exclusive_or_expression
197 %type	<l_node>	and_expression
198 %type	<l_node>	equality_expression
199 %type	<l_node>	relational_expression
200 %type	<l_node>	shift_expression
201 %type	<l_node>	additive_expression
202 %type	<l_node>	multiplicative_expression
203 %type	<l_node>	cast_expression
204 %type	<l_node>	unary_expression
205 %type	<l_node>	postfix_expression
206 %type	<l_node>	primary_expression
207 %type	<l_node>	argument_expression_list
208 
209 %type	<l_tok>		assignment_operator
210 %type	<l_tok>		unary_operator
211 %type	<l_tok>		struct_or_union
212 
213 %%
214 
215 dtrace_program: d_expression DT_TOK_EOF { return (dt_node_root($1)); }
216 	|	d_program DT_TOK_EOF { return (dt_node_root($1)); }
217 	|	d_type DT_TOK_EOF { return (dt_node_root($1)); }
218 	;
219 
220 d_expression:	DT_CTX_DEXPR { $$ = NULL; }
221 	|	DT_CTX_DEXPR expression { $$ = $2; }
222 	;
223 
224 d_program:	DT_CTX_DPROG { $$ = dt_node_program(NULL); }
225 	|	DT_CTX_DPROG translation_unit { $$ = dt_node_program($2); }
226 	;
227 
228 d_type:		DT_CTX_DTYPE { $$ = NULL; }
229 	|	DT_CTX_DTYPE type_name { $$ = (dt_node_t *)$2; }
230 	;
231 
232 translation_unit:
233 		external_declaration
234 	|	translation_unit external_declaration { $$ = LINK($1, $2); }
235 	;
236 
237 external_declaration:
238 		inline_definition
239 	|	translator_definition
240 	|	provider_definition
241 	|	probe_definition
242 	|	declaration
243 	;
244 
245 inline_definition:
246 		DT_KEY_INLINE declaration_specifiers declarator
247 		    { dt_scope_push(NULL, CTF_ERR); } DT_TOK_ASGN
248 		    assignment_expression ';' {
249 			/*
250 			 * We push a new declaration scope before shifting the
251 			 * assignment_expression in order to preserve ds_class
252 			 * and ds_ident for use in dt_node_inline().  Once the
253 			 * entire inline_definition rule is matched, pop the
254 			 * scope and construct the inline using the saved decl.
255 			 */
256 			dt_scope_pop();
257 			$$ = dt_node_inline($6);
258 		}
259 	;
260 
261 translator_definition:
262 		DT_KEY_XLATOR type_name DT_TOK_LT type_name
263 		    DT_TOK_IDENT DT_TOK_GT '{' translator_member_list '}' ';' {
264 			$$ = dt_node_xlator($2, $4, $5, $8);
265 		}
266 	|	DT_KEY_XLATOR type_name DT_TOK_LT type_name
267 		    DT_TOK_IDENT DT_TOK_GT '{' '}' ';' {
268 			$$ = dt_node_xlator($2, $4, $5, NULL);
269 		}
270 	;
271 
272 translator_member_list:
273 		translator_member
274 	|	translator_member_list translator_member { $$ = LINK($1,$2); }
275 	;
276 
277 translator_member:
278 		DT_TOK_IDENT DT_TOK_ASGN assignment_expression ';' {
279 			$$ = dt_node_member(NULL, $1, $3);
280 		}
281 	;
282 
283 provider_definition:
284 		DT_KEY_PROVIDER DT_TOK_IDENT '{' provider_probe_list '}' ';' {
285 			$$ = dt_node_provider($2, $4);
286 		}
287 	|	DT_KEY_PROVIDER DT_TOK_IDENT '{' '}' ';' {
288 			$$ = dt_node_provider($2, NULL);
289 		}
290 	;
291 
292 provider_probe_list:
293 		provider_probe
294 	|	provider_probe_list provider_probe { $$ = LINK($1, $2); }
295 	;
296 
297 provider_probe:
298 		DT_KEY_PROBE DT_TOK_IDENT function DT_TOK_COLON function ';' {
299 			$$ = dt_node_probe($2, 2, $3, $5);
300 		}
301 	|	DT_KEY_PROBE DT_TOK_IDENT function ';' {
302 			$$ = dt_node_probe($2, 1, $3, NULL);
303 		}
304 	;
305 
306 probe_definition:
307 		probe_specifiers {
308 			/*
309 			 * If the input stream is a file, do not permit a probe
310 			 * specification without / <pred> / or { <act> } after
311 			 * it.  This can only occur if the next token is EOF or
312 			 * an ambiguous predicate was slurped up as a comment.
313 			 * We cannot perform this check if input() is a string
314 			 * because dtrace(8) [-fmnP] also use the compiler and
315 			 * things like dtrace -n BEGIN have to be accepted.
316 			 */
317 			if (yypcb->pcb_fileptr != NULL) {
318 				dnerror($1, D_SYNTAX, "expected predicate and/"
319 				    "or actions following probe description\n");
320 			}
321 			$$ = dt_node_clause($1, NULL, NULL);
322 			yybegin(YYS_CLAUSE);
323 		}
324 	|	probe_specifiers '{' statement_list '}' {
325 			$$ = dt_node_clause($1, NULL, $3);
326 			yybegin(YYS_CLAUSE);
327 		}
328 	|	probe_specifiers DT_TOK_DIV expression DT_TOK_EPRED {
329 			dnerror($3, D_SYNTAX, "expected actions { } following "
330 			    "probe description and predicate\n");
331 		}
332 	|	probe_specifiers DT_TOK_DIV expression DT_TOK_EPRED
333 		    '{' statement_list '}' {
334 			$$ = dt_node_clause($1, $3, $6);
335 			yybegin(YYS_CLAUSE);
336 		}
337 	;
338 
339 probe_specifiers:
340 		probe_specifier_list { yybegin(YYS_EXPR); $$ = $1; }
341 	;
342 
343 probe_specifier_list:
344 		probe_specifier
345 	|	probe_specifier_list DT_TOK_COMMA probe_specifier {
346 			$$ = LINK($1, $3);
347 		}
348 	;
349 
350 probe_specifier:
351 		DT_TOK_PSPEC { $$ = dt_node_pdesc_by_name($1); }
352 	|	DT_TOK_INT   { $$ = dt_node_pdesc_by_id($1); }
353 	;
354 
355 statement_list_impl: /* empty */ { $$ = NULL; }
356 	|	statement_list_impl statement { $$ = LINK($1, $2); }
357 	;
358 
359 statement_list:
360 		statement_list_impl { $$ = $1; }
361 	|	statement_list_impl expression {
362 			$$ = LINK($1, dt_node_statement($2));
363 		}
364 	;
365 
366 statement_or_block:
367 		statement
368 	|	'{' statement_list '}' { $$ = $2; }
369 
370 statement:	';' { $$ = NULL; }
371 	|	expression ';' { $$ = dt_node_statement($1); }
372 	|	DT_KEY_IF DT_TOK_LPAR expression DT_TOK_RPAR statement_or_block {
373 			$$ = dt_node_if($3, $5, NULL);
374 		}
375 	|	DT_KEY_IF DT_TOK_LPAR expression DT_TOK_RPAR
376 		statement_or_block DT_KEY_ELSE statement_or_block {
377 			$$ = dt_node_if($3, $5, $7);
378 		}
379 	;
380 
381 argument_expression_list:
382 		assignment_expression
383 	|	argument_expression_list DT_TOK_COMMA assignment_expression {
384 			$$ = LINK($1, $3);
385 		}
386 	;
387 
388 primary_expression:
389 		DT_TOK_IDENT { $$ = dt_node_ident($1); }
390 	|	DT_TOK_AGG { $$ = dt_node_ident($1); }
391 	|	DT_TOK_INT { $$ = dt_node_int($1); }
392 	|	DT_TOK_STRING { $$ = dt_node_string($1); }
393 	|	DT_KEY_SELF { $$ = dt_node_ident(DUP("self")); }
394 	|	DT_KEY_THIS { $$ = dt_node_ident(DUP("this")); }
395 	|	DT_TOK_LPAR expression DT_TOK_RPAR { $$ = $2; }
396 	;
397 
398 postfix_expression:
399 		primary_expression
400 	|	postfix_expression
401 		    DT_TOK_LBRAC argument_expression_list DT_TOK_RBRAC {
402 			$$ = OP2(DT_TOK_LBRAC, $1, $3);
403 		}
404 	|	postfix_expression DT_TOK_LPAR DT_TOK_RPAR {
405 			$$ = dt_node_func($1, NULL);
406 		}
407 	|	postfix_expression
408 		    DT_TOK_LPAR argument_expression_list DT_TOK_RPAR {
409 			$$ = dt_node_func($1, $3);
410 		}
411 	|	postfix_expression DT_TOK_DOT DT_TOK_IDENT {
412 			$$ = OP2(DT_TOK_DOT, $1, dt_node_ident($3));
413 		}
414 	|	postfix_expression DT_TOK_DOT DT_TOK_TNAME {
415 			$$ = OP2(DT_TOK_DOT, $1, dt_node_ident($3));
416 		}
417 	|	postfix_expression DT_TOK_PTR DT_TOK_IDENT {
418 			$$ = OP2(DT_TOK_PTR, $1, dt_node_ident($3));
419 		}
420 	|	postfix_expression DT_TOK_PTR DT_TOK_TNAME {
421 			$$ = OP2(DT_TOK_PTR, $1, dt_node_ident($3));
422 		}
423 	|	postfix_expression DT_TOK_ADDADD {
424 			$$ = OP1(DT_TOK_POSTINC, $1);
425 		}
426 	|	postfix_expression DT_TOK_SUBSUB {
427 			$$ = OP1(DT_TOK_POSTDEC, $1);
428 		}
429 	|	DT_TOK_OFFSETOF DT_TOK_LPAR type_name DT_TOK_COMMA
430 		    DT_TOK_IDENT DT_TOK_RPAR {
431 			$$ = dt_node_offsetof($3, $5);
432 		}
433 	|	DT_TOK_OFFSETOF DT_TOK_LPAR type_name DT_TOK_COMMA
434 		    DT_TOK_TNAME DT_TOK_RPAR {
435 			$$ = dt_node_offsetof($3, $5);
436 		}
437 	|	DT_TOK_XLATE DT_TOK_LT type_name DT_TOK_GT
438 		    DT_TOK_LPAR expression DT_TOK_RPAR {
439 			$$ = OP2(DT_TOK_XLATE, dt_node_type($3), $6);
440 		}
441 	;
442 
443 unary_expression:
444 		postfix_expression
445 	|	DT_TOK_ADDADD unary_expression { $$ = OP1(DT_TOK_PREINC, $2); }
446 	|	DT_TOK_SUBSUB unary_expression { $$ = OP1(DT_TOK_PREDEC, $2); }
447 	|	unary_operator cast_expression { $$ = OP1($1, $2); }
448 	|	DT_TOK_SIZEOF unary_expression { $$ = OP1(DT_TOK_SIZEOF, $2); }
449 	|	DT_TOK_SIZEOF DT_TOK_LPAR type_name DT_TOK_RPAR {
450 			$$ = OP1(DT_TOK_SIZEOF, dt_node_type($3));
451 		}
452 	|	DT_TOK_STRINGOF unary_expression {
453 			$$ = OP1(DT_TOK_STRINGOF, $2);
454 		}
455 	;
456 
457 unary_operator:	DT_TOK_BAND { $$ = DT_TOK_ADDROF; }
458 	|	DT_TOK_MUL { $$ = DT_TOK_DEREF; }
459 	|	DT_TOK_ADD { $$ = DT_TOK_IPOS; }
460 	|	DT_TOK_SUB { $$ = DT_TOK_INEG; }
461 	|	DT_TOK_BNEG { $$ = DT_TOK_BNEG; }
462 	|	DT_TOK_LNEG { $$ = DT_TOK_LNEG; }
463 	;
464 
465 cast_expression:
466 		unary_expression
467 	|	DT_TOK_LPAR type_name DT_TOK_RPAR cast_expression {
468 			$$ = OP2(DT_TOK_LPAR, dt_node_type($2), $4);
469 		}
470 	;
471 
472 multiplicative_expression:
473 		cast_expression
474 	|	multiplicative_expression DT_TOK_MUL cast_expression {
475 			$$ = OP2(DT_TOK_MUL, $1, $3);
476 		}
477 	|	multiplicative_expression DT_TOK_DIV cast_expression {
478 			$$ = OP2(DT_TOK_DIV, $1, $3);
479 		}
480 	|	multiplicative_expression DT_TOK_MOD cast_expression {
481 			$$ = OP2(DT_TOK_MOD, $1, $3);
482 		}
483 	;
484 
485 additive_expression:
486 		multiplicative_expression
487 	|	additive_expression DT_TOK_ADD multiplicative_expression {
488 			$$ = OP2(DT_TOK_ADD, $1, $3);
489 		}
490 	|	additive_expression DT_TOK_SUB multiplicative_expression {
491 			$$ = OP2(DT_TOK_SUB, $1, $3);
492 		}
493 	;
494 
495 shift_expression:
496 		additive_expression
497 	|	shift_expression DT_TOK_LSH additive_expression {
498 			$$ = OP2(DT_TOK_LSH, $1, $3);
499 		}
500 	|	shift_expression DT_TOK_RSH additive_expression {
501 			$$ = OP2(DT_TOK_RSH, $1, $3);
502 		}
503 	;
504 
505 relational_expression:
506 		shift_expression
507 	|	relational_expression DT_TOK_LT shift_expression {
508 			$$ = OP2(DT_TOK_LT, $1, $3);
509 		}
510 	|	relational_expression DT_TOK_GT shift_expression {
511 			$$ = OP2(DT_TOK_GT, $1, $3);
512 		}
513 	|	relational_expression DT_TOK_LE shift_expression {
514 			$$ = OP2(DT_TOK_LE, $1, $3);
515 		}
516 	|	relational_expression DT_TOK_GE shift_expression {
517 			$$ = OP2(DT_TOK_GE, $1, $3);
518 		}
519 	;
520 
521 equality_expression:
522 		relational_expression
523 	|	equality_expression DT_TOK_EQU relational_expression {
524 			$$ = OP2(DT_TOK_EQU, $1, $3);
525 		}
526 	|	equality_expression DT_TOK_NEQ relational_expression {
527 			$$ = OP2(DT_TOK_NEQ, $1, $3);
528 		}
529 	;
530 
531 and_expression:
532 		equality_expression
533 	|	and_expression DT_TOK_BAND equality_expression {
534 			$$ = OP2(DT_TOK_BAND, $1, $3);
535 		}
536 	;
537 
538 exclusive_or_expression:
539 		and_expression
540 	|	exclusive_or_expression DT_TOK_XOR and_expression {
541 			$$ = OP2(DT_TOK_XOR, $1, $3);
542 		}
543 	;
544 
545 inclusive_or_expression:
546 		exclusive_or_expression
547 	|	inclusive_or_expression DT_TOK_BOR exclusive_or_expression {
548 			$$ = OP2(DT_TOK_BOR, $1, $3);
549 		}
550 	;
551 
552 logical_and_expression:
553 		inclusive_or_expression
554 	|	logical_and_expression DT_TOK_LAND inclusive_or_expression {
555 			$$ = OP2(DT_TOK_LAND, $1, $3);
556 		}
557 	;
558 
559 logical_xor_expression:
560 		logical_and_expression
561 	|	logical_xor_expression DT_TOK_LXOR logical_and_expression {
562 			$$ = OP2(DT_TOK_LXOR, $1, $3);
563 		}
564 	;
565 
566 logical_or_expression:
567 		logical_xor_expression
568 	|	logical_or_expression DT_TOK_LOR logical_xor_expression {
569 			$$ = OP2(DT_TOK_LOR, $1, $3);
570 		}
571 	;
572 
573 constant_expression: conditional_expression
574 	;
575 
576 conditional_expression:
577 		logical_or_expression
578 	|	logical_or_expression DT_TOK_QUESTION expression DT_TOK_COLON
579 		    conditional_expression { $$ = OP3($1, $3, $5); }
580 	;
581 
582 assignment_expression:
583 		conditional_expression
584 	|	unary_expression assignment_operator assignment_expression {
585 			$$ = OP2($2, $1, $3);
586 		}
587 	;
588 
589 assignment_operator:
590 		DT_TOK_ASGN   { $$ = DT_TOK_ASGN; }
591 	|	DT_TOK_MUL_EQ { $$ = DT_TOK_MUL_EQ; }
592 	|	DT_TOK_DIV_EQ { $$ = DT_TOK_DIV_EQ; }
593 	|	DT_TOK_MOD_EQ { $$ = DT_TOK_MOD_EQ; }
594 	|	DT_TOK_ADD_EQ { $$ = DT_TOK_ADD_EQ; }
595 	|	DT_TOK_SUB_EQ { $$ = DT_TOK_SUB_EQ; }
596 	|	DT_TOK_LSH_EQ { $$ = DT_TOK_LSH_EQ; }
597 	|	DT_TOK_RSH_EQ { $$ = DT_TOK_RSH_EQ; }
598 	|	DT_TOK_AND_EQ { $$ = DT_TOK_AND_EQ; }
599 	|	DT_TOK_XOR_EQ { $$ = DT_TOK_XOR_EQ; }
600 	|	DT_TOK_OR_EQ  { $$ = DT_TOK_OR_EQ; }
601 	;
602 
603 expression:	assignment_expression
604 	|	expression DT_TOK_COMMA assignment_expression {
605 			$$ = OP2(DT_TOK_COMMA, $1, $3);
606 		}
607 	;
608 
609 declaration:	declaration_specifiers ';' {
610 			$$ = dt_node_decl();
611 			dt_decl_free(dt_decl_pop());
612 			yybegin(YYS_CLAUSE);
613 		}
614 	|	declaration_specifiers init_declarator_list ';' {
615 			$$ = $2;
616 			dt_decl_free(dt_decl_pop());
617 			yybegin(YYS_CLAUSE);
618 		}
619 	;
620 
621 declaration_specifiers:
622 		d_storage_class_specifier
623 	|	d_storage_class_specifier declaration_specifiers
624 	|	type_specifier
625 	|	type_specifier declaration_specifiers
626 	|	type_qualifier
627 	|	type_qualifier declaration_specifiers
628 	;
629 
630 parameter_declaration_specifiers:
631 		storage_class_specifier
632 	|	storage_class_specifier declaration_specifiers
633 	|	type_specifier
634 	|	type_specifier declaration_specifiers
635 	|	type_qualifier
636 	|	type_qualifier declaration_specifiers
637 	;
638 
639 storage_class_specifier:
640 		DT_KEY_AUTO { dt_decl_class(DT_DC_AUTO); }
641 	|	DT_KEY_REGISTER { dt_decl_class(DT_DC_REGISTER); }
642 	|	DT_KEY_STATIC { dt_decl_class(DT_DC_STATIC); }
643 	|	DT_KEY_EXTERN { dt_decl_class(DT_DC_EXTERN); }
644 	|	DT_KEY_TYPEDEF { dt_decl_class(DT_DC_TYPEDEF); }
645 	;
646 
647 d_storage_class_specifier:
648 		storage_class_specifier
649 	|	DT_KEY_SELF { dt_decl_class(DT_DC_SELF); }
650 	|	DT_KEY_THIS { dt_decl_class(DT_DC_THIS); }
651 	;
652 
653 type_specifier:	DT_KEY_VOID { $$ = dt_decl_spec(CTF_K_INTEGER, DUP("void")); }
654 	|	DT_KEY_CHAR { $$ = dt_decl_spec(CTF_K_INTEGER, DUP("char")); }
655 	|	DT_KEY_SHORT { $$ = dt_decl_attr(DT_DA_SHORT); }
656 	|	DT_KEY_INT { $$ = dt_decl_spec(CTF_K_INTEGER, DUP("int")); }
657 	|	DT_KEY_LONG { $$ = dt_decl_attr(DT_DA_LONG); }
658 	|	DT_KEY_FLOAT { $$ = dt_decl_spec(CTF_K_FLOAT, DUP("float")); }
659 	|	DT_KEY_DOUBLE { $$ = dt_decl_spec(CTF_K_FLOAT, DUP("double")); }
660 	|	DT_KEY_SIGNED { $$ = dt_decl_attr(DT_DA_SIGNED); }
661 	|	DT_KEY_UNSIGNED { $$ = dt_decl_attr(DT_DA_UNSIGNED); }
662 	|	DT_KEY_USERLAND { $$ = dt_decl_attr(DT_DA_USER); }
663 	|	DT_KEY_STRING {
664 			$$ = dt_decl_spec(CTF_K_TYPEDEF, DUP("string"));
665 		}
666 	|	DT_TOK_TNAME { $$ = dt_decl_spec(CTF_K_TYPEDEF, $1); }
667 	|	struct_or_union_specifier
668 	|	enum_specifier
669 	;
670 
671 type_qualifier:	DT_KEY_CONST { $$ = dt_decl_attr(DT_DA_CONST); }
672 	|	DT_KEY_RESTRICT { $$ = dt_decl_attr(DT_DA_RESTRICT); }
673 	|	DT_KEY_VOLATILE { $$ = dt_decl_attr(DT_DA_VOLATILE); }
674 	;
675 
676 struct_or_union_specifier:
677 		struct_or_union_definition struct_declaration_list '}' {
678 			$$ = dt_scope_pop();
679 		}
680 	|	struct_or_union DT_TOK_IDENT { $$ = dt_decl_spec($1, $2); }
681 	|	struct_or_union DT_TOK_TNAME { $$ = dt_decl_spec($1, $2); }
682 	;
683 
684 struct_or_union_definition:
685 		struct_or_union '{' { dt_decl_sou($1, NULL); }
686 	|	struct_or_union DT_TOK_IDENT '{' { dt_decl_sou($1, $2); }
687 	|	struct_or_union DT_TOK_TNAME '{' { dt_decl_sou($1, $2); }
688 	;
689 
690 struct_or_union:
691 		DT_KEY_STRUCT { $$ = CTF_K_STRUCT; }
692 	|	DT_KEY_UNION { $$ = CTF_K_UNION; }
693 	;
694 
695 struct_declaration_list:
696 		struct_declaration
697 	|	struct_declaration_list struct_declaration
698 	;
699 
700 init_declarator_list:
701 		init_declarator
702 	|	init_declarator_list DT_TOK_COMMA init_declarator {
703 			$$ = LINK($1, $3);
704 		}
705 	;
706 
707 init_declarator:
708 		declarator {
709 			$$ = dt_node_decl();
710 			dt_decl_reset();
711 		}
712 	;
713 
714 struct_declaration:
715 		specifier_qualifier_list struct_declarator_list ';' {
716 			dt_decl_free(dt_decl_pop());
717 		}
718 	;
719 
720 specifier_qualifier_list:
721 		type_specifier
722 	|	type_specifier specifier_qualifier_list { $$ = $2; }
723 	|	type_qualifier
724 	|	type_qualifier specifier_qualifier_list { $$ = $2; }
725 	;
726 
727 struct_declarator_list:
728 		struct_declarator
729 	|	struct_declarator_list DT_TOK_COMMA struct_declarator
730 	;
731 
732 struct_declarator:
733 		declarator { dt_decl_member(NULL); }
734 	|	DT_TOK_COLON constant_expression { dt_decl_member($2); }
735 	|	declarator DT_TOK_COLON constant_expression {
736 			dt_decl_member($3);
737 		}
738 	;
739 
740 enum_specifier:
741 		enum_definition enumerator_list '}' { $$ = dt_scope_pop(); }
742 	|	enum_definition enumerator_list DT_TOK_COMMA '}' { $$ = dt_scope_pop(); }
743 	|	DT_KEY_ENUM DT_TOK_IDENT { $$ = dt_decl_spec(CTF_K_ENUM, $2); }
744 	|	DT_KEY_ENUM DT_TOK_TNAME { $$ = dt_decl_spec(CTF_K_ENUM, $2); }
745 	;
746 
747 enum_definition:
748 		DT_KEY_ENUM '{' { dt_decl_enum(NULL); }
749 	|	DT_KEY_ENUM DT_TOK_IDENT '{' { dt_decl_enum($2); }
750 	|	DT_KEY_ENUM DT_TOK_TNAME '{' { dt_decl_enum($2); }
751 	;
752 
753 enumerator_list:
754 		enumerator
755 	|	enumerator_list DT_TOK_COMMA enumerator
756 	;
757 
758 enumerator:	DT_TOK_IDENT { dt_decl_enumerator($1, NULL); }
759 	|	DT_TOK_IDENT DT_TOK_ASGN expression {
760 			dt_decl_enumerator($1, $3);
761 		}
762 	;
763 
764 declarator:	direct_declarator
765 	|	pointer direct_declarator
766 	;
767 
768 direct_declarator:
769 		DT_TOK_IDENT { $$ = dt_decl_ident($1); }
770 	|	lparen declarator DT_TOK_RPAR { $$ = $2; }
771 	|	direct_declarator array { dt_decl_array($2); }
772 	|	direct_declarator function { dt_decl_func($1, $2); }
773 	;
774 
775 lparen:		DT_TOK_LPAR { dt_decl_top()->dd_attr |= DT_DA_PAREN; }
776 	;
777 
778 pointer:	DT_TOK_MUL { $$ = dt_decl_ptr(); }
779 	|	DT_TOK_MUL type_qualifier_list { $$ = dt_decl_ptr(); }
780 	|	DT_TOK_MUL pointer { $$ = dt_decl_ptr(); }
781 	|	DT_TOK_MUL type_qualifier_list pointer { $$ = dt_decl_ptr(); }
782 	;
783 
784 type_qualifier_list:
785 		type_qualifier
786 	|	type_qualifier_list type_qualifier { $$ = $2; }
787 	;
788 
789 parameter_type_list:
790 		parameter_list
791 	|	DT_TOK_ELLIPSIS { $$ = dt_node_vatype(); }
792 	|	parameter_list DT_TOK_COMMA DT_TOK_ELLIPSIS {
793 			$$ = LINK($1, dt_node_vatype());
794 		}
795 	;
796 
797 parameter_list:	parameter_declaration
798 	|	parameter_list DT_TOK_COMMA parameter_declaration {
799 			$$ = LINK($1, $3);
800 		}
801 	;
802 
803 parameter_declaration:
804 		parameter_declaration_specifiers {
805 			$$ = dt_node_type(NULL);
806 		}
807 	|	parameter_declaration_specifiers declarator {
808 			$$ = dt_node_type(NULL);
809 		}
810 	|	parameter_declaration_specifiers abstract_declarator {
811 			$$ = dt_node_type(NULL);
812 		}
813 	;
814 
815 type_name:	specifier_qualifier_list {
816 			$$ = dt_decl_pop();
817 		}
818 	|	specifier_qualifier_list abstract_declarator {
819 			$$ = dt_decl_pop();
820 		}
821 	;
822 
823 abstract_declarator:
824 		pointer
825 	|	direct_abstract_declarator
826 	|	pointer direct_abstract_declarator
827 	;
828 
829 direct_abstract_declarator:
830 		lparen abstract_declarator DT_TOK_RPAR { $$ = $2; }
831 	|	direct_abstract_declarator array { dt_decl_array($2); }
832 	|	array { dt_decl_array($1); $$ = NULL; }
833 	|	direct_abstract_declarator function { dt_decl_func($1, $2); }
834 	|	function { dt_decl_func(NULL, $1); }
835 	;
836 
837 array:		DT_TOK_LBRAC { dt_scope_push(NULL, CTF_ERR); }
838 		    array_parameters DT_TOK_RBRAC {
839 			dt_scope_pop();
840 			$$ = $3;
841 		}
842 	;
843 
844 array_parameters:
845 		/* empty */		{ $$ = NULL; }
846 	|	constant_expression	{ $$ = $1; }
847 	|	parameter_type_list	{ $$ = $1; }
848 	;
849 
850 function:	DT_TOK_LPAR { dt_scope_push(NULL, CTF_ERR); }
851 		    function_parameters DT_TOK_RPAR {
852 			dt_scope_pop();
853 			$$ = $3;
854 		}
855 	;
856 
857 function_parameters:
858 		/* empty */		{ $$ = NULL; }
859 	|	parameter_type_list	{ $$ = $1; }
860 	;
861 
862 %%
863