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