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%type	<l_str>		dtrace_keyword_ident
214
215%%
216
217dtrace_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
222d_expression:	DT_CTX_DEXPR { $$ = NULL; }
223	|	DT_CTX_DEXPR expression { $$ = $2; }
224	;
225
226d_program:	DT_CTX_DPROG { $$ = dt_node_program(NULL); }
227	|	DT_CTX_DPROG translation_unit { $$ = dt_node_program($2); }
228	;
229
230d_type:		DT_CTX_DTYPE { $$ = NULL; }
231	|	DT_CTX_DTYPE type_name { $$ = (dt_node_t *)$2; }
232	;
233
234translation_unit:
235		external_declaration
236	|	translation_unit external_declaration { $$ = LINK($1, $2); }
237	;
238
239external_declaration:
240		inline_definition
241	|	translator_definition
242	|	provider_definition
243	|	probe_definition
244	|	declaration
245	;
246
247inline_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
263translator_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
274translator_member_list:
275		translator_member
276	|	translator_member_list translator_member { $$ = LINK($1,$2); }
277	;
278
279translator_member:
280		DT_TOK_IDENT DT_TOK_ASGN assignment_expression ';' {
281			$$ = dt_node_member(NULL, $1, $3);
282		}
283	;
284
285provider_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
294provider_probe_list:
295		provider_probe
296	|	provider_probe_list provider_probe { $$ = LINK($1, $2); }
297	;
298
299provider_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
309probe_definition:
310		probe_specifiers {
311			/*
312			 * If the input stream is a file, do not permit a probe
313			 * specification without / <pred> / or { <act> } after
314			 * it.  This can only occur if the next token is EOF or
315			 * an ambiguous predicate was slurped up as a comment.
316			 * We cannot perform this check if input() is a string
317			 * because dtrace(1M) [-fmnP] also use the compiler and
318			 * things like dtrace -n BEGIN have to be accepted.
319			 */
320			if (yypcb->pcb_fileptr != NULL) {
321				dnerror($1, D_SYNTAX, "expected predicate and/"
322				    "or actions following probe description\n");
323			}
324			$$ = dt_node_clause($1, NULL, NULL);
325			yybegin(YYS_CLAUSE);
326		}
327	|	probe_specifiers '{' statement_list '}' {
328			$$ = dt_node_clause($1, NULL, $3);
329			yybegin(YYS_CLAUSE);
330		}
331	|	probe_specifiers DT_TOK_DIV expression DT_TOK_EPRED {
332			dnerror($3, D_SYNTAX, "expected actions { } following "
333			    "probe description and predicate\n");
334		}
335	|	probe_specifiers DT_TOK_DIV expression DT_TOK_EPRED
336		    '{' statement_list '}' {
337			$$ = dt_node_clause($1, $3, $6);
338			yybegin(YYS_CLAUSE);
339		}
340	;
341
342probe_specifiers:
343		probe_specifier_list { yybegin(YYS_EXPR); $$ = $1; }
344	;
345
346probe_specifier_list:
347		probe_specifier
348	|	probe_specifier_list DT_TOK_COMMA probe_specifier {
349			$$ = LINK($1, $3);
350		}
351	;
352
353probe_specifier:
354		DT_TOK_PSPEC { $$ = dt_node_pdesc_by_name($1); }
355	|	DT_TOK_INT   { $$ = dt_node_pdesc_by_id($1); }
356	;
357
358statement_list_impl: /* empty */ { $$ = NULL; }
359	|	statement_list_impl statement { $$ = LINK($1, $2); }
360	;
361
362statement_list:
363		statement_list_impl { $$ = $1; }
364	|	statement_list_impl expression {
365			$$ = LINK($1, dt_node_statement($2));
366		}
367	;
368
369statement_or_block:
370		statement
371	|	'{' statement_list '}' { $$ = $2; }
372
373statement:	';' { $$ = NULL; }
374	|	expression ';' { $$ = dt_node_statement($1); }
375	|	DT_KEY_IF DT_TOK_LPAR expression DT_TOK_RPAR statement_or_block {
376			$$ = dt_node_if($3, $5, NULL);
377		}
378	|	DT_KEY_IF DT_TOK_LPAR expression DT_TOK_RPAR
379		statement_or_block DT_KEY_ELSE statement_or_block {
380			$$ = dt_node_if($3, $5, $7);
381		}
382	;
383
384argument_expression_list:
385		assignment_expression
386	|	argument_expression_list DT_TOK_COMMA assignment_expression {
387			$$ = LINK($1, $3);
388		}
389	;
390
391primary_expression:
392		DT_TOK_IDENT { $$ = dt_node_ident($1); }
393	|	DT_TOK_AGG { $$ = dt_node_ident($1); }
394	|	DT_TOK_INT { $$ = dt_node_int($1); }
395	|	DT_TOK_STRING { $$ = dt_node_string($1); }
396	|	DT_KEY_SELF { $$ = dt_node_ident(DUP("self")); }
397	|	DT_KEY_THIS { $$ = dt_node_ident(DUP("this")); }
398	|	DT_TOK_LPAR expression DT_TOK_RPAR { $$ = $2; }
399	;
400
401postfix_expression:
402		primary_expression
403	|	postfix_expression
404		    DT_TOK_LBRAC argument_expression_list DT_TOK_RBRAC {
405			$$ = OP2(DT_TOK_LBRAC, $1, $3);
406		}
407	|	postfix_expression DT_TOK_LPAR DT_TOK_RPAR {
408			$$ = dt_node_func($1, NULL);
409		}
410	|	postfix_expression
411		    DT_TOK_LPAR argument_expression_list DT_TOK_RPAR {
412			$$ = dt_node_func($1, $3);
413		}
414	|	postfix_expression DT_TOK_DOT DT_TOK_IDENT {
415			$$ = OP2(DT_TOK_DOT, $1, dt_node_ident($3));
416		}
417	|	postfix_expression DT_TOK_DOT DT_TOK_TNAME {
418			$$ = OP2(DT_TOK_DOT, $1, dt_node_ident($3));
419		}
420	|	postfix_expression DT_TOK_DOT dtrace_keyword_ident {
421			$$ = OP2(DT_TOK_DOT, $1, dt_node_ident($3));
422		}
423	|	postfix_expression DT_TOK_PTR DT_TOK_IDENT {
424			$$ = OP2(DT_TOK_PTR, $1, dt_node_ident($3));
425		}
426	|	postfix_expression DT_TOK_PTR DT_TOK_TNAME {
427			$$ = OP2(DT_TOK_PTR, $1, dt_node_ident($3));
428		}
429	|	postfix_expression DT_TOK_PTR dtrace_keyword_ident {
430			$$ = OP2(DT_TOK_PTR, $1, dt_node_ident($3));
431		}
432	|	postfix_expression DT_TOK_ADDADD {
433			$$ = OP1(DT_TOK_POSTINC, $1);
434		}
435	|	postfix_expression DT_TOK_SUBSUB {
436			$$ = OP1(DT_TOK_POSTDEC, $1);
437		}
438	|	DT_TOK_OFFSETOF DT_TOK_LPAR type_name DT_TOK_COMMA
439		    DT_TOK_IDENT DT_TOK_RPAR {
440			$$ = dt_node_offsetof($3, $5);
441		}
442	|	DT_TOK_OFFSETOF DT_TOK_LPAR type_name DT_TOK_COMMA
443		    DT_TOK_TNAME DT_TOK_RPAR {
444			$$ = dt_node_offsetof($3, $5);
445		}
446	|	DT_TOK_OFFSETOF DT_TOK_LPAR type_name DT_TOK_COMMA
447		    dtrace_keyword_ident DT_TOK_RPAR {
448			$$ = dt_node_offsetof($3, $5);
449		}
450	|	DT_TOK_XLATE DT_TOK_LT type_name DT_TOK_GT
451		    DT_TOK_LPAR expression DT_TOK_RPAR {
452			$$ = OP2(DT_TOK_XLATE, dt_node_type($3), $6);
453		}
454	;
455
456unary_expression:
457		postfix_expression
458	|	DT_TOK_ADDADD unary_expression { $$ = OP1(DT_TOK_PREINC, $2); }
459	|	DT_TOK_SUBSUB unary_expression { $$ = OP1(DT_TOK_PREDEC, $2); }
460	|	unary_operator cast_expression { $$ = OP1($1, $2); }
461	|	DT_TOK_SIZEOF unary_expression { $$ = OP1(DT_TOK_SIZEOF, $2); }
462	|	DT_TOK_SIZEOF DT_TOK_LPAR type_name DT_TOK_RPAR {
463			$$ = OP1(DT_TOK_SIZEOF, dt_node_type($3));
464		}
465	|	DT_TOK_STRINGOF unary_expression {
466			$$ = OP1(DT_TOK_STRINGOF, $2);
467		}
468	;
469
470unary_operator:	DT_TOK_BAND { $$ = DT_TOK_ADDROF; }
471	|	DT_TOK_MUL { $$ = DT_TOK_DEREF; }
472	|	DT_TOK_ADD { $$ = DT_TOK_IPOS; }
473	|	DT_TOK_SUB { $$ = DT_TOK_INEG; }
474	|	DT_TOK_BNEG { $$ = DT_TOK_BNEG; }
475	|	DT_TOK_LNEG { $$ = DT_TOK_LNEG; }
476	;
477
478cast_expression:
479		unary_expression
480	|	DT_TOK_LPAR type_name DT_TOK_RPAR cast_expression {
481			$$ = OP2(DT_TOK_LPAR, dt_node_type($2), $4);
482		}
483	;
484
485multiplicative_expression:
486		cast_expression
487	|	multiplicative_expression DT_TOK_MUL cast_expression {
488			$$ = OP2(DT_TOK_MUL, $1, $3);
489		}
490	|	multiplicative_expression DT_TOK_DIV cast_expression {
491			$$ = OP2(DT_TOK_DIV, $1, $3);
492		}
493	|	multiplicative_expression DT_TOK_MOD cast_expression {
494			$$ = OP2(DT_TOK_MOD, $1, $3);
495		}
496	;
497
498additive_expression:
499		multiplicative_expression
500	|	additive_expression DT_TOK_ADD multiplicative_expression {
501			$$ = OP2(DT_TOK_ADD, $1, $3);
502		}
503	|	additive_expression DT_TOK_SUB multiplicative_expression {
504			$$ = OP2(DT_TOK_SUB, $1, $3);
505		}
506	;
507
508shift_expression:
509		additive_expression
510	|	shift_expression DT_TOK_LSH additive_expression {
511			$$ = OP2(DT_TOK_LSH, $1, $3);
512		}
513	|	shift_expression DT_TOK_RSH additive_expression {
514			$$ = OP2(DT_TOK_RSH, $1, $3);
515		}
516	;
517
518relational_expression:
519		shift_expression
520	|	relational_expression DT_TOK_LT shift_expression {
521			$$ = OP2(DT_TOK_LT, $1, $3);
522		}
523	|	relational_expression DT_TOK_GT shift_expression {
524			$$ = OP2(DT_TOK_GT, $1, $3);
525		}
526	|	relational_expression DT_TOK_LE shift_expression {
527			$$ = OP2(DT_TOK_LE, $1, $3);
528		}
529	|	relational_expression DT_TOK_GE shift_expression {
530			$$ = OP2(DT_TOK_GE, $1, $3);
531		}
532	;
533
534equality_expression:
535		relational_expression
536	|	equality_expression DT_TOK_EQU relational_expression {
537			$$ = OP2(DT_TOK_EQU, $1, $3);
538		}
539	|	equality_expression DT_TOK_NEQ relational_expression {
540			$$ = OP2(DT_TOK_NEQ, $1, $3);
541		}
542	;
543
544and_expression:
545		equality_expression
546	|	and_expression DT_TOK_BAND equality_expression {
547			$$ = OP2(DT_TOK_BAND, $1, $3);
548		}
549	;
550
551exclusive_or_expression:
552		and_expression
553	|	exclusive_or_expression DT_TOK_XOR and_expression {
554			$$ = OP2(DT_TOK_XOR, $1, $3);
555		}
556	;
557
558inclusive_or_expression:
559		exclusive_or_expression
560	|	inclusive_or_expression DT_TOK_BOR exclusive_or_expression {
561			$$ = OP2(DT_TOK_BOR, $1, $3);
562		}
563	;
564
565logical_and_expression:
566		inclusive_or_expression
567	|	logical_and_expression DT_TOK_LAND inclusive_or_expression {
568			$$ = OP2(DT_TOK_LAND, $1, $3);
569		}
570	;
571
572logical_xor_expression:
573		logical_and_expression
574	|	logical_xor_expression DT_TOK_LXOR logical_and_expression {
575			$$ = OP2(DT_TOK_LXOR, $1, $3);
576		}
577	;
578
579logical_or_expression:
580		logical_xor_expression
581	|	logical_or_expression DT_TOK_LOR logical_xor_expression {
582			$$ = OP2(DT_TOK_LOR, $1, $3);
583		}
584	;
585
586constant_expression: conditional_expression
587	;
588
589conditional_expression:
590		logical_or_expression
591	|	logical_or_expression DT_TOK_QUESTION expression DT_TOK_COLON
592		    conditional_expression { $$ = OP3($1, $3, $5); }
593	;
594
595assignment_expression:
596		conditional_expression
597	|	unary_expression assignment_operator assignment_expression {
598			$$ = OP2($2, $1, $3);
599		}
600	;
601
602assignment_operator:
603		DT_TOK_ASGN   { $$ = DT_TOK_ASGN; }
604	|	DT_TOK_MUL_EQ { $$ = DT_TOK_MUL_EQ; }
605	|	DT_TOK_DIV_EQ { $$ = DT_TOK_DIV_EQ; }
606	|	DT_TOK_MOD_EQ { $$ = DT_TOK_MOD_EQ; }
607	|	DT_TOK_ADD_EQ { $$ = DT_TOK_ADD_EQ; }
608	|	DT_TOK_SUB_EQ { $$ = DT_TOK_SUB_EQ; }
609	|	DT_TOK_LSH_EQ { $$ = DT_TOK_LSH_EQ; }
610	|	DT_TOK_RSH_EQ { $$ = DT_TOK_RSH_EQ; }
611	|	DT_TOK_AND_EQ { $$ = DT_TOK_AND_EQ; }
612	|	DT_TOK_XOR_EQ { $$ = DT_TOK_XOR_EQ; }
613	|	DT_TOK_OR_EQ  { $$ = DT_TOK_OR_EQ; }
614	;
615
616expression:	assignment_expression
617	|	expression DT_TOK_COMMA assignment_expression {
618			$$ = OP2(DT_TOK_COMMA, $1, $3);
619		}
620	;
621
622declaration:	declaration_specifiers ';' {
623			$$ = dt_node_decl();
624			dt_decl_free(dt_decl_pop());
625			yybegin(YYS_CLAUSE);
626		}
627	|	declaration_specifiers init_declarator_list ';' {
628			$$ = $2;
629			dt_decl_free(dt_decl_pop());
630			yybegin(YYS_CLAUSE);
631		}
632	;
633
634declaration_specifiers:
635		d_storage_class_specifier
636	|	d_storage_class_specifier declaration_specifiers
637	|	type_specifier
638	|	type_specifier declaration_specifiers
639	|	type_qualifier
640	|	type_qualifier declaration_specifiers
641	;
642
643parameter_declaration_specifiers:
644		storage_class_specifier
645	|	storage_class_specifier declaration_specifiers
646	|	type_specifier
647	|	type_specifier declaration_specifiers
648	|	type_qualifier
649	|	type_qualifier declaration_specifiers
650	;
651
652storage_class_specifier:
653		DT_KEY_AUTO { dt_decl_class(DT_DC_AUTO); }
654	|	DT_KEY_REGISTER { dt_decl_class(DT_DC_REGISTER); }
655	|	DT_KEY_STATIC { dt_decl_class(DT_DC_STATIC); }
656	|	DT_KEY_EXTERN { dt_decl_class(DT_DC_EXTERN); }
657	|	DT_KEY_TYPEDEF { dt_decl_class(DT_DC_TYPEDEF); }
658	;
659
660d_storage_class_specifier:
661		storage_class_specifier
662	|	DT_KEY_SELF { dt_decl_class(DT_DC_SELF); }
663	|	DT_KEY_THIS { dt_decl_class(DT_DC_THIS); }
664	;
665
666type_specifier:	DT_KEY_VOID { $$ = dt_decl_spec(CTF_K_INTEGER, DUP("void")); }
667	|	DT_KEY_CHAR { $$ = dt_decl_spec(CTF_K_INTEGER, DUP("char")); }
668	|	DT_KEY_SHORT { $$ = dt_decl_attr(DT_DA_SHORT); }
669	|	DT_KEY_INT { $$ = dt_decl_spec(CTF_K_INTEGER, DUP("int")); }
670	|	DT_KEY_LONG { $$ = dt_decl_attr(DT_DA_LONG); }
671	|	DT_KEY_FLOAT { $$ = dt_decl_spec(CTF_K_FLOAT, DUP("float")); }
672	|	DT_KEY_DOUBLE { $$ = dt_decl_spec(CTF_K_FLOAT, DUP("double")); }
673	|	DT_KEY_SIGNED { $$ = dt_decl_attr(DT_DA_SIGNED); }
674	|	DT_KEY_UNSIGNED { $$ = dt_decl_attr(DT_DA_UNSIGNED); }
675	|	DT_KEY_USERLAND { $$ = dt_decl_attr(DT_DA_USER); }
676	|	DT_KEY_STRING {
677			$$ = dt_decl_spec(CTF_K_TYPEDEF, DUP("string"));
678		}
679	|	DT_TOK_TNAME { $$ = dt_decl_spec(CTF_K_TYPEDEF, $1); }
680	|	struct_or_union_specifier
681	|	enum_specifier
682	;
683
684type_qualifier:	DT_KEY_CONST { $$ = dt_decl_attr(DT_DA_CONST); }
685	|	DT_KEY_RESTRICT { $$ = dt_decl_attr(DT_DA_RESTRICT); }
686	|	DT_KEY_VOLATILE { $$ = dt_decl_attr(DT_DA_VOLATILE); }
687	;
688
689struct_or_union_specifier:
690		struct_or_union_definition struct_declaration_list '}' {
691			$$ = dt_scope_pop();
692		}
693	|	struct_or_union DT_TOK_IDENT { $$ = dt_decl_spec($1, $2); }
694	|	struct_or_union DT_TOK_TNAME { $$ = dt_decl_spec($1, $2); }
695	;
696
697struct_or_union_definition:
698		struct_or_union '{' { dt_decl_sou($1, NULL); }
699	|	struct_or_union DT_TOK_IDENT '{' { dt_decl_sou($1, $2); }
700	|	struct_or_union DT_TOK_TNAME '{' { dt_decl_sou($1, $2); }
701	;
702
703struct_or_union:
704		DT_KEY_STRUCT { $$ = CTF_K_STRUCT; }
705	|	DT_KEY_UNION { $$ = CTF_K_UNION; }
706	;
707
708struct_declaration_list:
709		struct_declaration
710	|	struct_declaration_list struct_declaration
711	;
712
713init_declarator_list:
714		init_declarator
715	|	init_declarator_list DT_TOK_COMMA init_declarator {
716			$$ = LINK($1, $3);
717		}
718	;
719
720init_declarator:
721		declarator {
722			$$ = dt_node_decl();
723			dt_decl_reset();
724		}
725	;
726
727struct_declaration:
728		specifier_qualifier_list struct_declarator_list ';' {
729			dt_decl_free(dt_decl_pop());
730		}
731	;
732
733specifier_qualifier_list:
734		type_specifier
735	|	type_specifier specifier_qualifier_list { $$ = $2; }
736	|	type_qualifier
737	|	type_qualifier specifier_qualifier_list { $$ = $2; }
738	;
739
740struct_declarator_list:
741		struct_declarator
742	|	struct_declarator_list DT_TOK_COMMA struct_declarator
743	;
744
745struct_declarator:
746		declarator { dt_decl_member(NULL); }
747	|	DT_TOK_COLON constant_expression { dt_decl_member($2); }
748	|	declarator DT_TOK_COLON constant_expression {
749			dt_decl_member($3);
750		}
751	;
752
753enum_specifier:
754		enum_definition enumerator_list '}' { $$ = dt_scope_pop(); }
755	|	DT_KEY_ENUM DT_TOK_IDENT { $$ = dt_decl_spec(CTF_K_ENUM, $2); }
756	|	DT_KEY_ENUM DT_TOK_TNAME { $$ = dt_decl_spec(CTF_K_ENUM, $2); }
757	;
758
759enum_definition:
760		DT_KEY_ENUM '{' { dt_decl_enum(NULL); }
761	|	DT_KEY_ENUM DT_TOK_IDENT '{' { dt_decl_enum($2); }
762	|	DT_KEY_ENUM DT_TOK_TNAME '{' { dt_decl_enum($2); }
763	;
764
765enumerator_list:
766		enumerator
767	|	enumerator_list DT_TOK_COMMA enumerator
768	;
769
770enumerator:	DT_TOK_IDENT { dt_decl_enumerator($1, NULL); }
771	|	DT_TOK_IDENT DT_TOK_ASGN expression {
772			dt_decl_enumerator($1, $3);
773		}
774	;
775
776declarator:	direct_declarator
777	|	pointer direct_declarator
778	;
779
780direct_declarator:
781		DT_TOK_IDENT { $$ = dt_decl_ident($1); }
782	|	lparen declarator DT_TOK_RPAR { $$ = $2; }
783	|	direct_declarator array { dt_decl_array($2); }
784	|	direct_declarator function { dt_decl_func($1, $2); }
785	;
786
787lparen:		DT_TOK_LPAR { dt_decl_top()->dd_attr |= DT_DA_PAREN; }
788	;
789
790pointer:	DT_TOK_MUL { $$ = dt_decl_ptr(); }
791	|	DT_TOK_MUL type_qualifier_list { $$ = dt_decl_ptr(); }
792	|	DT_TOK_MUL pointer { $$ = dt_decl_ptr(); }
793	|	DT_TOK_MUL type_qualifier_list pointer { $$ = dt_decl_ptr(); }
794	;
795
796type_qualifier_list:
797		type_qualifier
798	|	type_qualifier_list type_qualifier { $$ = $2; }
799	;
800
801parameter_type_list:
802		parameter_list
803	|	DT_TOK_ELLIPSIS { $$ = dt_node_vatype(); }
804	|	parameter_list DT_TOK_COMMA DT_TOK_ELLIPSIS {
805			$$ = LINK($1, dt_node_vatype());
806		}
807	;
808
809parameter_list:	parameter_declaration
810	|	parameter_list DT_TOK_COMMA parameter_declaration {
811			$$ = LINK($1, $3);
812		}
813	;
814
815parameter_declaration:
816		parameter_declaration_specifiers {
817			$$ = dt_node_type(NULL);
818		}
819	|	parameter_declaration_specifiers declarator {
820			$$ = dt_node_type(NULL);
821		}
822	|	parameter_declaration_specifiers abstract_declarator {
823			$$ = dt_node_type(NULL);
824		}
825	;
826
827type_name:	specifier_qualifier_list {
828			$$ = dt_decl_pop();
829		}
830	|	specifier_qualifier_list abstract_declarator {
831			$$ = dt_decl_pop();
832		}
833	;
834
835abstract_declarator:
836		pointer
837	|	direct_abstract_declarator
838	|	pointer direct_abstract_declarator
839	;
840
841direct_abstract_declarator:
842		lparen abstract_declarator DT_TOK_RPAR { $$ = $2; }
843	|	direct_abstract_declarator array { dt_decl_array($2); }
844	|	array { dt_decl_array($1); $$ = NULL; }
845	|	direct_abstract_declarator function { dt_decl_func($1, $2); }
846	|	function { dt_decl_func(NULL, $1); }
847	;
848
849array:		DT_TOK_LBRAC { dt_scope_push(NULL, CTF_ERR); }
850		    array_parameters DT_TOK_RBRAC {
851			dt_scope_pop();
852			$$ = $3;
853		}
854	;
855
856array_parameters:
857		/* empty */ 		{ $$ = NULL; }
858	|	constant_expression	{ $$ = $1; }
859	|	parameter_type_list	{ $$ = $1; }
860	;
861
862function:	DT_TOK_LPAR { dt_scope_push(NULL, CTF_ERR); }
863		    function_parameters DT_TOK_RPAR {
864			dt_scope_pop();
865			$$ = $3;
866		}
867	;
868
869function_parameters:
870		/* empty */ 		{ $$ = NULL; }
871	|	parameter_type_list	{ $$ = $1; }
872	;
873
874dtrace_keyword_ident:
875	  DT_KEY_PROBE { $$ = DUP("probe"); }
876	| DT_KEY_PROVIDER { $$ = DUP("provider"); }
877	| DT_KEY_SELF { $$ = DUP("self"); }
878	| DT_KEY_STRING { $$ = DUP("string"); }
879	| DT_TOK_STRINGOF { $$ = DUP("stringof"); }
880	| DT_KEY_USERLAND { $$ = DUP("userland"); }
881	| DT_TOK_XLATE { $$ = DUP("xlate"); }
882	| DT_KEY_XLATOR { $$ = DUP("translator"); }
883	;
884
885%%
886