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