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