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