source: translator/Parser/cfa.y @ c11e31c

aaron-thesisarm-ehcleanup-dtorsctordeferred_resndemanglergc_noraiijacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerresolv-newstringwith_gc
Last change on this file since c11e31c was c11e31c, checked in by Peter A. Buhr <pabuhr@…>, 7 years ago

add inline and attribute qualifiers, cfa.y comment formatting, fix error message in isIntegralType

  • Property mode set to 100644
File size: 98.7 KB
Line 
1//                              -*- Mode: C++ -*-
2//
3// CForall Grammar Version 1.0, Copyright (C) Peter A. Buhr 2001
4//
5// cfa.y --
6//
7// Author           : Peter A. Buhr
8// Created On       : Sat Sep  1 20:22:55 2001
9// Last Modified By : Peter A. Buhr
10// Last Modified On : Tue May 12 17:24:53 2015
11// Update Count     : 963
12//
13
14// This grammar is based on the ANSI99/11 C grammar, specifically parts of EXPRESSION and STATEMENTS, and on the C
15// grammar by James A. Roskind, specifically parts of DECLARATIONS and EXTERNAL DEFINITIONS.  While parts have been
16// copied, important changes have been made in all sections; these changes are sufficient to constitute a new grammar.
17// In particular, this grammar attempts to be more syntactically precise, i.e., it parses less incorrect language syntax
18// that must be subsequently rejected by semantic checks.  Nevertheless, there are still several semantic checks
19// required and many are noted in the grammar. Finally, the grammar is extended with GCC and CFA language extensions.
20
21// Acknowledgments to Richard Bilson, Glen Ditchfield, and Rodolfo Gabriel Esteves who all helped when I got stuck with
22// the grammar.
23
24// The root language for this grammar is ANSI99/11 C. All of ANSI99/11 is parsed, except for:
25//
26// 1. designation with '=' (use ':' instead)
27//
28// Most of the syntactic extensions from ANSI90 to ANSI11 C are marked with the comment "C99/C11". This grammar also has
29// two levels of extensions. The first extensions cover most of the GCC C extensions, except for:
30//
31// 1. nested functions
32// 2. generalized lvalues
33// 3. designation with and without '=' (use ':' instead)
34// 4. attributes not allowed in parenthesis of declarator
35//
36// All of the syntactic extensions for GCC C are marked with the comment "GCC". The second extensions are for Cforall
37// (CFA), which fixes several of C's outstanding problems and extends C with many modern language concepts. All of the
38// syntactic extensions for CFA C are marked with the comment "CFA". As noted above, there is one unreconcileable
39// parsing problem between C99 and CFA with respect to designators; this is discussed in detail before the "designation"
40// grammar rule.
41
42%{
43#define YYDEBUG_LEXER_TEXT (yylval)                     // lexer loads this up each time
44#define YYDEBUG 1                                       // get the pretty debugging code to compile
45
46#undef __GNUC_MINOR__
47
48#include <cstdio>
49#include <stack>
50#include "TypedefTable.h"
51#include "lex.h"
52#include "ParseNode.h"
53#include "LinkageSpec.h"
54
55DeclarationNode *theTree = 0;                           // the resulting parse tree
56LinkageSpec::Type linkage = LinkageSpec::Cforall;
57std::stack< LinkageSpec::Type > linkageStack;
58TypedefTable typedefTable;
59%}
60
61//************************* TERMINAL TOKENS ********************************
62
63// keywords
64%token TYPEDEF
65%token AUTO EXTERN REGISTER STATIC
66%token INLINE                                           // C99
67%token FORTRAN                                          // C99, extension ISO/IEC 9899:1999 Section J.5.9(1)
68%token CONST VOLATILE
69%token RESTRICT                                         // C99
70%token FORALL LVALUE                                    // CFA
71%token VOID CHAR SHORT INT LONG FLOAT DOUBLE SIGNED UNSIGNED
72%token BOOL COMPLEX IMAGINARY                           // C99
73%token TYPEOF LABEL                                     // GCC
74%token ENUM STRUCT UNION
75%token TYPE FTYPE DTYPE CONTEXT                         // CFA
76%token SIZEOF
77%token ATTRIBUTE EXTENSION                              // GCC
78%token IF ELSE SWITCH CASE DEFAULT DO WHILE FOR BREAK CONTINUE GOTO RETURN
79%token CHOOSE FALLTHRU TRY CATCH FINALLY THROW          // CFA
80%token ASM                                              // C99, extension ISO/IEC 9899:1999 Section J.5.10(1)
81%token ALIGNAS ALIGNOF ATOMIC GENERIC NORETURN STATICASSERT THREADLOCAL // C11
82
83// names and constants: lexer differentiates between identifier and typedef names
84%token<tok> IDENTIFIER          QUOTED_IDENTIFIER       TYPEDEFname             TYPEGENname
85%token<tok> ATTR_IDENTIFIER     ATTR_TYPEDEFname        ATTR_TYPEGENname
86%token<tok> INTEGERconstant     FLOATINGconstant        CHARACTERconstant       STRINGliteral
87%token<tok> ZERO                ONE                     // CFA
88
89// multi-character operators
90%token ARROW                    /* ->                           */
91%token ICR DECR                 /* ++   --                      */
92%token LS RS                    /* <<   >>                      */
93%token LE GE EQ NE              /* <=   >=      ==      !=      */
94%token ANDAND OROR              /* &&   ||                      */
95%token ELLIPSIS                 /* ...                          */
96
97%token MULTassign       DIVassign       MODassign       /* *=   /=      %=      */
98%token PLUSassign       MINUSassign                     /* +=   -=              */
99%token LSassign         RSassign                        /* <<=  >>=             */
100%token ANDassign        ERassign        ORassign        /* &=   ^=      |=      */
101
102// Types declaration
103%union
104{
105    Token tok;
106    ParseNode *pn;
107    ExpressionNode *en;
108    DeclarationNode *decl;
109    DeclarationNode::TyCon aggKey;
110    DeclarationNode::TypeClass tclass;
111    StatementNode *sn;
112    ConstantNode *constant;
113    InitializerNode *in;
114}
115
116%type<tok> zero_one  identifier  no_attr_identifier  no_01_identifier
117%type<tok> identifier_or_typedef_name  no_attr_identifier_or_typedef_name  no_01_identifier_or_typedef_name
118%type<constant> string_literal_list
119
120// expressions
121%type<constant> constant
122%type<en> tuple                         tuple_expression_list
123%type<en> unary_operator                assignment_operator
124%type<en> primary_expression            postfix_expression              unary_expression
125%type<en> cast_expression               multiplicative_expression       additive_expression     shift_expression
126%type<en> relational_expression         equality_expression             AND_expression          exclusive_OR_expression
127%type<en> inclusive_OR_expression       logical_AND_expression          logical_OR_expression   conditional_expression
128%type<en> constant_expression           assignment_expression           assignment_expression_opt
129%type<en> comma_expression              comma_expression_opt
130%type<en> argument_expression_list      argument_expression             for_control_expression  assignment_opt
131%type<en> subrange
132
133// statements
134%type<sn> labeled_statement     compound_statement      expression_statement    selection_statement
135%type<sn> iteration_statement   jump_statement          exception_statement     asm_statement
136%type<sn> fall_through_opt      fall_through
137%type<sn> statement             statement_list
138%type<sn> block_item_list       block_item
139%type<sn> case_clause
140%type<en> case_value            case_value_list
141%type<sn> case_label            case_label_list
142%type<sn> switch_clause_list_opt switch_clause_list     choose_clause_list_opt  choose_clause_list
143%type<pn> handler_list          handler_clause          finally_clause
144
145// declarations
146%type<decl> abstract_array abstract_declarator abstract_function abstract_parameter_array
147%type<decl> abstract_parameter_declaration abstract_parameter_declarator abstract_parameter_function
148%type<decl> abstract_parameter_ptr abstract_ptr
149
150%type<aggKey> aggregate_key
151%type<decl>  aggregate_name
152
153%type<decl> array_dimension array_parameter_1st_dimension array_parameter_dimension multi_array_dimension
154
155%type<decl> assertion assertion_list_opt
156
157%type<en>   bit_subrange_size_opt bit_subrange_size
158
159%type<decl> basic_declaration_specifier basic_type_name basic_type_specifier direct_type_name indirect_type_name
160
161%type<decl> context_declaration context_declaration_list context_declaring_list context_specifier
162
163%type<decl> declaration declaration_list declaration_list_opt declaration_qualifier_list
164%type<decl> declaration_specifier declarator declaring_list
165
166%type<decl> elaborated_type_name
167
168%type<decl> enumerator_list enum_name
169%type<en> enumerator_value_opt
170
171%type<decl> exception_declaration external_definition external_definition_list external_definition_list_opt
172
173%type<decl> field_declaration field_declaration_list field_declarator field_declaring_list
174%type<en> field field_list
175
176%type<decl> function_array function_declarator function_definition function_no_ptr function_ptr
177
178%type<decl> identifier_parameter_array identifier_parameter_declarator identifier_parameter_function
179%type<decl> identifier_parameter_ptr identifier_list
180
181%type<decl> new_abstract_array new_abstract_declarator_no_tuple new_abstract_declarator_tuple
182%type<decl> new_abstract_function new_abstract_parameter_declaration new_abstract_parameter_list
183%type<decl> new_abstract_ptr new_abstract_tuple
184
185%type<decl> new_array_parameter_1st_dimension
186
187%type<decl> new_context_declaring_list new_declaration new_field_declaring_list
188%type<decl> new_function_declaration new_function_return new_function_specifier
189
190%type<decl> new_identifier_parameter_array new_identifier_parameter_declarator_no_tuple
191%type<decl> new_identifier_parameter_declarator_tuple new_identifier_parameter_ptr
192
193%type<decl> new_parameter_declaration new_parameter_list new_parameter_type_list new_parameter_type_list_opt
194
195%type<decl> new_typedef_declaration new_variable_declaration new_variable_specifier
196
197%type<decl> old_declaration old_declaration_list old_declaration_list_opt old_function_array
198%type<decl> old_function_declarator old_function_no_ptr old_function_ptr
199
200%type<decl> parameter_declaration parameter_list parameter_type_list
201%type<decl> parameter_type_list_opt
202
203%type<decl> paren_identifier paren_typedef
204
205%type<decl> storage_class storage_class_name storage_class_list
206
207%type<decl> sue_declaration_specifier sue_type_specifier
208
209%type<tclass> type_class
210%type<decl> type_declarator type_declarator_name type_declaring_list
211
212%type<decl> typedef typedef_array typedef_declaration typedef_declaration_specifier typedef_expression
213%type<decl> typedef_function typedef_parameter_array typedef_parameter_function typedef_parameter_ptr
214%type<decl> typedef_parameter_redeclarator typedef_ptr typedef_redeclarator typedef_type_specifier
215%type<decl> typegen_declaration_specifier typegen_type_specifier
216
217%type<decl> type_name type_name_no_function
218%type<decl> type_parameter type_parameter_list
219
220%type<en> type_name_list
221
222%type<decl> type_qualifier type_qualifier_name type_qualifier_list type_qualifier_list_opt type_specifier
223
224%type<decl> variable_abstract_array variable_abstract_declarator variable_abstract_function
225%type<decl> variable_abstract_ptr variable_array variable_declarator variable_function variable_ptr
226
227// initializers
228%type<in>  initializer initializer_list initializer_opt
229
230// designators
231%type<en>  designator designator_list designation
232
233
234// Handle single shift/reduce conflict for dangling else by shifting the ELSE token. For example, this string is
235// ambiguous:
236// .---------.                  matches IF '(' comma_expression ')' statement
237// if ( C ) S1 else S2
238// `-----------------'  matches IF '(' comma_expression ')' statement ELSE statement */
239
240%nonassoc THEN  // rule precedence for IF '(' comma_expression ')' statement
241%nonassoc ELSE  // token precedence for start of else clause in IF statement
242
243%start translation_unit                                 // parse-tree root
244
245%%
246//************************* Namespace Management ********************************
247
248// The grammar in the ANSI C standard is not strictly context-free, since it relies upon the distinct terminal symbols
249// "identifier" and "TYPEDEFname" that are lexically identical.  While it is possible to write a purely context-free
250// grammar, such a grammar would obscure the relationship between syntactic and semantic constructs.  Hence, this
251// grammar uses the ANSI style.
252//
253// Cforall compounds this problem by introducing type names local to the scope of a declaration (for instance, those
254// introduced through "forall" qualifiers), and by introducing "type generators" -- parametrized types.  This latter
255// type name creates a third class of identifiers that must be distinguished by the scanner.
256//
257// Since the scanner cannot distinguish among the different classes of identifiers without some context information, it
258// accesses a data structure (the TypedefTable) to allow classification of an identifier that it has just read.
259// Semantic actions during the parser update this data structure when the class of identifiers change.
260//
261// Because the Cforall language is block-scoped, there is the possibility that an identifier can change its class in a
262// local scope; it must revert to its original class at the end of the block.  Since type names can be local to a
263// particular declaration, each declaration is itself a scope.  This requires distinguishing between type names that are
264// local to the current declaration scope and those that persist past the end of the declaration (i.e., names defined in
265// "typedef" or "type" declarations).
266//
267// The non-terminals "push" and "pop" derive the empty string; their only use is to denote the opening and closing of
268// scopes.  Every push must have a matching pop, although it is regrettable the matching pairs do not always occur
269// within the same rule.  These non-terminals may appear in more contexts than strictly necessary from a semantic point
270// of view.  Unfortunately, these extra rules are necessary to prevent parsing conflicts -- the parser may not have
271// enough context and look-ahead information to decide whether a new scope is necessary, so the effect of these extra
272// rules is to open a new scope unconditionally.  As the grammar evolves, it may be neccesary to add or move around
273// "push" and "pop" nonterminals to resolve conflicts of this sort.
274
275push:
276                {
277                    typedefTable.enterScope();
278                }
279        ;
280
281pop:
282                {
283                    typedefTable.leaveScope();
284                }
285        ;
286
287//************************* CONSTANTS ********************************
288
289constant:
290                // ENUMERATIONconstant is not included here; it is treated as a variable with type "enumeration
291                // constant".
292        INTEGERconstant                                 { $$ = new ConstantNode(ConstantNode::Integer,   $1); }
293        | FLOATINGconstant                              { $$ = new ConstantNode(ConstantNode::Float,     $1); }
294        | CHARACTERconstant                             { $$ = new ConstantNode(ConstantNode::Character, $1); }
295        ;
296
297identifier:
298        IDENTIFIER
299        | ATTR_IDENTIFIER                               // CFA
300        | zero_one                                      // CFA
301        ;
302
303no_01_identifier:
304        IDENTIFIER
305        | ATTR_IDENTIFIER                               // CFA
306        ;
307
308no_attr_identifier:
309        IDENTIFIER
310        ;
311
312zero_one:                                               // CFA
313        ZERO
314        | ONE
315        ;
316
317string_literal_list:                                    // juxtaposed strings are concatenated
318        STRINGliteral                                   { $$ = new ConstantNode(ConstantNode::String, $1); }
319        | string_literal_list STRINGliteral             { $$ = $1->append( $2 ); }
320        ;
321
322//************************* EXPRESSIONS ********************************
323
324primary_expression:
325        IDENTIFIER                                      // typedef name cannot be used as a variable name
326                { $$ = new VarRefNode($1); }
327        | zero_one
328                { $$ = new VarRefNode($1); }
329        | constant
330                { $$ = $1; }
331        | string_literal_list
332                { $$ = $1; }
333        | '(' comma_expression ')'
334                { $$ = $2; }
335        | '(' compound_statement ')'                    // GCC, lambda expression
336                { $$ = new ValofExprNode($2); }
337        ;
338
339postfix_expression:
340        primary_expression
341        | postfix_expression '[' push assignment_expression pop ']'
342                // CFA, comma_expression disallowed in the context because it results in a commom user error:
343                // subscripting a matrix with x[i,j] instead of x[i][j]. While this change is not backwards
344                // compatible, there seems to be little advantage to this feature and many disadvantages. It is
345                // possible to write x[(i,j)] in CFA, which is equivalent to the old x[i,j].
346                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Index), $1, $4); }
347        | postfix_expression '(' argument_expression_list ')'
348                { $$ = new CompositeExprNode($1, $3); }
349        | postfix_expression '.' no_attr_identifier
350                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::FieldSel), $1, new VarRefNode($3)); }
351        | postfix_expression '.' '[' push field_list pop ']' // CFA, tuple field selector
352        | postfix_expression ARROW no_attr_identifier
353                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::PFieldSel), $1, new VarRefNode($3)); }
354        | postfix_expression ARROW '[' push field_list pop ']' // CFA, tuple field selector
355        | postfix_expression ICR
356                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::IncrPost), $1); }
357        | postfix_expression DECR
358                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::DecrPost), $1); }
359                // GCC has priority: cast_expression
360        | '(' type_name_no_function ')' '{' initializer_list comma_opt '}' // C99
361                { $$ = 0; }
362        ;
363
364argument_expression_list:
365        argument_expression
366        | argument_expression_list ',' argument_expression
367                                                        { $$ = (ExpressionNode *)($1->set_link($3)); }
368        ;
369
370argument_expression:
371        // empty
372                { $$ = 0; }                             // use default argument
373        | assignment_expression
374        | no_attr_identifier ':' assignment_expression
375                                                        { $$ = $3->set_asArgName($1); }
376                // Only a list of no_attr_identifier_or_typedef_name is allowed in this context. However, there is
377                // insufficient look ahead to distinguish between this list of parameter names and a tuple, so the
378                // tuple form must be used with an appropriate semantic check.
379        | '[' push assignment_expression pop ']' ':' assignment_expression
380                                                        { $$ = $7->set_asArgName($3); }
381        | '[' push assignment_expression ',' tuple_expression_list pop ']' ':' assignment_expression
382                                                        { $$ = $9->set_asArgName(new CompositeExprNode( new OperatorNode( OperatorNode::TupleC ), (ExpressionNode *)$3->set_link( flattenCommas( $5 )))); }
383        ;
384
385field_list:                                             // CFA, tuple field selector
386        field
387        | field_list ',' field                          { $$ = (ExpressionNode *)$1->set_link( $3 ); }
388        ;
389
390field:                                                  // CFA, tuple field selector
391        no_attr_identifier
392                                                        { $$ = new VarRefNode( $1 ); }
393        | no_attr_identifier '.' field
394                                                        { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::FieldSel), new VarRefNode( $1 ), $3); }
395        | no_attr_identifier '.' '[' push field_list pop ']'
396                                                        { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::FieldSel), new VarRefNode( $1 ), $5); }
397        | no_attr_identifier ARROW field
398                                                        { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::PFieldSel), new VarRefNode( $1 ), $3); }
399        | no_attr_identifier ARROW '[' push field_list pop ']'
400                                                        { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::PFieldSel), new VarRefNode( $1 ), $5); }
401        ;
402
403unary_expression:
404        postfix_expression
405        | ICR unary_expression
406                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Incr), $2); }
407        | DECR unary_expression
408                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Decr), $2); }
409        | EXTENSION cast_expression                     // GCC
410                { $$ = $2; }
411        | unary_operator cast_expression
412                { $$ = new CompositeExprNode($1, $2); }
413        | '!' cast_expression
414                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Neg), $2); }
415        | '*' cast_expression                           // CFA
416                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::PointTo), $2); }
417                // '*' is is separated from unary_operator because of shift/reduce conflict in:
418                //      { * X; } // dereference X
419                //      { * int X; } // CFA declaration of pointer to int
420                // '&' must be moved here if C++ reference variables are supported.
421        | SIZEOF unary_expression
422                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::SizeOf), $2); }
423        | SIZEOF '(' type_name_no_function ')'
424                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::SizeOf), new TypeValueNode($3)); }
425        | ATTR_IDENTIFIER
426                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Attr), new VarRefNode($1)); }
427        | ATTR_IDENTIFIER '(' type_name ')'
428                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Attr), new VarRefNode($1), new TypeValueNode($3)); }
429        | ATTR_IDENTIFIER '(' argument_expression ')'
430                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Attr), new VarRefNode($1), $3); }
431        | ALIGNOF unary_expression                      // GCC, variable alignment
432                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::AlignOf), $2); }
433        | ALIGNOF '(' type_name_no_function ')'         // GCC, type alignment
434                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::AlignOf), new TypeValueNode($3)); }
435        | ANDAND no_attr_identifier                     // GCC, address of label
436                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::LabelAddress), new VarRefNode($2, true)); }
437        ;
438
439unary_operator:
440        '&'                                             { $$ = new OperatorNode(OperatorNode::AddressOf); }
441        | '+'                                           { $$ = new OperatorNode(OperatorNode::UnPlus); }
442        | '-'                                           { $$ = new OperatorNode(OperatorNode::UnMinus); }
443        | '~'                                           { $$ = new OperatorNode(OperatorNode::BitNeg); }
444        ;
445
446cast_expression:
447        unary_expression
448        | '(' type_name_no_function ')' cast_expression
449                                                        { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Cast), new TypeValueNode($2), $4); }
450        | '(' type_name_no_function ')' tuple
451                                                        { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Cast), new TypeValueNode($2), $4); }
452        ;
453
454multiplicative_expression:
455        cast_expression
456        | multiplicative_expression '*' cast_expression
457                                                        { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Mul),$1,$3); }
458        | multiplicative_expression '/' cast_expression
459                                                        { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Div),$1,$3); }
460        | multiplicative_expression '%' cast_expression
461                                                        { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Mod),$1,$3); }
462        ;
463
464additive_expression:
465        multiplicative_expression
466        | additive_expression '+' multiplicative_expression
467                                                        { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Plus),$1,$3); }
468        | additive_expression '-' multiplicative_expression
469                                                        { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Minus),$1,$3); }
470        ;
471
472shift_expression:
473        additive_expression
474        | shift_expression LS additive_expression
475                                                        { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::LShift),$1,$3); }
476        | shift_expression RS additive_expression
477                                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::RShift),$1,$3); }
478        ;
479
480relational_expression:
481        shift_expression
482        | relational_expression '<' shift_expression
483                                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::LThan),$1,$3); }
484        | relational_expression '>' shift_expression
485                                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::GThan),$1,$3); }
486        | relational_expression LE shift_expression
487                                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::LEThan),$1,$3); }
488        | relational_expression GE shift_expression
489                                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::GEThan),$1,$3); }
490        ;
491
492equality_expression:
493        relational_expression
494        | equality_expression EQ relational_expression
495                                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Eq), $1, $3); }
496        | equality_expression NE relational_expression
497                                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Neq), $1, $3); }
498        ;
499
500AND_expression:
501        equality_expression
502        | AND_expression '&' equality_expression
503                                                { $$ =new CompositeExprNode(new OperatorNode(OperatorNode::BitAnd), $1, $3); }
504        ;
505
506exclusive_OR_expression:
507        AND_expression
508        | exclusive_OR_expression '^' AND_expression
509                                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Xor), $1, $3); }
510        ;
511
512inclusive_OR_expression:
513        exclusive_OR_expression
514        | inclusive_OR_expression '|' exclusive_OR_expression
515                                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::BitOr), $1, $3); }
516        ;
517
518logical_AND_expression:
519        inclusive_OR_expression
520        | logical_AND_expression ANDAND inclusive_OR_expression
521                                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::And), $1, $3); }
522        ;
523
524logical_OR_expression:
525        logical_AND_expression
526        | logical_OR_expression OROR logical_AND_expression
527                                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Or), $1, $3); }
528        ;
529
530conditional_expression:
531        logical_OR_expression
532        | logical_OR_expression '?' comma_expression ':' conditional_expression
533                                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Cond),
534                                                                       (ExpressionNode *)mkList((*$1,*$3,*$5))); }
535        | logical_OR_expression '?' /* empty */ ':' conditional_expression // GCC, omitted first operand
536                                                { $$=new CompositeExprNode(new OperatorNode(OperatorNode::NCond),$1,$4); }
537        | logical_OR_expression '?' comma_expression ':' tuple // CFA, tuple expression
538                                                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Cond),
539                                                                       (ExpressionNode *)mkList(( *$1, *$3, *$5 ))); }
540        ;
541
542constant_expression:
543        conditional_expression
544        ;
545
546assignment_expression:
547                // CFA, assignment is separated from assignment_operator to ensure no assignment operations for tuples
548        conditional_expression
549        | unary_expression '=' assignment_expression
550                                                        { $$ =new CompositeExprNode(new OperatorNode(OperatorNode::Assign), $1, $3); }
551        | unary_expression assignment_operator assignment_expression
552                                                        { $$ =new CompositeExprNode($2, $1, $3); }
553        | tuple assignment_opt                          // CFA, tuple expression
554                {
555                  if ( $2 == 0 ) {
556                    $$ = $1;
557                  } else {
558                    $$ = new CompositeExprNode( new OperatorNode( OperatorNode::Assign ), $1, $2 );
559                  }
560                }
561        ;
562
563assignment_expression_opt:
564        // empty
565                { $$ = new NullExprNode; }
566        | assignment_expression
567        ;
568
569tuple:                                                  // CFA, tuple
570                // CFA, one assignment_expression is factored out of comma_expression to eliminate a shift/reduce
571                // conflict with comma_expression in new_identifier_parameter_array and new_abstract_array
572        '[' push pop ']'
573                { $$ = new CompositeExprNode( new OperatorNode( OperatorNode::TupleC ) ); }
574        | '[' push assignment_expression pop ']'
575                { $$ = new CompositeExprNode( new OperatorNode( OperatorNode::TupleC ), $3 ); }
576        | '[' push ',' tuple_expression_list pop ']'
577                { $$ = new CompositeExprNode( new OperatorNode( OperatorNode::TupleC ), (ExpressionNode *)(new NullExprNode)->set_link( $4 ) ); }
578        | '[' push assignment_expression ',' tuple_expression_list pop ']'
579                { $$ = new CompositeExprNode( new OperatorNode( OperatorNode::TupleC ), (ExpressionNode *)$3->set_link( flattenCommas( $5 ) ) ); }
580        ;
581
582tuple_expression_list:
583        assignment_expression_opt
584        | tuple_expression_list ',' assignment_expression_opt
585                { $$ = (ExpressionNode *)$1->set_link( $3 ); }
586        ;
587
588assignment_operator:
589        MULTassign                                      { $$ = new OperatorNode(OperatorNode::MulAssn);   }
590        | DIVassign                                     { $$ = new OperatorNode(OperatorNode::DivAssn);   }
591        | MODassign                                     { $$ = new OperatorNode(OperatorNode::ModAssn);   }
592        | PLUSassign                                    { $$ = new OperatorNode(OperatorNode::PlusAssn);  }
593        | MINUSassign                                   { $$ = new OperatorNode(OperatorNode::MinusAssn); }
594        | LSassign                                      { $$ = new OperatorNode(OperatorNode::LSAssn);    }
595        | RSassign                                      { $$ = new OperatorNode(OperatorNode::RSAssn);    }
596        | ANDassign                                     { $$ = new OperatorNode(OperatorNode::AndAssn);   }
597        | ERassign                                      { $$ = new OperatorNode(OperatorNode::ERAssn);    }
598        | ORassign                                      { $$ = new OperatorNode(OperatorNode::OrAssn);    }
599        ;
600
601comma_expression:
602        assignment_expression
603        | comma_expression ',' assignment_expression    // { $$ = (ExpressionNode *)$1->add_to_list($3); }
604                               { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Comma),$1,$3); }
605        ;
606
607comma_expression_opt:
608        // empty
609                { $$ = 0; }
610        | comma_expression
611        ;
612
613//*************************** STATEMENTS *******************************
614
615statement:
616        labeled_statement
617        | compound_statement
618        | expression_statement                          { $$ = $1; }
619        | selection_statement
620        | iteration_statement
621        | jump_statement
622        | exception_statement
623        | asm_statement
624        ;
625
626labeled_statement:
627        no_attr_identifier ':' attribute_list_opt statement
628                { $$ = $4->add_label($1);}
629        ;
630
631compound_statement:
632        '{' '}'
633                { $$ = new CompoundStmtNode( (StatementNode *)0 ); }
634        | '{'
635                // Two scopes are necessary because the block itself has a scope, but every declaration within the block
636                // also requires its own scope
637          push push
638          label_declaration_opt                         // GCC, local labels
639          block_item_list pop '}'                       // C99, intermix declarations and statements
640                { $$ = new CompoundStmtNode( $5 ); }
641        ;
642
643block_item_list:                                        // C99
644        block_item
645        | block_item_list push block_item
646                { if ($1 != 0) { $1->set_link($3); $$ = $1; } }
647        ;
648
649block_item:
650        declaration                                     // CFA, new & old style declarations
651                { $$ = new StatementNode( $1 ); }
652        | EXTENSION declaration                         // GCC
653                { $$ = new StatementNode( $2 ); }
654        | statement pop
655        ;
656
657statement_list:
658        statement
659        | statement_list statement
660                { if ($1 != 0) { $1->set_link($2); $$ = $1; } }
661        ;
662
663expression_statement:
664        comma_expression_opt ';'
665                { $$ = new StatementNode(StatementNode::Exp, $1, 0); }
666        ;
667
668selection_statement:
669        IF '(' comma_expression ')' statement           %prec THEN
670                // explicitly deal with the shift/reduce conflict on if/else
671                { $$ = new StatementNode(StatementNode::If, $3, $5); }
672        | IF '(' comma_expression ')' statement ELSE statement
673                { $$ = new StatementNode(StatementNode::If, $3, (StatementNode *)mkList((*$5, *$7)) ); }
674        | SWITCH '(' comma_expression ')' case_clause   // CFA
675                { $$ = new StatementNode(StatementNode::Switch, $3, $5); }
676        | SWITCH '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt '}' // CFA
677                { $$ = new StatementNode(StatementNode::Switch, $3, $8); /* xxx */ }
678                // The semantics of the declaration list is changed to include any associated initialization, which is
679                // performed *before* the transfer to the appropriate case clause.  Statements after the initial
680                // declaration list can never be executed, and therefore, are removed from the grammar even though C
681                // allows it.
682        | CHOOSE '(' comma_expression ')' case_clause   // CFA
683                { $$ = new StatementNode(StatementNode::Choose, $3, $5); }
684        | CHOOSE '(' comma_expression ')' '{' push declaration_list_opt choose_clause_list_opt '}' // CFA
685                { $$ = new StatementNode(StatementNode::Choose, $3, $8); }
686        ;
687
688// CASE and DEFAULT clauses are only allowed in the SWITCH statement, precluding Duff's device. In addition, a case
689// clause allows a list of values and subranges.
690
691case_value:                                             // CFA
692        constant_expression                     { $$ = $1; }
693        | constant_expression ELLIPSIS constant_expression // GCC, subrange
694                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Range),$1,$3); }
695        | subrange                                      // CFA, subrange
696        ;
697
698case_value_list:                                        // CFA
699        case_value
700        | case_value_list ',' case_value
701                {  $$ = new CompositeExprNode(new OperatorNode( OperatorNode::TupleC ), (ExpressionNode *)(tupleContents($1))->set_link($3) ); }
702        ;
703
704case_label:                                             // CFA
705        CASE case_value_list ':'                {  $$ = new StatementNode(StatementNode::Case, $2, 0); }
706        | DEFAULT ':'                           {  $$ = new StatementNode(StatementNode::Default);     }
707                // A semantic check is required to ensure only one default clause per switch/choose statement.
708        ;
709
710case_label_list:                                        // CFA
711        case_label
712        | case_label_list case_label            { $$ = (StatementNode *)($1->set_link($2)); }
713        ;
714
715case_clause:                                            // CFA
716        case_label_list statement               {  $$ = $1->append_last_case($2); }
717        ;
718
719switch_clause_list_opt:                                 // CFA
720        // empty
721                { $$ = 0; }
722        | switch_clause_list
723        ;
724
725switch_clause_list:                                     // CFA
726        case_label_list statement_list
727                                                { $$ = $1->append_last_case($2); }
728        | switch_clause_list case_label_list statement_list
729                                                { $$ = (StatementNode *)($1->set_link($2->append_last_case($3))); }
730        ;
731
732choose_clause_list_opt:                                 // CFA
733        // empty
734                { $$ = 0; }
735        | choose_clause_list
736        ;
737
738choose_clause_list:                                     // CFA
739        case_label_list fall_through
740                { $$ = $1->append_last_case($2); }
741        | case_label_list statement_list fall_through_opt
742                { $$ = $1->append_last_case((StatementNode *)mkList((*$2,*$3))); }
743        | choose_clause_list case_label_list fall_through
744                { $$ = (StatementNode *)($1->set_link($2->append_last_case($3))); }
745        | choose_clause_list case_label_list statement_list fall_through_opt
746                { $$ = (StatementNode *)($1->set_link($2->append_last_case((StatementNode *)mkList((*$3,*$4))))); }
747        ;
748
749fall_through_opt:                                       // CFA
750        // empty
751                { $$ = 0; }
752        | fall_through
753        ;
754
755fall_through:                                           // CFA
756        FALLTHRU                                { $$ = new StatementNode(StatementNode::Fallthru, 0, 0); }
757        | FALLTHRU ';'                          { $$ = new StatementNode(StatementNode::Fallthru, 0, 0); }
758        ;
759
760iteration_statement:
761        WHILE '(' comma_expression ')' statement
762                                                { $$ = new StatementNode(StatementNode::While, $3, $5); }
763        | DO statement WHILE '(' comma_expression ')' ';'
764                                                { $$ = new StatementNode(StatementNode::Do, $5, $2); }
765        | FOR '(' push for_control_expression ')' statement
766                                                { $$ = new StatementNode(StatementNode::For, $4, $6); }
767        ;
768
769for_control_expression:
770        comma_expression_opt pop ';' comma_expression_opt ';' comma_expression_opt
771                                                { $$ = new ForCtlExprNode($1, $4, $6); }
772        | declaration comma_expression_opt ';' comma_expression_opt // C99
773                // Like C++, the loop index can be declared local to the loop.
774                                                { $$ = new ForCtlExprNode($1, $2, $4); }
775        ;
776
777jump_statement:
778        GOTO no_attr_identifier ';'
779                                                { $$ = new StatementNode(StatementNode::Goto, $2); }
780        | GOTO '*' comma_expression ';'         // GCC, computed goto
781                // The syntax for the GCC computed goto violates normal expression precedence, e.g., goto *i+3; =>
782                // goto *(i+3); whereas normal operator precedence yields goto (*i)+3;
783                                                { $$ = new StatementNode(StatementNode::Goto, $3); }
784        | CONTINUE ';'
785                // A semantic check is required to ensure this statement appears only in the body of an iteration
786                // statement.
787                                                { $$ = new StatementNode(StatementNode::Continue, 0, 0); }
788        | CONTINUE no_attr_identifier ';'       // CFA, multi-level continue
789                // A semantic check is required to ensure this statement appears only in the body of an iteration
790                // statement, and the target of the transfer appears only at the start of an iteration statement.
791                                                { $$ = new StatementNode(StatementNode::Continue, $2); }
792        | BREAK ';'
793                // A semantic check is required to ensure this statement appears only in the body of an iteration
794                // statement.
795                                                { $$ = new StatementNode(StatementNode::Break, 0, 0); }
796        | BREAK no_attr_identifier ';'          // CFA, multi-level exit
797                // A semantic check is required to ensure this statement appears only in the body of an iteration
798                // statement, and the target of the transfer appears only at the start of an iteration statement.
799                                                { $$ = new StatementNode(StatementNode::Break, $2 ); }
800        | RETURN comma_expression_opt ';'
801                                                { $$ = new StatementNode(StatementNode::Return, $2, 0); }
802        | THROW assignment_expression ';'
803                                                { $$ = new StatementNode(StatementNode::Throw, $2, 0); }
804        | THROW ';'
805                                                { $$ = new StatementNode(StatementNode::Throw, 0, 0); }
806        ;
807
808exception_statement:
809        TRY compound_statement handler_list
810                             { $$ = new StatementNode(StatementNode::Try, 0,(StatementNode *)(mkList((*$2,*$3)))); }
811        | TRY compound_statement finally_clause
812                             { $$ = new StatementNode(StatementNode::Try, 0,(StatementNode *)(mkList((*$2,*$3)))); }
813        | TRY compound_statement handler_list finally_clause
814                             {
815                               $3->set_link($4);
816                               $$ = new StatementNode(StatementNode::Try, 0,(StatementNode *)(mkList((*$2,*$3))));
817                             }
818        ;
819
820handler_list:
821                // There must be at least one catch clause
822        handler_clause
823                // ISO/IEC 9899:1999 Section 15.3(6) If present, a "..." handler shall be the last handler for its try
824                // block.
825        | CATCH '(' ELLIPSIS ')' compound_statement
826                                                { $$ = StatementNode::newCatchStmt( 0, $5, true ); }
827        | handler_clause CATCH '(' ELLIPSIS ')' compound_statement
828                                                { $$ = $1->set_link( StatementNode::newCatchStmt( 0, $6, true ) ); }
829        ;
830
831handler_clause:
832        CATCH '(' push push exception_declaration pop ')' compound_statement pop
833                                                { $$ = StatementNode::newCatchStmt($5, $8); }
834        | handler_clause CATCH '(' push push exception_declaration pop ')' compound_statement pop
835                                                { $$ = $1->set_link( StatementNode::newCatchStmt($6, $9) );   }
836        ;
837
838finally_clause:
839        FINALLY compound_statement
840                                                { $$ = new StatementNode(StatementNode::Finally, 0, $2);
841                                                  std::cout << "Just created a finally node" << std::endl;
842                                                }
843        ;
844
845exception_declaration:
846                // A semantic check is required to ensure type_specifier does not create a new type, e.g.:
847                //
848                //      catch ( struct { int i; } x ) ...
849                //
850                // This new type cannot catch any thrown type because of name equivalence among types.
851        type_specifier
852        | type_specifier declarator
853                {
854                    typedefTable.addToEnclosingScope( TypedefTable::ID );
855                    $$ = $2->addType( $1 );
856                }
857        | type_specifier variable_abstract_declarator
858                {   $$ = $2->addType( $1 ); }
859        | new_abstract_declarator_tuple no_attr_identifier // CFA
860                {
861                    typedefTable.addToEnclosingScope( TypedefTable::ID );
862                    $$ = $1->addName( $2 );
863                }
864        | new_abstract_declarator_tuple                 // CFA
865        ;
866
867asm_statement:
868        ASM type_qualifier_list_opt '(' constant_expression ')' ';'
869                                                { $$ = new StatementNode(StatementNode::Asm, 0, 0); }
870        | ASM type_qualifier_list_opt '(' constant_expression ':' asm_operands_opt ')' ';' // remaining GCC
871                                                { $$ = new StatementNode(StatementNode::Asm, 0, 0); }
872        | ASM type_qualifier_list_opt '(' constant_expression ':' asm_operands_opt ':' asm_operands_opt ')' ';'
873                                                { $$ = new StatementNode(StatementNode::Asm, 0, 0); }
874        | ASM type_qualifier_list_opt '(' constant_expression ':' asm_operands_opt ':' asm_operands_opt ':'
875                        asm_clobbers_list ')' ';'
876                                                { $$ = new StatementNode(StatementNode::Asm, 0, 0); }
877        ;
878
879asm_operands_opt:                                       // GCC
880        // empty
881        | asm_operands_list
882        ;
883
884asm_operands_list:                                      // GCC
885        asm_operand
886        | asm_operands_list ',' asm_operand
887        ;
888
889asm_operand:                                            // GCC
890        STRINGliteral '(' constant_expression ')'       {}
891        ;
892
893asm_clobbers_list:                                      // GCC
894        STRINGliteral                           {}
895        | asm_clobbers_list ',' STRINGliteral
896        ;
897
898//******************************* DECLARATIONS *********************************
899
900declaration_list_opt:                                   // used at beginning of switch statement
901        pop
902                { $$ = 0; }
903        | declaration_list
904        ;
905
906declaration_list:
907        declaration
908        | declaration_list push declaration
909                { $$ = $1->appendList( $3 ); }
910        ;
911
912old_declaration_list_opt:                               // used to declare parameter types in K&R style functions
913        pop
914                { $$ = 0; }
915        | old_declaration_list
916        ;
917
918old_declaration_list:
919        old_declaration
920        | old_declaration_list push old_declaration
921                { $$ = $1->appendList( $3 ); }
922        ;
923
924label_declaration_opt:                                  // GCC, local label
925        // empty
926        | label_declaration_list
927        ;
928
929label_declaration_list:                                 // GCC, local label
930        LABEL label_list ';'
931        | label_declaration_list LABEL label_list ';'
932        ;
933
934label_list:                                             // GCC, local label
935        no_attr_identifier_or_typedef_name              {}
936        | label_list ',' no_attr_identifier_or_typedef_name {}
937        ;
938
939declaration:                                            // CFA, new & old style declarations
940        new_declaration
941        | old_declaration
942        ;
943
944// C declaration syntax is notoriously confusing and error prone. Cforall provides its own type, variable and function
945// declarations. CFA declarations use the same declaration tokens as in C; however, CFA places declaration modifiers to
946// the left of the base type, while C declarations place modifiers to the right of the base type. CFA declaration
947// modifiers are interpreted from left to right and the entire type specification is distributed across all variables in
948// the declaration list (as in Pascal).  ANSI C and the new CFA declarations may appear together in the same program
949// block, but cannot be mixed within a specific declaration.
950//
951//          CFA             C
952//      [10] int x;     int x[10];      // array of 10 integers
953//      [10] * char y;  char *y[10];    // array of 10 pointers to char
954
955new_declaration:                                        // CFA
956        new_variable_declaration pop ';'
957        | new_typedef_declaration pop ';'
958        | new_function_declaration pop ';'
959        | type_declaring_list pop ';'
960        | context_specifier pop ';'
961        ;
962
963new_variable_declaration:                               // CFA
964        new_variable_specifier initializer_opt
965                {
966                        typedefTable.addToEnclosingScope( TypedefTable::ID );
967                        $$ = $1;
968                }
969        | declaration_qualifier_list new_variable_specifier initializer_opt
970                // declaration_qualifier_list also includes type_qualifier_list, so a semantic check is necessary to
971                // preclude them as a type_qualifier cannot appear in that context.
972                {
973                        typedefTable.addToEnclosingScope( TypedefTable::ID );
974                        $$ = $2->addQualifiers( $1 );
975                }
976        | new_variable_declaration pop ',' push identifier_or_typedef_name initializer_opt
977                {
978                        typedefTable.addToEnclosingScope( *$5, TypedefTable::ID );
979                        $$ = $1->appendList( $1->cloneType( $5 ) );
980                }
981        ;
982
983new_variable_specifier:                                 // CFA
984                // A semantic check is required to ensure asm_name only appears on declarations with implicit or
985                // explicit static storage-class
986        new_abstract_declarator_no_tuple identifier_or_typedef_name asm_name_opt
987                {
988                        typedefTable.setNextIdentifier( *$2 );
989                        $$ = $1->addName( $2 );
990                }
991        | new_abstract_tuple identifier_or_typedef_name asm_name_opt
992                {
993                        typedefTable.setNextIdentifier( *$2 );
994                        $$ = $1->addName( $2 );
995                }
996        | type_qualifier_list new_abstract_tuple identifier_or_typedef_name asm_name_opt
997                {
998                        typedefTable.setNextIdentifier( *$3 );
999                        $$ = $2->addQualifiers( $1 )->addName( $3 );
1000                }
1001        ;
1002
1003new_function_declaration:                               // CFA
1004        new_function_specifier
1005                {
1006                        typedefTable.addToEnclosingScope( TypedefTable::ID );
1007                        $$ = $1;
1008                }
1009        | declaration_qualifier_list new_function_specifier
1010                // declaration_qualifier_list also includes type_qualifier_list, so a semantic check is necessary to
1011                // preclude them as a type_qualifier cannot appear in this context.
1012                {
1013                        typedefTable.addToEnclosingScope( TypedefTable::ID );
1014                        $$ = $2->addQualifiers( $1 );
1015                }
1016        | new_function_declaration pop ',' push identifier_or_typedef_name
1017                {
1018                        typedefTable.addToEnclosingScope( *$5, TypedefTable::ID );
1019                        $$ = $1->appendList( $1->cloneType( $5 ) );
1020                }
1021        ;
1022
1023new_function_specifier:                                 // CFA
1024        '[' push pop ']' identifier '(' push new_parameter_type_list_opt pop ')'
1025                {
1026                        typedefTable.setNextIdentifier( *($5) );
1027                        $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, 0, true );
1028                }
1029        | '[' push pop ']' TYPEDEFname '(' push new_parameter_type_list_opt pop ')'
1030                {
1031                        typedefTable.setNextIdentifier( *($5) );
1032                        $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, 0, true );
1033                }
1034                /* identifier_or_typedef_name must be broken apart because of the sequence:
1035
1036                   '[' ']' identifier_or_typedef_name '(' new_parameter_type_list_opt ')'
1037                   '[' ']' type_specifier
1038
1039                   type_specifier can resolve to just TYPEDEFname (e.g. typedef int T; int f( T );). Therefore
1040                   this must be flattened to allow lookahead to the '(' without having to reduce
1041                   identifier_or_typedef_name. */
1042        | new_abstract_tuple identifier_or_typedef_name '(' push new_parameter_type_list_opt pop ')'
1043                /* To obtain LR(1), this rule must be factored out from function return type (see
1044                   new_abstract_declarator). */
1045                {
1046                        $$ = DeclarationNode::newFunction( $2, $1, $5, 0, true );
1047                }
1048        | new_function_return identifier_or_typedef_name '(' push new_parameter_type_list_opt pop ')'
1049                {
1050                        $$ = DeclarationNode::newFunction( $2, $1, $5, 0, true );
1051                }
1052        ;
1053
1054new_function_return:                                    // CFA
1055        '[' push new_parameter_list pop ']'
1056                { $$ = DeclarationNode::newTuple( $3 ); }
1057        | '[' push new_parameter_list pop ',' push new_abstract_parameter_list pop ']'
1058                /* To obtain LR(1), the last new_abstract_parameter_list is added into this flattened rule to
1059                   lookahead to the ']'. */
1060                { $$ = DeclarationNode::newTuple( $3->appendList( $7 ) ); }
1061        ;
1062
1063new_typedef_declaration:                                // CFA
1064        TYPEDEF new_variable_specifier
1065                {
1066                        typedefTable.addToEnclosingScope( TypedefTable::TD);
1067                        $$ = $2->addTypedef();
1068                }
1069        | TYPEDEF new_function_specifier
1070                {
1071                        typedefTable.addToEnclosingScope( TypedefTable::TD);
1072                        $$ = $2->addTypedef();
1073                }
1074        | new_typedef_declaration pop ',' push no_attr_identifier
1075                {
1076                        typedefTable.addToEnclosingScope( *$5, TypedefTable::TD);
1077                        $$ = $1->appendList( $1->cloneType( $5 ) );
1078                }
1079        ;
1080
1081/* Traditionally typedef is part of storage-class specifier for syntactic convenience only. Here, it is
1082   factored out as a separate form of declaration, which syntactically precludes storage-class specifiers and
1083   initialization. */
1084
1085typedef_declaration:
1086        TYPEDEF type_specifier declarator
1087                {
1088                        typedefTable.addToEnclosingScope( TypedefTable::TD);
1089                        $$ = $3->addType( $2 )->addTypedef();
1090                }
1091        | typedef_declaration pop ',' push declarator
1092                {
1093                        typedefTable.addToEnclosingScope( TypedefTable::TD);
1094                        $$ = $1->appendList( $1->cloneBaseType( $5 )->addTypedef() );
1095                }
1096        | type_qualifier_list TYPEDEF type_specifier declarator // remaining OBSOLESCENT (see 2)
1097                {
1098                        typedefTable.addToEnclosingScope( TypedefTable::TD);
1099                        $$ = $4->addType( $3 )->addQualifiers( $1 )->addTypedef();
1100                }
1101        | type_specifier TYPEDEF declarator
1102                {
1103                        typedefTable.addToEnclosingScope( TypedefTable::TD);
1104                        $$ = $3->addType( $1 )->addTypedef();
1105                }
1106        | type_specifier TYPEDEF type_qualifier_list declarator
1107                {
1108                        typedefTable.addToEnclosingScope( TypedefTable::TD);
1109                        $$ = $4->addQualifiers($1)->addTypedef()->addType($1);
1110                }
1111        ;
1112
1113typedef_expression:                                     // GCC, naming expression type
1114        TYPEDEF no_attr_identifier '=' assignment_expression
1115                {
1116                        typedefTable.addToEnclosingScope(*($2), TypedefTable::TD);
1117                        $$ = DeclarationNode::newName( 0 ); // XXX
1118                }
1119        | typedef_expression pop ',' push no_attr_identifier '=' assignment_expression
1120                {
1121                        typedefTable.addToEnclosingScope(*($5), TypedefTable::TD);
1122                        $$ = DeclarationNode::newName( 0 ); // XXX
1123                }
1124        ;
1125
1126old_declaration:
1127        declaring_list pop ';'
1128        | typedef_declaration pop ';'
1129        | typedef_expression pop ';'                    // GCC, naming expression type
1130        | sue_declaration_specifier pop ';'
1131        ;
1132
1133declaring_list:
1134                /* A semantic check is required to ensure asm_name only appears on declarations with implicit
1135                   or explicit static storage-class */
1136        declaration_specifier declarator asm_name_opt initializer_opt
1137                {
1138                        typedefTable.addToEnclosingScope( TypedefTable::ID );
1139                        $$ = ($2->addType( $1 ))->addInitializer($4);
1140                }
1141        | declaring_list ',' attribute_list_opt declarator asm_name_opt initializer_opt
1142                {
1143                        typedefTable.addToEnclosingScope( TypedefTable::ID );
1144                        $$ = $1->appendList( $1->cloneBaseType( $4->addInitializer($6) ) );
1145                }
1146        ;
1147
1148declaration_specifier:                                  // type specifier + storage class
1149        basic_declaration_specifier
1150        | sue_declaration_specifier
1151        | typedef_declaration_specifier
1152        | typegen_declaration_specifier
1153        ;
1154
1155type_specifier:                                         // declaration specifier - storage class
1156        basic_type_specifier
1157        | sue_type_specifier
1158        | typedef_type_specifier
1159        | typegen_type_specifier
1160        ;
1161
1162type_qualifier_list_opt:                                // GCC, used in asm_statement
1163        // empty
1164                { $$ = 0; }
1165        | type_qualifier_list
1166        ;
1167
1168type_qualifier_list:
1169                /* A semantic check is necessary to ensure a type qualifier is appropriate for the kind of
1170                   declaration.
1171
1172                   ISO/IEC 9899:1999 Section 6.7.3(4) : If the same qualifier appears more than once in the
1173                   same specifier-qualifier-list, either directly or via one or more typedefs, the behavior is
1174                   the same as if it appeared only once. */
1175        type_qualifier
1176        | type_qualifier_list type_qualifier
1177                { $$ = $1->addQualifiers( $2 ); }
1178        ;
1179
1180type_qualifier:
1181        type_qualifier_name
1182        | attribute
1183                { $$ = DeclarationNode::newQualifier( DeclarationNode::Attribute ); }
1184        ;
1185
1186type_qualifier_name:
1187        CONST
1188                { $$ = DeclarationNode::newQualifier( DeclarationNode::Const ); }
1189        | RESTRICT
1190                { $$ = DeclarationNode::newQualifier( DeclarationNode::Restrict ); }
1191        | VOLATILE
1192                { $$ = DeclarationNode::newQualifier( DeclarationNode::Volatile ); }
1193        | LVALUE                                        // CFA
1194                { $$ = DeclarationNode::newQualifier( DeclarationNode::Lvalue ); }
1195        | ATOMIC
1196                { $$ = DeclarationNode::newQualifier( DeclarationNode::Atomic ); }
1197        | FORALL '('
1198                {
1199                        typedefTable.enterScope();
1200                }
1201          type_parameter_list ')'                       // CFA
1202                {
1203                        typedefTable.leaveScope();
1204                        $$ = DeclarationNode::newForall( $4 );
1205                }
1206        ;
1207
1208declaration_qualifier_list:
1209        storage_class_list
1210        | type_qualifier_list storage_class_list        // remaining OBSOLESCENT (see 2)
1211                { $$ = $1->addQualifiers( $2 ); }
1212        | declaration_qualifier_list type_qualifier_list storage_class_list
1213                { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
1214        ;
1215
1216storage_class_list:
1217                /* A semantic check is necessary to ensure a storage class is appropriate for the kind of
1218                   declaration and that only one of each is specified, except for inline, which can appear
1219                   with the others.
1220
1221                   ISO/IEC 9899:1999 Section 6.7.1(2) : At most, one storage-class specifier may be given in
1222                   the declaration specifiers in a declaration. */
1223        storage_class
1224        | storage_class_list storage_class
1225                { $$ = $1->addQualifiers( $2 ); }
1226        ;
1227
1228storage_class:
1229        storage_class_name
1230        ;
1231
1232storage_class_name:
1233        EXTERN
1234                { $$ = DeclarationNode::newStorageClass( DeclarationNode::Extern ); }
1235        | STATIC
1236                { $$ = DeclarationNode::newStorageClass( DeclarationNode::Static ); }
1237        | AUTO
1238                { $$ = DeclarationNode::newStorageClass( DeclarationNode::Auto ); }
1239        | REGISTER
1240                { $$ = DeclarationNode::newStorageClass( DeclarationNode::Register ); }
1241        | INLINE                                        // C99
1242                // INLINE is essentially a storage class specifier for functions, and hence, belongs here.
1243                { $$ = DeclarationNode::newStorageClass( DeclarationNode::Inline ); }
1244        | FORTRAN                                       // C99
1245                { $$ = DeclarationNode::newStorageClass( DeclarationNode::Fortran ); }
1246        ;
1247
1248basic_type_name:
1249        CHAR
1250                { $$ = DeclarationNode::newBasicType( DeclarationNode::Char ); }
1251        | DOUBLE
1252                { $$ = DeclarationNode::newBasicType( DeclarationNode::Double ); }
1253        | FLOAT
1254                { $$ = DeclarationNode::newBasicType( DeclarationNode::Float ); }
1255        | INT
1256                { $$ = DeclarationNode::newBasicType( DeclarationNode::Int ); }
1257        | LONG
1258                { $$ = DeclarationNode::newModifier( DeclarationNode::Long ); }
1259        | SHORT
1260                { $$ = DeclarationNode::newModifier( DeclarationNode::Short ); }
1261        | SIGNED
1262                { $$ = DeclarationNode::newModifier( DeclarationNode::Signed ); }
1263        | UNSIGNED
1264                { $$ = DeclarationNode::newModifier( DeclarationNode::Unsigned ); }
1265        | VOID
1266                { $$ = DeclarationNode::newBasicType( DeclarationNode::Void ); }
1267        | BOOL                                          // C99
1268                { $$ = DeclarationNode::newBasicType( DeclarationNode::Bool ); }
1269        | COMPLEX                                       // C99
1270                { $$ = DeclarationNode::newBasicType( DeclarationNode::Complex ); }
1271        | IMAGINARY                                     // C99
1272                { $$ = DeclarationNode::newBasicType( DeclarationNode::Imaginary ); }
1273        ;
1274
1275basic_declaration_specifier:
1276                // A semantic check is necessary for conflicting storage classes.
1277        basic_type_specifier
1278        | declaration_qualifier_list basic_type_specifier
1279                { $$ = $2->addQualifiers( $1 ); }
1280        | basic_declaration_specifier storage_class     // remaining OBSOLESCENT (see 2)
1281                { $$ = $1->addQualifiers( $2 ); }
1282        | basic_declaration_specifier storage_class type_qualifier_list
1283                { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
1284        | basic_declaration_specifier storage_class basic_type_specifier
1285                { $$ = $3->addQualifiers( $2 )->addType( $1 ); }
1286        ;
1287
1288basic_type_specifier:
1289        direct_type_name
1290        | type_qualifier_list_opt indirect_type_name type_qualifier_list_opt
1291                { $$ = $2->addQualifiers( $1 )->addQualifiers( $3 ); }
1292        ;
1293
1294direct_type_name:
1295                // A semantic check is necessary for conflicting type qualifiers.
1296        basic_type_name
1297        | type_qualifier_list basic_type_name
1298                { $$ = $2->addQualifiers( $1 ); }
1299        | direct_type_name type_qualifier
1300                { $$ = $1->addQualifiers( $2 ); }
1301        | direct_type_name basic_type_name
1302                { $$ = $1->addType( $2 ); }
1303        ;
1304
1305indirect_type_name:
1306        TYPEOF '(' type_name ')'                        // GCC: typeof(x) y;
1307                { $$ = $3; }
1308        | TYPEOF '(' comma_expression ')'               // GCC: typeof(a+b) y;
1309                { $$ = DeclarationNode::newTypeof( $3 ); }
1310        | ATTR_TYPEGENname '(' type_name ')'            // CFA: e.g., @type(x) y;
1311                { $$ = DeclarationNode::newAttr( $1, $3 ); }
1312        | ATTR_TYPEGENname '(' comma_expression ')'     // CFA: e.g., @type(a+b) y;
1313                { $$ = DeclarationNode::newAttr( $1, $3 ); }
1314        ;
1315
1316sue_declaration_specifier:
1317        sue_type_specifier
1318        | declaration_qualifier_list sue_type_specifier
1319                { $$ = $2->addQualifiers( $1 ); }
1320        | sue_declaration_specifier storage_class       // remaining OBSOLESCENT (see 2)
1321                { $$ = $1->addQualifiers( $2 ); }
1322        | sue_declaration_specifier storage_class type_qualifier_list
1323                { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
1324        ;
1325
1326sue_type_specifier:
1327        elaborated_type_name                            // struct, union, enum
1328        | type_qualifier_list elaborated_type_name
1329                { $$ = $2->addQualifiers( $1 ); }
1330        | sue_type_specifier type_qualifier
1331                { $$ = $1->addQualifiers( $2 ); }
1332        ;
1333
1334typedef_declaration_specifier:
1335        typedef_type_specifier
1336        | declaration_qualifier_list typedef_type_specifier
1337                { $$ = $2->addQualifiers( $1 ); }
1338        | typedef_declaration_specifier storage_class   // remaining OBSOLESCENT (see 2)
1339                { $$ = $1->addQualifiers( $2 ); }
1340        | typedef_declaration_specifier storage_class type_qualifier_list
1341                { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
1342        ;
1343
1344typedef_type_specifier:                                 // typedef types
1345        TYPEDEFname
1346                { $$ = DeclarationNode::newFromTypedef( $1 ); }
1347        | type_qualifier_list TYPEDEFname
1348                { $$ = DeclarationNode::newFromTypedef( $2 )->addQualifiers( $1 ); }
1349        | typedef_type_specifier type_qualifier
1350                { $$ = $1->addQualifiers( $2 ); }
1351        ;
1352
1353elaborated_type_name:
1354        aggregate_name
1355        | enum_name
1356        ;
1357
1358aggregate_name:
1359        aggregate_key '{' field_declaration_list '}'
1360                { $$ = DeclarationNode::newAggregate( $1, 0, 0, 0, $3 ); }
1361        | aggregate_key no_attr_identifier_or_typedef_name
1362                { $$ = DeclarationNode::newAggregate( $1, $2, 0, 0, 0 ); }
1363        | aggregate_key no_attr_identifier_or_typedef_name '{' field_declaration_list '}'
1364                { $$ = DeclarationNode::newAggregate( $1, $2, 0, 0, $4 ); }
1365        | aggregate_key '(' push type_parameter_list pop ')' '{' field_declaration_list '}' // CFA
1366                { $$ = DeclarationNode::newAggregate( $1, 0, $4, 0, $8 ); }
1367        | aggregate_key '(' push type_parameter_list pop ')' no_attr_identifier_or_typedef_name // CFA
1368                { $$ = DeclarationNode::newAggregate( $1, $7, $4, 0, 0 ); }
1369        | aggregate_key '(' push type_parameter_list pop ')' no_attr_identifier_or_typedef_name '{' field_declaration_list '}' // CFA
1370                { $$ = DeclarationNode::newAggregate( $1, $7, $4, 0, $9 ); }
1371        | aggregate_key '(' push type_parameter_list pop ')' '(' type_name_list ')' '{' field_declaration_list '}' // CFA
1372                { $$ = DeclarationNode::newAggregate( $1, 0, $4, $8, $11 ); }
1373        | aggregate_key '(' push type_name_list pop ')' no_attr_identifier_or_typedef_name // CFA
1374                // push and pop are only to prevent S/R conflicts
1375                { $$ = DeclarationNode::newAggregate( $1, $7, 0, $4, 0 ); }
1376        | aggregate_key '(' push type_parameter_list pop ')' '(' type_name_list ')' no_attr_identifier_or_typedef_name '{' field_declaration_list '}' // CFA
1377                { $$ = DeclarationNode::newAggregate( $1, $10, $4, $8, $12 ); }
1378        ;
1379
1380aggregate_key:
1381        STRUCT attribute_list_opt
1382                { $$ = DeclarationNode::Struct; }
1383        | UNION attribute_list_opt
1384                { $$ = DeclarationNode::Union; }
1385        ;
1386
1387field_declaration_list:
1388        field_declaration
1389                { $$ = $1; }
1390        | field_declaration_list field_declaration
1391                { $$ = $1->appendList( $2 ); }
1392        ;
1393
1394field_declaration:
1395        new_field_declaring_list ';'                    // CFA, new style field declaration
1396        | EXTENSION new_field_declaring_list ';'        // GCC
1397                { $$ = $2; }
1398        | field_declaring_list ';'
1399        | EXTENSION field_declaring_list ';'            // GCC
1400                { $$ = $2; }
1401        ;
1402
1403new_field_declaring_list:                               // CFA, new style field declaration
1404        new_abstract_declarator_tuple                   // CFA, no field name
1405        | new_abstract_declarator_tuple no_attr_identifier_or_typedef_name
1406                { $$ = $1->addName( $2 ); }
1407        | new_field_declaring_list ',' no_attr_identifier_or_typedef_name
1408                { $$ = $1->appendList( $1->cloneType( $3 ) ); }
1409        | new_field_declaring_list ','                  // CFA, no field name
1410                { $$ = $1->appendList( $1->cloneType( 0 ) ); }
1411        ;
1412
1413field_declaring_list:
1414        type_specifier field_declarator
1415                { $$ = $2->addType( $1 ); }
1416        | field_declaring_list ',' attribute_list_opt field_declarator
1417                { $$ = $1->appendList( $1->cloneBaseType( $4 ) ); }
1418        ;
1419
1420field_declarator:
1421        // empty
1422                { $$ = DeclarationNode::newName( 0 ); /* XXX */ } // CFA, no field name
1423        | bit_subrange_size                             // no field name
1424                { $$ = DeclarationNode::newBitfield( $1 ); }
1425        | variable_declarator bit_subrange_size_opt
1426                // A semantic check is required to ensure bit_subrange only appears on base type int.
1427                { $$ = $1->addBitfield( $2 ); }
1428        | typedef_redeclarator bit_subrange_size_opt
1429                // A semantic check is required to ensure bit_subrange only appears on base type int.
1430                { $$ = $1->addBitfield( $2 ); }
1431        | variable_abstract_declarator                  // CFA, no field name
1432        ;
1433
1434bit_subrange_size_opt:
1435        // empty
1436                { $$ = 0; }
1437        | bit_subrange_size
1438                { $$ = $1; }
1439        ;
1440
1441bit_subrange_size:
1442        ':' constant_expression
1443                { $$ = $2; }
1444        ;
1445
1446enum_key:
1447        ENUM attribute_list_opt
1448        ;
1449
1450enum_name:
1451        enum_key '{' enumerator_list comma_opt '}'
1452                { $$ = DeclarationNode::newEnum( 0, $3 ); }
1453        | enum_key no_attr_identifier_or_typedef_name '{' enumerator_list comma_opt '}'
1454                { $$ = DeclarationNode::newEnum( $2, $4 ); }
1455        | enum_key no_attr_identifier_or_typedef_name
1456                { $$ = DeclarationNode::newEnum( $2, 0 ); }
1457        ;
1458
1459enumerator_list:
1460        no_attr_identifier_or_typedef_name enumerator_value_opt
1461                { $$ = DeclarationNode::newEnumConstant( $1, $2 ); }
1462        | enumerator_list ',' no_attr_identifier_or_typedef_name enumerator_value_opt
1463                { $$ = $1->appendList( DeclarationNode::newEnumConstant( $3, $4 ) ); }
1464        ;
1465
1466enumerator_value_opt:
1467        // empty
1468                { $$ = 0; }
1469        | '=' constant_expression
1470                { $$ = $2; }
1471        ;
1472
1473// Minimum of one parameter after which ellipsis is allowed only at the end.
1474
1475new_parameter_type_list_opt:                            // CFA
1476        // empty
1477                { $$ = 0; }
1478        | new_parameter_type_list
1479        ;
1480
1481new_parameter_type_list:                                // CFA, abstract + real
1482        new_abstract_parameter_list
1483        | new_parameter_list
1484        | new_parameter_list pop ',' push new_abstract_parameter_list
1485                { $$ = $1->appendList( $5 ); }
1486        | new_abstract_parameter_list pop ',' push ELLIPSIS
1487                { $$ = $1->addVarArgs(); }
1488        | new_parameter_list pop ',' push ELLIPSIS
1489                { $$ = $1->addVarArgs(); }
1490        ;
1491
1492new_parameter_list:                                     // CFA
1493                // To obtain LR(1) between new_parameter_list and new_abstract_tuple, the last
1494                // new_abstract_parameter_list is factored out from new_parameter_list, flattening the rules
1495                // to get lookahead to the ']'.
1496        new_parameter_declaration
1497        | new_abstract_parameter_list pop ',' push new_parameter_declaration
1498                { $$ = $1->appendList( $5 ); }
1499        | new_parameter_list pop ',' push new_parameter_declaration
1500                { $$ = $1->appendList( $5 ); }
1501        | new_parameter_list pop ',' push new_abstract_parameter_list pop ',' push new_parameter_declaration
1502                { $$ = $1->appendList( $5 )->appendList( $9 ); }
1503        ;
1504
1505new_abstract_parameter_list:                            // CFA, new & old style abstract
1506        new_abstract_parameter_declaration
1507        | new_abstract_parameter_list pop ',' push new_abstract_parameter_declaration
1508                { $$ = $1->appendList( $5 ); }
1509        ;
1510
1511parameter_type_list_opt:
1512        // empty
1513                { $$ = 0; }
1514        | parameter_type_list
1515        ;
1516
1517parameter_type_list:
1518        parameter_list
1519        | parameter_list pop ',' push ELLIPSIS
1520                { $$ = $1->addVarArgs(); }
1521        ;
1522
1523parameter_list:                                         // abstract + real
1524        abstract_parameter_declaration
1525        | parameter_declaration
1526        | parameter_list pop ',' push abstract_parameter_declaration
1527                { $$ = $1->appendList( $5 ); }
1528        | parameter_list pop ',' push parameter_declaration
1529                { $$ = $1->appendList( $5 ); }
1530        ;
1531
1532// Provides optional identifier names (abstract_declarator/variable_declarator), no initialization, different
1533// semantics for typedef name by using typedef_parameter_redeclarator instead of typedef_redeclarator, and
1534// function prototypes.
1535
1536new_parameter_declaration:                              // CFA, new & old style parameter declaration
1537        parameter_declaration
1538        | new_identifier_parameter_declarator_no_tuple identifier_or_typedef_name assignment_opt
1539                { $$ = $1->addName( $2 ); }
1540        | new_abstract_tuple identifier_or_typedef_name assignment_opt
1541                // To obtain LR(1), these rules must be duplicated here (see new_abstract_declarator).
1542                { $$ = $1->addName( $2 ); }
1543        | type_qualifier_list new_abstract_tuple identifier_or_typedef_name assignment_opt
1544                { $$ = $2->addName( $3 )->addQualifiers( $1 ); }
1545        | new_function_specifier
1546        ;
1547
1548new_abstract_parameter_declaration:                     // CFA, new & old style parameter declaration
1549        abstract_parameter_declaration
1550        | new_identifier_parameter_declarator_no_tuple
1551        | new_abstract_tuple
1552                // To obtain LR(1), these rules must be duplicated here (see new_abstract_declarator).
1553        | type_qualifier_list new_abstract_tuple
1554                { $$ = $2->addQualifiers( $1 ); }
1555        | new_abstract_function
1556        ;
1557
1558parameter_declaration:
1559        declaration_specifier identifier_parameter_declarator assignment_opt
1560                {
1561                    typedefTable.addToEnclosingScope( TypedefTable::ID );
1562                    $$ = $2->addType( $1 )->addInitializer( new InitializerNode($3) );
1563                }
1564        | declaration_specifier typedef_parameter_redeclarator assignment_opt
1565                {
1566                    typedefTable.addToEnclosingScope( TypedefTable::ID );
1567                    $$ = $2->addType( $1 )->addInitializer( new InitializerNode($3) );
1568                }
1569        ;
1570
1571abstract_parameter_declaration:
1572        declaration_specifier
1573        | declaration_specifier abstract_parameter_declarator
1574                { $$ = $2->addType( $1 ); }
1575        ;
1576
1577// ISO/IEC 9899:1999 Section 6.9.1(6) : "An identifier declared as a typedef name shall not be redeclared as a
1578// parameter." Because the scope of the K&R-style parameter-list sees the typedef first, the following is
1579// based only on identifiers.  The ANSI-style parameter-list can redefine a typedef name.
1580
1581identifier_list:                                        // K&R-style parameter list => no types
1582        no_attr_identifier
1583                { $$ = DeclarationNode::newName( $1 ); }
1584        | identifier_list ',' no_attr_identifier
1585                { $$ = $1->appendList( DeclarationNode::newName( $3 ) ); }
1586        ;
1587
1588identifier_or_typedef_name:
1589        identifier
1590        | TYPEDEFname
1591        | TYPEGENname
1592        ;
1593
1594no_01_identifier_or_typedef_name:
1595        no_01_identifier
1596        | TYPEDEFname
1597        | TYPEGENname
1598        ;
1599
1600no_attr_identifier_or_typedef_name:
1601        no_attr_identifier
1602        | TYPEDEFname
1603        | TYPEGENname
1604        ;
1605
1606type_name_no_function:                                  // sizeof, alignof, cast (constructor)
1607        new_abstract_declarator_tuple                   // CFA
1608        | type_specifier
1609        | type_specifier variable_abstract_declarator
1610                { $$ = $2->addType( $1 ); }
1611        ;
1612
1613type_name:                                              // typeof, assertion
1614        new_abstract_declarator_tuple                   // CFA
1615        | new_abstract_function                         // CFA
1616        | type_specifier
1617        | type_specifier abstract_declarator
1618                { $$ = $2->addType( $1 ); }
1619        ;
1620
1621initializer_opt:
1622        /* empty */                                     { $$ = 0; }
1623        | '=' initializer                               { $$ = $2; }
1624        ;
1625
1626initializer:
1627        assignment_expression                           { $$ = new InitializerNode($1); }
1628        | '{' initializer_list comma_opt '}'            { $$ = new InitializerNode($2, true); }
1629        ;
1630
1631initializer_list:
1632        initializer
1633        | designation initializer                       { $$ = $2->set_designators( $1 ); }
1634        | initializer_list ',' initializer              { $$ = (InitializerNode *)( $1->set_link($3) ); }
1635        | initializer_list ',' designation initializer
1636                                                        { $$ = (InitializerNode *)( $1->set_link( $4->set_designators($3) ) ); }
1637        ;
1638
1639// There is an unreconcileable parsing problem between C99 and CFA with respect to designators. The problem
1640// is use of '=' to separator the designator from the initializer value, as in:
1641//
1642//      int x[10] = { [1] = 3 };
1643//
1644// The string "[1] = 3" can be parsed as a designator assignment or a tuple assignment.  To disambiguate this
1645// case, CFA changes the syntax from "=" to ":" as the separator between the designator and initializer. GCC
1646// does uses ":" for field selection. The optional use of the "=" in GCC, or in this case ":", cannot be
1647// supported either due to shift/reduce conflicts
1648
1649designation:
1650        designator_list ':'                             // C99, CFA uses ":" instead of "="
1651        | no_attr_identifier_or_typedef_name ':'        // GCC, field name
1652                                                        { $$ = new VarRefNode( $1 ); }
1653        ;
1654
1655designator_list:                                        // C99
1656        designator
1657        | designator_list designator                    { $$ = (ExpressionNode *)($1->set_link( $2 )); }
1658        ;
1659
1660designator:
1661        '.' no_attr_identifier_or_typedef_name          // C99, field name
1662                                                        { $$ = new VarRefNode( $2 ); }
1663        | '[' push assignment_expression pop ']'        // C99, single array element
1664                /* assignment_expression used instead of constant_expression because of shift/reduce conflicts
1665                   with tuple. */
1666                                                        { $$ = $3; }
1667        | '[' push subrange pop ']'                     // CFA, multiple array elements
1668                                                        { $$ = $3; }
1669        | '[' push constant_expression ELLIPSIS constant_expression pop ']' // GCC, multiple array elements
1670                                                        { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Range), $3, $5); }
1671        | '.' '[' push field_list pop ']'               // CFA, tuple field selector
1672                                                        { $$ = $4; }
1673        ;
1674
1675// The CFA type system is based on parametric polymorphism, the ability to declare functions with type
1676// parameters, rather than an object-oriented type system. This required four groups of extensions:
1677//
1678// Overloading: function, data, and operator identifiers may be overloaded.
1679//
1680// Type declarations: "type" is used to generate new types for declaring objects. Similarly, "dtype" is used
1681//     for object and incomplete types, and "ftype" is used for function types. Type declarations with
1682//     initializers provide definitions of new types. Type declarations with storage class "extern" provide
1683//     opaque types.
1684//
1685// Polymorphic functions: A forall clause declares a type parameter. The corresponding argument is inferred at
1686//     the call site. A polymorphic function is not a template; it is a function, with an address and a type.
1687//
1688// Specifications and Assertions: Specifications are collections of declarations parameterized by one or more
1689//     types. They serve many of the purposes of abstract classes, and specification hierarchies resemble
1690//     subclass hierarchies. Unlike classes, they can define relationships between types.  Assertions declare
1691//     that a type or types provide the operations declared by a specification.  Assertions are normally used
1692//     to declare requirements on type arguments of polymorphic functions.
1693
1694typegen_declaration_specifier:                          // CFA
1695        typegen_type_specifier
1696        | declaration_qualifier_list typegen_type_specifier
1697                { $$ = $2->addQualifiers( $1 ); }
1698        | typegen_declaration_specifier storage_class   // remaining OBSOLESCENT (see 2)
1699                { $$ = $1->addQualifiers( $2 ); }
1700        | typegen_declaration_specifier storage_class type_qualifier_list
1701                { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
1702        ;
1703
1704typegen_type_specifier:                                 // CFA
1705        TYPEGENname '(' type_name_list ')'
1706                { $$ = DeclarationNode::newFromTypeGen( $1, $3 ); }
1707        | type_qualifier_list TYPEGENname '(' type_name_list ')'
1708                { $$ = DeclarationNode::newFromTypeGen( $2, $4 )->addQualifiers( $1 ); }
1709        | typegen_type_specifier type_qualifier
1710                { $$ = $1->addQualifiers( $2 ); }
1711        ;
1712
1713type_parameter_list:                                    // CFA
1714        type_parameter assignment_opt
1715        | type_parameter_list ',' type_parameter assignment_opt
1716                { $$ = $1->appendList( $3 ); }
1717        ;
1718
1719type_parameter:                                         // CFA
1720        type_class no_attr_identifier_or_typedef_name
1721                { typedefTable.addToEnclosingScope(*($2), TypedefTable::TD); }
1722          assertion_list_opt
1723                { $$ = DeclarationNode::newTypeParam( $1, $2 )->addAssertions( $4 ); }
1724        | type_specifier identifier_parameter_declarator
1725        ;
1726
1727type_class:                                             // CFA
1728        TYPE
1729                { $$ = DeclarationNode::Type; }
1730        | DTYPE
1731                { $$ = DeclarationNode::Ftype; }
1732        | FTYPE
1733                { $$ = DeclarationNode::Dtype; }
1734        ;
1735
1736assertion_list_opt:                                     // CFA
1737        // empty
1738                { $$ = 0; }
1739        | assertion_list_opt assertion
1740                { $$ = $1 == 0 ? $2 : $1->appendList( $2 ); }
1741        ;
1742
1743assertion:                                              // CFA
1744        '|' no_attr_identifier_or_typedef_name '(' type_name_list ')'
1745                {
1746                    typedefTable.openContext( *($2) );
1747                    $$ = DeclarationNode::newContextUse( $2, $4 );
1748                }
1749        | '|' '{' push context_declaration_list '}'
1750                { $$ = $4; }
1751        | '|' '(' push type_parameter_list pop ')' '{' push context_declaration_list '}' '(' type_name_list ')'
1752                { $$ = 0; }
1753        ;
1754
1755type_name_list:                                         // CFA
1756        type_name
1757                { $$ = new TypeValueNode( $1 ); }
1758        | assignment_expression
1759        | type_name_list ',' type_name
1760                { $$ = (ExpressionNode *)($1->set_link(new TypeValueNode( $3 ))); }
1761        | type_name_list ',' assignment_expression
1762                { $$ = (ExpressionNode *)($1->set_link($3)); }
1763        ;
1764
1765type_declaring_list:                                    // CFA
1766        TYPE type_declarator
1767                { $$ = $2; }
1768        | storage_class_list TYPE type_declarator
1769                { $$ = $3->addQualifiers( $1 ); }
1770        | type_declaring_list ',' type_declarator
1771                { $$ = $1->appendList( $3->copyStorageClasses( $1 ) ); }
1772        ;
1773
1774type_declarator:                                        // CFA
1775        type_declarator_name assertion_list_opt
1776                { $$ = $1->addAssertions( $2 ); }
1777        | type_declarator_name assertion_list_opt '=' type_name
1778                { $$ = $1->addAssertions( $2 )->addType( $4 ); }
1779        ;
1780
1781type_declarator_name:                                   // CFA
1782        no_attr_identifier_or_typedef_name
1783                {
1784                    typedefTable.addToEnclosingScope(*($1), TypedefTable::TD);
1785                    $$ = DeclarationNode::newTypeDecl( $1, 0 );
1786                }
1787        | no_01_identifier_or_typedef_name '(' push type_parameter_list pop ')'
1788                {
1789                    typedefTable.addToEnclosingScope(*($1), TypedefTable::TG);
1790                    $$ = DeclarationNode::newTypeDecl( $1, $4 );
1791                }
1792        ;
1793
1794context_specifier:                                      // CFA
1795        CONTEXT no_attr_identifier_or_typedef_name '(' push type_parameter_list pop ')' '{' '}'
1796                {
1797                    typedefTable.addToEnclosingScope(*($2), TypedefTable::ID );
1798                    $$ = DeclarationNode::newContext( $2, $5, 0 );
1799                }
1800        | CONTEXT no_attr_identifier_or_typedef_name '(' push type_parameter_list pop ')' '{'
1801                {
1802                    typedefTable.enterContext( *($2) );
1803                    typedefTable.enterScope();
1804                }
1805          context_declaration_list '}'
1806                {
1807                    typedefTable.leaveContext();
1808                    typedefTable.addToEnclosingScope(*($2), TypedefTable::ID );
1809                    $$ = DeclarationNode::newContext( $2, $5, $10 );
1810                }
1811        ;
1812
1813context_declaration_list:                               // CFA
1814        context_declaration
1815        | context_declaration_list push context_declaration
1816                { $$ = $1->appendList( $3 ); }
1817        ;
1818
1819context_declaration:                                    // CFA
1820        new_context_declaring_list pop ';'
1821        | context_declaring_list pop ';'
1822        ;
1823
1824new_context_declaring_list:                             // CFA
1825        new_variable_specifier
1826                {
1827                    typedefTable.addToEnclosingScope2( TypedefTable::ID );
1828                    $$ = $1;
1829                }
1830        | new_function_specifier
1831                {
1832                    typedefTable.addToEnclosingScope2( TypedefTable::ID );
1833                    $$ = $1;
1834                }
1835        | new_context_declaring_list pop ',' push identifier_or_typedef_name
1836                {
1837                    typedefTable.addToEnclosingScope2( *($5), TypedefTable::ID );
1838                    $$ = $1->appendList( $1->cloneType( $5 ) );
1839                }
1840        ;
1841
1842context_declaring_list:                                 // CFA
1843        type_specifier declarator
1844                {
1845                    typedefTable.addToEnclosingScope2( TypedefTable::ID );
1846                    $$ = $2->addType( $1 );
1847                }
1848        | context_declaring_list pop ',' push declarator
1849                {
1850                    typedefTable.addToEnclosingScope2( TypedefTable::ID );
1851                    $$ = $1->appendList( $1->cloneBaseType( $5 ) );
1852                }
1853        ;
1854
1855//***************************** EXTERNAL DEFINITIONS *****************************
1856
1857translation_unit:
1858        // empty
1859                {}                                      // empty input file
1860        | external_definition_list
1861                {
1862                  if ( theTree ) {
1863                    theTree->appendList( $1 );
1864                  } else {
1865                    theTree = $1;
1866                  }
1867                }
1868        ;
1869
1870external_definition_list:
1871        external_definition
1872        | external_definition_list push external_definition
1873                {
1874                    if ( $1 ) {
1875                        $$ = $1->appendList( $3 );
1876                    } else {
1877                        $$ = $3;
1878                    }
1879                }
1880        ;
1881
1882external_definition_list_opt:
1883        // empty
1884                { $$ = 0; }
1885        | external_definition_list
1886        ;
1887
1888external_definition:
1889        declaration
1890        | function_definition
1891        | asm_statement                                 // GCC, global assembler statement
1892                {}
1893        | EXTERN STRINGliteral
1894                {
1895                  linkageStack.push( linkage );
1896                  linkage = LinkageSpec::fromString( *$2 );
1897                }
1898          '{' external_definition_list_opt '}'          // C++-style linkage specifier
1899                {
1900                  linkage = linkageStack.top();
1901                  linkageStack.pop();
1902                  $$ = $5;
1903                }
1904        | EXTENSION external_definition
1905                { $$ = $2; }
1906        ;
1907
1908function_definition:
1909        new_function_specifier compound_statement       // CFA
1910                {
1911                    typedefTable.addToEnclosingScope( TypedefTable::ID );
1912                    typedefTable.leaveScope();
1913                    $$ = $1->addFunctionBody( $2 );
1914                }
1915        | declaration_qualifier_list new_function_specifier compound_statement // CFA
1916                // declaration_qualifier_list also includes type_qualifier_list, so a semantic check is
1917                // necessary to preclude them as a type_qualifier cannot appear in this context.
1918                {
1919                    typedefTable.addToEnclosingScope( TypedefTable::ID );
1920                    typedefTable.leaveScope();
1921                    $$ = $2->addFunctionBody( $3 )->addQualifiers( $1 );
1922                }
1923
1924        | declaration_specifier function_declarator compound_statement
1925                {
1926                    typedefTable.addToEnclosingScope( TypedefTable::ID );
1927                    typedefTable.leaveScope();
1928                    $$ = $2->addFunctionBody( $3 )->addType( $1 );
1929                }
1930
1931                // These rules are a concession to the "implicit int" type_specifier because there is a
1932                // significant amount of code with functions missing a type-specifier on the return type.
1933                // Parsing is possible because function_definition does not appear in the context of an
1934                // expression (nested functions would preclude this concession). A function prototype
1935                // declaration must still have a type_specifier. OBSOLESCENT (see 1)
1936        | function_declarator compound_statement
1937                {
1938                    typedefTable.addToEnclosingScope( TypedefTable::ID );
1939                    typedefTable.leaveScope();
1940                    $$ = $1->addFunctionBody( $2 );
1941                }
1942        | type_qualifier_list function_declarator compound_statement
1943                {
1944                    typedefTable.addToEnclosingScope( TypedefTable::ID );
1945                    typedefTable.leaveScope();
1946                    $$ = $2->addFunctionBody( $3 )->addQualifiers( $1 );
1947                }
1948        | declaration_qualifier_list function_declarator compound_statement
1949                {
1950                    typedefTable.addToEnclosingScope( TypedefTable::ID );
1951                    typedefTable.leaveScope();
1952                    $$ = $2->addFunctionBody( $3 )->addQualifiers( $1 );
1953                }
1954        | declaration_qualifier_list type_qualifier_list function_declarator compound_statement
1955                {
1956                    typedefTable.addToEnclosingScope( TypedefTable::ID );
1957                    typedefTable.leaveScope();
1958                    $$ = $3->addFunctionBody( $4 )->addQualifiers( $2 )->addQualifiers( $1 );
1959                }
1960
1961                // Old-style K&R function definition, OBSOLESCENT (see 4)
1962        | declaration_specifier old_function_declarator push old_declaration_list_opt compound_statement
1963                {
1964                    typedefTable.addToEnclosingScope( TypedefTable::ID );
1965                    typedefTable.leaveScope();
1966                    $$ = $2->addOldDeclList( $4 )->addFunctionBody( $5 )->addType( $1 );
1967                }
1968        | old_function_declarator push old_declaration_list_opt compound_statement
1969                {
1970                    typedefTable.addToEnclosingScope( TypedefTable::ID );
1971                    typedefTable.leaveScope();
1972                    $$ = $1->addOldDeclList( $3 )->addFunctionBody( $4 );
1973                }
1974        | type_qualifier_list old_function_declarator push old_declaration_list_opt compound_statement
1975                {
1976                    typedefTable.addToEnclosingScope( TypedefTable::ID );
1977                    typedefTable.leaveScope();
1978                    $$ = $2->addOldDeclList( $4 )->addFunctionBody( $5 )->addQualifiers( $1 );
1979                }
1980
1981                // Old-style K&R function definition with "implicit int" type_specifier, OBSOLESCENT (see 4)
1982        | declaration_qualifier_list old_function_declarator push old_declaration_list_opt compound_statement
1983                {
1984                    typedefTable.addToEnclosingScope( TypedefTable::ID );
1985                    typedefTable.leaveScope();
1986                    $$ = $2->addOldDeclList( $4 )->addFunctionBody( $5 )->addQualifiers( $1 );
1987                }
1988        | declaration_qualifier_list type_qualifier_list old_function_declarator push old_declaration_list_opt
1989                        compound_statement
1990                {
1991                    typedefTable.addToEnclosingScope( TypedefTable::ID );
1992                    typedefTable.leaveScope();
1993                    $$ = $3->addOldDeclList( $5 )->addFunctionBody( $6 )->addQualifiers( $2 )->addQualifiers( $1 );
1994                }
1995        ;
1996
1997declarator:
1998        variable_declarator
1999        | function_declarator
2000        | typedef_redeclarator
2001        ;
2002
2003subrange:
2004        constant_expression '~' constant_expression     // CFA, integer subrange
2005                { $$ = new CompositeExprNode(new OperatorNode(OperatorNode::Range), $1, $3); }
2006        ;
2007
2008asm_name_opt:                                           // GCC
2009        // empty
2010        | ASM '(' string_literal_list ')' attribute_list_opt
2011        ;
2012
2013attribute_list_opt:                                     // GCC
2014        // empty
2015        | attribute_list
2016        ;
2017
2018attribute_list:                                         // GCC
2019        attribute
2020        | attribute_list attribute
2021        ;
2022
2023attribute:                                              // GCC
2024        ATTRIBUTE '(' '(' attribute_parameter_list ')' ')'
2025        ;
2026
2027attribute_parameter_list:                               // GCC
2028        attrib
2029        | attribute_parameter_list ',' attrib
2030        ;
2031
2032attrib:                                                 // GCC
2033        // empty
2034        | any_word
2035        | any_word '(' comma_expression_opt ')'
2036        ;
2037
2038any_word:                                               // GCC
2039        identifier_or_typedef_name {}
2040        | storage_class_name {}
2041        | basic_type_name {}
2042        | type_qualifier {}
2043        ;
2044
2045// ============================================================================
2046// The following sections are a series of grammar patterns used to parse declarators. Multiple patterns are
2047// necessary because the type of an identifier in wrapped around the identifier in the same form as its usage
2048// in an expression, as in:
2049//
2050//      int (*f())[10] { ... };
2051//      ... (*f())[3] += 1;     // definition mimics usage
2052//
2053// Because these patterns are highly recursive, changes at a lower level in the recursion require copying some
2054// or all of the pattern. Each of these patterns has some subtle variation to ensure correct syntax in a
2055// particular context.
2056// ============================================================================
2057
2058// ----------------------------------------------------------------------------
2059// The set of valid declarators before a compound statement for defining a function is less than the set of
2060// declarators to define a variable or function prototype, e.g.:
2061//
2062//      valid declaration       invalid definition
2063//      -----------------       ------------------
2064//      int f;                  int f {}
2065//      int *f;                 int *f {}
2066//      int f[10];              int f[10] {}
2067//      int (*f)(int);          int (*f)(int) {}
2068//
2069// To preclude this syntactic anomaly requires separating the grammar rules for variable and function
2070// declarators, hence variable_declarator and function_declarator.
2071// ----------------------------------------------------------------------------
2072
2073// This pattern parses a declaration of a variable that is not redefining a typedef name. The pattern
2074// precludes declaring an array of functions versus a pointer to an array of functions.
2075
2076variable_declarator:
2077        paren_identifier attribute_list_opt
2078        | variable_ptr
2079        | variable_array attribute_list_opt
2080        | variable_function attribute_list_opt
2081        ;
2082
2083paren_identifier:
2084        identifier
2085                {
2086                    typedefTable.setNextIdentifier( *($1) );
2087                    $$ = DeclarationNode::newName( $1 );
2088                }
2089        | '(' paren_identifier ')'                      // redundant parenthesis
2090                { $$ = $2; }
2091        ;
2092
2093variable_ptr:
2094        '*' variable_declarator
2095                { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
2096        | '*' type_qualifier_list variable_declarator
2097                { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
2098        | '(' variable_ptr ')'
2099                { $$ = $2; }
2100        ;
2101
2102variable_array:
2103        paren_identifier array_dimension
2104                { $$ = $1->addArray( $2 ); }
2105        | '(' variable_ptr ')' array_dimension
2106                { $$ = $2->addArray( $4 ); }
2107        | '(' variable_array ')' multi_array_dimension  // redundant parenthesis
2108                { $$ = $2->addArray( $4 ); }
2109        | '(' variable_array ')'                        // redundant parenthesis
2110                { $$ = $2; }
2111        ;
2112
2113variable_function:
2114        '(' variable_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
2115                { $$ = $2->addParamList( $6 ); }
2116        | '(' variable_function ')'                     // redundant parenthesis
2117                { $$ = $2; }
2118        ;
2119
2120// This pattern parses a function declarator that is not redefining a typedef name. Because functions cannot
2121// be nested, there is no context where a function definition can redefine a typedef name. To allow nested
2122// functions requires further separation of variable and function declarators in typedef_redeclarator.  The
2123// pattern precludes returning arrays and functions versus pointers to arrays and functions.
2124
2125function_declarator:
2126        function_no_ptr attribute_list_opt
2127        | function_ptr
2128        | function_array attribute_list_opt
2129        ;
2130
2131function_no_ptr:
2132        paren_identifier '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
2133                { $$ = $1->addParamList( $4 ); }
2134        | '(' function_ptr ')' '(' push parameter_type_list_opt pop ')'
2135                { $$ = $2->addParamList( $6 ); }
2136        | '(' function_no_ptr ')'                       // redundant parenthesis
2137                { $$ = $2; }
2138        ;
2139
2140function_ptr:
2141        '*' function_declarator
2142                { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
2143        | '*' type_qualifier_list function_declarator
2144                { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
2145        | '(' function_ptr ')'
2146                { $$ = $2; }
2147        ;
2148
2149function_array:
2150        '(' function_ptr ')' array_dimension
2151                { $$ = $2->addArray( $4 ); }
2152        | '(' function_array ')' multi_array_dimension  // redundant parenthesis
2153                { $$ = $2->addArray( $4 ); }
2154        | '(' function_array ')'                        // redundant parenthesis
2155                { $$ = $2; }
2156        ;
2157
2158// This pattern parses an old-style K&R function declarator (OBSOLESCENT, see 4) that is not redefining a
2159// typedef name (see function_declarator for additional comments). The pattern precludes returning arrays and
2160// functions versus pointers to arrays and functions.
2161
2162old_function_declarator:
2163        old_function_no_ptr
2164        | old_function_ptr
2165        | old_function_array
2166        ;
2167
2168old_function_no_ptr:
2169        paren_identifier '(' identifier_list ')'        // function_declarator handles empty parameter
2170                { $$ = $1->addIdList( $3 ); }
2171        | '(' old_function_ptr ')' '(' identifier_list ')'
2172                { $$ = $2->addIdList( $5 ); }
2173        | '(' old_function_no_ptr ')'                   // redundant parenthesis
2174                { $$ = $2; }
2175        ;
2176
2177old_function_ptr:
2178        '*' old_function_declarator
2179                { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
2180        | '*' type_qualifier_list old_function_declarator
2181                { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
2182        | '(' old_function_ptr ')'
2183                { $$ = $2; }
2184        ;
2185
2186old_function_array:
2187        '(' old_function_ptr ')' array_dimension
2188                { $$ = $2->addArray( $4 ); }
2189        | '(' old_function_array ')' multi_array_dimension // redundant parenthesis
2190                { $$ = $2->addArray( $4 ); }
2191        | '(' old_function_array ')'                    // redundant parenthesis
2192                { $$ = $2; }
2193        ;
2194
2195// This pattern parses a declaration for a variable or function prototype that redefines a typedef name, e.g.:
2196//
2197//      typedef int foo;
2198//      {
2199//         int foo; // redefine typedef name in new scope
2200//      }
2201//
2202// The pattern precludes declaring an array of functions versus a pointer to an array of functions, and
2203// returning arrays and functions versus pointers to arrays and functions.
2204
2205typedef_redeclarator:
2206        paren_typedef attribute_list_opt
2207        | typedef_ptr
2208        | typedef_array attribute_list_opt
2209        | typedef_function attribute_list_opt
2210        ;
2211
2212paren_typedef:
2213        TYPEDEFname
2214                {
2215                typedefTable.setNextIdentifier( *($1) );
2216                $$ = DeclarationNode::newName( $1 );
2217                }
2218        | '(' paren_typedef ')'
2219                { $$ = $2; }
2220        ;
2221
2222typedef_ptr:
2223        '*' typedef_redeclarator
2224                { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
2225        | '*' type_qualifier_list typedef_redeclarator
2226                { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
2227        | '(' typedef_ptr ')'
2228                { $$ = $2; }
2229        ;
2230
2231typedef_array:
2232        paren_typedef array_dimension
2233                { $$ = $1->addArray( $2 ); }
2234        | '(' typedef_ptr ')' array_dimension
2235                { $$ = $2->addArray( $4 ); }
2236        | '(' typedef_array ')' multi_array_dimension   // redundant parenthesis
2237                { $$ = $2->addArray( $4 ); }
2238        | '(' typedef_array ')'                         // redundant parenthesis
2239                { $$ = $2; }
2240        ;
2241
2242typedef_function:
2243        paren_typedef '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
2244                { $$ = $1->addParamList( $4 ); }
2245        | '(' typedef_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
2246                { $$ = $2->addParamList( $6 ); }
2247        | '(' typedef_function ')'                      // redundant parenthesis
2248                { $$ = $2; }
2249        ;
2250
2251// This pattern parses a declaration for a parameter variable or function prototype that is not redefining a
2252// typedef name and allows the C99 array options, which can only appear in a parameter list.  The pattern
2253// precludes declaring an array of functions versus a pointer to an array of functions, and returning arrays
2254// and functions versus pointers to arrays and functions.
2255
2256identifier_parameter_declarator:
2257        paren_identifier attribute_list_opt
2258        | identifier_parameter_ptr
2259        | identifier_parameter_array attribute_list_opt
2260        | identifier_parameter_function attribute_list_opt
2261        ;
2262
2263identifier_parameter_ptr:
2264        '*' identifier_parameter_declarator
2265                { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
2266        | '*' type_qualifier_list identifier_parameter_declarator
2267                { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
2268        | '(' identifier_parameter_ptr ')'
2269                { $$ = $2; }
2270        ;
2271
2272identifier_parameter_array:
2273        paren_identifier array_parameter_dimension
2274                { $$ = $1->addArray( $2 ); }
2275        | '(' identifier_parameter_ptr ')' array_dimension
2276                { $$ = $2->addArray( $4 ); }
2277        | '(' identifier_parameter_array ')' multi_array_dimension // redundant parenthesis
2278                { $$ = $2->addArray( $4 ); }
2279        | '(' identifier_parameter_array ')'            // redundant parenthesis
2280                { $$ = $2; }
2281        ;
2282
2283identifier_parameter_function:
2284        paren_identifier '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
2285                { $$ = $1->addParamList( $4 ); }
2286        | '(' identifier_parameter_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
2287                { $$ = $2->addParamList( $6 ); }
2288        | '(' identifier_parameter_function ')'         // redundant parenthesis
2289                { $$ = $2; }
2290        ;
2291
2292// This pattern parses a declaration for a parameter variable or function prototype that is redefining a typedef name,
2293// e.g.:
2294//
2295//      typedef int foo;
2296//      int f( int foo ); // redefine typedef name in new scope
2297//
2298// and allows the C99 array options, which can only appear in a parameter list.  In addition, the pattern handles the
2299// special meaning of parenthesis around a typedef name:
2300//
2301//      ISO/IEC 9899:1999 Section 6.7.5.3(11) : "In a parameter declaration, a single typedef name in
2302//      parentheses is taken to be an abstract declarator that specifies a function with a single parameter,
2303//      not as redundant parentheses around the identifier."
2304//
2305// which precludes the following cases:
2306//
2307//      typedef float T;
2308//      int f( int ( T [5] ) );                 // see abstract_parameter_declarator
2309//      int g( int ( T ( int ) ) );             // see abstract_parameter_declarator
2310//      int f( int f1( T a[5] ) );              // see identifier_parameter_declarator
2311//      int g( int g1( T g2( int p ) ) );       // see identifier_parameter_declarator
2312//
2313// In essence, a '(' immediately to the left of typedef name, T, is interpreted as starting a parameter type list, and
2314// not as redundant parentheses around a redeclaration of T. Finally, the pattern also precludes declaring an array of
2315// functions versus a pointer to an array of functions, and returning arrays and functions versus pointers to arrays and
2316// functions.
2317
2318typedef_parameter_redeclarator:
2319        typedef attribute_list_opt
2320        | typedef_parameter_ptr
2321        | typedef_parameter_array attribute_list_opt
2322        | typedef_parameter_function attribute_list_opt
2323        ;
2324
2325typedef:
2326        TYPEDEFname
2327                {
2328                    typedefTable.setNextIdentifier( *($1) );
2329                    $$ = DeclarationNode::newName( $1 );
2330                }
2331        ;
2332
2333typedef_parameter_ptr:
2334        '*' typedef_parameter_redeclarator
2335                { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
2336        | '*' type_qualifier_list typedef_parameter_redeclarator
2337                { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
2338        | '(' typedef_parameter_ptr ')'
2339                { $$ = $2; }
2340        ;
2341
2342typedef_parameter_array:
2343        typedef array_parameter_dimension
2344                { $$ = $1->addArray( $2 ); }
2345        | '(' typedef_parameter_ptr ')' array_parameter_dimension
2346                { $$ = $2->addArray( $4 ); }
2347        ;
2348
2349typedef_parameter_function:
2350        typedef '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
2351                { $$ = $1->addParamList( $4 ); }
2352        | '(' typedef_parameter_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
2353                { $$ = $2->addParamList( $6 ); }
2354        ;
2355
2356// This pattern parses a declaration of an abstract variable or function prototype, i.e., there is no identifier to
2357// which the type applies, e.g.:
2358//
2359//      sizeof( int );
2360//      sizeof( int [10] );
2361//
2362// The pattern precludes declaring an array of functions versus a pointer to an array of functions, and returning arrays
2363// and functions versus pointers to arrays and functions.
2364
2365abstract_declarator:
2366        abstract_ptr
2367        | abstract_array attribute_list_opt
2368        | abstract_function attribute_list_opt
2369        ;
2370
2371abstract_ptr:
2372        '*'
2373                { $$ = DeclarationNode::newPointer( 0 ); }
2374        | '*' type_qualifier_list
2375                { $$ = DeclarationNode::newPointer( $2 ); }
2376        | '*' abstract_declarator
2377                { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
2378        | '*' type_qualifier_list abstract_declarator
2379                { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
2380        | '(' abstract_ptr ')'
2381                { $$ = $2; }
2382        ;
2383
2384abstract_array:
2385        array_dimension
2386        | '(' abstract_ptr ')' array_dimension
2387                { $$ = $2->addArray( $4 ); }
2388        | '(' abstract_array ')' multi_array_dimension  // redundant parenthesis
2389                { $$ = $2->addArray( $4 ); }
2390        | '(' abstract_array ')'                        // redundant parenthesis
2391                { $$ = $2; }
2392        ;
2393
2394abstract_function:
2395        '(' push parameter_type_list_opt pop ')'        // empty parameter list OBSOLESCENT (see 3)
2396                { $$ = DeclarationNode::newFunction( 0, 0, $3, 0 ); }
2397        | '(' abstract_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
2398                { $$ = $2->addParamList( $6 ); }
2399        | '(' abstract_function ')'                     // redundant parenthesis
2400                { $$ = $2; }
2401        ;
2402
2403array_dimension:
2404                // Only the first dimension can be empty.
2405        '[' push pop ']'
2406                { $$ = DeclarationNode::newArray( 0, 0, false ); }
2407        | '[' push pop ']' multi_array_dimension
2408                { $$ = DeclarationNode::newArray( 0, 0, false )->addArray( $5 ); }
2409        | multi_array_dimension
2410        ;
2411
2412multi_array_dimension:
2413        '[' push assignment_expression pop ']'
2414                { $$ = DeclarationNode::newArray( $3, 0, false ); }
2415        | '[' push '*' pop ']'                          // C99
2416                { $$ = DeclarationNode::newVarArray( 0 ); }
2417        | multi_array_dimension '[' push assignment_expression pop ']'
2418                { $$ = $1->addArray( DeclarationNode::newArray( $4, 0, false ) ); }
2419        | multi_array_dimension '[' push '*' pop ']'    // C99
2420                { $$ = $1->addArray( DeclarationNode::newVarArray( 0 ) ); }
2421        ;
2422
2423// This pattern parses a declaration of a parameter abstract variable or function prototype, i.e., there is no
2424// identifier to which the type applies, e.g.:
2425//
2426//      int f( int );           // abstract variable parameter; no parameter name specified
2427//      int f( int (int) );     // abstract function-prototype parameter; no parameter name specified
2428//
2429// The pattern precludes declaring an array of functions versus a pointer to an array of functions, and returning arrays
2430// and functions versus pointers to arrays and functions. */
2431
2432abstract_parameter_declarator:
2433        abstract_parameter_ptr
2434        | abstract_parameter_array attribute_list_opt
2435        | abstract_parameter_function attribute_list_opt
2436        ;
2437
2438abstract_parameter_ptr:
2439        '*'
2440                { $$ = DeclarationNode::newPointer( 0 ); }
2441        | '*' type_qualifier_list
2442                { $$ = DeclarationNode::newPointer( $2 ); }
2443        | '*' abstract_parameter_declarator
2444                { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
2445        | '*' type_qualifier_list abstract_parameter_declarator
2446                { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
2447        | '(' abstract_parameter_ptr ')'
2448                { $$ = $2; }
2449        ;
2450
2451abstract_parameter_array:
2452        array_parameter_dimension
2453        | '(' abstract_parameter_ptr ')' array_parameter_dimension
2454                { $$ = $2->addArray( $4 ); }
2455        | '(' abstract_parameter_array ')' multi_array_dimension // redundant parenthesis
2456                { $$ = $2->addArray( $4 ); }
2457        | '(' abstract_parameter_array ')'              // redundant parenthesis
2458                { $$ = $2; }
2459        ;
2460
2461abstract_parameter_function:
2462        '(' push parameter_type_list_opt pop ')'        // empty parameter list OBSOLESCENT (see 3)
2463                { $$ = DeclarationNode::newFunction( 0, 0, $3, 0 ); }
2464        | '(' abstract_parameter_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
2465                { $$ = $2->addParamList( $6 ); }
2466        | '(' abstract_parameter_function ')'           // redundant parenthesis
2467                { $$ = $2; }
2468        ;
2469
2470array_parameter_dimension:
2471                // Only the first dimension can be empty or have qualifiers.
2472        array_parameter_1st_dimension
2473        | array_parameter_1st_dimension multi_array_dimension
2474                { $$ = $1->addArray( $2 ); }
2475        | multi_array_dimension
2476        ;
2477
2478// The declaration of an array parameter has additional syntax over arrays in normal variable declarations:
2479//
2480//      ISO/IEC 9899:1999 Section 6.7.5.2(1) : "The optional type qualifiers and the keyword static shall appear only in
2481//      a declaration of a function parameter with an array type, and then only in the outermost array type derivation."
2482
2483array_parameter_1st_dimension:
2484        '[' push pop ']'
2485                { $$ = DeclarationNode::newArray( 0, 0, false ); }
2486        // multi_array_dimension handles the '[' '*' ']' case
2487        | '[' push type_qualifier_list '*' pop ']'      // remaining C99
2488                { $$ = DeclarationNode::newVarArray( $3 ); }
2489        | '[' push type_qualifier_list pop ']'
2490                { $$ = DeclarationNode::newArray( 0, $3, false ); }
2491        // multi_array_dimension handles the '[' assignment_expression ']' case
2492        | '[' push type_qualifier_list assignment_expression pop ']'
2493                { $$ = DeclarationNode::newArray( $4, $3, false ); }
2494        | '[' push STATIC type_qualifier_list_opt assignment_expression pop ']'
2495                { $$ = DeclarationNode::newArray( $5, $4, true ); }
2496        | '[' push type_qualifier_list STATIC assignment_expression pop ']'
2497                { $$ = DeclarationNode::newArray( $5, $3, true ); }
2498        ;
2499
2500// This pattern parses a declaration of an abstract variable, i.e., there is no identifier to which the type applies,
2501// e.g.:
2502//
2503//      sizeof( int ); // abstract variable; no identifier name specified
2504//
2505// The pattern precludes declaring an array of functions versus a pointer to an array of functions, and returning arrays
2506// and functions versus pointers to arrays and functions. */
2507
2508variable_abstract_declarator:
2509        variable_abstract_ptr
2510        | variable_abstract_array attribute_list_opt
2511        | variable_abstract_function attribute_list_opt
2512        ;
2513
2514variable_abstract_ptr:
2515        '*'
2516                { $$ = DeclarationNode::newPointer( 0 ); }
2517        | '*' type_qualifier_list
2518                { $$ = DeclarationNode::newPointer( $2 ); }
2519        | '*' variable_abstract_declarator
2520                { $$ = $2->addPointer( DeclarationNode::newPointer( 0 ) ); }
2521        | '*' type_qualifier_list variable_abstract_declarator
2522                { $$ = $3->addPointer( DeclarationNode::newPointer( $2 ) ); }
2523        | '(' variable_abstract_ptr ')'
2524                { $$ = $2; }
2525        ;
2526
2527variable_abstract_array:
2528        array_dimension
2529        | '(' variable_abstract_ptr ')' array_dimension
2530                { $$ = $2->addArray( $4 ); }
2531        | '(' variable_abstract_array ')' multi_array_dimension // redundant parenthesis
2532                { $$ = $2->addArray( $4 ); }
2533        | '(' variable_abstract_array ')'               // redundant parenthesis
2534                { $$ = $2; }
2535        ;
2536
2537variable_abstract_function:
2538        '(' variable_abstract_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
2539                { $$ = $2->addParamList( $6 ); }
2540        | '(' variable_abstract_function ')'            // redundant parenthesis
2541                { $$ = $2; }
2542        ;
2543
2544// This pattern parses a new-style declaration for a parameter variable or function prototype that is either an
2545// identifier or typedef name and allows the C99 array options, which can only appear in a parameter list.
2546
2547new_identifier_parameter_declarator_tuple:              // CFA
2548        new_identifier_parameter_declarator_no_tuple
2549        | new_abstract_tuple
2550        | type_qualifier_list new_abstract_tuple
2551                { $$ = $2->addQualifiers( $1 ); }
2552        ;
2553
2554new_identifier_parameter_declarator_no_tuple:           // CFA
2555        new_identifier_parameter_ptr
2556        | new_identifier_parameter_array
2557        ;
2558
2559new_identifier_parameter_ptr:                           // CFA
2560        '*' type_specifier
2561                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
2562        | type_qualifier_list '*' type_specifier
2563                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
2564        | '*' new_abstract_function
2565                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
2566        | type_qualifier_list '*' new_abstract_function
2567                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
2568        | '*' new_identifier_parameter_declarator_tuple
2569                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
2570        | type_qualifier_list '*' new_identifier_parameter_declarator_tuple
2571                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
2572        ;
2573
2574new_identifier_parameter_array:                         // CFA
2575                // Only the first dimension can be empty or have qualifiers. Empty dimension must be factored out due to
2576                // shift/reduce conflict with new-style empty (void) function return type. */
2577        '[' push pop ']' type_specifier
2578                { $$ = $5->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
2579        | new_array_parameter_1st_dimension type_specifier
2580                { $$ = $2->addNewArray( $1 ); }
2581        | '[' push pop ']' multi_array_dimension type_specifier
2582                { $$ = $6->addNewArray( $5 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
2583        | new_array_parameter_1st_dimension multi_array_dimension type_specifier
2584                { $$ = $3->addNewArray( $2 )->addNewArray( $1 ); }
2585        | multi_array_dimension type_specifier
2586                { $$ = $2->addNewArray( $1 ); }
2587        | '[' push pop ']' new_identifier_parameter_ptr
2588                { $$ = $5->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
2589        | new_array_parameter_1st_dimension new_identifier_parameter_ptr
2590                { $$ = $2->addNewArray( $1 ); }
2591        | '[' push pop ']' multi_array_dimension new_identifier_parameter_ptr
2592                { $$ = $6->addNewArray( $5 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
2593        | new_array_parameter_1st_dimension multi_array_dimension new_identifier_parameter_ptr
2594                { $$ = $3->addNewArray( $2 )->addNewArray( $1 ); }
2595        | multi_array_dimension new_identifier_parameter_ptr
2596                { $$ = $2->addNewArray( $1 ); }
2597        ;
2598
2599new_array_parameter_1st_dimension:
2600        '[' push type_qualifier_list '*' pop ']'        // remaining C99
2601                { $$ = DeclarationNode::newVarArray( $3 ); }
2602        | '[' push type_qualifier_list assignment_expression pop ']'
2603                { $$ = DeclarationNode::newArray( $4, $3, false ); }
2604        | '[' push declaration_qualifier_list assignment_expression pop ']'
2605                // declaration_qualifier_list must be used because of shift/reduce conflict with assignment_expression,
2606                // so a semantic check is necessary to preclude them as a type_qualifier cannot appear in this
2607                // context.
2608                { $$ = DeclarationNode::newArray( $4, $3, true ); }
2609        | '[' push declaration_qualifier_list type_qualifier_list assignment_expression pop ']'
2610                { $$ = DeclarationNode::newArray( $5, $4->addQualifiers( $3 ), true ); }
2611        ;
2612
2613// This pattern parses a new-style declaration of an abstract variable or function prototype, i.e., there is no
2614// identifier to which the type applies, e.g.:
2615//
2616//      [int] f( int );         // abstract variable parameter; no parameter name specified
2617//      [int] f( [int] (int) ); // abstract function-prototype parameter; no parameter name specified
2618//
2619// These rules need LR(3):
2620//
2621//      new_abstract_tuple identifier_or_typedef_name
2622//      '[' new_parameter_list ']' identifier_or_typedef_name '(' new_parameter_type_list_opt ')'
2623//
2624// since a function return type can be syntactically identical to a tuple type:
2625//
2626//      [int, int] t;
2627//      [int, int] f( int );
2628//
2629// Therefore, it is necessary to look at the token after identifier_or_typedef_name to know when to reduce
2630// new_abstract_tuple. To make this LR(1), several rules have to be flattened (lengthened) to allow the necessary
2631// lookahead. To accomplish this, new_abstract_declarator has an entry point without tuple, and tuple declarations are
2632// duplicated when appearing with new_function_specifier.
2633
2634new_abstract_declarator_tuple:                          // CFA
2635        new_abstract_tuple
2636        | type_qualifier_list new_abstract_tuple
2637                { $$ = $2->addQualifiers( $1 ); }
2638        | new_abstract_declarator_no_tuple
2639        ;
2640
2641new_abstract_declarator_no_tuple:                       // CFA
2642        new_abstract_ptr
2643        | new_abstract_array
2644        ;
2645
2646new_abstract_ptr:                                       // CFA
2647        '*' type_specifier
2648                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
2649        | type_qualifier_list '*' type_specifier
2650                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
2651        | '*' new_abstract_function
2652                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
2653        | type_qualifier_list '*' new_abstract_function
2654                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
2655        | '*' new_abstract_declarator_tuple
2656                { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0 ) ); }
2657        | type_qualifier_list '*' new_abstract_declarator_tuple
2658                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1 ) ); }
2659        ;
2660
2661new_abstract_array:                                     // CFA
2662                // Only the first dimension can be empty. Empty dimension must be factored out due to shift/reduce
2663                // conflict with empty (void) function return type.
2664        '[' push pop ']' type_specifier
2665                { $$ = $5->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
2666        | '[' push pop ']' multi_array_dimension type_specifier
2667                { $$ = $6->addNewArray( $5 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
2668        | multi_array_dimension type_specifier
2669                { $$ = $2->addNewArray( $1 ); }
2670        | '[' push pop ']' new_abstract_ptr
2671                { $$ = $5->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
2672        | '[' push pop ']' multi_array_dimension new_abstract_ptr
2673                { $$ = $6->addNewArray( $5 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
2674        | multi_array_dimension new_abstract_ptr
2675                { $$ = $2->addNewArray( $1 ); }
2676        ;
2677
2678new_abstract_tuple:                                     // CFA
2679        '[' push new_abstract_parameter_list pop ']'
2680                { $$ = DeclarationNode::newTuple( $3 ); }
2681        ;
2682
2683new_abstract_function:                                  // CFA
2684        '[' push pop ']' '(' new_parameter_type_list_opt ')'
2685                { $$ = DeclarationNode::newFunction( 0, DeclarationNode::newTuple( 0 ), $6, 0 ); }
2686        | new_abstract_tuple '(' push new_parameter_type_list_opt pop ')'
2687                { $$ = DeclarationNode::newFunction( 0, $1, $4, 0 ); }
2688        | new_function_return '(' push new_parameter_type_list_opt pop ')'
2689                { $$ = DeclarationNode::newFunction( 0, $1, $4, 0 ); }
2690        ;
2691
2692// 1) ISO/IEC 9899:1999 Section 6.7.2(2) : "At least one type specifier shall be given in the declaration specifiers in
2693//    each declaration, and in the specifier-qualifier list in each structure declaration and type name."
2694//
2695// 2) ISO/IEC 9899:1999 Section 6.11.5(1) : "The placement of a storage-class specifier other than at the beginning of
2696//    the declaration specifiers in a declaration is an obsolescent feature."
2697//
2698// 3) ISO/IEC 9899:1999 Section 6.11.6(1) : "The use of function declarators with empty parentheses (not
2699//    prototype-format parameter type declarators) is an obsolescent feature."
2700//
2701// 4) ISO/IEC 9899:1999 Section 6.11.7(1) : "The use of function definitions with separate parameter identifier and
2702//    declaration lists (not prototype-format parameter type and identifier declarators) is an obsolescent feature.
2703
2704//************************* MISCELLANEOUS ********************************
2705
2706comma_opt:                                              // redundant comma
2707        // empty
2708        | ','
2709        ;
2710
2711assignment_opt:
2712        // empty
2713                { $$ = 0; }
2714        | '=' assignment_expression
2715                { $$ = $2; }
2716        ;
2717
2718%%
2719// ----end of grammar----
2720
2721void yyerror( char *string ) {
2722    using std::cout;
2723    using std::endl;
2724    cout << "Error ";
2725    if ( yyfilename ) {
2726        cout << "in file " << yyfilename << " ";
2727    }
2728    cout << "at line " << yylineno << " reading token \"" << *(yylval.tok.str) << "\"" << endl;
2729}
2730
2731// Local Variables: //
2732// fill-column: 110 //
2733// compile-command: "make install" //
2734// End: //
Note: See TracBrowser for help on using the repository browser.