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