source: src/Parser/parser.yy@ 924534e

Last change on this file since 924534e was dc3fbe5, checked in by Andrew Beach <ajbeach@…>, 2 years ago

Factored out the ParseNode's next field into a new child type. This is only type safe when used in the given one level curiously reoccurring template pattern, as it is now. This allowed most of the intermedate helpers to be removed.

  • Property mode set to 100644
File size: 176.0 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// parser.yy --
8//
9// Author : Peter A. Buhr
10// Created On : Sat Sep 1 20:22:55 2001
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Fri Feb 23 18:25:46 2024
13// Update Count : 6484
14//
15
16// This grammar is based on the ANSI99/11 C grammar, specifically parts of EXPRESSION and STATEMENTS, and on the C
17// grammar by James A. Roskind, specifically parts of DECLARATIONS and EXTERNAL DEFINITIONS. While parts have been
18// copied, important changes have been made in all sections; these changes are sufficient to constitute a new grammar.
19// In particular, this grammar attempts to be more syntactically precise, i.e., it parses less incorrect language syntax
20// that must be subsequently rejected by semantic checks. Nevertheless, there are still several semantic checks
21// required and many are noted in the grammar. Finally, the grammar is extended with GCC and CFA language extensions.
22
23// Acknowledgments to Richard Bilson, Glen Ditchfield, and Rodolfo Gabriel Esteves who all helped when I got stuck with
24// the grammar.
25
26// The root language for this grammar is ANSI99/11 C. All of ANSI99/11 is parsed, except for:
27//
28// designation with '=' (use ':' instead)
29//
30// This incompatibility is discussed in detail before the "designation" grammar rule. Most of the syntactic extensions
31// from ANSI90 to ANSI11 C are marked with the comment "C99/C11".
32
33// This grammar also has two levels of extensions. The first extensions cover most of the GCC C extensions. All of the
34// syntactic extensions for GCC C are marked with the comment "GCC". The second extensions are for Cforall (CFA), which
35// fixes several of C's outstanding problems and extends C with many modern language concepts. All of the syntactic
36// extensions for CFA C are marked with the comment "CFA".
37
38%{
39#define YYDEBUG_LEXER_TEXT( yylval ) // lexer loads this up each time
40#define YYDEBUG 1 // get the pretty debugging code to compile
41#define YYERROR_VERBOSE // more information in syntax errors
42
43#undef __GNUC_MINOR__
44
45#include <cstdio>
46#include <sstream>
47#include <stack>
48using namespace std;
49
50#include "DeclarationNode.h" // for DeclarationNode, ...
51#include "ExpressionNode.h" // for ExpressionNode, ...
52#include "InitializerNode.h" // for InitializerNode, ...
53#include "ParserTypes.h"
54#include "StatementNode.h" // for build_...
55#include "TypedefTable.h"
56#include "TypeData.h"
57#include "Common/SemanticError.h" // error_str
58#include "Common/utility.h" // for maybeMoveBuild, maybeBuild, CodeLo...
59
60// lex uses __null in a boolean context, it's fine.
61#ifdef __clang__
62#pragma GCC diagnostic ignored "-Wparentheses-equality"
63#endif
64
65extern DeclarationNode * parseTree;
66extern ast::Linkage::Spec linkage;
67extern TypedefTable typedefTable;
68
69stack<ast::Linkage::Spec> linkageStack;
70
71bool appendStr( string & to, string & from ) {
72 // 1. Multiple strings are concatenated into a single string but not combined internally. The reason is that
73 // "\x12" "3" is treated as 2 characters versus 1 because "escape sequences are converted into single members of
74 // the execution character set just prior to adjacent string literal concatenation" (C11, Section 6.4.5-8). It is
75 // easier to let the C compiler handle this case.
76 //
77 // 2. String encodings are transformed into canonical form (one encoding at start) so the encoding can be found
78 // without searching the string, e.g.: "abc" L"def" L"ghi" => L"abc" "def" "ghi". Multiple encodings must match,
79 // e.g., u"a" U"b" L"c" is disallowed.
80
81 if ( from[0] != '"' ) { // encoding ?
82 if ( to[0] != '"' ) { // encoding ?
83 if ( to[0] != from[0] || to[1] != from[1] ) { // different encodings ?
84 yyerror( "non-matching string encodings for string-literal concatenation" );
85 return false; // parse error, must call YYERROR in action
86 } else if ( from[1] == '8' ) {
87 from.erase( 0, 1 ); // remove 2nd encoding
88 } // if
89 } else {
90 if ( from[1] == '8' ) { // move encoding to start
91 to = "u8" + to;
92 from.erase( 0, 1 ); // remove 2nd encoding
93 } else {
94 to = from[0] + to;
95 } // if
96 } // if
97 from.erase( 0, 1 ); // remove 2nd encoding
98 } // if
99 to += " " + from; // concatenated into single string
100 return true;
101} // appendStr
102
103DeclarationNode * distAttr( DeclarationNode * typeSpec, DeclarationNode * declList ) {
104 // Distribute type specifier across all declared variables, e.g., static, const, __attribute__.
105 assert( declList );
106
107 // Do not distribute attributes for aggregates because the attributes surrounding the aggregate belong it not the
108 // variables in the declaration list, e.g.,
109 //
110 // struct __attribute__(( aligned(128) )) S { ...
111 // } v1 __attribute__(( aligned(64) )), v2 __attribute__(( aligned(32) )), v3;
112 // struct S v4;
113 //
114 // v1 => 64, v2 =>32, v3 => 128, v2 => 128
115 //
116 // Anonymous aggregates are a special case because there is no aggregate to bind the attribute to; hence it floats
117 // to the declaration list.
118 //
119 // struct __attribute__(( aligned(128) )) /*anonymous */ { ... } v1;
120 //
121 // v1 => 128
122
123 bool copyattr = ! (typeSpec->type && typeSpec->type->kind == TypeData::Aggregate && ! typeSpec->type->aggregate.anon );
124
125 // addType copies the type information for the aggregate instances from typeSpec into cl's aggInst.aggregate.
126 DeclarationNode * cl = (new DeclarationNode)->addType( typeSpec ); // typeSpec IS DELETED!!!
127
128 // Start at second variable in declaration list and clone the type specifiers for each variable..
129 for ( DeclarationNode * cur = dynamic_cast<DeclarationNode *>( declList->get_next() ); cur != nullptr; cur = dynamic_cast<DeclarationNode *>( cur->get_next() ) ) {
130 cl->cloneBaseType( cur, copyattr ); // cur is modified
131 } // for
132
133 // Add first variable in declaration list with hidden type information in aggInst.aggregate, which is used by
134 // extractType to recover the type for the aggregate instances.
135 declList->addType( cl, copyattr ); // cl IS DELETED!!!
136 return declList;
137} // distAttr
138
139void distExt( DeclarationNode * declaration ) {
140 // distribute EXTENSION across all declarations
141 for ( DeclarationNode *iter = declaration; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
142 iter->set_extension( true );
143 } // for
144} // distExt
145
146void distInl( DeclarationNode * declaration ) {
147 // distribute INLINE across all declarations
148 for ( DeclarationNode *iter = declaration; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
149 iter->set_inLine( true );
150 } // for
151} // distInl
152
153void distQual( DeclarationNode * declaration, DeclarationNode * qualifiers ) {
154 // distribute qualifiers across all non-variable declarations in a distribution statemement
155 for ( DeclarationNode * iter = declaration; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
156 // SKULLDUGGERY: Distributions are parsed inside out, so qualifiers are added to declarations inside out. Since
157 // addQualifiers appends to the back of the list, the forall clauses are in the wrong order (right to left). To
158 // get the qualifiers in the correct order and still use addQualifiers (otherwise, 90% of addQualifiers has to
159 // be copied to add to front), the appropriate forall pointers are interchanged before calling addQualifiers.
160 DeclarationNode * clone = qualifiers->clone();
161 if ( qualifiers->type ) { // forall clause ? (handles SC)
162 if ( iter->type->kind == TypeData::Aggregate ) { // struct/union ?
163 swap( clone->type->forall, iter->type->aggregate.params );
164 iter->addQualifiers( clone );
165 } else if ( iter->type->kind == TypeData::AggregateInst && iter->type->aggInst.aggregate->aggregate.body ) { // struct/union ?
166 // Create temporary node to hold aggregate, call addQualifiers as above, then put nodes back together.
167 DeclarationNode newnode;
168 swap( newnode.type, iter->type->aggInst.aggregate );
169 swap( clone->type->forall, newnode.type->aggregate.params );
170 newnode.addQualifiers( clone );
171 swap( newnode.type, iter->type->aggInst.aggregate );
172 } else if ( iter->type->kind == TypeData::Function ) { // routines ?
173 swap( clone->type->forall, iter->type->forall );
174 iter->addQualifiers( clone );
175 } // if
176 } else { // just SC qualifiers
177 iter->addQualifiers( clone );
178 } // if
179 } // for
180 delete qualifiers;
181} // distQual
182
183// There is an ambiguity for inline generic-routine return-types and generic routines.
184// forall( otype T ) struct S { int i; } bar( T ) {}
185// Does the forall bind to the struct or the routine, and how would it be possible to explicitly specify the binding.
186// forall( otype T ) struct S { int T; } forall( otype W ) bar( W ) {}
187// Currently, the forall is associated with the routine, and the generic type has to be separately defined:
188// forall( otype T ) struct S { int T; };
189// forall( otype W ) bar( W ) {}
190
191void rebindForall( DeclarationNode * declSpec, DeclarationNode * funcDecl ) {
192 if ( declSpec->type->kind == TypeData::Aggregate ) { // ignore aggregate definition
193 funcDecl->type->forall = declSpec->type->aggregate.params; // move forall from aggregate to function type
194 declSpec->type->aggregate.params = nullptr;
195 } // if
196} // rebindForall
197
198string * build_postfix_name( string * name ) {
199 *name = string("__postfix_func_") + *name;
200 return name;
201} // build_postfix_name
202
203DeclarationNode * fieldDecl( DeclarationNode * typeSpec, DeclarationNode * fieldList ) {
204 if ( ! fieldList ) { // field declarator ?
205 if ( ! ( typeSpec->type && (typeSpec->type->kind == TypeData::Aggregate || typeSpec->type->kind == TypeData::Enum) ) ) {
206 stringstream ss;
207 // printf( "fieldDecl1 typeSpec %p\n", typeSpec ); typeSpec->type->print( std::cout );
208 SemanticWarning( yylloc, Warning::SuperfluousDecl, ss.str().c_str() );
209 return nullptr;
210 } // if
211 // printf( "fieldDecl2 typeSpec %p\n", typeSpec ); typeSpec->type->print( std::cout );
212 fieldList = DeclarationNode::newName( nullptr );
213 } // if
214
215 // printf( "fieldDecl3 typeSpec %p\n", typeSpec ); typeSpec->print( std::cout, 0 );
216 DeclarationNode * temp = distAttr( typeSpec, fieldList ); // mark all fields in list
217 // printf( "fieldDecl4 temp %p\n", temp ); temp->print( std::cout, 0 );
218 return temp;
219} // fieldDecl
220
221#define NEW_ZERO new ExpressionNode( build_constantInteger( yylloc, *new string( "0" ) ) )
222#define NEW_ONE new ExpressionNode( build_constantInteger( yylloc, *new string( "1" ) ) )
223#define UPDOWN( compop, left, right ) (compop == OperKinds::LThan || compop == OperKinds::LEThan ? left : right)
224#define MISSING_ANON_FIELD "syntax error, missing loop fields with an anonymous loop index is meaningless as loop index is unavailable in loop body."
225#define MISSING_LOW "syntax error, missing low value for up-to range so index is uninitialized."
226#define MISSING_HIGH "syntax error, missing high value for down-to range so index is uninitialized."
227
228static ForCtrl * makeForCtrl(
229 const CodeLocation & location,
230 DeclarationNode * init,
231 enum OperKinds compop,
232 ExpressionNode * comp,
233 ExpressionNode * inc ) {
234 // Wrap both comp/inc if they are non-null.
235 if ( comp ) comp = new ExpressionNode( build_binary_val( location,
236 compop,
237 new ExpressionNode( build_varref( location, new string( *init->name ) ) ),
238 comp ) );
239 if ( inc ) inc = new ExpressionNode( build_binary_val( location,
240 // choose += or -= for upto/downto
241 compop == OperKinds::LThan || compop == OperKinds::LEThan ? OperKinds::PlusAssn : OperKinds::MinusAssn,
242 new ExpressionNode( build_varref( location, new string( *init->name ) ) ),
243 inc ) );
244 // The StatementNode call frees init->name, it must happen later.
245 return new ForCtrl( new StatementNode( init ), comp, inc );
246}
247
248ForCtrl * forCtrl( const CodeLocation & location, DeclarationNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
249 if ( index->initializer ) {
250 SemanticError( yylloc, "syntax error, direct initialization disallowed. Use instead: type var; initialization ~ comparison ~ increment." );
251 } // if
252 if ( index->next ) {
253 SemanticError( yylloc, "syntax error, multiple loop indexes disallowed in for-loop declaration." );
254 } // if
255 DeclarationNode * initDecl = index->addInitializer( new InitializerNode( start ) );
256 return makeForCtrl( location, initDecl, compop, comp, inc );
257} // forCtrl
258
259ForCtrl * forCtrl( const CodeLocation & location, ExpressionNode * type, string * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
260 ast::ConstantExpr * constant = dynamic_cast<ast::ConstantExpr *>(type->expr.get());
261 if ( constant && (constant->rep == "0" || constant->rep == "1") ) {
262 type = new ExpressionNode( new ast::CastExpr( location, maybeMoveBuild(type), new ast::BasicType( ast::BasicType::SignedInt ) ) );
263 } // if
264 DeclarationNode * initDecl = distAttr(
265 DeclarationNode::newTypeof( type, true ),
266 DeclarationNode::newName( index )->addInitializer( new InitializerNode( start ) )
267 );
268 return makeForCtrl( location, initDecl, compop, comp, inc );
269} // forCtrl
270
271ForCtrl * forCtrl( const CodeLocation & location, ExpressionNode * type, ExpressionNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
272 if ( auto identifier = dynamic_cast<ast::NameExpr *>(index->expr.get()) ) {
273 return forCtrl( location, type, new string( identifier->name ), start, compop, comp, inc );
274 } else if ( auto commaExpr = dynamic_cast<ast::CommaExpr *>( index->expr.get() ) ) {
275 if ( auto identifier = commaExpr->arg1.as<ast::NameExpr>() ) {
276 return forCtrl( location, type, new string( identifier->name ), start, compop, comp, inc );
277 } else {
278 SemanticError( yylloc, "syntax error, loop-index name missing. Expression disallowed." ); return nullptr;
279 } // if
280 } else {
281 SemanticError( yylloc, "syntax error, loop-index name missing. Expression disallowed." ); return nullptr;
282 } // if
283} // forCtrl
284
285static void IdentifierBeforeIdentifier( string & identifier1, string & identifier2, const char * kind ) {
286 SemanticError( yylloc, "syntax error, adjacent identifiers \"%s\" and \"%s\" are not meaningful in an %s.\n"
287 "Possible cause is misspelled type name or missing generic parameter.",
288 identifier1.c_str(), identifier2.c_str(), kind );
289} // IdentifierBeforeIdentifier
290
291static void IdentifierBeforeType( string & identifier, const char * kind ) {
292 SemanticError( yylloc, "syntax error, identifier \"%s\" cannot appear before a %s.\n"
293 "Possible cause is misspelled storage/CV qualifier, misspelled typename, or missing generic parameter.",
294 identifier.c_str(), kind );
295} // IdentifierBeforeType
296
297bool forall = false; // aggregate have one or more forall qualifiers ?
298
299// https://www.gnu.org/software/bison/manual/bison.html#Location-Type
300#define YYLLOC_DEFAULT(Cur, Rhs, N) \
301if ( N ) { \
302 (Cur).first_line = YYRHSLOC( Rhs, 1 ).first_line; \
303 (Cur).first_column = YYRHSLOC( Rhs, 1 ).first_column; \
304 (Cur).last_line = YYRHSLOC( Rhs, N ).last_line; \
305 (Cur).last_column = YYRHSLOC( Rhs, N ).last_column; \
306 (Cur).filename = YYRHSLOC( Rhs, 1 ).filename; \
307} else { \
308 (Cur).first_line = (Cur).last_line = YYRHSLOC( Rhs, 0 ).last_line; \
309 (Cur).first_column = (Cur).last_column = YYRHSLOC( Rhs, 0 ).last_column; \
310 (Cur).filename = YYRHSLOC( Rhs, 0 ).filename; \
311}
312%}
313
314%define parse.error verbose
315
316// Types declaration for productions
317
318%union {
319 Token tok;
320 ExpressionNode * expr;
321 DeclarationNode * decl;
322 ast::AggregateDecl::Aggregate aggKey;
323 ast::TypeDecl::Kind tclass;
324 StatementNode * stmt;
325 ClauseNode * clause;
326 ast::WaitForStmt * wfs;
327 ast::WaitUntilStmt::ClauseNode * wucn;
328 CondCtl * ifctl;
329 ForCtrl * forctl;
330 LabelNode * labels;
331 InitializerNode * init;
332 OperKinds oper;
333 std::string * str;
334 bool is_volatile;
335 EnumHiding enum_hiding;
336 ast::ExceptionKind except_kind;
337 ast::GenericExpr * genexpr;
338}
339
340// ************************ TERMINAL TOKENS ********************************
341
342// keywords
343%token TYPEDEF
344%token EXTERN STATIC AUTO REGISTER
345%token THREADLOCALGCC THREADLOCALC11 // GCC, C11
346%token INLINE FORTRAN // C99, extension ISO/IEC 9899:1999 Section J.5.9(1)
347%token NORETURN // C11
348%token CONST VOLATILE
349%token RESTRICT // C99
350%token ATOMIC // C11
351%token FORALL MUTEX VIRTUAL VTABLE COERCE // CFA
352%token VOID CHAR SHORT INT LONG FLOAT DOUBLE SIGNED UNSIGNED
353%token BOOL COMPLEX IMAGINARY // C99
354%token INT128 UINT128 uuFLOAT80 uuFLOAT128 // GCC
355%token uFLOAT16 uFLOAT32 uFLOAT32X uFLOAT64 uFLOAT64X uFLOAT128 // GCC
356%token DECIMAL32 DECIMAL64 DECIMAL128 // GCC
357%token ZERO_T ONE_T // CFA
358%token SIZEOF TYPEOF VA_LIST VA_ARG AUTO_TYPE // GCC
359%token OFFSETOF BASETYPEOF TYPEID // CFA
360%token ENUM STRUCT UNION
361%token EXCEPTION // CFA
362%token GENERATOR COROUTINE MONITOR THREAD // CFA
363%token OTYPE FTYPE DTYPE TTYPE TRAIT // CFA
364// %token RESUME // CFA
365%token LABEL // GCC
366%token SUSPEND // CFA
367%token ATTRIBUTE EXTENSION // GCC
368%token IF ELSE SWITCH CASE DEFAULT DO WHILE FOR BREAK CONTINUE GOTO RETURN
369%token CHOOSE FALLTHRU FALLTHROUGH WITH WHEN WAITFOR WAITUNTIL // CFA
370%token CORUN COFOR
371%token DISABLE ENABLE TRY THROW THROWRESUME AT // CFA
372%token ASM // C99, extension ISO/IEC 9899:1999 Section J.5.10(1)
373%token ALIGNAS ALIGNOF GENERIC STATICASSERT // C11
374
375// names and constants: lexer differentiates between identifier and typedef names
376%token<tok> IDENTIFIER TYPEDIMname TYPEDEFname TYPEGENname
377%token<tok> TIMEOUT WAND WOR CATCH RECOVER CATCHRESUME FIXUP FINALLY // CFA
378%token<tok> INTEGERconstant CHARACTERconstant STRINGliteral
379%token<tok> DIRECTIVE
380// Floating point constant is broken into three kinds of tokens because of the ambiguity with tuple indexing and
381// overloading constants 0/1, e.g., x.1 is lexed as (x)(.1), where (.1) is a factional constant, but is semantically
382// converted into the tuple index (.)(1). e.g., 3.x
383%token<tok> FLOATING_DECIMALconstant FLOATING_FRACTIONconstant FLOATINGconstant
384
385// multi-character operators
386%token ARROW // ->
387%token ICR DECR // ++ --
388%token LS RS // << >>
389%token LE GE EQ NE // <= >= == !=
390%token ANDAND OROR // && ||
391%token ELLIPSIS // ...
392
393%token EXPassign MULTassign DIVassign MODassign // \= *= /= %=
394%token PLUSassign MINUSassign // += -=
395%token LSassign RSassign // <<= >>=
396%token ANDassign ERassign ORassign // &= ^= |=
397
398%token ErangeUpEq ErangeDown ErangeDownEq // ~= -~ -~=
399%token ATassign // @=
400
401%type<tok> identifier identifier_at identifier_or_type_name attr_name
402%type<tok> quasi_keyword
403%type<expr> string_literal
404%type<str> string_literal_list
405
406%type<enum_hiding> hide_opt visible_hide_opt
407
408// expressions
409%type<expr> constant
410%type<expr> tuple tuple_expression_list
411%type<oper> ptrref_operator unary_operator assignment_operator simple_assignment_operator compound_assignment_operator
412%type<expr> primary_expression postfix_expression unary_expression
413%type<expr> cast_expression_list cast_expression exponential_expression multiplicative_expression additive_expression
414%type<expr> shift_expression relational_expression equality_expression
415%type<expr> AND_expression exclusive_OR_expression inclusive_OR_expression
416%type<expr> logical_AND_expression logical_OR_expression
417%type<expr> conditional_expression constant_expression assignment_expression assignment_expression_opt
418%type<expr> comma_expression comma_expression_opt
419%type<expr> argument_expression_list_opt argument_expression_list argument_expression default_initializer_opt
420%type<ifctl> conditional_declaration
421%type<forctl> for_control_expression for_control_expression_list
422%type<oper> upupeq updown updowneq downupdowneq
423%type<expr> subrange
424%type<decl> asm_name_opt
425%type<expr> asm_operands_opt asm_operands_list asm_operand
426%type<labels> label_list
427%type<expr> asm_clobbers_list_opt
428%type<is_volatile> asm_volatile_opt
429%type<expr> handler_predicate_opt
430%type<genexpr> generic_association generic_assoc_list
431
432// statements
433%type<stmt> statement labeled_statement compound_statement
434%type<stmt> statement_decl statement_decl_list statement_list_nodecl
435%type<stmt> selection_statement if_statement
436%type<clause> switch_clause_list_opt switch_clause_list
437%type<expr> case_value
438%type<clause> case_clause case_value_list case_label case_label_list
439%type<stmt> iteration_statement jump_statement
440%type<stmt> expression_statement asm_statement
441%type<stmt> with_statement
442%type<expr> with_clause_opt
443%type<stmt> corun_statement cofor_statement
444%type<stmt> exception_statement
445%type<clause> handler_clause finally_clause
446%type<except_kind> handler_key
447%type<stmt> mutex_statement
448%type<expr> when_clause when_clause_opt waitfor waituntil timeout
449%type<stmt> waitfor_statement waituntil_statement
450%type<wfs> wor_waitfor_clause
451%type<wucn> waituntil_clause wand_waituntil_clause wor_waituntil_clause
452
453// declarations
454%type<decl> abstract_declarator abstract_ptr abstract_array abstract_function array_dimension multi_array_dimension
455%type<decl> abstract_parameter_declarator_opt abstract_parameter_declarator abstract_parameter_ptr abstract_parameter_array abstract_parameter_function array_parameter_dimension array_parameter_1st_dimension
456%type<decl> abstract_parameter_declaration
457
458%type<aggKey> aggregate_key aggregate_data aggregate_control
459%type<decl> aggregate_type aggregate_type_nobody
460
461%type<decl> assertion assertion_list assertion_list_opt
462
463%type<expr> bit_subrange_size_opt bit_subrange_size
464
465%type<decl> basic_declaration_specifier basic_type_name basic_type_specifier direct_type indirect_type
466%type<decl> vtable vtable_opt default_opt
467
468%type<decl> trait_declaration trait_declaration_list trait_declaring_list trait_specifier
469
470%type<decl> declaration declaration_list declaration_list_opt declaration_qualifier_list
471%type<decl> declaration_specifier declaration_specifier_nobody declarator declaring_list
472
473%type<decl> elaborated_type elaborated_type_nobody
474
475%type<decl> enumerator_list enum_type enum_type_nobody
476%type<init> enumerator_value_opt
477
478%type<decl> external_definition external_definition_list external_definition_list_opt
479
480%type<decl> exception_declaration
481
482%type<decl> field_declaration_list_opt field_declaration field_declaring_list_opt field_declarator field_abstract_list_opt field_abstract
483%type<expr> field field_name_list field_name fraction_constants_opt
484
485%type<decl> external_function_definition function_definition function_array function_declarator function_no_ptr function_ptr
486
487%type<decl> identifier_parameter_declarator identifier_parameter_ptr identifier_parameter_array identifier_parameter_function
488%type<decl> identifier_list
489
490%type<decl> cfa_abstract_array cfa_abstract_declarator_no_tuple cfa_abstract_declarator_tuple
491%type<decl> cfa_abstract_function cfa_abstract_parameter_declaration cfa_abstract_parameter_list
492%type<decl> cfa_abstract_ptr cfa_abstract_tuple
493
494%type<decl> cfa_array_parameter_1st_dimension
495
496%type<decl> cfa_trait_declaring_list cfa_declaration cfa_field_declaring_list cfa_field_abstract_list
497%type<decl> cfa_function_declaration cfa_function_return cfa_function_specifier
498
499%type<decl> cfa_identifier_parameter_array cfa_identifier_parameter_declarator_no_tuple
500%type<decl> cfa_identifier_parameter_declarator_tuple cfa_identifier_parameter_ptr
501
502%type<decl> cfa_parameter_declaration cfa_parameter_list cfa_parameter_ellipsis_list_opt
503
504%type<decl> cfa_typedef_declaration cfa_variable_declaration cfa_variable_specifier
505
506%type<decl> c_declaration static_assert
507%type<decl> KR_function_declarator KR_function_no_ptr KR_function_ptr KR_function_array
508%type<decl> KR_parameter_list KR_parameter_list_opt
509
510%type<decl> parameter_declaration parameter_list parameter_type_list_opt
511
512%type<decl> paren_identifier paren_type
513
514%type<decl> storage_class storage_class_list
515
516%type<decl> sue_declaration_specifier sue_declaration_specifier_nobody sue_type_specifier sue_type_specifier_nobody
517
518%type<tclass> type_class new_type_class
519%type<decl> type_declarator type_declarator_name type_declaring_list
520
521%type<decl> type_declaration_specifier type_type_specifier type_name typegen_name
522%type<decl> typedef_name typedef_declaration typedef_expression
523
524%type<decl> variable_type_redeclarator variable_type_ptr variable_type_array variable_type_function
525%type<decl> general_function_declarator function_type_redeclarator function_type_array function_type_no_ptr function_type_ptr
526
527%type<decl> type_parameter_redeclarator type_parameter_ptr type_parameter_array type_parameter_function
528
529%type<decl> type type_no_function
530%type<decl> type_parameter type_parameter_list type_initializer_opt
531
532%type<expr> type_parameters_opt type_list array_type_list
533
534%type<decl> type_qualifier type_qualifier_name forall type_qualifier_list_opt type_qualifier_list
535%type<decl> type_specifier type_specifier_nobody
536
537%type<decl> variable_declarator variable_ptr variable_array variable_function
538%type<decl> variable_abstract_declarator variable_abstract_ptr variable_abstract_array variable_abstract_function
539
540%type<decl> attribute_list_opt attribute_list attribute attribute_name_list attribute_name
541
542// initializers
543%type<init> initializer initializer_list_opt initializer_opt
544
545// designators
546%type<expr> designator designator_list designation
547
548
549// Handle shift/reduce conflict for dangling else by shifting the ELSE token. For example, this string is ambiguous:
550// .---------. matches IF '(' comma_expression ')' statement . (reduce)
551// if ( C ) S1 else S2
552// `-----------------' matches IF '(' comma_expression ')' statement . (shift) ELSE statement */
553// Similar issues exit with the waitfor statement.
554
555// Order of these lines matters (low-to-high precedence). THEN is left associative over WAND/WOR/TIMEOUT/ELSE, WAND/WOR
556// is left associative over TIMEOUT/ELSE, and TIMEOUT is left associative over ELSE.
557%precedence THEN // rule precedence for IF/WAITFOR statement
558%precedence ANDAND // token precedence for start of WAND in WAITFOR statement
559%precedence WAND // token precedence for start of WAND in WAITFOR statement
560%precedence OROR // token precedence for start of WOR in WAITFOR statement
561%precedence WOR // token precedence for start of WOR in WAITFOR statement
562%precedence TIMEOUT // token precedence for start of TIMEOUT in WAITFOR statement
563%precedence CATCH // token precedence for start of TIMEOUT in WAITFOR statement
564%precedence RECOVER // token precedence for start of TIMEOUT in WAITFOR statement
565%precedence CATCHRESUME // token precedence for start of TIMEOUT in WAITFOR statement
566%precedence FIXUP // token precedence for start of TIMEOUT in WAITFOR statement
567%precedence FINALLY // token precedence for start of TIMEOUT in WAITFOR statement
568%precedence ELSE // token precedence for start of else clause in IF/WAITFOR statement
569
570
571// Handle shift/reduce conflict for generic type by shifting the '(' token. For example, this string is ambiguous:
572// forall( otype T ) struct Foo { T v; };
573// .-----. matches pointer to function returning a generic (which is impossible without a type)
574// Foo ( *fp )( int );
575// `---' matches start of TYPEGENname '('
576// must be:
577// Foo( int ) ( *fp )( int );
578// The same problem occurs here:
579// forall( otype T ) struct Foo { T v; } ( *fp )( int );
580// must be:
581// forall( otype T ) struct Foo { T v; } ( int ) ( *fp )( int );
582
583// Order of these lines matters (low-to-high precedence).
584%precedence TYPEGENname
585%precedence '}'
586%precedence '('
587
588// %precedence RESUME
589// %precedence '{'
590// %precedence ')'
591
592%locations // support location tracking for error messages
593
594%start translation_unit // parse-tree root
595
596%%
597// ************************ Namespace Management ********************************
598
599// The C grammar is not context free because it relies on the distinct terminal symbols "identifier" and "TYPEDEFname",
600// which are lexically identical.
601//
602// typedef int foo; // identifier foo must now be scanned as TYPEDEFname
603// foo f; // to allow it to appear in this context
604//
605// While it may be possible to write a purely context-free grammar, such a grammar would obscure the relationship
606// between syntactic and semantic constructs. Cforall compounds this problem by introducing type names local to the
607// scope of a declaration (for instance, those introduced through "forall" qualifiers), and by introducing "type
608// generators" -- parameterized types. This latter type name creates a third class of identifiers, "TYPEGENname", which
609// must be distinguished by the lexical scanner.
610//
611// Since the scanner cannot distinguish among the different classes of identifiers without some context information,
612// there is a type table (typedefTable), which holds type names and identifiers that override type names, for each named
613// scope. During parsing, semantic actions update the type table by adding new identifiers in the current scope. For
614// each context that introduces a name scope, a new level is created in the type table and that level is popped on
615// exiting the scope. Since type names can be local to a particular declaration, each declaration is itself a scope.
616// This requires distinguishing between type names that are local to the current declaration scope and those that
617// persist past the end of the declaration (i.e., names defined in "typedef" or "otype" declarations).
618//
619// The non-terminals "push" and "pop" denote the opening and closing of named scopes. Every push has a matching pop in
620// the production rule. There are multiple lists of declarations, where each declaration is a named scope, so pop/push
621// around the list separator.
622//
623// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
624// push pop push pop
625
626push:
627 { typedefTable.enterScope(); }
628 ;
629
630pop:
631 { typedefTable.leaveScope(); }
632 ;
633
634// ************************ CONSTANTS ********************************
635
636constant:
637 // ENUMERATIONconstant is not included here; it is treated as a variable with type "enumeration constant".
638 INTEGERconstant { $$ = new ExpressionNode( build_constantInteger( yylloc, *$1 ) ); }
639 | FLOATING_DECIMALconstant { $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); }
640 | FLOATING_FRACTIONconstant { $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); }
641 | FLOATINGconstant { $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); }
642 | CHARACTERconstant { $$ = new ExpressionNode( build_constantChar( yylloc, *$1 ) ); }
643 ;
644
645quasi_keyword: // CFA
646 TIMEOUT
647 | WAND
648 | WOR
649 | CATCH
650 | RECOVER
651 | CATCHRESUME
652 | FIXUP
653 | FINALLY
654 ;
655
656identifier:
657 IDENTIFIER
658 | quasi_keyword
659 ;
660
661identifier_at:
662 identifier
663 | '@' // CFA
664 { Token tok = { new string( DeclarationNode::anonymous.newName() ), yylval.tok.loc }; $$ = tok; }
665 ;
666
667string_literal:
668 string_literal_list { $$ = new ExpressionNode( build_constantStr( yylloc, *$1 ) ); }
669 ;
670
671string_literal_list: // juxtaposed strings are concatenated
672 STRINGliteral { $$ = $1; } // conversion from tok to str
673 | string_literal_list STRINGliteral
674 {
675 if ( ! appendStr( *$1, *$2 ) ) YYERROR; // append 2nd juxtaposed string to 1st
676 delete $2; // allocated by lexer
677 $$ = $1; // conversion from tok to str
678 }
679 ;
680
681// ************************ EXPRESSIONS ********************************
682
683primary_expression:
684 IDENTIFIER // typedef name cannot be used as a variable name
685 { $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); }
686 | quasi_keyword
687 { $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); }
688 | TYPEDIMname // CFA, generic length argument
689 // { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( DeclarationNode::newFromTypedef( $1 ) ) ) ); }
690 // { $$ = new ExpressionNode( build_varref( $1 ) ); }
691 { $$ = new ExpressionNode( build_dimensionref( yylloc, $1 ) ); }
692 | tuple
693 | '(' comma_expression ')'
694 { $$ = $2; }
695 | '(' compound_statement ')' // GCC, lambda expression
696 { $$ = new ExpressionNode( new ast::StmtExpr( yylloc, dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( $2 ) ) ) ); }
697 | type_name '.' identifier // CFA, nested type
698 { $$ = new ExpressionNode( build_qualified_expr( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
699 | type_name '.' '[' field_name_list ']' // CFA, nested type / tuple field selector
700 { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
701 | GENERIC '(' assignment_expression ',' generic_assoc_list ')' // C11
702 {
703 // add the missing control expression to the GenericExpr and return it
704 $5->control = maybeMoveBuild( $3 );
705 $$ = new ExpressionNode( $5 );
706 }
707 // | RESUME '(' comma_expression ')'
708 // { SemanticError( yylloc, "Resume expression is currently unimplemented." ); $$ = nullptr; }
709 // | RESUME '(' comma_expression ')' compound_statement
710 // { SemanticError( yylloc, "Resume expression is currently unimplemented." ); $$ = nullptr; }
711 | IDENTIFIER IDENTIFIER // invalid syntax rule
712 { IdentifierBeforeIdentifier( *$1.str, *$2.str, "expression" ); $$ = nullptr; }
713 | IDENTIFIER type_qualifier // invalid syntax rule
714 { IdentifierBeforeType( *$1.str, "type qualifier" ); $$ = nullptr; }
715 | IDENTIFIER storage_class // invalid syntax rule
716 { IdentifierBeforeType( *$1.str, "storage class" ); $$ = nullptr; }
717 | IDENTIFIER basic_type_name // invalid syntax rule
718 { IdentifierBeforeType( *$1.str, "type" ); $$ = nullptr; }
719 | IDENTIFIER TYPEDEFname // invalid syntax rule
720 { IdentifierBeforeType( *$1.str, "type" ); $$ = nullptr; }
721 | IDENTIFIER TYPEGENname // invalid syntax rule
722 { IdentifierBeforeType( *$1.str, "type" ); $$ = nullptr; }
723 ;
724
725generic_assoc_list: // C11
726 generic_association
727 | generic_assoc_list ',' generic_association
728 {
729 // steal the association node from the singleton and delete the wrapper
730 assert( 1 == $3->associations.size() );
731 $1->associations.push_back( $3->associations.front() );
732 delete $3;
733 $$ = $1;
734 }
735 ;
736
737generic_association: // C11
738 type_no_function ':' assignment_expression
739 {
740 // create a GenericExpr wrapper with one association pair
741 $$ = new ast::GenericExpr( yylloc, nullptr, { { maybeMoveBuildType( $1 ), maybeMoveBuild( $3 ) } } );
742 }
743 | DEFAULT ':' assignment_expression
744 { $$ = new ast::GenericExpr( yylloc, nullptr, { { maybeMoveBuild( $3 ) } } ); }
745 ;
746
747postfix_expression:
748 primary_expression
749 | postfix_expression '[' assignment_expression ',' tuple_expression_list ']'
750 // Historic, transitional: Disallow commas in subscripts.
751 // Switching to this behaviour may help check if a C compatibilty case uses comma-exprs in subscripts.
752 // Current: Commas in subscripts make tuples.
753 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)($3->set_last( $5 ) ) )) ) ); }
754 | postfix_expression '[' assignment_expression ']'
755 // CFA, comma_expression disallowed in this context because it results in a common user error: subscripting a
756 // matrix with x[i,j] instead of x[i][j]. While this change is not backwards compatible, there seems to be
757 // little advantage to this feature and many disadvantages. It is possible to write x[(i,j)] in CFA, which is
758 // equivalent to the old x[i,j].
759 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); }
760 | constant '[' assignment_expression ']' // 3[a], 'a'[a], 3.5[a]
761 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); }
762 | string_literal '[' assignment_expression ']' // "abc"[3], 3["abc"]
763 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); }
764 | postfix_expression '{' argument_expression_list_opt '}' // CFA, constructor call
765 {
766 Token fn;
767 fn.str = new std::string( "?{}" ); // location undefined - use location of '{'?
768 $$ = new ExpressionNode( new ast::ConstructorExpr( yylloc, build_func( yylloc, new ExpressionNode( build_varref( yylloc, fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) );
769 }
770 | postfix_expression '(' argument_expression_list_opt ')'
771 { $$ = new ExpressionNode( build_func( yylloc, $1, $3 ) ); }
772 | VA_ARG '(' primary_expression ',' declaration_specifier_nobody abstract_parameter_declarator_opt ')'
773 // { SemanticError( yylloc, "va_arg is currently unimplemented." ); $$ = nullptr; }
774 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, new string( "__builtin_va_arg") ) ),
775 (ExpressionNode *)($3->set_last( (ExpressionNode *)($6 ? $6->addType( $5 ) : $5) )) ) ); }
776 | postfix_expression '`' identifier // CFA, postfix call
777 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); }
778 | constant '`' identifier // CFA, postfix call
779 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); }
780 | string_literal '`' identifier // CFA, postfix call
781 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); }
782
783 // SKULLDUGGERY: The typedef table used for parsing does not store fields in structures. To parse a qualified
784 // name, it is assumed all name-tokens after the first are identifiers, regardless of how the lexer identifies
785 // them. For example:
786 //
787 // struct S;
788 // forall(T) struct T;
789 // union U;
790 // enum E { S, T, E };
791 // struct Z { int S, T, Z, E, U; };
792 // void fred () {
793 // Z z;
794 // z.S; // lexer returns S is TYPEDEFname
795 // z.T; // lexer returns T is TYPEGENname
796 // z.Z; // lexer returns Z is TYPEDEFname
797 // z.U; // lexer returns U is TYPEDEFname
798 // z.E; // lexer returns E is TYPEDEFname
799 // }
800 | postfix_expression '.' identifier
801 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
802 | postfix_expression '.' TYPEDEFname // CFA, SKULLDUGGERY
803 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
804 | postfix_expression '.' TYPEGENname // CFA, SKULLDUGGERY
805 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
806
807 | postfix_expression '.' INTEGERconstant // CFA, tuple index
808 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_constantInteger( yylloc, *$3 ) ) ); }
809 | postfix_expression FLOATING_FRACTIONconstant // CFA, tuple index
810 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_field_name_FLOATING_FRACTIONconstant( yylloc, *$2 ) ) ); }
811 | postfix_expression '.' '[' field_name_list ']' // CFA, tuple field selector
812 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); }
813 | postfix_expression '.' aggregate_control
814 { $$ = new ExpressionNode( build_keyword_cast( yylloc, $3, $1 ) ); }
815 | postfix_expression ARROW identifier
816 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
817 | postfix_expression ARROW INTEGERconstant // CFA, tuple index
818 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_constantInteger( yylloc, *$3 ) ) ); }
819 | postfix_expression ARROW '[' field_name_list ']' // CFA, tuple field selector
820 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); }
821 | postfix_expression ICR
822 { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::IncrPost, $1 ) ); }
823 | postfix_expression DECR
824 { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::DecrPost, $1 ) ); }
825 | '(' type_no_function ')' '{' initializer_list_opt comma_opt '}' // C99, compound-literal
826 { $$ = new ExpressionNode( build_compoundLiteral( yylloc, $2, new InitializerNode( $5, true ) ) ); }
827 | '(' type_no_function ')' '@' '{' initializer_list_opt comma_opt '}' // CFA, explicit C compound-literal
828 { $$ = new ExpressionNode( build_compoundLiteral( yylloc, $2, (new InitializerNode( $6, true ))->set_maybeConstructed( false ) ) ); }
829 | '^' primary_expression '{' argument_expression_list_opt '}' // CFA, destructor call
830 {
831 Token fn;
832 fn.str = new string( "^?{}" ); // location undefined
833 $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, fn ) ), (ExpressionNode *)( $2 )->set_last( $4 ) ) );
834 }
835 ;
836
837argument_expression_list_opt:
838 // empty
839 { $$ = nullptr; }
840 | argument_expression_list
841 ;
842
843argument_expression_list:
844 argument_expression
845 | argument_expression_list_opt ',' argument_expression
846 { $$ = (ExpressionNode *)($1->set_last( $3 )); }
847 ;
848
849argument_expression:
850 '@' // CFA, default parameter
851 { SemanticError( yylloc, "Default parameter for argument is currently unimplemented." ); $$ = nullptr; }
852 // { $$ = new ExpressionNode( build_constantInteger( *new string( "2" ) ) ); }
853 | assignment_expression
854 ;
855
856field_name_list: // CFA, tuple field selector
857 field
858 | field_name_list ',' field { $$ = (ExpressionNode *)($1->set_last( $3 )); }
859 ;
860
861field: // CFA, tuple field selector
862 field_name
863 | FLOATING_DECIMALconstant field
864 { $$ = new ExpressionNode( build_fieldSel( yylloc, new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( yylloc, *$1 ) ), maybeMoveBuild( $2 ) ) ); }
865 | FLOATING_DECIMALconstant '[' field_name_list ']'
866 { $$ = new ExpressionNode( build_fieldSel( yylloc, new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( yylloc, *$1 ) ), build_tuple( yylloc, $3 ) ) ); }
867 | field_name '.' field
868 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, maybeMoveBuild( $3 ) ) ); }
869 | field_name '.' '[' field_name_list ']'
870 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); }
871 | field_name ARROW field
872 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, maybeMoveBuild( $3 ) ) ); }
873 | field_name ARROW '[' field_name_list ']'
874 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); }
875 ;
876
877field_name:
878 INTEGERconstant fraction_constants_opt
879 { $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_constantInteger( yylloc, *$1 ), $2 ) ); }
880 | FLOATINGconstant fraction_constants_opt
881 { $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_field_name_FLOATINGconstant( yylloc, *$1 ), $2 ) ); }
882 | identifier_at fraction_constants_opt // CFA, allow anonymous fields
883 {
884 $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_varref( yylloc, $1 ), $2 ) );
885 }
886 ;
887
888fraction_constants_opt:
889 // empty
890 { $$ = nullptr; }
891 | fraction_constants_opt FLOATING_FRACTIONconstant
892 {
893 ast::Expr * constant = build_field_name_FLOATING_FRACTIONconstant( yylloc, *$2 );
894 $$ = $1 != nullptr ? new ExpressionNode( build_fieldSel( yylloc, $1, constant ) ) : new ExpressionNode( constant );
895 }
896 ;
897
898unary_expression:
899 postfix_expression
900 // first location where constant/string can have operator applied: sizeof 3/sizeof "abc" still requires
901 // semantics checks, e.g., ++3, 3--, *3, &&3
902 | constant
903 | string_literal
904 { $$ = $1; }
905 | EXTENSION cast_expression // GCC
906 { $$ = $2->set_extension( true ); }
907 // '*' ('&') is separated from unary_operator because of shift/reduce conflict in:
908 // { * X; } // dereference X
909 // { * int X; } // CFA declaration of pointer to int
910 | ptrref_operator cast_expression // CFA
911 {
912 switch ( $1 ) {
913 case OperKinds::AddressOf:
914 $$ = new ExpressionNode( new ast::AddressExpr( maybeMoveBuild( $2 ) ) );
915 break;
916 case OperKinds::PointTo:
917 $$ = new ExpressionNode( build_unary_val( yylloc, $1, $2 ) );
918 break;
919 case OperKinds::And:
920 $$ = new ExpressionNode( new ast::AddressExpr( new ast::AddressExpr( maybeMoveBuild( $2 ) ) ) );
921 break;
922 default:
923 assert( false );
924 }
925 }
926 | unary_operator cast_expression
927 { $$ = new ExpressionNode( build_unary_val( yylloc, $1, $2 ) ); }
928 | ICR unary_expression
929 { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::Incr, $2 ) ); }
930 | DECR unary_expression
931 { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::Decr, $2 ) ); }
932 | SIZEOF unary_expression
933 { $$ = new ExpressionNode( new ast::SizeofExpr( yylloc, maybeMoveBuild( $2 ) ) ); }
934 | SIZEOF '(' type_no_function ')'
935 { $$ = new ExpressionNode( new ast::SizeofExpr( yylloc, maybeMoveBuildType( $3 ) ) ); }
936 | ALIGNOF unary_expression // GCC, variable alignment
937 { $$ = new ExpressionNode( new ast::AlignofExpr( yylloc, maybeMoveBuild( $2 ) ) ); }
938 | ALIGNOF '(' type_no_function ')' // GCC, type alignment
939 { $$ = new ExpressionNode( new ast::AlignofExpr( yylloc, maybeMoveBuildType( $3 ) ) ); }
940 | OFFSETOF '(' type_no_function ',' identifier ')'
941 { $$ = new ExpressionNode( build_offsetOf( yylloc, $3, build_varref( yylloc, $5 ) ) ); }
942 | TYPEID '(' type_no_function ')'
943 {
944 SemanticError( yylloc, "typeid name is currently unimplemented." ); $$ = nullptr;
945 // $$ = new ExpressionNode( build_offsetOf( $3, build_varref( $5 ) ) );
946 }
947 ;
948
949ptrref_operator:
950 '*' { $$ = OperKinds::PointTo; }
951 | '&' { $$ = OperKinds::AddressOf; }
952 // GCC, address of label must be handled by semantic check for ref,ref,label
953 | ANDAND { $$ = OperKinds::And; }
954 ;
955
956unary_operator:
957 '+' { $$ = OperKinds::UnPlus; }
958 | '-' { $$ = OperKinds::UnMinus; }
959 | '!' { $$ = OperKinds::Neg; }
960 | '~' { $$ = OperKinds::BitNeg; }
961 ;
962
963cast_expression:
964 unary_expression
965 | '(' type_no_function ')' cast_expression
966 { $$ = new ExpressionNode( build_cast( yylloc, $2, $4 ) ); }
967 | '(' aggregate_control '&' ')' cast_expression // CFA
968 { $$ = new ExpressionNode( build_keyword_cast( yylloc, $2, $5 ) ); }
969 | '(' aggregate_control '*' ')' cast_expression // CFA
970 { $$ = new ExpressionNode( build_keyword_cast( yylloc, $2, $5 ) ); }
971 | '(' VIRTUAL ')' cast_expression // CFA
972 { $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $4 ), maybeMoveBuildType( nullptr ) ) ); }
973 | '(' VIRTUAL type_no_function ')' cast_expression // CFA
974 { $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $5 ), maybeMoveBuildType( $3 ) ) ); }
975 | '(' RETURN type_no_function ')' cast_expression // CFA
976 { $$ = new ExpressionNode( build_cast( yylloc, $3, $5, ast::CastExpr::Return ) ); }
977 | '(' COERCE type_no_function ')' cast_expression // CFA
978 { SemanticError( yylloc, "Coerce cast is currently unimplemented." ); $$ = nullptr; }
979 | '(' qualifier_cast_list ')' cast_expression // CFA
980 { SemanticError( yylloc, "Qualifier cast is currently unimplemented." ); $$ = nullptr; }
981// | '(' type_no_function ')' tuple
982// { $$ = new ast::ExpressionNode( build_cast( yylloc, $2, $4 ) ); }
983 ;
984
985qualifier_cast_list:
986 cast_modifier type_qualifier_name
987 | cast_modifier MUTEX
988 | qualifier_cast_list cast_modifier type_qualifier_name
989 | qualifier_cast_list cast_modifier MUTEX
990 ;
991
992cast_modifier:
993 '-'
994 | '+'
995 ;
996
997exponential_expression:
998 cast_expression
999 | exponential_expression '\\' cast_expression
1000 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Exp, $1, $3 ) ); }
1001 ;
1002
1003multiplicative_expression:
1004 exponential_expression
1005 | multiplicative_expression '*' exponential_expression
1006 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Mul, $1, $3 ) ); }
1007 | multiplicative_expression '/' exponential_expression
1008 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Div, $1, $3 ) ); }
1009 | multiplicative_expression '%' exponential_expression
1010 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Mod, $1, $3 ) ); }
1011 ;
1012
1013additive_expression:
1014 multiplicative_expression
1015 | additive_expression '+' multiplicative_expression
1016 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Plus, $1, $3 ) ); }
1017 | additive_expression '-' multiplicative_expression
1018 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Minus, $1, $3 ) ); }
1019 ;
1020
1021shift_expression:
1022 additive_expression
1023 | shift_expression LS additive_expression
1024 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LShift, $1, $3 ) ); }
1025 | shift_expression RS additive_expression
1026 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::RShift, $1, $3 ) ); }
1027 ;
1028
1029relational_expression:
1030 shift_expression
1031 | relational_expression '<' shift_expression
1032 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LThan, $1, $3 ) ); }
1033 | relational_expression '>' shift_expression
1034 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::GThan, $1, $3 ) ); }
1035 | relational_expression LE shift_expression
1036 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LEThan, $1, $3 ) ); }
1037 | relational_expression GE shift_expression
1038 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::GEThan, $1, $3 ) ); }
1039 ;
1040
1041equality_expression:
1042 relational_expression
1043 | equality_expression EQ relational_expression
1044 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Eq, $1, $3 ) ); }
1045 | equality_expression NE relational_expression
1046 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Neq, $1, $3 ) ); }
1047 ;
1048
1049AND_expression:
1050 equality_expression
1051 | AND_expression '&' equality_expression
1052 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::BitAnd, $1, $3 ) ); }
1053 ;
1054
1055exclusive_OR_expression:
1056 AND_expression
1057 | exclusive_OR_expression '^' AND_expression
1058 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Xor, $1, $3 ) ); }
1059 ;
1060
1061inclusive_OR_expression:
1062 exclusive_OR_expression
1063 | inclusive_OR_expression '|' exclusive_OR_expression
1064 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::BitOr, $1, $3 ) ); }
1065 ;
1066
1067logical_AND_expression:
1068 inclusive_OR_expression
1069 | logical_AND_expression ANDAND inclusive_OR_expression
1070 { $$ = new ExpressionNode( build_and_or( yylloc, $1, $3, ast::AndExpr ) ); }
1071 ;
1072
1073logical_OR_expression:
1074 logical_AND_expression
1075 | logical_OR_expression OROR logical_AND_expression
1076 { $$ = new ExpressionNode( build_and_or( yylloc, $1, $3, ast::OrExpr ) ); }
1077 ;
1078
1079conditional_expression:
1080 logical_OR_expression
1081 | logical_OR_expression '?' comma_expression ':' conditional_expression
1082 { $$ = new ExpressionNode( build_cond( yylloc, $1, $3, $5 ) ); }
1083 | logical_OR_expression '?' /* empty */ ':' conditional_expression // GCC, omitted first operand
1084 { $$ = new ExpressionNode( build_cond( yylloc, $1, nullptr, $4 ) ); }
1085 ;
1086
1087constant_expression:
1088 conditional_expression
1089 ;
1090
1091assignment_expression:
1092 // CFA, assignment is separated from assignment_operator to ensure no assignment operations for tuples
1093 conditional_expression
1094 | unary_expression assignment_operator assignment_expression
1095 {
1096// if ( $2 == OperKinds::AtAssn ) {
1097// SemanticError( yylloc, "C @= assignment is currently unimplemented." ); $$ = nullptr;
1098// } else {
1099 $$ = new ExpressionNode( build_binary_val( yylloc, $2, $1, $3 ) );
1100// } // if
1101 }
1102 | unary_expression '=' '{' initializer_list_opt comma_opt '}'
1103 { SemanticError( yylloc, "Initializer assignment is currently unimplemented." ); $$ = nullptr; }
1104 ;
1105
1106assignment_expression_opt:
1107 // empty
1108 { $$ = nullptr; }
1109 | assignment_expression
1110 ;
1111
1112assignment_operator:
1113 simple_assignment_operator
1114 | compound_assignment_operator
1115 ;
1116
1117simple_assignment_operator:
1118 '=' { $$ = OperKinds::Assign; }
1119 | ATassign { $$ = OperKinds::AtAssn; } // CFA
1120 ;
1121
1122compound_assignment_operator:
1123 EXPassign { $$ = OperKinds::ExpAssn; }
1124 | MULTassign { $$ = OperKinds::MulAssn; }
1125 | DIVassign { $$ = OperKinds::DivAssn; }
1126 | MODassign { $$ = OperKinds::ModAssn; }
1127 | PLUSassign { $$ = OperKinds::PlusAssn; }
1128 | MINUSassign { $$ = OperKinds::MinusAssn; }
1129 | LSassign { $$ = OperKinds::LSAssn; }
1130 | RSassign { $$ = OperKinds::RSAssn; }
1131 | ANDassign { $$ = OperKinds::AndAssn; }
1132 | ERassign { $$ = OperKinds::ERAssn; }
1133 | ORassign { $$ = OperKinds::OrAssn; }
1134 ;
1135
1136tuple: // CFA, tuple
1137 // CFA, one assignment_expression is factored out of comma_expression to eliminate a shift/reduce conflict with
1138 // comma_expression in cfa_identifier_parameter_array and cfa_abstract_array
1139// '[' ']'
1140// { $$ = new ExpressionNode( build_tuple() ); }
1141// | '[' push assignment_expression pop ']'
1142// { $$ = new ExpressionNode( build_tuple( $3 ) ); }
1143 '[' ',' tuple_expression_list ']'
1144 { $$ = new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( $3 ) ) ); }
1145 | '[' push assignment_expression pop ',' tuple_expression_list ']'
1146 { $$ = new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)($3->set_last( $6 ) ) )); }
1147 ;
1148
1149tuple_expression_list:
1150 assignment_expression
1151 | '@' // CFA
1152 { SemanticError( yylloc, "Eliding tuple element with '@' is currently unimplemented." ); $$ = nullptr; }
1153 | tuple_expression_list ',' assignment_expression
1154 { $$ = (ExpressionNode *)($1->set_last( $3 )); }
1155 | tuple_expression_list ',' '@'
1156 { SemanticError( yylloc, "Eliding tuple element with '@' is currently unimplemented." ); $$ = nullptr; }
1157 ;
1158
1159comma_expression:
1160 assignment_expression
1161 | comma_expression ',' assignment_expression
1162 { $$ = new ExpressionNode( new ast::CommaExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
1163 ;
1164
1165comma_expression_opt:
1166 // empty
1167 { $$ = nullptr; }
1168 | comma_expression
1169 ;
1170
1171// ************************** STATEMENTS *******************************
1172
1173statement:
1174 labeled_statement
1175 | compound_statement
1176 | expression_statement
1177 | selection_statement
1178 | iteration_statement
1179 | jump_statement
1180 | with_statement
1181 | mutex_statement
1182 | waitfor_statement
1183 | waituntil_statement
1184 | corun_statement
1185 | cofor_statement
1186 | exception_statement
1187 | enable_disable_statement
1188 { SemanticError( yylloc, "enable/disable statement is currently unimplemented." ); $$ = nullptr; }
1189 | asm_statement
1190 | DIRECTIVE
1191 { $$ = new StatementNode( build_directive( yylloc, $1 ) ); }
1192 ;
1193
1194labeled_statement:
1195 // labels cannot be identifiers 0 or 1
1196 identifier_or_type_name ':' attribute_list_opt statement
1197 { $$ = $4->add_label( yylloc, $1, $3 ); }
1198 | identifier_or_type_name ':' attribute_list_opt error // invalid syntax rule
1199 {
1200 SemanticError( yylloc, "syntx error, label \"%s\" must be associated with a statement, "
1201 "where a declaration, case, or default is not a statement.\n"
1202 "Move the label or terminate with a semicolon.", $1.str->c_str() );
1203 $$ = nullptr;
1204 }
1205 ;
1206
1207compound_statement:
1208 '{' '}'
1209 { $$ = new StatementNode( build_compound( yylloc, (StatementNode *)0 ) ); }
1210 | '{' push
1211 local_label_declaration_opt // GCC, local labels appear at start of block
1212 statement_decl_list // C99, intermix declarations and statements
1213 pop '}'
1214 { $$ = new StatementNode( build_compound( yylloc, $4 ) ); }
1215 ;
1216
1217statement_decl_list: // C99
1218 statement_decl
1219 | statement_decl_list statement_decl
1220 { assert( $1 ); $1->set_last( $2 ); $$ = $1; }
1221 ;
1222
1223statement_decl:
1224 declaration // CFA, new & old style declarations
1225 { $$ = new StatementNode( $1 ); }
1226 | EXTENSION declaration // GCC
1227 { distExt( $2 ); $$ = new StatementNode( $2 ); }
1228 | function_definition
1229 { $$ = new StatementNode( $1 ); }
1230 | EXTENSION function_definition // GCC
1231 { distExt( $2 ); $$ = new StatementNode( $2 ); }
1232 | statement
1233 ;
1234
1235statement_list_nodecl:
1236 statement
1237 | statement_list_nodecl statement
1238 { assert( $1 ); $1->set_last( $2 ); $$ = $1; }
1239 | statement_list_nodecl error // invalid syntax rule
1240 { SemanticError( yylloc, "syntax error, declarations only allowed at the start of the switch body, i.e., after the '{'." ); $$ = nullptr; }
1241 ;
1242
1243expression_statement:
1244 comma_expression_opt ';'
1245 { $$ = new StatementNode( build_expr( yylloc, $1 ) ); }
1246 ;
1247
1248selection_statement:
1249 // pop causes a S/R conflict without separating the IF statement into a non-terminal even after resolving
1250 // the inherent S/R conflict with THEN/ELSE.
1251 push if_statement pop
1252 { $$ = $2; }
1253 | SWITCH '(' comma_expression ')' case_clause
1254 { $$ = new StatementNode( build_switch( yylloc, true, $3, $5 ) ); }
1255 | SWITCH '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt pop '}' // CFA
1256 {
1257 StatementNode *sw = new StatementNode( build_switch( yylloc, true, $3, $8 ) );
1258 // The semantics of the declaration list is changed to include associated initialization, which is performed
1259 // *before* the transfer to the appropriate case clause by hoisting the declarations into a compound
1260 // statement around the switch. Statements after the initial declaration list can never be executed, and
1261 // therefore, are removed from the grammar even though C allows it. The change also applies to choose
1262 // statement.
1263 $$ = $7 ? new StatementNode( build_compound( yylloc, (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
1264 }
1265 | SWITCH '(' comma_expression ')' '{' error '}' // CFA, invalid syntax rule error
1266 { SemanticError( yylloc, "synatx error, declarations can only appear before the list of case clauses." ); $$ = nullptr; }
1267 | CHOOSE '(' comma_expression ')' case_clause // CFA
1268 { $$ = new StatementNode( build_switch( yylloc, false, $3, $5 ) ); }
1269 | CHOOSE '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt pop '}' // CFA
1270 {
1271 StatementNode *sw = new StatementNode( build_switch( yylloc, false, $3, $8 ) );
1272 $$ = $7 ? new StatementNode( build_compound( yylloc, (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
1273 }
1274 | CHOOSE '(' comma_expression ')' '{' error '}' // CFA, invalid syntax rule
1275 { SemanticError( yylloc, "syntax error, declarations can only appear before the list of case clauses." ); $$ = nullptr; }
1276 ;
1277
1278if_statement:
1279 IF '(' conditional_declaration ')' statement %prec THEN
1280 // explicitly deal with the shift/reduce conflict on if/else
1281 { $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), nullptr ) ); }
1282 | IF '(' conditional_declaration ')' statement ELSE statement
1283 { $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), maybe_build_compound( yylloc, $7 ) ) ); }
1284 ;
1285
1286conditional_declaration:
1287 comma_expression
1288 { $$ = new CondCtl( nullptr, $1 ); }
1289 | c_declaration // no semi-colon
1290 { $$ = new CondCtl( $1, nullptr ); }
1291 | cfa_declaration // no semi-colon
1292 { $$ = new CondCtl( $1, nullptr ); }
1293 | declaration comma_expression // semi-colon separated
1294 { $$ = new CondCtl( $1, $2 ); }
1295 ;
1296
1297// CASE and DEFAULT clauses are only allowed in the SWITCH statement, precluding Duff's device. In addition, a case
1298// clause allows a list of values and subranges.
1299
1300case_value: // CFA
1301 constant_expression { $$ = $1; }
1302 | constant_expression ELLIPSIS constant_expression // GCC, subrange
1303 { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
1304 | subrange // CFA, subrange
1305 ;
1306
1307case_value_list: // CFA
1308 case_value { $$ = new ClauseNode( build_case( yylloc, $1 ) ); }
1309 // convert case list, e.g., "case 1, 3, 5:" into "case 1: case 3: case 5"
1310 | case_value_list ',' case_value { $$ = $1->set_last( new ClauseNode( build_case( yylloc, $3 ) ) ); }
1311 ;
1312
1313case_label: // CFA
1314 CASE error // invalid syntax rule
1315 { SemanticError( yylloc, "syntax error, case list missing after case." ); $$ = nullptr; }
1316 | CASE case_value_list ':' { $$ = $2; }
1317 | CASE case_value_list error // invalid syntax rule
1318 { SemanticError( yylloc, "syntax error, colon missing after case list." ); $$ = nullptr; }
1319 | DEFAULT ':' { $$ = new ClauseNode( build_default( yylloc ) ); }
1320 // A semantic check is required to ensure only one default clause per switch/choose statement.
1321 | DEFAULT error // invalid syntax rule
1322 { SemanticError( yylloc, "syntax error, colon missing after default." ); $$ = nullptr; }
1323 ;
1324
1325case_label_list: // CFA
1326 case_label
1327 | case_label_list case_label { $$ = $1->set_last( $2 ); }
1328 ;
1329
1330case_clause: // CFA
1331 case_label_list statement { $$ = $1->append_last_case( maybe_build_compound( yylloc, $2 ) ); }
1332 ;
1333
1334switch_clause_list_opt: // CFA
1335 // empty
1336 { $$ = nullptr; }
1337 | switch_clause_list
1338 ;
1339
1340switch_clause_list: // CFA
1341 case_label_list statement_list_nodecl
1342 { $$ = $1->append_last_case( new StatementNode( build_compound( yylloc, $2 ) ) ); }
1343 | switch_clause_list case_label_list statement_list_nodecl
1344 { $$ = $1->set_last( $2->append_last_case( new StatementNode( build_compound( yylloc, $3 ) ) ) ); }
1345 ;
1346
1347iteration_statement:
1348 WHILE '(' ')' statement %prec THEN // CFA => while ( 1 )
1349 { $$ = new StatementNode( build_while( yylloc, new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( yylloc, $4 ) ) ); }
1350 | WHILE '(' ')' statement ELSE statement // CFA
1351 {
1352 $$ = new StatementNode( build_while( yylloc, new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( yylloc, $4 ) ) );
1353 SemanticWarning( yylloc, Warning::SuperfluousElse );
1354 }
1355 | WHILE '(' conditional_declaration ')' statement %prec THEN
1356 { $$ = new StatementNode( build_while( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); }
1357 | WHILE '(' conditional_declaration ')' statement ELSE statement // CFA
1358 { $$ = new StatementNode( build_while( yylloc, $3, maybe_build_compound( yylloc, $5 ), $7 ) ); }
1359 | DO statement WHILE '(' ')' ';' // CFA => do while( 1 )
1360 { $$ = new StatementNode( build_do_while( yylloc, NEW_ONE, maybe_build_compound( yylloc, $2 ) ) ); }
1361 | DO statement WHILE '(' ')' ELSE statement // CFA
1362 {
1363 $$ = new StatementNode( build_do_while( yylloc, NEW_ONE, maybe_build_compound( yylloc, $2 ) ) );
1364 SemanticWarning( yylloc, Warning::SuperfluousElse );
1365 }
1366 | DO statement WHILE '(' comma_expression ')' ';'
1367 { $$ = new StatementNode( build_do_while( yylloc, $5, maybe_build_compound( yylloc, $2 ) ) ); }
1368 | DO statement WHILE '(' comma_expression ')' ELSE statement // CFA
1369 { $$ = new StatementNode( build_do_while( yylloc, $5, maybe_build_compound( yylloc, $2 ), $8 ) ); }
1370 | FOR '(' ')' statement %prec THEN // CFA => for ( ;; )
1371 { $$ = new StatementNode( build_for( yylloc, new ForCtrl( nullptr, nullptr, nullptr ), maybe_build_compound( yylloc, $4 ) ) ); }
1372 | FOR '(' ')' statement ELSE statement // CFA
1373 {
1374 $$ = new StatementNode( build_for( yylloc, new ForCtrl( nullptr, nullptr, nullptr ), maybe_build_compound( yylloc, $4 ) ) );
1375 SemanticWarning( yylloc, Warning::SuperfluousElse );
1376 }
1377 | FOR '(' for_control_expression_list ')' statement %prec THEN
1378 { $$ = new StatementNode( build_for( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); }
1379 | FOR '(' for_control_expression_list ')' statement ELSE statement // CFA
1380 { $$ = new StatementNode( build_for( yylloc, $3, maybe_build_compound( yylloc, $5 ), $7 ) ); }
1381 ;
1382
1383for_control_expression_list:
1384 for_control_expression
1385 | for_control_expression_list ':' for_control_expression
1386 // ForCtrl + ForCtrl:
1387 // init + init => multiple declaration statements that are hoisted
1388 // condition + condition => (expression) && (expression)
1389 // change + change => (expression), (expression)
1390 {
1391 $1->init->set_last( $3->init );
1392 if ( $1->condition ) {
1393 if ( $3->condition ) {
1394 $1->condition->expr.reset( new ast::LogicalExpr( yylloc, $1->condition->expr.release(), $3->condition->expr.release(), ast::AndExpr ) );
1395 } // if
1396 } else $1->condition = $3->condition;
1397 if ( $1->change ) {
1398 if ( $3->change ) {
1399 $1->change->expr.reset( new ast::CommaExpr( yylloc, $1->change->expr.release(), $3->change->expr.release() ) );
1400 } // if
1401 } else $1->change = $3->change;
1402 $$ = $1;
1403 }
1404 ;
1405
1406for_control_expression:
1407 ';' comma_expression_opt ';' comma_expression_opt
1408 { $$ = new ForCtrl( nullptr, $2, $4 ); }
1409 | comma_expression ';' comma_expression_opt ';' comma_expression_opt
1410 {
1411 StatementNode * init = $1 ? new StatementNode( new ast::ExprStmt( yylloc, maybeMoveBuild( $1 ) ) ) : nullptr;
1412 $$ = new ForCtrl( init, $3, $5 );
1413 }
1414 | declaration comma_expression_opt ';' comma_expression_opt // C99, declaration has ';'
1415 { $$ = new ForCtrl( new StatementNode( $1 ), $2, $4 ); }
1416
1417 | '@' ';' comma_expression // CFA, empty loop-index
1418 { $$ = new ForCtrl( nullptr, $3, nullptr ); }
1419 | '@' ';' comma_expression ';' comma_expression // CFA, empty loop-index
1420 { $$ = new ForCtrl( nullptr, $3, $5 ); }
1421
1422 | comma_expression // CFA, anonymous loop-index
1423 { $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), NEW_ZERO, OperKinds::LThan, $1->clone(), NEW_ONE ); }
1424 | downupdowneq comma_expression // CFA, anonymous loop-index
1425 { $$ = forCtrl( yylloc, $2, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $1, NEW_ZERO, $2->clone() ), $1, UPDOWN( $1, $2->clone(), NEW_ZERO ), NEW_ONE ); }
1426
1427 | comma_expression updowneq comma_expression // CFA, anonymous loop-index
1428 { $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), NEW_ONE ); }
1429 | '@' updowneq comma_expression // CFA, anonymous loop-index
1430 {
1431 if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
1432 else $$ = forCtrl( yylloc, $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, NEW_ONE );
1433 }
1434 | comma_expression updowneq '@' // CFA, anonymous loop-index
1435 {
1436 if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; }
1437 else { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
1438 }
1439 | comma_expression updowneq comma_expression '~' comma_expression // CFA, anonymous loop-index
1440 { $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), $5 ); }
1441 | '@' updowneq comma_expression '~' comma_expression // CFA, anonymous loop-index
1442 {
1443 if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
1444 else $$ = forCtrl( yylloc, $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, $5 );
1445 }
1446 | comma_expression updowneq '@' '~' comma_expression // CFA, anonymous loop-index
1447 {
1448 if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; }
1449 else { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
1450 }
1451 | comma_expression updowneq comma_expression '~' '@' // CFA, invalid syntax rule
1452 { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; }
1453 | '@' updowneq '@' // CFA, invalid syntax rule
1454 { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; }
1455 | '@' updowneq comma_expression '~' '@' // CFA, invalid syntax rule
1456 { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; }
1457 | comma_expression updowneq '@' '~' '@' // CFA, invalid syntax rule
1458 { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; }
1459 | '@' updowneq '@' '~' '@' // CFA, invalid syntax rule
1460 { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; }
1461
1462 | comma_expression ';' comma_expression // CFA
1463 { $$ = forCtrl( yylloc, $3, $1, NEW_ZERO, OperKinds::LThan, $3->clone(), NEW_ONE ); }
1464 | comma_expression ';' downupdowneq comma_expression // CFA
1465 { $$ = forCtrl( yylloc, $4, $1, UPDOWN( $3, NEW_ZERO, $4->clone() ), $3, UPDOWN( $3, $4->clone(), NEW_ZERO ), NEW_ONE ); }
1466
1467 | comma_expression ';' comma_expression updowneq comma_expression // CFA
1468 { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), NEW_ONE ); }
1469 | comma_expression ';' '@' updowneq comma_expression // CFA
1470 {
1471 if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
1472 else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, NEW_ONE );
1473 }
1474 | comma_expression ';' comma_expression updowneq '@' // CFA
1475 {
1476 if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
1477 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "syntax error, equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
1478 else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, NEW_ONE );
1479 }
1480 | comma_expression ';' '@' updowneq '@' // CFA, invalid syntax rule
1481 { SemanticError( yylloc, "syntax error, missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; }
1482
1483 | comma_expression ';' comma_expression updowneq comma_expression '~' comma_expression // CFA
1484 { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), $7 ); }
1485 | comma_expression ';' '@' updowneq comma_expression '~' comma_expression // CFA, invalid syntax rule
1486 {
1487 if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
1488 else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, $7 );
1489 }
1490 | comma_expression ';' comma_expression updowneq '@' '~' comma_expression // CFA
1491 {
1492 if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
1493 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "syntax error, equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
1494 else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, $7 );
1495 }
1496 | comma_expression ';' comma_expression updowneq comma_expression '~' '@' // CFA
1497 { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), nullptr ); }
1498 | comma_expression ';' '@' updowneq comma_expression '~' '@' // CFA, invalid syntax rule
1499 {
1500 if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
1501 else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, nullptr );
1502 }
1503 | comma_expression ';' comma_expression updowneq '@' '~' '@' // CFA
1504 {
1505 if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
1506 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "syntax error, equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
1507 else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, nullptr );
1508 }
1509 | comma_expression ';' '@' updowneq '@' '~' '@' // CFA
1510 { SemanticError( yylloc, "syntax error, missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; }
1511
1512 | declaration comma_expression // CFA
1513 { $$ = forCtrl( yylloc, $1, NEW_ZERO, OperKinds::LThan, $2, NEW_ONE ); }
1514 | declaration downupdowneq comma_expression // CFA
1515 { $$ = forCtrl( yylloc, $1, UPDOWN( $2, NEW_ZERO, $3 ), $2, UPDOWN( $2, $3->clone(), NEW_ZERO ), NEW_ONE ); }
1516
1517 | declaration comma_expression updowneq comma_expression // CFA
1518 { $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2->clone(), $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), NEW_ONE ); }
1519 | declaration '@' updowneq comma_expression // CFA
1520 {
1521 if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
1522 else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, NEW_ONE );
1523 }
1524 | declaration comma_expression updowneq '@' // CFA
1525 {
1526 if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
1527 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "syntax error, equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
1528 else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, NEW_ONE );
1529 }
1530
1531 | declaration comma_expression updowneq comma_expression '~' comma_expression // CFA
1532 { $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), $6 ); }
1533 | declaration '@' updowneq comma_expression '~' comma_expression // CFA
1534 {
1535 if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
1536 else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, $6 );
1537 }
1538 | declaration comma_expression updowneq '@' '~' comma_expression // CFA
1539 {
1540 if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
1541 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "syntax error, equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
1542 else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, $6 );
1543 }
1544 | declaration comma_expression updowneq comma_expression '~' '@' // CFA
1545 { $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), nullptr ); }
1546 | declaration '@' updowneq comma_expression '~' '@' // CFA
1547 {
1548 if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
1549 else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, nullptr );
1550 }
1551 | declaration comma_expression updowneq '@' '~' '@' // CFA
1552 {
1553 if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
1554 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "syntax error, equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
1555 else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, nullptr );
1556 }
1557 | declaration '@' updowneq '@' '~' '@' // CFA, invalid syntax rule
1558 { SemanticError( yylloc, "syntax error, missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; }
1559
1560 | comma_expression ';' TYPEDEFname // CFA, array type
1561 {
1562 SemanticError( yylloc, "Type iterator is currently unimplemented." ); $$ = nullptr;
1563 //$$ = forCtrl( new ExpressionNode( build_varref( $3 ) ), $1, nullptr, OperKinds::Range, nullptr, nullptr );
1564 }
1565 | comma_expression ';' downupdowneq TYPEDEFname // CFA, array type
1566 {
1567 if ( $3 == OperKinds::LEThan || $3 == OperKinds::GEThan ) {
1568 SemanticError( yylloc, "syntax error, all enumeration ranges are equal (all values). Remove \"=~\"." ); $$ = nullptr;
1569 }
1570 SemanticError( yylloc, "Type iterator is currently unimplemented." ); $$ = nullptr;
1571 }
1572 ;
1573
1574downupdowneq:
1575 ErangeDown
1576 { $$ = OperKinds::GThan; }
1577 | ErangeUpEq
1578 { $$ = OperKinds::LEThan; }
1579 | ErangeDownEq
1580 { $$ = OperKinds::GEThan; }
1581 ;
1582
1583updown:
1584 '~'
1585 { $$ = OperKinds::LThan; }
1586 | ErangeDown
1587 { $$ = OperKinds::GThan; }
1588 ;
1589
1590updowneq:
1591 updown
1592 | ErangeUpEq
1593 { $$ = OperKinds::LEThan; }
1594 | ErangeDownEq
1595 { $$ = OperKinds::GEThan; }
1596 ;
1597
1598jump_statement:
1599 GOTO identifier_or_type_name ';'
1600 { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Goto ) ); }
1601 | GOTO '*' comma_expression ';' // GCC, computed goto
1602 // The syntax for the GCC computed goto violates normal expression precedence, e.g., goto *i+3; => goto *(i+3);
1603 // whereas normal operator precedence yields goto (*i)+3;
1604 { $$ = new StatementNode( build_computedgoto( $3 ) ); }
1605 // A semantic check is required to ensure fallthru appears only in the body of a choose statement.
1606 | fall_through_name ';' // CFA
1607 { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::FallThrough ) ); }
1608 | fall_through_name identifier_or_type_name ';' // CFA
1609 { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::FallThrough ) ); }
1610 | fall_through_name DEFAULT ';' // CFA
1611 { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::FallThroughDefault ) ); }
1612 | CONTINUE ';'
1613 // A semantic check is required to ensure this statement appears only in the body of an iteration statement.
1614 { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::Continue ) ); }
1615 | CONTINUE identifier_or_type_name ';' // CFA, multi-level continue
1616 // A semantic check is required to ensure this statement appears only in the body of an iteration statement, and
1617 // the target of the transfer appears only at the start of an iteration statement.
1618 { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Continue ) ); }
1619 | BREAK ';'
1620 // A semantic check is required to ensure this statement appears only in the body of an iteration statement.
1621 { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::Break ) ); }
1622 | BREAK identifier_or_type_name ';' // CFA, multi-level exit
1623 // A semantic check is required to ensure this statement appears only in the body of an iteration statement, and
1624 // the target of the transfer appears only at the start of an iteration statement.
1625 { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Break ) ); }
1626 | RETURN comma_expression_opt ';'
1627 { $$ = new StatementNode( build_return( yylloc, $2 ) ); }
1628 | RETURN '{' initializer_list_opt comma_opt '}' ';'
1629 { SemanticError( yylloc, "Initializer return is currently unimplemented." ); $$ = nullptr; }
1630 | SUSPEND ';'
1631 { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::None ) ); }
1632 | SUSPEND compound_statement
1633 { $$ = new StatementNode( build_suspend( yylloc, $2, ast::SuspendStmt::None ) ); }
1634 | SUSPEND COROUTINE ';'
1635 { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::Coroutine ) ); }
1636 | SUSPEND COROUTINE compound_statement
1637 { $$ = new StatementNode( build_suspend( yylloc, $3, ast::SuspendStmt::Coroutine ) ); }
1638 | SUSPEND GENERATOR ';'
1639 { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::Generator ) ); }
1640 | SUSPEND GENERATOR compound_statement
1641 { $$ = new StatementNode( build_suspend( yylloc, $3, ast::SuspendStmt::Generator ) ); }
1642 | THROW assignment_expression_opt ';' // handles rethrow
1643 { $$ = new StatementNode( build_throw( yylloc, $2 ) ); }
1644 | THROWRESUME assignment_expression_opt ';' // handles reresume
1645 { $$ = new StatementNode( build_resume( yylloc, $2 ) ); }
1646 | THROWRESUME assignment_expression_opt AT assignment_expression ';' // handles reresume
1647 { $$ = new StatementNode( build_resume_at( $2, $4 ) ); }
1648 ;
1649
1650fall_through_name: // CFA
1651 FALLTHRU
1652 | FALLTHROUGH
1653 ;
1654
1655with_statement:
1656 WITH '(' tuple_expression_list ')' statement
1657 { $$ = new StatementNode( build_with( yylloc, $3, $5 ) ); }
1658 ;
1659
1660// If MUTEX becomes a general qualifier, there are shift/reduce conflicts, so possibly change syntax to "with mutex".
1661mutex_statement:
1662 MUTEX '(' argument_expression_list_opt ')' statement
1663 {
1664 if ( ! $3 ) { SemanticError( yylloc, "syntax error, mutex argument list cannot be empty." ); $$ = nullptr; }
1665 $$ = new StatementNode( build_mutex( yylloc, $3, $5 ) );
1666 }
1667 ;
1668
1669when_clause:
1670 WHEN '(' comma_expression ')' { $$ = $3; }
1671 ;
1672
1673when_clause_opt:
1674 // empty
1675 { $$ = nullptr; }
1676 | when_clause
1677 ;
1678
1679cast_expression_list:
1680 cast_expression
1681 | cast_expression_list ',' cast_expression
1682 // { $$ = (ExpressionNode *)($1->set_last( $3 )); }
1683 { SemanticError( yylloc, "List of mutex member is currently unimplemented." ); $$ = nullptr; }
1684 ;
1685
1686timeout:
1687 TIMEOUT '(' comma_expression ')' { $$ = $3; }
1688 ;
1689
1690wor:
1691 OROR
1692 | WOR
1693
1694waitfor:
1695 WAITFOR '(' cast_expression ')'
1696 { $$ = $3; }
1697 | WAITFOR '(' cast_expression_list ':' argument_expression_list_opt ')'
1698 { $$ = (ExpressionNode *)($3->set_last( $5 )); }
1699 ;
1700
1701wor_waitfor_clause:
1702 when_clause_opt waitfor statement %prec THEN
1703 // Called first: create header for WaitForStmt.
1704 { $$ = build_waitfor( yylloc, new ast::WaitForStmt( yylloc ), $1, $2, maybe_build_compound( yylloc, $3 ) ); }
1705 | wor_waitfor_clause wor when_clause_opt waitfor statement
1706 { $$ = build_waitfor( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ); }
1707 | wor_waitfor_clause wor when_clause_opt ELSE statement
1708 { $$ = build_waitfor_else( yylloc, $1, $3, maybe_build_compound( yylloc, $5 ) ); }
1709 | wor_waitfor_clause wor when_clause_opt timeout statement %prec THEN
1710 { $$ = build_waitfor_timeout( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ); }
1711 // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
1712 | wor_waitfor_clause wor when_clause_opt timeout statement wor ELSE statement // invalid syntax rule
1713 { SemanticError( yylloc, "syntax error, else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
1714 | wor_waitfor_clause wor when_clause_opt timeout statement wor when_clause ELSE statement
1715 { $$ = build_waitfor_else( yylloc, build_waitfor_timeout( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ), $7, maybe_build_compound( yylloc, $9 ) ); }
1716 ;
1717
1718waitfor_statement:
1719 wor_waitfor_clause %prec THEN
1720 { $$ = new StatementNode( $1 ); }
1721 ;
1722
1723wand:
1724 ANDAND
1725 | WAND
1726 ;
1727
1728waituntil:
1729 WAITUNTIL '(' comma_expression ')'
1730 { $$ = $3; }
1731 ;
1732
1733waituntil_clause:
1734 when_clause_opt waituntil statement
1735 { $$ = build_waituntil_clause( yylloc, $1, $2, maybe_build_compound( yylloc, $3 ) ); }
1736 | '(' wor_waituntil_clause ')'
1737 { $$ = $2; }
1738 ;
1739
1740wand_waituntil_clause:
1741 waituntil_clause %prec THEN
1742 { $$ = $1; }
1743 | waituntil_clause wand wand_waituntil_clause
1744 { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::AND, $1, $3 ); }
1745 ;
1746
1747wor_waituntil_clause:
1748 wand_waituntil_clause
1749 { $$ = $1; }
1750 | wor_waituntil_clause wor wand_waituntil_clause
1751 { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::OR, $1, $3 ); }
1752 | wor_waituntil_clause wor when_clause_opt ELSE statement
1753 { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1, build_waituntil_else( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); }
1754 ;
1755
1756waituntil_statement:
1757 wor_waituntil_clause %prec THEN
1758 { $$ = new StatementNode( build_waituntil_stmt( yylloc, $1 ) ); }
1759 ;
1760
1761corun_statement:
1762 CORUN statement
1763 { $$ = new StatementNode( build_corun( yylloc, $2 ) ); }
1764 ;
1765
1766cofor_statement:
1767 COFOR '(' for_control_expression_list ')' statement
1768 { $$ = new StatementNode( build_cofor( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); }
1769 ;
1770
1771exception_statement:
1772 TRY compound_statement handler_clause %prec THEN
1773 { $$ = new StatementNode( build_try( yylloc, $2, $3, nullptr ) ); }
1774 | TRY compound_statement finally_clause
1775 { $$ = new StatementNode( build_try( yylloc, $2, nullptr, $3 ) ); }
1776 | TRY compound_statement handler_clause finally_clause
1777 { $$ = new StatementNode( build_try( yylloc, $2, $3, $4 ) ); }
1778 ;
1779
1780handler_clause:
1781 handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement
1782 { $$ = new ClauseNode( build_catch( yylloc, $1, $4, $6, $8 ) ); }
1783 | handler_clause handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement
1784 { $$ = $1->set_last( new ClauseNode( build_catch( yylloc, $2, $5, $7, $9 ) ) ); }
1785 ;
1786
1787handler_predicate_opt:
1788 // empty
1789 { $$ = nullptr; }
1790 | ';' conditional_expression { $$ = $2; }
1791 ;
1792
1793handler_key:
1794 CATCH { $$ = ast::Terminate; }
1795 | RECOVER { $$ = ast::Terminate; }
1796 | CATCHRESUME { $$ = ast::Resume; }
1797 | FIXUP { $$ = ast::Resume; }
1798 ;
1799
1800finally_clause:
1801 FINALLY compound_statement { $$ = new ClauseNode( build_finally( yylloc, $2 ) ); }
1802 ;
1803
1804exception_declaration:
1805 // No SUE declaration in parameter list.
1806 type_specifier_nobody
1807 | type_specifier_nobody declarator
1808 { $$ = $2->addType( $1 ); }
1809 | type_specifier_nobody variable_abstract_declarator
1810 { $$ = $2->addType( $1 ); }
1811 | cfa_abstract_declarator_tuple identifier // CFA
1812 { $$ = $1->addName( $2 ); }
1813 | cfa_abstract_declarator_tuple // CFA
1814 ;
1815
1816enable_disable_statement:
1817 enable_disable_key identifier_list compound_statement
1818 ;
1819
1820enable_disable_key:
1821 ENABLE
1822 | DISABLE
1823 ;
1824
1825asm_statement:
1826 ASM asm_volatile_opt '(' string_literal ')' ';'
1827 { $$ = new StatementNode( build_asm( yylloc, $2, $4, nullptr ) ); }
1828 | ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ')' ';' // remaining GCC
1829 { $$ = new StatementNode( build_asm( yylloc, $2, $4, $6 ) ); }
1830 | ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ':' asm_operands_opt ')' ';'
1831 { $$ = new StatementNode( build_asm( yylloc, $2, $4, $6, $8 ) ); }
1832 | ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ':' asm_operands_opt ':' asm_clobbers_list_opt ')' ';'
1833 { $$ = new StatementNode( build_asm( yylloc, $2, $4, $6, $8, $10 ) ); }
1834 | ASM asm_volatile_opt GOTO '(' string_literal ':' ':' asm_operands_opt ':' asm_clobbers_list_opt ':' label_list ')' ';'
1835 { $$ = new StatementNode( build_asm( yylloc, $2, $5, nullptr, $8, $10, $12 ) ); }
1836 ;
1837
1838asm_volatile_opt: // GCC
1839 // empty
1840 { $$ = false; }
1841 | VOLATILE
1842 { $$ = true; }
1843 ;
1844
1845asm_operands_opt: // GCC
1846 // empty
1847 { $$ = nullptr; } // use default argument
1848 | asm_operands_list
1849 ;
1850
1851asm_operands_list: // GCC
1852 asm_operand
1853 | asm_operands_list ',' asm_operand
1854 { $$ = (ExpressionNode *)($1->set_last( $3 )); }
1855 ;
1856
1857asm_operand: // GCC
1858 string_literal '(' constant_expression ')'
1859 { $$ = new ExpressionNode( new ast::AsmExpr( yylloc, "", maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
1860 | '[' IDENTIFIER ']' string_literal '(' constant_expression ')'
1861 {
1862 $$ = new ExpressionNode( new ast::AsmExpr( yylloc, *$2.str, maybeMoveBuild( $4 ), maybeMoveBuild( $6 ) ) );
1863 delete $2.str;
1864 }
1865 ;
1866
1867asm_clobbers_list_opt: // GCC
1868 // empty
1869 { $$ = nullptr; } // use default argument
1870 | string_literal
1871 { $$ = $1; }
1872 | asm_clobbers_list_opt ',' string_literal
1873 { $$ = (ExpressionNode *)( $1->set_last( $3 ) ); }
1874 ;
1875
1876label_list:
1877 identifier
1878 {
1879 $$ = new LabelNode(); $$->labels.emplace_back( yylloc, *$1 );
1880 delete $1; // allocated by lexer
1881 }
1882 | label_list ',' identifier
1883 {
1884 $$ = $1; $1->labels.emplace_back( yylloc, *$3 );
1885 delete $3; // allocated by lexer
1886 }
1887 ;
1888
1889// ****************************** DECLARATIONS *********************************
1890
1891declaration_list_opt: // used at beginning of switch statement
1892 // empty
1893 { $$ = nullptr; }
1894 | declaration_list
1895 ;
1896
1897declaration_list:
1898 declaration
1899 | declaration_list declaration { $$ = $1->set_last( $2 ); }
1900 ;
1901
1902KR_parameter_list_opt: // used to declare parameter types in K&R style functions
1903 // empty
1904 { $$ = nullptr; }
1905 | KR_parameter_list
1906 ;
1907
1908KR_parameter_list:
1909 c_declaration ';'
1910 { $$ = $1; }
1911 | KR_parameter_list c_declaration ';'
1912 { $$ = $1->set_last( $2 ); }
1913 ;
1914
1915local_label_declaration_opt: // GCC, local label
1916 // empty
1917 | local_label_declaration_list
1918 ;
1919
1920local_label_declaration_list: // GCC, local label
1921 LABEL local_label_list ';'
1922 | local_label_declaration_list LABEL local_label_list ';'
1923 ;
1924
1925local_label_list: // GCC, local label
1926 identifier_or_type_name
1927 | local_label_list ',' identifier_or_type_name
1928 ;
1929
1930declaration: // old & new style declarations
1931 c_declaration ';'
1932 | cfa_declaration ';' // CFA
1933 | static_assert // C11
1934 ;
1935
1936static_assert:
1937 STATICASSERT '(' constant_expression ',' string_literal ')' ';' // C11
1938 { $$ = DeclarationNode::newStaticAssert( $3, maybeMoveBuild( $5 ) ); }
1939 | STATICASSERT '(' constant_expression ')' ';' // CFA
1940 { $$ = DeclarationNode::newStaticAssert( $3, build_constantStr( yylloc, *new string( "\"\"" ) ) ); }
1941
1942// C declaration syntax is notoriously confusing and error prone. Cforall provides its own type, variable and function
1943// declarations. CFA declarations use the same declaration tokens as in C; however, CFA places declaration modifiers to
1944// the left of the base type, while C declarations place modifiers to the right of the base type. CFA declaration
1945// modifiers are interpreted from left to right and the entire type specification is distributed across all variables in
1946// the declaration list (as in Pascal). ANSI C and the new CFA declarations may appear together in the same program
1947// block, but cannot be mixed within a specific declaration.
1948//
1949// CFA C
1950// [10] int x; int x[10]; // array of 10 integers
1951// [10] * char y; char *y[10]; // array of 10 pointers to char
1952
1953cfa_declaration: // CFA
1954 cfa_variable_declaration
1955 | cfa_typedef_declaration
1956 | cfa_function_declaration
1957 | type_declaring_list
1958 { SemanticError( yylloc, "otype declaration is currently unimplemented." ); $$ = nullptr; }
1959 | trait_specifier
1960 ;
1961
1962cfa_variable_declaration: // CFA
1963 cfa_variable_specifier initializer_opt
1964 { $$ = $1->addInitializer( $2 ); }
1965 | declaration_qualifier_list cfa_variable_specifier initializer_opt
1966 // declaration_qualifier_list also includes type_qualifier_list, so a semantic check is necessary to preclude
1967 // them as a type_qualifier cannot appear in that context.
1968 { $$ = $2->addQualifiers( $1 )->addInitializer( $3 ); }
1969 | cfa_variable_declaration pop ',' push identifier_or_type_name initializer_opt
1970 { $$ = $1->set_last( $1->cloneType( $5 )->addInitializer( $6 ) ); }
1971 ;
1972
1973cfa_variable_specifier: // CFA
1974 // A semantic check is required to ensure asm_name only appears on declarations with implicit or explicit static
1975 // storage-class
1976 cfa_abstract_declarator_no_tuple identifier_or_type_name asm_name_opt
1977 { $$ = $1->addName( $2 )->addAsmName( $3 ); }
1978 | cfa_abstract_tuple identifier_or_type_name asm_name_opt
1979 { $$ = $1->addName( $2 )->addAsmName( $3 ); }
1980 | type_qualifier_list cfa_abstract_tuple identifier_or_type_name asm_name_opt
1981 { $$ = $2->addQualifiers( $1 )->addName( $3 )->addAsmName( $4 ); }
1982 ;
1983
1984cfa_function_declaration: // CFA
1985 cfa_function_specifier
1986 | type_qualifier_list cfa_function_specifier
1987 { $$ = $2->addQualifiers( $1 ); }
1988 | declaration_qualifier_list cfa_function_specifier
1989 { $$ = $2->addQualifiers( $1 ); }
1990 | declaration_qualifier_list type_qualifier_list cfa_function_specifier
1991 { $$ = $3->addQualifiers( $1 )->addQualifiers( $2 ); }
1992 | cfa_function_declaration ',' identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')'
1993 {
1994 // Append the return type at the start (left-hand-side) to each identifier in the list.
1995 DeclarationNode * ret = new DeclarationNode;
1996 ret->type = maybeCopy( $1->type->base );
1997 $$ = $1->set_last( DeclarationNode::newFunction( $3, ret, $6, nullptr ) );
1998 }
1999 ;
2000
2001cfa_function_specifier: // CFA
2002// '[' ']' identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' // S/R conflict
2003// {
2004// $$ = DeclarationNode::newFunction( $3, DeclarationNode::newTuple( 0 ), $6, nullptr, true );
2005// }
2006// '[' ']' identifier '(' push cfa_parameter_ellipsis_list_opt pop ')'
2007// {
2008// typedefTable.setNextIdentifier( *$5 );
2009// $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, nullptr, true );
2010// }
2011// | '[' ']' TYPEDEFname '(' push cfa_parameter_ellipsis_list_opt pop ')'
2012// {
2013// typedefTable.setNextIdentifier( *$5 );
2014// $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, nullptr, true );
2015// }
2016// | '[' ']' typegen_name
2017 // identifier_or_type_name must be broken apart because of the sequence:
2018 //
2019 // '[' ']' identifier_or_type_name '(' cfa_parameter_ellipsis_list_opt ')'
2020 // '[' ']' type_specifier
2021 //
2022 // type_specifier can resolve to just TYPEDEFname (e.g., typedef int T; int f( T );). Therefore this must be
2023 // flattened to allow lookahead to the '(' without having to reduce identifier_or_type_name.
2024 cfa_abstract_tuple identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' attribute_list_opt
2025 // To obtain LR(1 ), this rule must be factored out from function return type (see cfa_abstract_declarator).
2026 { $$ = DeclarationNode::newFunction( $2, $1, $5, nullptr )->addQualifiers( $8 ); }
2027 | cfa_function_return identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' attribute_list_opt
2028 { $$ = DeclarationNode::newFunction( $2, $1, $5, nullptr )->addQualifiers( $8 ); }
2029 ;
2030
2031cfa_function_return: // CFA
2032 '[' push cfa_parameter_list pop ']'
2033 { $$ = DeclarationNode::newTuple( $3 ); }
2034 | '[' push cfa_parameter_list pop ',' push cfa_abstract_parameter_list pop ']'
2035 // To obtain LR(1 ), the last cfa_abstract_parameter_list is added into this flattened rule to lookahead to the ']'.
2036 { $$ = DeclarationNode::newTuple( $3->set_last( $7 ) ); }
2037 ;
2038
2039cfa_typedef_declaration: // CFA
2040 TYPEDEF cfa_variable_specifier
2041 {
2042 typedefTable.addToEnclosingScope( *$2->name, TYPEDEFname, "cfa_typedef_declaration 1" );
2043 $$ = $2->addTypedef();
2044 }
2045 | TYPEDEF cfa_function_specifier
2046 {
2047 typedefTable.addToEnclosingScope( *$2->name, TYPEDEFname, "cfa_typedef_declaration 2" );
2048 $$ = $2->addTypedef();
2049 }
2050 | cfa_typedef_declaration pop ',' push identifier
2051 {
2052 typedefTable.addToEnclosingScope( *$5, TYPEDEFname, "cfa_typedef_declaration 3" );
2053 $$ = $1->set_last( $1->cloneType( $5 ) );
2054 }
2055 ;
2056
2057// Traditionally typedef is part of storage-class specifier for syntactic convenience only. Here, it is factored out as
2058// a separate form of declaration, which syntactically precludes storage-class specifiers and initialization.
2059
2060typedef_declaration:
2061 TYPEDEF type_specifier declarator
2062 {
2063 typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "typedef_declaration 1" );
2064 if ( $2->type->forall || ($2->type->kind == TypeData::Aggregate && $2->type->aggregate.params) ) {
2065 SemanticError( yylloc, "forall qualifier in typedef is currently unimplemented." ); $$ = nullptr;
2066 } else $$ = $3->addType( $2 )->addTypedef(); // watchout frees $2 and $3
2067 }
2068 | typedef_declaration ',' declarator
2069 {
2070 typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "typedef_declaration 2" );
2071 $$ = $1->set_last( $1->cloneBaseType( $3 )->addTypedef() );
2072 }
2073 | type_qualifier_list TYPEDEF type_specifier declarator // remaining OBSOLESCENT (see 2 )
2074 { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; }
2075 | type_specifier TYPEDEF declarator
2076 { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; }
2077 | type_specifier TYPEDEF type_qualifier_list declarator
2078 { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; }
2079 ;
2080
2081typedef_expression:
2082 // deprecated GCC, naming expression type: typedef name = exp; gives a name to the type of an expression
2083 TYPEDEF identifier '=' assignment_expression
2084 {
2085 SemanticError( yylloc, "TYPEDEF expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
2086 }
2087 | typedef_expression ',' identifier '=' assignment_expression
2088 {
2089 SemanticError( yylloc, "TYPEDEF expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
2090 }
2091 ;
2092
2093c_declaration:
2094 declaration_specifier declaring_list
2095 { $$ = distAttr( $1, $2 ); }
2096 | typedef_declaration
2097 | typedef_expression // deprecated GCC, naming expression type
2098 | sue_declaration_specifier
2099 {
2100 assert( $1->type );
2101 if ( $1->type->qualifiers.any() ) { // CV qualifiers ?
2102 SemanticError( yylloc, "syntax error, useless type qualifier(s) in empty declaration." ); $$ = nullptr;
2103 }
2104 // enums are never empty declarations because there must have at least one enumeration.
2105 if ( $1->type->kind == TypeData::AggregateInst && $1->storageClasses.any() ) { // storage class ?
2106 SemanticError( yylloc, "syntax error, useless storage qualifier(s) in empty aggregate declaration." ); $$ = nullptr;
2107 }
2108 }
2109 ;
2110
2111declaring_list:
2112 // A semantic check is required to ensure asm_name only appears on declarations with implicit or explicit static
2113 // storage-class
2114 variable_declarator asm_name_opt initializer_opt
2115 { $$ = $1->addAsmName( $2 )->addInitializer( $3 ); }
2116 | variable_type_redeclarator asm_name_opt initializer_opt
2117 { $$ = $1->addAsmName( $2 )->addInitializer( $3 ); }
2118
2119 | general_function_declarator asm_name_opt
2120 { $$ = $1->addAsmName( $2 )->addInitializer( nullptr ); }
2121 | general_function_declarator asm_name_opt '=' VOID
2122 { $$ = $1->addAsmName( $2 )->addInitializer( new InitializerNode( true ) ); }
2123
2124 | declaring_list ',' attribute_list_opt declarator asm_name_opt initializer_opt
2125 { $$ = $1->set_last( $4->addQualifiers( $3 )->addAsmName( $5 )->addInitializer( $6 ) ); }
2126 ;
2127
2128general_function_declarator:
2129 function_type_redeclarator
2130 | function_declarator
2131 ;
2132
2133declaration_specifier: // type specifier + storage class
2134 basic_declaration_specifier
2135 | type_declaration_specifier
2136 | sue_declaration_specifier
2137 | sue_declaration_specifier invalid_types // invalid syntax rule
2138 {
2139 SemanticError( yylloc, "syntax error, expecting ';' at end of \"%s\" declaration.",
2140 $1->type->enumeration.name ? "enum" : ast::AggregateDecl::aggrString( $1->type->aggregate.kind ) );
2141 $$ = nullptr;
2142 }
2143 ;
2144
2145invalid_types:
2146 aggregate_key
2147 | basic_type_name
2148 | indirect_type
2149 ;
2150
2151declaration_specifier_nobody: // type specifier + storage class - {...}
2152 // Preclude SUE declarations in restricted scopes:
2153 //
2154 // int f( struct S { int i; } s1, Struct S s2 ) { struct S s3; ... }
2155 //
2156 // because it is impossible to call f due to name equivalence.
2157 basic_declaration_specifier
2158 | sue_declaration_specifier_nobody
2159 | type_declaration_specifier
2160 ;
2161
2162type_specifier: // type specifier
2163 basic_type_specifier
2164 | sue_type_specifier
2165 | type_type_specifier
2166 ;
2167
2168type_specifier_nobody: // type specifier - {...}
2169 // Preclude SUE declarations in restricted scopes:
2170 //
2171 // int f( struct S { int i; } s1, Struct S s2 ) { struct S s3; ... }
2172 //
2173 // because it is impossible to call f due to name equivalence.
2174 basic_type_specifier
2175 | sue_type_specifier_nobody
2176 | type_type_specifier
2177 ;
2178
2179type_qualifier_list_opt: // GCC, used in asm_statement
2180 // empty
2181 { $$ = nullptr; }
2182 | type_qualifier_list
2183 ;
2184
2185type_qualifier_list:
2186 // A semantic check is necessary to ensure a type qualifier is appropriate for the kind of declaration.
2187 //
2188 // ISO/IEC 9899:1999 Section 6.7.3(4 ) : If the same qualifier appears more than once in the same
2189 // specifier-qualifier-list, either directly or via one or more typedefs, the behavior is the same as if it
2190 // appeared only once.
2191 type_qualifier
2192 | type_qualifier_list type_qualifier
2193 { $$ = $1->addQualifiers( $2 ); }
2194 ;
2195
2196type_qualifier:
2197 type_qualifier_name
2198 | attribute // trick handles most attribute locations
2199 ;
2200
2201type_qualifier_name:
2202 CONST
2203 { $$ = DeclarationNode::newTypeQualifier( ast::CV::Const ); }
2204 | RESTRICT
2205 { $$ = DeclarationNode::newTypeQualifier( ast::CV::Restrict ); }
2206 | VOLATILE
2207 { $$ = DeclarationNode::newTypeQualifier( ast::CV::Volatile ); }
2208 | ATOMIC
2209 { $$ = DeclarationNode::newTypeQualifier( ast::CV::Atomic ); }
2210 | forall
2211 { $$ = DeclarationNode::newForall( $1 ); }
2212 ;
2213
2214forall:
2215 FORALL '(' type_parameter_list ')' // CFA
2216 { $$ = $3; }
2217 ;
2218
2219declaration_qualifier_list:
2220 storage_class_list
2221 | type_qualifier_list storage_class_list // remaining OBSOLESCENT (see 2 )
2222 { $$ = $1->addQualifiers( $2 ); }
2223 | declaration_qualifier_list type_qualifier_list storage_class_list
2224 { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
2225 ;
2226
2227storage_class_list:
2228 // A semantic check is necessary to ensure a storage class is appropriate for the kind of declaration and that
2229 // only one of each is specified, except for inline, which can appear with the others.
2230 //
2231 // ISO/IEC 9899:1999 Section 6.7.1(2) : At most, one storage-class specifier may be given in the declaration
2232 // specifiers in a declaration.
2233 storage_class
2234 | storage_class_list storage_class
2235 { $$ = $1->addQualifiers( $2 ); }
2236 ;
2237
2238storage_class:
2239 EXTERN
2240 { $$ = DeclarationNode::newStorageClass( ast::Storage::Extern ); }
2241 | STATIC
2242 { $$ = DeclarationNode::newStorageClass( ast::Storage::Static ); }
2243 | AUTO
2244 { $$ = DeclarationNode::newStorageClass( ast::Storage::Auto ); }
2245 | REGISTER
2246 { $$ = DeclarationNode::newStorageClass( ast::Storage::Register ); }
2247 | THREADLOCALGCC // GCC
2248 { $$ = DeclarationNode::newStorageClass( ast::Storage::ThreadLocalGcc ); }
2249 | THREADLOCALC11 // C11
2250 { $$ = DeclarationNode::newStorageClass( ast::Storage::ThreadLocalC11 ); }
2251 // Put function specifiers here to simplify parsing rules, but separate them semantically.
2252 | INLINE // C99
2253 { $$ = DeclarationNode::newFuncSpecifier( ast::Function::Inline ); }
2254 | FORTRAN // C99
2255 { $$ = DeclarationNode::newFuncSpecifier( ast::Function::Fortran ); }
2256 | NORETURN // C11
2257 { $$ = DeclarationNode::newFuncSpecifier( ast::Function::Noreturn ); }
2258 ;
2259
2260basic_type_name:
2261 VOID
2262 { $$ = DeclarationNode::newBasicType( DeclarationNode::Void ); }
2263 | BOOL // C99
2264 { $$ = DeclarationNode::newBasicType( DeclarationNode::Bool ); }
2265 | CHAR
2266 { $$ = DeclarationNode::newBasicType( DeclarationNode::Char ); }
2267 | INT
2268 { $$ = DeclarationNode::newBasicType( DeclarationNode::Int ); }
2269 | INT128
2270 { $$ = DeclarationNode::newBasicType( DeclarationNode::Int128 ); }
2271 | UINT128
2272 { $$ = DeclarationNode::newBasicType( DeclarationNode::Int128 )->addType( DeclarationNode::newSignedNess( DeclarationNode::Unsigned ) ); }
2273 | FLOAT
2274 { $$ = DeclarationNode::newBasicType( DeclarationNode::Float ); }
2275 | DOUBLE
2276 { $$ = DeclarationNode::newBasicType( DeclarationNode::Double ); }
2277 | uuFLOAT80
2278 { $$ = DeclarationNode::newBasicType( DeclarationNode::uuFloat80 ); }
2279 | uuFLOAT128
2280 { $$ = DeclarationNode::newBasicType( DeclarationNode::uuFloat128 ); }
2281 | uFLOAT16
2282 { $$ = DeclarationNode::newBasicType( DeclarationNode::uFloat16 ); }
2283 | uFLOAT32
2284 { $$ = DeclarationNode::newBasicType( DeclarationNode::uFloat32 ); }
2285 | uFLOAT32X
2286 { $$ = DeclarationNode::newBasicType( DeclarationNode::uFloat32x ); }
2287 | uFLOAT64
2288 { $$ = DeclarationNode::newBasicType( DeclarationNode::uFloat64 ); }
2289 | uFLOAT64X
2290 { $$ = DeclarationNode::newBasicType( DeclarationNode::uFloat64x ); }
2291 | uFLOAT128
2292 { $$ = DeclarationNode::newBasicType( DeclarationNode::uFloat128 ); }
2293 | DECIMAL32
2294 { SemanticError( yylloc, "_Decimal32 is currently unimplemented." ); $$ = nullptr; }
2295 | DECIMAL64
2296 { SemanticError( yylloc, "_Decimal64 is currently unimplemented." ); $$ = nullptr; }
2297 | DECIMAL128
2298 { SemanticError( yylloc, "_Decimal128 is currently unimplemented." ); $$ = nullptr; }
2299 | COMPLEX // C99
2300 { $$ = DeclarationNode::newComplexType( DeclarationNode::Complex ); }
2301 | IMAGINARY // C99
2302 { $$ = DeclarationNode::newComplexType( DeclarationNode::Imaginary ); }
2303 | SIGNED
2304 { $$ = DeclarationNode::newSignedNess( DeclarationNode::Signed ); }
2305 | UNSIGNED
2306 { $$ = DeclarationNode::newSignedNess( DeclarationNode::Unsigned ); }
2307 | SHORT
2308 { $$ = DeclarationNode::newLength( DeclarationNode::Short ); }
2309 | LONG
2310 { $$ = DeclarationNode::newLength( DeclarationNode::Long ); }
2311 | VA_LIST // GCC, __builtin_va_list
2312 { $$ = DeclarationNode::newBuiltinType( DeclarationNode::Valist ); }
2313 | AUTO_TYPE
2314 { $$ = DeclarationNode::newBuiltinType( DeclarationNode::AutoType ); }
2315 | vtable
2316 ;
2317
2318vtable_opt:
2319 // empty
2320 { $$ = nullptr; }
2321 | vtable
2322 ;
2323
2324vtable:
2325 VTABLE '(' type_name ')' default_opt
2326 { $$ = DeclarationNode::newVtableType( $3 ); }
2327 // { SemanticError( yylloc, "vtable is currently unimplemented." ); $$ = nullptr; }
2328 ;
2329
2330default_opt:
2331 // empty
2332 { $$ = nullptr; }
2333 | DEFAULT
2334 { SemanticError( yylloc, "vtable default is currently unimplemented." ); $$ = nullptr; }
2335 ;
2336
2337basic_declaration_specifier:
2338 // A semantic check is necessary for conflicting storage classes.
2339 basic_type_specifier
2340 | declaration_qualifier_list basic_type_specifier
2341 { $$ = $2->addQualifiers( $1 ); }
2342 | basic_declaration_specifier storage_class // remaining OBSOLESCENT (see 2)
2343 { $$ = $1->addQualifiers( $2 ); }
2344 | basic_declaration_specifier storage_class type_qualifier_list
2345 { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
2346 | basic_declaration_specifier storage_class basic_type_specifier
2347 { $$ = $3->addQualifiers( $2 )->addType( $1 ); }
2348 ;
2349
2350basic_type_specifier:
2351 direct_type
2352 // Cannot have type modifiers, e.g., short, long, etc.
2353 | type_qualifier_list_opt indirect_type type_qualifier_list_opt
2354 { $$ = $2->addQualifiers( $1 )->addQualifiers( $3 ); }
2355 ;
2356
2357direct_type:
2358 basic_type_name
2359 | type_qualifier_list basic_type_name
2360 { $$ = $2->addQualifiers( $1 ); }
2361 | direct_type type_qualifier
2362 { $$ = $1->addQualifiers( $2 ); }
2363 | direct_type basic_type_name
2364 { $$ = $1->addType( $2 ); }
2365 ;
2366
2367indirect_type:
2368 TYPEOF '(' type ')' // GCC: typeof( x ) y;
2369 { $$ = $3; }
2370 | TYPEOF '(' comma_expression ')' // GCC: typeof( a+b ) y;
2371 { $$ = DeclarationNode::newTypeof( $3 ); }
2372 | BASETYPEOF '(' type ')' // CFA: basetypeof( x ) y;
2373 { $$ = DeclarationNode::newTypeof( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ), true ); }
2374 | BASETYPEOF '(' comma_expression ')' // CFA: basetypeof( a+b ) y;
2375 { $$ = DeclarationNode::newTypeof( $3, true ); }
2376 | ZERO_T // CFA
2377 { $$ = DeclarationNode::newBuiltinType( DeclarationNode::Zero ); }
2378 | ONE_T // CFA
2379 { $$ = DeclarationNode::newBuiltinType( DeclarationNode::One ); }
2380 ;
2381
2382sue_declaration_specifier: // struct, union, enum + storage class + type specifier
2383 sue_type_specifier
2384 | declaration_qualifier_list sue_type_specifier
2385 { $$ = $2->addQualifiers( $1 ); }
2386 | sue_declaration_specifier storage_class // remaining OBSOLESCENT (see 2)
2387 { $$ = $1->addQualifiers( $2 ); }
2388 | sue_declaration_specifier storage_class type_qualifier_list
2389 { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
2390 ;
2391
2392sue_type_specifier: // struct, union, enum + type specifier
2393 elaborated_type
2394 | type_qualifier_list
2395 { if ( $1->type != nullptr && $1->type->forall ) forall = true; } // remember generic type
2396 elaborated_type
2397 { $$ = $3->addQualifiers( $1 ); }
2398 | sue_type_specifier type_qualifier
2399 {
2400 if ( $2->type != nullptr && $2->type->forall ) forall = true; // remember generic type
2401 $$ = $1->addQualifiers( $2 );
2402 }
2403 ;
2404
2405sue_declaration_specifier_nobody: // struct, union, enum - {...} + storage class + type specifier
2406 sue_type_specifier_nobody
2407 | declaration_qualifier_list sue_type_specifier_nobody
2408 { $$ = $2->addQualifiers( $1 ); }
2409 | sue_declaration_specifier_nobody storage_class // remaining OBSOLESCENT (see 2)
2410 { $$ = $1->addQualifiers( $2 ); }
2411 | sue_declaration_specifier_nobody storage_class type_qualifier_list
2412 { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
2413 ;
2414
2415sue_type_specifier_nobody: // struct, union, enum - {...} + type specifier
2416 elaborated_type_nobody
2417 | type_qualifier_list elaborated_type_nobody
2418 { $$ = $2->addQualifiers( $1 ); }
2419 | sue_type_specifier_nobody type_qualifier
2420 { $$ = $1->addQualifiers( $2 ); }
2421 ;
2422
2423type_declaration_specifier:
2424 type_type_specifier
2425 | declaration_qualifier_list type_type_specifier
2426 { $$ = $2->addQualifiers( $1 ); }
2427 | type_declaration_specifier storage_class // remaining OBSOLESCENT (see 2)
2428 { $$ = $1->addQualifiers( $2 ); }
2429 | type_declaration_specifier storage_class type_qualifier_list
2430 { $$ = $1->addQualifiers( $2 )->addQualifiers( $3 ); }
2431 ;
2432
2433type_type_specifier: // typedef types
2434 type_name
2435 | type_qualifier_list type_name
2436 { $$ = $2->addQualifiers( $1 ); }
2437 | type_type_specifier type_qualifier
2438 { $$ = $1->addQualifiers( $2 ); }
2439 ;
2440
2441type_name:
2442 TYPEDEFname
2443 { $$ = DeclarationNode::newFromTypedef( $1 ); }
2444 | '.' TYPEDEFname
2445 { $$ = DeclarationNode::newQualifiedType( DeclarationNode::newFromGlobalScope(), DeclarationNode::newFromTypedef( $2 ) ); }
2446 | type_name '.' TYPEDEFname
2447 { $$ = DeclarationNode::newQualifiedType( $1, DeclarationNode::newFromTypedef( $3 ) ); }
2448 | typegen_name
2449 | '.' typegen_name
2450 { $$ = DeclarationNode::newQualifiedType( DeclarationNode::newFromGlobalScope(), $2 ); }
2451 | type_name '.' typegen_name
2452 { $$ = DeclarationNode::newQualifiedType( $1, $3 ); }
2453 ;
2454
2455typegen_name: // CFA
2456 TYPEGENname
2457 { $$ = DeclarationNode::newFromTypeGen( $1, nullptr ); }
2458 | TYPEGENname '(' ')'
2459 { $$ = DeclarationNode::newFromTypeGen( $1, nullptr ); }
2460 | TYPEGENname '(' type_list ')'
2461 { $$ = DeclarationNode::newFromTypeGen( $1, $3 ); }
2462 ;
2463
2464elaborated_type: // struct, union, enum
2465 aggregate_type
2466 | enum_type
2467 ;
2468
2469elaborated_type_nobody: // struct, union, enum - {...}
2470 aggregate_type_nobody
2471 | enum_type_nobody
2472 ;
2473
2474aggregate_type: // struct, union
2475 aggregate_key attribute_list_opt
2476 { forall = false; } // reset
2477 '{' field_declaration_list_opt '}' type_parameters_opt
2478 { $$ = DeclarationNode::newAggregate( $1, nullptr, $7, $5, true )->addQualifiers( $2 ); }
2479 | aggregate_key attribute_list_opt identifier
2480 {
2481 typedefTable.makeTypedef( *$3, forall || typedefTable.getEnclForall() ? TYPEGENname : TYPEDEFname, "aggregate_type: 1" );
2482 forall = false; // reset
2483 }
2484 '{' field_declaration_list_opt '}' type_parameters_opt
2485 {
2486 $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 );
2487 }
2488 | aggregate_key attribute_list_opt TYPEDEFname // unqualified type name
2489 {
2490 typedefTable.makeTypedef( *$3, forall || typedefTable.getEnclForall() ? TYPEGENname : TYPEDEFname, "aggregate_type: 2" );
2491 forall = false; // reset
2492 }
2493 '{' field_declaration_list_opt '}' type_parameters_opt
2494 {
2495 DeclarationNode::newFromTypedef( $3 );
2496 $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 );
2497 }
2498 | aggregate_key attribute_list_opt TYPEGENname // unqualified type name
2499 {
2500 typedefTable.makeTypedef( *$3, forall || typedefTable.getEnclForall() ? TYPEGENname : TYPEDEFname, "aggregate_type: 3" );
2501 forall = false; // reset
2502 }
2503 '{' field_declaration_list_opt '}' type_parameters_opt
2504 {
2505 DeclarationNode::newFromTypeGen( $3, nullptr );
2506 $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 );
2507 }
2508 | aggregate_type_nobody
2509 ;
2510
2511type_parameters_opt:
2512 // empty
2513 { $$ = nullptr; } %prec '}'
2514 | '(' type_list ')'
2515 { $$ = $2; }
2516 ;
2517
2518aggregate_type_nobody: // struct, union - {...}
2519 aggregate_key attribute_list_opt identifier
2520 {
2521 typedefTable.makeTypedef( *$3, forall || typedefTable.getEnclForall() ? TYPEGENname : TYPEDEFname, "aggregate_type_nobody" );
2522 forall = false; // reset
2523 $$ = DeclarationNode::newAggregate( $1, $3, nullptr, nullptr, false )->addQualifiers( $2 );
2524 }
2525 | aggregate_key attribute_list_opt type_name
2526 {
2527 forall = false; // reset
2528 // Create new generic declaration with same name as previous forward declaration, where the IDENTIFIER is
2529 // switched to a TYPEGENname. Link any generic arguments from typegen_name to new generic declaration and
2530 // delete newFromTypeGen.
2531 if ( $3->type->kind == TypeData::SymbolicInst && ! $3->type->symbolic.isTypedef ) {
2532 $$ = $3->addQualifiers( $2 );
2533 } else {
2534 $$ = DeclarationNode::newAggregate( $1, $3->type->symbolic.name, $3->type->symbolic.actuals, nullptr, false )->addQualifiers( $2 );
2535 $3->type->symbolic.name = nullptr; // copied to $$
2536 $3->type->symbolic.actuals = nullptr;
2537 delete $3;
2538 }
2539 }
2540 ;
2541
2542aggregate_key:
2543 aggregate_data
2544 | aggregate_control
2545 ;
2546
2547aggregate_data:
2548 STRUCT vtable_opt
2549 { $$ = ast::AggregateDecl::Struct; }
2550 | UNION
2551 { $$ = ast::AggregateDecl::Union; }
2552 | EXCEPTION // CFA
2553 { $$ = ast::AggregateDecl::Exception; }
2554 // { SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = ast::AggregateDecl::NoAggregate; }
2555 ;
2556
2557aggregate_control: // CFA
2558 MONITOR
2559 { $$ = ast::AggregateDecl::Monitor; }
2560 | MUTEX STRUCT
2561 { $$ = ast::AggregateDecl::Monitor; }
2562 | GENERATOR
2563 { $$ = ast::AggregateDecl::Generator; }
2564 | MUTEX GENERATOR
2565 {
2566 SemanticError( yylloc, "monitor generator is currently unimplemented." );
2567 $$ = ast::AggregateDecl::NoAggregate;
2568 }
2569 | COROUTINE
2570 { $$ = ast::AggregateDecl::Coroutine; }
2571 | MUTEX COROUTINE
2572 {
2573 SemanticError( yylloc, "monitor coroutine is currently unimplemented." );
2574 $$ = ast::AggregateDecl::NoAggregate;
2575 }
2576 | THREAD
2577 { $$ = ast::AggregateDecl::Thread; }
2578 | MUTEX THREAD
2579 {
2580 SemanticError( yylloc, "monitor thread is currently unimplemented." );
2581 $$ = ast::AggregateDecl::NoAggregate;
2582 }
2583 ;
2584
2585field_declaration_list_opt:
2586 // empty
2587 { $$ = nullptr; }
2588 | field_declaration_list_opt field_declaration
2589 { $$ = $1 ? $1->set_last( $2 ) : $2; }
2590 ;
2591
2592field_declaration:
2593 type_specifier field_declaring_list_opt ';'
2594 {
2595 // printf( "type_specifier1 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
2596 $$ = fieldDecl( $1, $2 );
2597 // printf( "type_specifier2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
2598 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
2599 // printf( "\tattr %s\n", attr->name.c_str() );
2600 // } // for
2601 }
2602 | type_specifier field_declaring_list_opt '}' // invalid syntax rule
2603 {
2604 SemanticError( yylloc, "syntax error, expecting ';' at end of previous declaration." );
2605 $$ = nullptr;
2606 }
2607 | EXTENSION type_specifier field_declaring_list_opt ';' // GCC
2608 { $$ = fieldDecl( $2, $3 ); distExt( $$ ); }
2609 | STATIC type_specifier field_declaring_list_opt ';' // CFA
2610 { SemanticError( yylloc, "STATIC aggregate field qualifier currently unimplemented." ); $$ = nullptr; }
2611 | INLINE type_specifier field_abstract_list_opt ';' // CFA
2612 {
2613 if ( ! $3 ) { // field declarator ?
2614 $3 = DeclarationNode::newName( nullptr );
2615 } // if
2616 $3->inLine = true;
2617 $$ = distAttr( $2, $3 ); // mark all fields in list
2618 distInl( $3 );
2619 }
2620 | INLINE aggregate_control ';' // CFA
2621 { SemanticError( yylloc, "INLINE aggregate control currently unimplemented." ); $$ = nullptr; }
2622 | typedef_declaration ';' // CFA
2623 | cfa_field_declaring_list ';' // CFA, new style field declaration
2624 | EXTENSION cfa_field_declaring_list ';' // GCC
2625 { distExt( $2 ); $$ = $2; } // mark all fields in list
2626 | INLINE cfa_field_abstract_list ';' // CFA, new style field declaration
2627 { $$ = $2; } // mark all fields in list
2628 | cfa_typedef_declaration ';' // CFA
2629 | static_assert // C11
2630 ;
2631
2632field_declaring_list_opt:
2633 // empty
2634 { $$ = nullptr; }
2635 | field_declarator
2636 | field_declaring_list_opt ',' attribute_list_opt field_declarator
2637 { $$ = $1->set_last( $4->addQualifiers( $3 ) ); }
2638 ;
2639
2640field_declarator:
2641 bit_subrange_size // C special case, no field name
2642 { $$ = DeclarationNode::newBitfield( $1 ); }
2643 | variable_declarator bit_subrange_size_opt
2644 // A semantic check is required to ensure bit_subrange only appears on integral types.
2645 { $$ = $1->addBitfield( $2 ); }
2646 | variable_type_redeclarator bit_subrange_size_opt
2647 // A semantic check is required to ensure bit_subrange only appears on integral types.
2648 { $$ = $1->addBitfield( $2 ); }
2649 | function_type_redeclarator bit_subrange_size_opt
2650 // A semantic check is required to ensure bit_subrange only appears on integral types.
2651 { $$ = $1->addBitfield( $2 ); }
2652 ;
2653
2654field_abstract_list_opt:
2655 // empty
2656 { $$ = nullptr; }
2657 | field_abstract
2658 | field_abstract_list_opt ',' attribute_list_opt field_abstract
2659 { $$ = $1->set_last( $4->addQualifiers( $3 ) ); }
2660 ;
2661
2662field_abstract:
2663 // no bit fields
2664 variable_abstract_declarator
2665 ;
2666
2667cfa_field_declaring_list: // CFA, new style field declaration
2668 // bit-fields are handled by C declarations
2669 cfa_abstract_declarator_tuple identifier_or_type_name
2670 { $$ = $1->addName( $2 ); }
2671 | cfa_field_declaring_list ',' identifier_or_type_name
2672 { $$ = $1->set_last( $1->cloneType( $3 ) ); }
2673 ;
2674
2675cfa_field_abstract_list: // CFA, new style field declaration
2676 // bit-fields are handled by C declarations
2677 cfa_abstract_declarator_tuple
2678 | cfa_field_abstract_list ','
2679 { $$ = $1->set_last( $1->cloneType( 0 ) ); }
2680 ;
2681
2682bit_subrange_size_opt:
2683 // empty
2684 { $$ = nullptr; }
2685 | bit_subrange_size
2686 ;
2687
2688bit_subrange_size:
2689 ':' assignment_expression
2690 { $$ = $2; }
2691 ;
2692
2693enum_type:
2694 ENUM attribute_list_opt '{' enumerator_list comma_opt '}'
2695 { $$ = DeclarationNode::newEnum( nullptr, $4, true, false )->addQualifiers( $2 ); }
2696 | ENUM attribute_list_opt '!' '{' enumerator_list comma_opt '}' // invalid syntax rule
2697 { SemanticError( yylloc, "syntax error, hiding ('!') the enumerator names of an anonymous enumeration means the names are inaccessible." ); $$ = nullptr; }
2698 | ENUM attribute_list_opt identifier
2699 { typedefTable.makeTypedef( *$3, "enum_type 1" ); }
2700 hide_opt '{' enumerator_list comma_opt '}'
2701 { $$ = DeclarationNode::newEnum( $3, $7, true, false, nullptr, $5 )->addQualifiers( $2 ); }
2702 | ENUM attribute_list_opt typedef_name hide_opt '{' enumerator_list comma_opt '}' // unqualified type name
2703 { $$ = DeclarationNode::newEnum( $3->name, $6, true, false, nullptr, $4 )->addQualifiers( $2 ); }
2704 | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt '{' enumerator_list comma_opt '}'
2705 {
2706 if ( $3->storageClasses.val != 0 || $3->type->qualifiers.any() ) {
2707 SemanticError( yylloc, "syntax error, storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." );
2708 }
2709 $$ = DeclarationNode::newEnum( nullptr, $7, true, true, $3 )->addQualifiers( $5 );
2710 }
2711 | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt '!' '{' enumerator_list comma_opt '}' // unqualified type name
2712 { SemanticError( yylloc, "syntax error, hiding ('!') the enumerator names of an anonymous enumeration means the names are inaccessible." ); $$ = nullptr; }
2713 | ENUM '(' ')' attribute_list_opt '{' enumerator_list comma_opt '}'
2714 {
2715 $$ = DeclarationNode::newEnum( nullptr, $6, true, true )->addQualifiers( $4 );
2716 }
2717 | ENUM '(' ')' attribute_list_opt '!' '{' enumerator_list comma_opt '}' // invalid syntax rule
2718 { SemanticError( yylloc, "syntax error, hiding ('!') the enumerator names of an anonymous enumeration means the names are inaccessible." ); $$ = nullptr; }
2719 | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt identifier attribute_list_opt
2720 {
2721 if ( $3 && ($3->storageClasses.any() || $3->type->qualifiers.val != 0 )) {
2722 SemanticError( yylloc, "syntax error, storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." );
2723 }
2724 typedefTable.makeTypedef( *$6, "enum_type 2" );
2725 }
2726 hide_opt '{' enumerator_list comma_opt '}'
2727 {
2728 $$ = DeclarationNode::newEnum( $6, $11, true, true, $3, $9 )->addQualifiers( $5 )->addQualifiers( $7 );
2729 }
2730 | ENUM '(' ')' attribute_list_opt identifier attribute_list_opt hide_opt '{' enumerator_list comma_opt '}'
2731 {
2732 $$ = DeclarationNode::newEnum( $5, $9, true, true, nullptr, $7 )->addQualifiers( $4 )->addQualifiers( $6 );
2733 }
2734 | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt typedef_name attribute_list_opt hide_opt '{' enumerator_list comma_opt '}'
2735 {
2736 $$ = DeclarationNode::newEnum( $6->name, $10, true, true, $3, $8 )->addQualifiers( $5 )->addQualifiers( $7 );
2737 }
2738 | ENUM '(' ')' attribute_list_opt typedef_name attribute_list_opt hide_opt '{' enumerator_list comma_opt '}'
2739 {
2740 $$ = DeclarationNode::newEnum( $5->name, $9, true, true, nullptr, $7 )->addQualifiers( $4 )->addQualifiers( $6 );
2741 }
2742 | enum_type_nobody
2743 ;
2744
2745hide_opt:
2746 // empty
2747 { $$ = EnumHiding::Visible; }
2748 | '!'
2749 { $$ = EnumHiding::Hide; }
2750 ;
2751
2752enum_type_nobody: // enum - {...}
2753 ENUM attribute_list_opt identifier
2754 {
2755 typedefTable.makeTypedef( *$3, "enum_type_nobody 1" );
2756 $$ = DeclarationNode::newEnum( $3, nullptr, false, false )->addQualifiers( $2 );
2757 }
2758 | ENUM attribute_list_opt type_name
2759 {
2760 typedefTable.makeTypedef( *$3->type->symbolic.name, "enum_type_nobody 2" );
2761 $$ = DeclarationNode::newEnum( $3->type->symbolic.name, nullptr, false, false )->addQualifiers( $2 );
2762 }
2763 ;
2764
2765enumerator_list:
2766 visible_hide_opt identifier_or_type_name enumerator_value_opt
2767 { $$ = DeclarationNode::newEnumValueGeneric( $2, $3 ); }
2768 | INLINE type_name
2769 { $$ = DeclarationNode::newEnumInLine( *$2->type->symbolic.name ); }
2770 | enumerator_list ',' visible_hide_opt identifier_or_type_name enumerator_value_opt
2771 { $$ = $1->set_last( DeclarationNode::newEnumValueGeneric( $4, $5 ) ); }
2772 | enumerator_list ',' INLINE type_name enumerator_value_opt
2773 { $$ = $1->set_last( DeclarationNode::newEnumValueGeneric( new string("inline"), nullptr ) ); }
2774 ;
2775
2776visible_hide_opt:
2777 hide_opt
2778 | '^'
2779 { $$ = EnumHiding::Visible; }
2780 ;
2781
2782enumerator_value_opt:
2783 // empty
2784 { $$ = nullptr; }
2785 | '=' constant_expression { $$ = new InitializerNode( $2 ); }
2786 | '=' '{' initializer_list_opt comma_opt '}' { $$ = new InitializerNode( $3, true ); }
2787 // | simple_assignment_operator initializer
2788 // { $$ = $1 == OperKinds::Assign ? $2 : $2->set_maybeConstructed( false ); }
2789 ;
2790
2791cfa_parameter_ellipsis_list_opt: // CFA, abstract + real
2792 // empty
2793 { $$ = DeclarationNode::newBasicType( DeclarationNode::Void ); }
2794 | ELLIPSIS
2795 { $$ = nullptr; }
2796 | cfa_abstract_parameter_list
2797 | cfa_parameter_list
2798 | cfa_parameter_list pop ',' push cfa_abstract_parameter_list
2799 { $$ = $1->set_last( $5 ); }
2800 | cfa_abstract_parameter_list pop ',' push ELLIPSIS
2801 { $$ = $1->addVarArgs(); }
2802 | cfa_parameter_list pop ',' push ELLIPSIS
2803 { $$ = $1->addVarArgs(); }
2804 ;
2805
2806cfa_parameter_list: // CFA
2807 // To obtain LR(1) between cfa_parameter_list and cfa_abstract_tuple, the last cfa_abstract_parameter_list is
2808 // factored out from cfa_parameter_list, flattening the rules to get lookahead to the ']'.
2809 cfa_parameter_declaration
2810 | cfa_abstract_parameter_list pop ',' push cfa_parameter_declaration
2811 { $$ = $1->set_last( $5 ); }
2812 | cfa_parameter_list pop ',' push cfa_parameter_declaration
2813 { $$ = $1->set_last( $5 ); }
2814 | cfa_parameter_list pop ',' push cfa_abstract_parameter_list pop ',' push cfa_parameter_declaration
2815 { $$ = $1->set_last( $5 )->set_last( $9 ); }
2816 ;
2817
2818cfa_abstract_parameter_list: // CFA, new & old style abstract
2819 cfa_abstract_parameter_declaration
2820 | cfa_abstract_parameter_list pop ',' push cfa_abstract_parameter_declaration
2821 { $$ = $1->set_last( $5 ); }
2822 ;
2823
2824parameter_type_list_opt:
2825 // empty
2826 { $$ = nullptr; }
2827 | ELLIPSIS
2828 { $$ = nullptr; }
2829 | parameter_list
2830 | parameter_list ',' ELLIPSIS
2831 { $$ = $1->addVarArgs(); }
2832 ;
2833
2834parameter_list: // abstract + real
2835 abstract_parameter_declaration
2836 | parameter_declaration
2837 | parameter_list ',' abstract_parameter_declaration
2838 { $$ = $1->set_last( $3 ); }
2839 | parameter_list ',' parameter_declaration
2840 { $$ = $1->set_last( $3 ); }
2841 ;
2842
2843// Provides optional identifier names (abstract_declarator/variable_declarator), no initialization, different semantics
2844// for typedef name by using type_parameter_redeclarator instead of typedef_redeclarator, and function prototypes.
2845
2846cfa_parameter_declaration: // CFA, new & old style parameter declaration
2847 parameter_declaration
2848 | cfa_identifier_parameter_declarator_no_tuple identifier_or_type_name default_initializer_opt
2849 { $$ = $1->addName( $2 ); }
2850 | cfa_abstract_tuple identifier_or_type_name default_initializer_opt
2851 // To obtain LR(1), these rules must be duplicated here (see cfa_abstract_declarator).
2852 { $$ = $1->addName( $2 ); }
2853 | type_qualifier_list cfa_abstract_tuple identifier_or_type_name default_initializer_opt
2854 { $$ = $2->addName( $3 )->addQualifiers( $1 ); }
2855 | cfa_function_specifier
2856 ;
2857
2858cfa_abstract_parameter_declaration: // CFA, new & old style parameter declaration
2859 abstract_parameter_declaration
2860 | cfa_identifier_parameter_declarator_no_tuple
2861 | cfa_abstract_tuple
2862 // To obtain LR(1), these rules must be duplicated here (see cfa_abstract_declarator).
2863 | type_qualifier_list cfa_abstract_tuple
2864 { $$ = $2->addQualifiers( $1 ); }
2865 | cfa_abstract_function
2866 ;
2867
2868parameter_declaration:
2869 // No SUE declaration in parameter list.
2870 declaration_specifier_nobody identifier_parameter_declarator default_initializer_opt
2871 { $$ = $2->addType( $1 )->addInitializer( $3 ? new InitializerNode( $3 ) : nullptr ); }
2872 | declaration_specifier_nobody type_parameter_redeclarator default_initializer_opt
2873 { $$ = $2->addType( $1 )->addInitializer( $3 ? new InitializerNode( $3 ) : nullptr ); }
2874 ;
2875
2876abstract_parameter_declaration:
2877 declaration_specifier_nobody default_initializer_opt
2878 { $$ = $1->addInitializer( $2 ? new InitializerNode( $2 ) : nullptr ); }
2879 | declaration_specifier_nobody abstract_parameter_declarator default_initializer_opt
2880 { $$ = $2->addType( $1 )->addInitializer( $3 ? new InitializerNode( $3 ) : nullptr ); }
2881 ;
2882
2883// ISO/IEC 9899:1999 Section 6.9.1(6) : "An identifier declared as a typedef name shall not be redeclared as a
2884// parameter." Because the scope of the K&R-style parameter-list sees the typedef first, the following is based only on
2885// identifiers. The ANSI-style parameter-list can redefine a typedef name.
2886
2887identifier_list: // K&R-style parameter list => no types
2888 identifier
2889 { $$ = DeclarationNode::newName( $1 ); }
2890 | identifier_list ',' identifier
2891 { $$ = $1->set_last( DeclarationNode::newName( $3 ) ); }
2892 ;
2893
2894identifier_or_type_name:
2895 identifier
2896 | TYPEDEFname
2897 | TYPEGENname
2898 ;
2899
2900type_no_function: // sizeof, alignof, cast (constructor)
2901 cfa_abstract_declarator_tuple // CFA
2902 | type_specifier // cannot be type_specifier_nobody, e.g., (struct S {}){} is a thing
2903 | type_specifier abstract_declarator
2904 { $$ = $2->addType( $1 ); }
2905 ;
2906
2907type: // typeof, assertion
2908 type_no_function
2909 | cfa_abstract_function // CFA
2910 ;
2911
2912initializer_opt:
2913 // empty
2914 { $$ = nullptr; }
2915 | simple_assignment_operator initializer { $$ = $1 == OperKinds::Assign ? $2 : $2->set_maybeConstructed( false ); }
2916 | '=' VOID { $$ = new InitializerNode( true ); }
2917 | '{' initializer_list_opt comma_opt '}' { $$ = new InitializerNode( $2, true ); }
2918 ;
2919
2920initializer:
2921 assignment_expression { $$ = new InitializerNode( $1 ); }
2922 | '{' initializer_list_opt comma_opt '}' { $$ = new InitializerNode( $2, true ); }
2923 ;
2924
2925initializer_list_opt:
2926 // empty
2927 { $$ = nullptr; }
2928 | initializer
2929 | designation initializer { $$ = $2->set_designators( $1 ); }
2930 | initializer_list_opt ',' initializer { $$ = (InitializerNode *)( $1->set_last( $3 ) ); }
2931 | initializer_list_opt ',' designation initializer { $$ = (InitializerNode *)($1->set_last( $4->set_designators( $3 ) )); }
2932 ;
2933
2934// There is an unreconcileable parsing problem between C99 and CFA with respect to designators. The problem is use of
2935// '=' to separator the designator from the initializer value, as in:
2936//
2937// int x[10] = { [1] = 3 };
2938//
2939// The string "[1] = 3" can be parsed as a designator assignment or a tuple assignment. To disambiguate this case, CFA
2940// changes the syntax from "=" to ":" as the separator between the designator and initializer. GCC does uses ":" for
2941// field selection. The optional use of the "=" in GCC, or in this case ":", cannot be supported either due to
2942// shift/reduce conflicts
2943
2944designation:
2945 designator_list ':' // C99, CFA uses ":" instead of "="
2946 | identifier_at ':' // GCC, field name
2947 { $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); }
2948 ;
2949
2950designator_list: // C99
2951 designator
2952 | designator_list designator
2953 { $$ = (ExpressionNode *)($1->set_last( $2 )); }
2954 //| designator_list designator { $$ = new ExpressionNode( $1, $2 ); }
2955 ;
2956
2957designator:
2958 '.' identifier_at // C99, field name
2959 { $$ = new ExpressionNode( build_varref( yylloc, $2 ) ); }
2960 | '[' push assignment_expression pop ']' // C99, single array element
2961 // assignment_expression used instead of constant_expression because of shift/reduce conflicts with tuple.
2962 { $$ = $3; }
2963 | '[' push subrange pop ']' // CFA, multiple array elements
2964 { $$ = $3; }
2965 | '[' push constant_expression ELLIPSIS constant_expression pop ']' // GCC, multiple array elements
2966 { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $3 ), maybeMoveBuild( $5 ) ) ); }
2967 | '.' '[' push field_name_list pop ']' // CFA, tuple field selector
2968 { $$ = $4; }
2969 ;
2970
2971// The CFA type system is based on parametric polymorphism, the ability to declare functions with type parameters,
2972// rather than an object-oriented type system. This required four groups of extensions:
2973//
2974// Overloading: function, data, and operator identifiers may be overloaded.
2975//
2976// Type declarations: "otype" is used to generate new types for declaring objects. Similarly, "dtype" is used for object
2977// and incomplete types, and "ftype" is used for function types. Type declarations with initializers provide
2978// definitions of new types. Type declarations with storage class "extern" provide opaque types.
2979//
2980// Polymorphic functions: A forall clause declares a type parameter. The corresponding argument is inferred at the call
2981// site. A polymorphic function is not a template; it is a function, with an address and a type.
2982//
2983// Specifications and Assertions: Specifications are collections of declarations parameterized by one or more
2984// types. They serve many of the purposes of abstract classes, and specification hierarchies resemble subclass
2985// hierarchies. Unlike classes, they can define relationships between types. Assertions declare that a type or
2986// types provide the operations declared by a specification. Assertions are normally used to declare requirements
2987// on type arguments of polymorphic functions.
2988
2989type_parameter_list: // CFA
2990 type_parameter
2991 | type_parameter_list ',' type_parameter
2992 { $$ = $1->set_last( $3 ); }
2993 ;
2994
2995type_initializer_opt: // CFA
2996 // empty
2997 { $$ = nullptr; }
2998 | '=' type
2999 { $$ = $2; }
3000 ;
3001
3002type_parameter: // CFA
3003 type_class identifier_or_type_name
3004 {
3005 typedefTable.addToScope( *$2, TYPEDEFname, "type_parameter 1" );
3006 if ( $1 == ast::TypeDecl::Otype ) { SemanticError( yylloc, "otype keyword is deprecated, use T " ); }
3007 if ( $1 == ast::TypeDecl::Dtype ) { SemanticError( yylloc, "dtype keyword is deprecated, use T &" ); }
3008 if ( $1 == ast::TypeDecl::Ttype ) { SemanticError( yylloc, "ttype keyword is deprecated, use T ..." ); }
3009 }
3010 type_initializer_opt assertion_list_opt
3011 { $$ = DeclarationNode::newTypeParam( $1, $2 )->addTypeInitializer( $4 )->addAssertions( $5 ); }
3012 | identifier_or_type_name new_type_class
3013 { typedefTable.addToScope( *$1, TYPEDEFname, "type_parameter 2" ); }
3014 type_initializer_opt assertion_list_opt
3015 { $$ = DeclarationNode::newTypeParam( $2, $1 )->addTypeInitializer( $4 )->addAssertions( $5 ); }
3016 | '[' identifier_or_type_name ']'
3017 {
3018 typedefTable.addToScope( *$2, TYPEDIMname, "type_parameter 3" );
3019 $$ = DeclarationNode::newTypeParam( ast::TypeDecl::Dimension, $2 );
3020 }
3021 // | type_specifier identifier_parameter_declarator
3022 | assertion_list
3023 { $$ = DeclarationNode::newTypeParam( ast::TypeDecl::Dtype, new string( DeclarationNode::anonymous.newName() ) )->addAssertions( $1 ); }
3024 | ENUM '(' identifier_or_type_name ')' identifier_or_type_name new_type_class type_initializer_opt assertion_list_opt
3025 {
3026 typedefTable.addToScope( *$3, TYPEDIMname, "type_parameter 4" );
3027 typedefTable.addToScope( *$5, TYPEDIMname, "type_parameter 5" );
3028 $$ = DeclarationNode::newTypeParam( $6, $5 )->addTypeInitializer( $7 )->addAssertions( $8 );
3029 }
3030 ;
3031
3032new_type_class: // CFA
3033 // empty
3034 { $$ = ast::TypeDecl::Otype; }
3035 | '&'
3036 { $$ = ast::TypeDecl::Dtype; }
3037 | '*'
3038 { $$ = ast::TypeDecl::DStype; } // dtype + sized
3039 // | '(' '*' ')'
3040 // { $$ = ast::TypeDecl::Ftype; }
3041 | ELLIPSIS
3042 { $$ = ast::TypeDecl::Ttype; }
3043 ;
3044
3045type_class: // CFA
3046 OTYPE
3047 { $$ = ast::TypeDecl::Otype; }
3048 | DTYPE
3049 { $$ = ast::TypeDecl::Dtype; }
3050 | FTYPE
3051 { $$ = ast::TypeDecl::Ftype; }
3052 | TTYPE
3053 { $$ = ast::TypeDecl::Ttype; }
3054 ;
3055
3056assertion_list_opt: // CFA
3057 // empty
3058 { $$ = nullptr; }
3059 | assertion_list
3060 ;
3061
3062assertion_list: // CFA
3063 assertion
3064 | assertion_list assertion
3065 { $$ = $1->set_last( $2 ); }
3066 ;
3067
3068assertion: // CFA
3069 '|' identifier_or_type_name '(' type_list ')'
3070 { $$ = DeclarationNode::newTraitUse( $2, $4 ); }
3071 | '|' '{' push trait_declaration_list pop '}'
3072 { $$ = $4; }
3073 // | '|' '(' push type_parameter_list pop ')' '{' push trait_declaration_list pop '}' '(' type_list ')'
3074 // { SemanticError( yylloc, "Generic data-type assertion is currently unimplemented." ); $$ = nullptr; }
3075 ;
3076
3077type_list: // CFA
3078 type
3079 { $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); }
3080 | assignment_expression
3081 | type_list ',' type
3082 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); }
3083 | type_list ',' assignment_expression
3084 { $$ = (ExpressionNode *)( $1->set_last( $3 )); }
3085 ;
3086
3087type_declaring_list: // CFA
3088 OTYPE type_declarator
3089 { $$ = $2; }
3090 | storage_class_list OTYPE type_declarator
3091 { $$ = $3->addQualifiers( $1 ); }
3092 | type_declaring_list ',' type_declarator
3093 { $$ = $1->set_last( $3->copySpecifiers( $1 ) ); }
3094 ;
3095
3096type_declarator: // CFA
3097 type_declarator_name assertion_list_opt
3098 { $$ = $1->addAssertions( $2 ); }
3099 | type_declarator_name assertion_list_opt '=' type
3100 { $$ = $1->addAssertions( $2 )->addType( $4 ); }
3101 ;
3102
3103type_declarator_name: // CFA
3104 identifier_or_type_name
3105 {
3106 typedefTable.addToEnclosingScope( *$1, TYPEDEFname, "type_declarator_name 1" );
3107 $$ = DeclarationNode::newTypeDecl( $1, nullptr );
3108 }
3109 | identifier_or_type_name '(' type_parameter_list ')'
3110 {
3111 typedefTable.addToEnclosingScope( *$1, TYPEGENname, "type_declarator_name 2" );
3112 $$ = DeclarationNode::newTypeDecl( $1, $3 );
3113 }
3114 ;
3115
3116trait_specifier: // CFA
3117 TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' '}'
3118 {
3119 SemanticWarning( yylloc, Warning::DeprecTraitSyntax );
3120 $$ = DeclarationNode::newTrait( $2, $4, nullptr );
3121 }
3122 | forall TRAIT identifier_or_type_name '{' '}' // alternate
3123 { $$ = DeclarationNode::newTrait( $3, $1, nullptr ); }
3124 | TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' push trait_declaration_list pop '}'
3125 {
3126 SemanticWarning( yylloc, Warning::DeprecTraitSyntax );
3127 $$ = DeclarationNode::newTrait( $2, $4, $8 );
3128 }
3129 | forall TRAIT identifier_or_type_name '{' push trait_declaration_list pop '}' // alternate
3130 { $$ = DeclarationNode::newTrait( $3, $1, $6 ); }
3131 ;
3132
3133trait_declaration_list: // CFA
3134 trait_declaration
3135 | trait_declaration_list pop push trait_declaration
3136 { $$ = $1->set_last( $4 ); }
3137 ;
3138
3139trait_declaration: // CFA
3140 cfa_trait_declaring_list ';'
3141 | trait_declaring_list ';'
3142 ;
3143
3144cfa_trait_declaring_list: // CFA
3145 cfa_variable_specifier
3146 | cfa_function_specifier
3147 | cfa_trait_declaring_list pop ',' push identifier_or_type_name
3148 { $$ = $1->set_last( $1->cloneType( $5 ) ); }
3149 ;
3150
3151trait_declaring_list: // CFA
3152 type_specifier declarator
3153 { $$ = $2->addType( $1 ); }
3154 | trait_declaring_list pop ',' push declarator
3155 { $$ = $1->set_last( $1->cloneBaseType( $5 ) ); }
3156 ;
3157
3158// **************************** EXTERNAL DEFINITIONS *****************************
3159
3160translation_unit:
3161 // empty, input file
3162 | external_definition_list
3163 { parseTree = parseTree ? parseTree->set_last( $1 ) : $1; }
3164 ;
3165
3166external_definition_list:
3167 push external_definition pop
3168 { $$ = $2; }
3169 | external_definition_list push external_definition pop
3170 { $$ = $1 ? $1->set_last( $3 ) : $3; }
3171 ;
3172
3173external_definition_list_opt:
3174 // empty
3175 { $$ = nullptr; }
3176 | external_definition_list
3177 ;
3178
3179up:
3180 { typedefTable.up( forall ); forall = false; }
3181 ;
3182
3183down:
3184 { typedefTable.down(); }
3185 ;
3186
3187external_definition:
3188 DIRECTIVE
3189 { $$ = DeclarationNode::newDirectiveStmt( new StatementNode( build_directive( yylloc, $1 ) ) ); }
3190 | declaration
3191 {
3192 // Variable declarations of anonymous types requires creating a unique type-name across multiple translation
3193 // unit, which is a dubious task, especially because C uses name rather than structural typing; hence it is
3194 // disallowed at the moment.
3195 if ( $1->linkage == ast::Linkage::Cforall && ! $1->storageClasses.is_static &&
3196 $1->type && $1->type->kind == TypeData::AggregateInst ) {
3197 if ( $1->type->aggInst.aggregate->kind == TypeData::Enum && $1->type->aggInst.aggregate->enumeration.anon ) {
3198 SemanticError( yylloc, "extern anonymous enumeration is currently unimplemented." ); $$ = nullptr;
3199 } else if ( $1->type->aggInst.aggregate->aggregate.anon ) { // handles struct or union
3200 SemanticError( yylloc, "extern anonymous struct/union is currently unimplemented." ); $$ = nullptr;
3201 }
3202 }
3203 }
3204 | IDENTIFIER IDENTIFIER
3205 { IdentifierBeforeIdentifier( *$1.str, *$2.str, " declaration" ); $$ = nullptr; }
3206 | IDENTIFIER type_qualifier // invalid syntax rule
3207 { IdentifierBeforeType( *$1.str, "type qualifier" ); $$ = nullptr; }
3208 | IDENTIFIER storage_class // invalid syntax rule
3209 { IdentifierBeforeType( *$1.str, "storage class" ); $$ = nullptr; }
3210 | IDENTIFIER basic_type_name // invalid syntax rule
3211 { IdentifierBeforeType( *$1.str, "type" ); $$ = nullptr; }
3212 | IDENTIFIER TYPEDEFname // invalid syntax rule
3213 { IdentifierBeforeType( *$1.str, "type" ); $$ = nullptr; }
3214 | IDENTIFIER TYPEGENname // invalid syntax rule
3215 { IdentifierBeforeType( *$1.str, "type" ); $$ = nullptr; }
3216 | external_function_definition
3217 | EXTENSION external_definition // GCC, multiple __extension__ allowed, meaning unknown
3218 {
3219 distExt( $2 ); // mark all fields in list
3220 $$ = $2;
3221 }
3222 | ASM '(' string_literal ')' ';' // GCC, global assembler statement
3223 { $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( yylloc, false, $3, nullptr ) ) ); }
3224 | EXTERN STRINGliteral
3225 {
3226 linkageStack.push( linkage ); // handle nested extern "C"/"Cforall"
3227 linkage = ast::Linkage::update( yylloc, linkage, $2 );
3228 }
3229 up external_definition down
3230 {
3231 linkage = linkageStack.top();
3232 linkageStack.pop();
3233 $$ = $5;
3234 }
3235 | EXTERN STRINGliteral // C++-style linkage specifier
3236 {
3237 linkageStack.push( linkage ); // handle nested extern "C"/"Cforall"
3238 linkage = ast::Linkage::update( yylloc, linkage, $2 );
3239 }
3240 '{' up external_definition_list_opt down '}'
3241 {
3242 linkage = linkageStack.top();
3243 linkageStack.pop();
3244 $$ = $6;
3245 }
3246 // global distribution
3247 | type_qualifier_list
3248 {
3249 if ( $1->type->qualifiers.any() ) {
3250 SemanticError( yylloc, "syntax error, CV qualifiers cannot be distributed; only storage-class and forall qualifiers." );
3251 }
3252 if ( $1->type->forall ) forall = true; // remember generic type
3253 }
3254 '{' up external_definition_list_opt down '}' // CFA, namespace
3255 {
3256 distQual( $5, $1 );
3257 forall = false;
3258 $$ = $5;
3259 }
3260 | declaration_qualifier_list
3261 {
3262 if ( $1->type && $1->type->qualifiers.any() ) {
3263 SemanticError( yylloc, "syntax error, CV qualifiers cannot be distributed; only storage-class and forall qualifiers." );
3264 }
3265 if ( $1->type && $1->type->forall ) forall = true; // remember generic type
3266 }
3267 '{' up external_definition_list_opt down '}' // CFA, namespace
3268 {
3269 distQual( $5, $1 );
3270 forall = false;
3271 $$ = $5;
3272 }
3273 | declaration_qualifier_list type_qualifier_list
3274 {
3275 if ( ($1->type && $1->type->qualifiers.any()) || ($2->type && $2->type->qualifiers.any()) ) {
3276 SemanticError( yylloc, "syntax error, CV qualifiers cannot be distributed; only storage-class and forall qualifiers." );
3277 }
3278 if ( ($1->type && $1->type->forall) || ($2->type && $2->type->forall) ) forall = true; // remember generic type
3279 }
3280 '{' up external_definition_list_opt down '}' // CFA, namespace
3281 {
3282 distQual( $6, $1->addQualifiers( $2 ) );
3283 forall = false;
3284 $$ = $6;
3285 }
3286 ;
3287
3288external_function_definition:
3289 function_definition
3290 // These rules are a concession to the "implicit int" type_specifier because there is a significant amount of
3291 // legacy code with global functions missing the type-specifier for the return type, and assuming "int".
3292 // Parsing is possible because function_definition does not appear in the context of an expression (nested
3293 // functions preclude this concession, i.e., all nested function must have a return type). A function prototype
3294 // declaration must still have a type_specifier. OBSOLESCENT (see 1)
3295 | function_declarator compound_statement
3296 { $$ = $1->addFunctionBody( $2 ); }
3297 | KR_function_declarator KR_parameter_list_opt compound_statement
3298 { $$ = $1->addOldDeclList( $2 )->addFunctionBody( $3 ); }
3299 ;
3300
3301with_clause_opt:
3302 // empty
3303 { $$ = nullptr; forall = false; }
3304 | WITH '(' tuple_expression_list ')' attribute_list_opt
3305 {
3306 $$ = $3; forall = false;
3307 if ( $5 ) {
3308 SemanticError( yylloc, "syntax error, attributes cannot be associated with function body. Move attribute(s) before \"with\" clause." );
3309 $$ = nullptr;
3310 } // if
3311 }
3312 ;
3313
3314function_definition:
3315 cfa_function_declaration with_clause_opt compound_statement // CFA
3316 {
3317 // Add the function body to the last identifier in the function definition list, i.e., foo3:
3318 // [const double] foo1(), foo2( int ), foo3( double ) { return 3.0; }
3319 $1->get_last()->addFunctionBody( $3, $2 );
3320 $$ = $1;
3321 }
3322 | declaration_specifier function_declarator with_clause_opt compound_statement
3323 {
3324 rebindForall( $1, $2 );
3325 $$ = $2->addFunctionBody( $4, $3 )->addType( $1 );
3326 }
3327 | declaration_specifier function_type_redeclarator with_clause_opt compound_statement
3328 {
3329 rebindForall( $1, $2 );
3330 $$ = $2->addFunctionBody( $4, $3 )->addType( $1 );
3331 }
3332 // handles default int return type, OBSOLESCENT (see 1)
3333 | type_qualifier_list function_declarator with_clause_opt compound_statement
3334 { $$ = $2->addFunctionBody( $4, $3 )->addQualifiers( $1 ); }
3335 // handles default int return type, OBSOLESCENT (see 1)
3336 | declaration_qualifier_list function_declarator with_clause_opt compound_statement
3337 { $$ = $2->addFunctionBody( $4, $3 )->addQualifiers( $1 ); }
3338 // handles default int return type, OBSOLESCENT (see 1)
3339 | declaration_qualifier_list type_qualifier_list function_declarator with_clause_opt compound_statement
3340 { $$ = $3->addFunctionBody( $5, $4 )->addQualifiers( $2 )->addQualifiers( $1 ); }
3341
3342 // Old-style K&R function definition, OBSOLESCENT (see 4)
3343 | declaration_specifier KR_function_declarator KR_parameter_list_opt with_clause_opt compound_statement
3344 {
3345 rebindForall( $1, $2 );
3346 $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5, $4 )->addType( $1 );
3347 }
3348 // handles default int return type, OBSOLESCENT (see 1)
3349 | type_qualifier_list KR_function_declarator KR_parameter_list_opt with_clause_opt compound_statement
3350 { $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5, $4 )->addQualifiers( $1 ); }
3351 // handles default int return type, OBSOLESCENT (see 1)
3352 | declaration_qualifier_list KR_function_declarator KR_parameter_list_opt with_clause_opt compound_statement
3353 { $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5, $4 )->addQualifiers( $1 ); }
3354 // handles default int return type, OBSOLESCENT (see 1)
3355 | declaration_qualifier_list type_qualifier_list KR_function_declarator KR_parameter_list_opt with_clause_opt compound_statement
3356 { $$ = $3->addOldDeclList( $4 )->addFunctionBody( $6, $5 )->addQualifiers( $2 )->addQualifiers( $1 ); }
3357 ;
3358
3359declarator:
3360 variable_declarator
3361 | variable_type_redeclarator
3362 | function_declarator
3363 | function_type_redeclarator
3364 ;
3365
3366subrange:
3367 constant_expression '~' constant_expression // CFA, integer subrange
3368 { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
3369 ;
3370
3371asm_name_opt: // GCC
3372 // empty
3373 { $$ = nullptr; }
3374 | ASM '(' string_literal ')' attribute_list_opt
3375 {
3376 DeclarationNode * name = new DeclarationNode();
3377 name->asmName = maybeMoveBuild( $3 );
3378 $$ = name->addQualifiers( $5 );
3379 }
3380 ;
3381
3382attribute_list_opt: // GCC
3383 // empty
3384 { $$ = nullptr; }
3385 | attribute_list
3386 ;
3387
3388attribute_list: // GCC
3389 attribute
3390 | attribute_list attribute
3391 { $$ = $2->addQualifiers( $1 ); }
3392 ;
3393
3394attribute: // GCC
3395 ATTRIBUTE '(' '(' attribute_name_list ')' ')'
3396 { $$ = $4; }
3397 ;
3398
3399attribute_name_list: // GCC
3400 attribute_name
3401 | attribute_name_list ',' attribute_name
3402 { $$ = $3->addQualifiers( $1 ); }
3403 ;
3404
3405attribute_name: // GCC
3406 // empty
3407 { $$ = nullptr; }
3408 | attr_name
3409 { $$ = DeclarationNode::newAttribute( $1 ); }
3410 | attr_name '(' argument_expression_list_opt ')'
3411 { $$ = DeclarationNode::newAttribute( $1, $3 ); }
3412 ;
3413
3414attr_name: // GCC
3415 IDENTIFIER
3416 | quasi_keyword
3417 | TYPEDEFname
3418 | TYPEGENname
3419 | FALLTHROUGH
3420 { $$ = Token{ new string( "fallthrough" ), { nullptr, -1 } }; }
3421 | CONST
3422 { $$ = Token{ new string( "__const__" ), { nullptr, -1 } }; }
3423 ;
3424
3425// ============================================================================
3426// The following sections are a series of grammar patterns used to parse declarators. Multiple patterns are necessary
3427// because the type of an identifier in wrapped around the identifier in the same form as its usage in an expression, as
3428// in:
3429//
3430// int (*f())[10] { ... };
3431// ... (*f())[3] += 1; // definition mimics usage
3432//
3433// Because these patterns are highly recursive, changes at a lower level in the recursion require copying some or all of
3434// the pattern. Each of these patterns has some subtle variation to ensure correct syntax in a particular context.
3435// ============================================================================
3436
3437// ----------------------------------------------------------------------------
3438// The set of valid declarators before a compound statement for defining a function is less than the set of declarators
3439// to define a variable or function prototype, e.g.:
3440//
3441// valid declaration invalid definition
3442// ----------------- ------------------
3443// int f; int f {}
3444// int *f; int *f {}
3445// int f[10]; int f[10] {}
3446// int (*f)(int); int (*f)(int) {}
3447//
3448// To preclude this syntactic anomaly requires separating the grammar rules for variable and function declarators, hence
3449// variable_declarator and function_declarator.
3450// ----------------------------------------------------------------------------
3451
3452// This pattern parses a declaration of a variable that is not redefining a typedef name. The pattern precludes
3453// declaring an array of functions versus a pointer to an array of functions.
3454
3455paren_identifier:
3456 identifier_at
3457 { $$ = DeclarationNode::newName( $1 ); }
3458 | '(' paren_identifier ')' // redundant parenthesis
3459 { $$ = $2; }
3460 ;
3461
3462variable_declarator:
3463 paren_identifier attribute_list_opt
3464 { $$ = $1->addQualifiers( $2 ); }
3465 | variable_ptr
3466 | variable_array attribute_list_opt
3467 { $$ = $1->addQualifiers( $2 ); }
3468 | variable_function attribute_list_opt
3469 { $$ = $1->addQualifiers( $2 ); }
3470 ;
3471
3472variable_ptr:
3473 ptrref_operator variable_declarator
3474 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
3475 | ptrref_operator type_qualifier_list variable_declarator
3476 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
3477 | '(' variable_ptr ')' attribute_list_opt // redundant parenthesis
3478 { $$ = $2->addQualifiers( $4 ); }
3479 | '(' attribute_list variable_ptr ')' attribute_list_opt // redundant parenthesis
3480 { $$ = $3->addQualifiers( $2 )->addQualifiers( $5 ); }
3481 ;
3482
3483variable_array:
3484 paren_identifier array_dimension
3485 { $$ = $1->addArray( $2 ); }
3486 | '(' variable_ptr ')' array_dimension
3487 { $$ = $2->addArray( $4 ); }
3488 | '(' attribute_list variable_ptr ')' array_dimension
3489 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
3490 | '(' variable_array ')' multi_array_dimension // redundant parenthesis
3491 { $$ = $2->addArray( $4 ); }
3492 | '(' attribute_list variable_array ')' multi_array_dimension // redundant parenthesis
3493 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
3494 | '(' variable_array ')' // redundant parenthesis
3495 { $$ = $2; }
3496 | '(' attribute_list variable_array ')' // redundant parenthesis
3497 { $$ = $3->addQualifiers( $2 ); }
3498 ;
3499
3500variable_function:
3501 '(' variable_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
3502 { $$ = $2->addParamList( $5 ); }
3503 | '(' attribute_list variable_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
3504 { $$ = $3->addQualifiers( $2 )->addParamList( $6 ); }
3505 | '(' variable_function ')' // redundant parenthesis
3506 { $$ = $2; }
3507 | '(' attribute_list variable_function ')' // redundant parenthesis
3508 { $$ = $3->addQualifiers( $2 ); }
3509 ;
3510
3511// This pattern parses a function declarator that is not redefining a typedef name. For non-nested functions, there is
3512// no context where a function definition can redefine a typedef name, i.e., the typedef and function name cannot exist
3513// is the same scope. The pattern precludes returning arrays and functions versus pointers to arrays and functions.
3514
3515function_declarator:
3516 function_no_ptr attribute_list_opt
3517 { $$ = $1->addQualifiers( $2 ); }
3518 | function_ptr
3519 | function_array attribute_list_opt
3520 { $$ = $1->addQualifiers( $2 ); }
3521 ;
3522
3523function_no_ptr:
3524 paren_identifier '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
3525 { $$ = $1->addParamList( $3 ); }
3526 | '(' function_ptr ')' '(' parameter_type_list_opt ')'
3527 { $$ = $2->addParamList( $5 ); }
3528 | '(' attribute_list function_ptr ')' '(' parameter_type_list_opt ')'
3529 { $$ = $3->addQualifiers( $2 )->addParamList( $6 ); }
3530 | '(' function_no_ptr ')' // redundant parenthesis
3531 { $$ = $2; }
3532 | '(' attribute_list function_no_ptr ')' // redundant parenthesis
3533 { $$ = $3->addQualifiers( $2 ); }
3534 ;
3535
3536function_ptr:
3537 ptrref_operator function_declarator
3538 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
3539 | ptrref_operator type_qualifier_list function_declarator
3540 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
3541 | '(' function_ptr ')' attribute_list_opt
3542 { $$ = $2->addQualifiers( $4 ); }
3543 | '(' attribute_list function_ptr ')' attribute_list_opt
3544 { $$ = $3->addQualifiers( $2 )->addQualifiers( $5 ); }
3545 ;
3546
3547function_array:
3548 '(' function_ptr ')' array_dimension
3549 { $$ = $2->addArray( $4 ); }
3550 | '(' attribute_list function_ptr ')' array_dimension
3551 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
3552 | '(' function_array ')' multi_array_dimension // redundant parenthesis
3553 { $$ = $2->addArray( $4 ); }
3554 | '(' attribute_list function_array ')' multi_array_dimension // redundant parenthesis
3555 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
3556 | '(' function_array ')' // redundant parenthesis
3557 { $$ = $2; }
3558 | '(' attribute_list function_array ')' // redundant parenthesis
3559 { $$ = $3->addQualifiers( $2 ); }
3560 ;
3561
3562// This pattern parses an old-style K&R function declarator (OBSOLESCENT, see 4)
3563//
3564// f( a, b, c ) int a, *b, c[]; {}
3565//
3566// that is not redefining a typedef name (see function_declarator for additional comments). The pattern precludes
3567// returning arrays and functions versus pointers to arrays and functions.
3568
3569KR_function_declarator:
3570 KR_function_no_ptr
3571 | KR_function_ptr
3572 | KR_function_array
3573 ;
3574
3575KR_function_no_ptr:
3576 paren_identifier '(' identifier_list ')' // function_declarator handles empty parameter
3577 { $$ = $1->addIdList( $3 ); }
3578 | '(' KR_function_ptr ')' '(' parameter_type_list_opt ')'
3579 { $$ = $2->addParamList( $5 ); }
3580 | '(' attribute_list KR_function_ptr ')' '(' parameter_type_list_opt ')'
3581 { $$ = $3->addQualifiers( $2 )->addParamList( $6 ); }
3582 | '(' KR_function_no_ptr ')' // redundant parenthesis
3583 { $$ = $2; }
3584 | '(' attribute_list KR_function_no_ptr ')' // redundant parenthesis
3585 { $$ = $3->addQualifiers( $2 ); }
3586 ;
3587
3588KR_function_ptr:
3589 ptrref_operator KR_function_declarator
3590 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
3591 | ptrref_operator type_qualifier_list KR_function_declarator
3592 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
3593 | '(' KR_function_ptr ')'
3594 { $$ = $2; }
3595 | '(' attribute_list KR_function_ptr ')'
3596 { $$ = $3->addQualifiers( $2 ); }
3597 ;
3598
3599KR_function_array:
3600 '(' KR_function_ptr ')' array_dimension
3601 { $$ = $2->addArray( $4 ); }
3602 | '(' attribute_list KR_function_ptr ')' array_dimension
3603 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
3604 | '(' KR_function_array ')' multi_array_dimension // redundant parenthesis
3605 { $$ = $2->addArray( $4 ); }
3606 | '(' attribute_list KR_function_array ')' multi_array_dimension // redundant parenthesis
3607 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
3608 | '(' KR_function_array ')' // redundant parenthesis
3609 { $$ = $2; }
3610 | '(' attribute_list KR_function_array ')' // redundant parenthesis
3611 { $$ = $3->addQualifiers( $2 ); }
3612 ;
3613
3614// This pattern parses a declaration for a variable that redefines a type name, e.g.:
3615//
3616// typedef int foo;
3617// {
3618// int foo; // redefine typedef name in new scope
3619// }
3620
3621paren_type:
3622 typedef_name
3623 {
3624 // hide type name in enclosing scope by variable name
3625 typedefTable.addToEnclosingScope( *$1->name, IDENTIFIER, "paren_type" );
3626 }
3627 | '(' paren_type ')'
3628 { $$ = $2; }
3629 ;
3630
3631variable_type_redeclarator:
3632 paren_type attribute_list_opt
3633 { $$ = $1->addQualifiers( $2 ); }
3634 | variable_type_ptr
3635 | variable_type_array attribute_list_opt
3636 { $$ = $1->addQualifiers( $2 ); }
3637 | variable_type_function attribute_list_opt
3638 { $$ = $1->addQualifiers( $2 ); }
3639 ;
3640
3641variable_type_ptr:
3642 ptrref_operator variable_type_redeclarator
3643 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
3644 | ptrref_operator type_qualifier_list variable_type_redeclarator
3645 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
3646 | '(' variable_type_ptr ')' attribute_list_opt // redundant parenthesis
3647 { $$ = $2->addQualifiers( $4 ); }
3648 | '(' attribute_list variable_type_ptr ')' attribute_list_opt // redundant parenthesis
3649 { $$ = $3->addQualifiers( $2 )->addQualifiers( $5 ); }
3650 ;
3651
3652variable_type_array:
3653 paren_type array_dimension
3654 { $$ = $1->addArray( $2 ); }
3655 | '(' variable_type_ptr ')' array_dimension
3656 { $$ = $2->addArray( $4 ); }
3657 | '(' attribute_list variable_type_ptr ')' array_dimension
3658 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
3659 | '(' variable_type_array ')' multi_array_dimension // redundant parenthesis
3660 { $$ = $2->addArray( $4 ); }
3661 | '(' attribute_list variable_type_array ')' multi_array_dimension // redundant parenthesis
3662 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
3663 | '(' variable_type_array ')' // redundant parenthesis
3664 { $$ = $2; }
3665 | '(' attribute_list variable_type_array ')' // redundant parenthesis
3666 { $$ = $3->addQualifiers( $2 ); }
3667 ;
3668
3669variable_type_function:
3670 '(' variable_type_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
3671 { $$ = $2->addParamList( $5 ); }
3672 | '(' attribute_list variable_type_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
3673 { $$ = $3->addQualifiers( $2 )->addParamList( $6 ); }
3674 | '(' variable_type_function ')' // redundant parenthesis
3675 { $$ = $2; }
3676 | '(' attribute_list variable_type_function ')' // redundant parenthesis
3677 { $$ = $3->addQualifiers( $2 ); }
3678 ;
3679
3680// This pattern parses a declaration for a function prototype that redefines a type name. It precludes declaring an
3681// array of functions versus a pointer to an array of functions, and returning arrays and functions versus pointers to
3682// arrays and functions.
3683
3684function_type_redeclarator:
3685 function_type_no_ptr attribute_list_opt
3686 { $$ = $1->addQualifiers( $2 ); }
3687 | function_type_ptr
3688 | function_type_array attribute_list_opt
3689 { $$ = $1->addQualifiers( $2 ); }
3690 ;
3691
3692function_type_no_ptr:
3693 paren_type '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
3694 { $$ = $1->addParamList( $3 ); }
3695 | '(' function_type_ptr ')' '(' parameter_type_list_opt ')'
3696 { $$ = $2->addParamList( $5 ); }
3697 | '(' attribute_list function_type_ptr ')' '(' parameter_type_list_opt ')'
3698 { $$ = $3->addQualifiers( $2 )->addParamList( $6 ); }
3699 | '(' function_type_no_ptr ')' // redundant parenthesis
3700 { $$ = $2; }
3701 | '(' attribute_list function_type_no_ptr ')' // redundant parenthesis
3702 { $$ = $3->addQualifiers( $2 ); }
3703 ;
3704
3705function_type_ptr:
3706 ptrref_operator function_type_redeclarator
3707 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
3708 | ptrref_operator type_qualifier_list function_type_redeclarator
3709 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
3710 | '(' function_type_ptr ')' attribute_list_opt
3711 { $$ = $2->addQualifiers( $4 ); }
3712 | '(' attribute_list function_type_ptr ')' attribute_list_opt
3713 { $$ = $3->addQualifiers( $2 )->addQualifiers( $5 ); }
3714 ;
3715
3716function_type_array:
3717 '(' function_type_ptr ')' array_dimension
3718 { $$ = $2->addArray( $4 ); }
3719 | '(' attribute_list function_type_ptr ')' array_dimension
3720 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
3721 | '(' function_type_array ')' multi_array_dimension // redundant parenthesis
3722 { $$ = $2->addArray( $4 ); }
3723 | '(' attribute_list function_type_array ')' multi_array_dimension // redundant parenthesis
3724 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
3725 | '(' function_type_array ')' // redundant parenthesis
3726 { $$ = $2; }
3727 | '(' attribute_list function_type_array ')' // redundant parenthesis
3728 { $$ = $3->addQualifiers( $2 ); }
3729 ;
3730
3731// This pattern parses a declaration for a parameter variable of a function prototype or actual that is not redefining a
3732// typedef name and allows the C99 array options, which can only appear in a parameter list. The pattern precludes
3733// declaring an array of functions versus a pointer to an array of functions, and returning arrays and functions versus
3734// pointers to arrays and functions.
3735
3736identifier_parameter_declarator:
3737 paren_identifier attribute_list_opt
3738 { $$ = $1->addQualifiers( $2 ); }
3739 | '&' MUTEX paren_identifier attribute_list_opt
3740 { $$ = $3->addPointer( DeclarationNode::newPointer( DeclarationNode::newTypeQualifier( ast::CV::Mutex ), OperKinds::AddressOf ) )->addQualifiers( $4 ); }
3741 | identifier_parameter_ptr
3742 | identifier_parameter_array attribute_list_opt
3743 { $$ = $1->addQualifiers( $2 ); }
3744 | identifier_parameter_function attribute_list_opt
3745 { $$ = $1->addQualifiers( $2 ); }
3746 ;
3747
3748identifier_parameter_ptr:
3749 ptrref_operator identifier_parameter_declarator
3750 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
3751 | ptrref_operator type_qualifier_list identifier_parameter_declarator
3752 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
3753 | '(' identifier_parameter_ptr ')' attribute_list_opt // redundant parenthesis
3754 { $$ = $2->addQualifiers( $4 ); }
3755 ;
3756
3757identifier_parameter_array:
3758 paren_identifier array_parameter_dimension
3759 { $$ = $1->addArray( $2 ); }
3760 | '(' identifier_parameter_ptr ')' array_dimension
3761 { $$ = $2->addArray( $4 ); }
3762 | '(' identifier_parameter_array ')' multi_array_dimension // redundant parenthesis
3763 { $$ = $2->addArray( $4 ); }
3764 | '(' identifier_parameter_array ')' // redundant parenthesis
3765 { $$ = $2; }
3766 ;
3767
3768identifier_parameter_function:
3769 paren_identifier '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
3770 { $$ = $1->addParamList( $3 ); }
3771 | '(' identifier_parameter_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
3772 { $$ = $2->addParamList( $5 ); }
3773 | '(' identifier_parameter_function ')' // redundant parenthesis
3774 { $$ = $2; }
3775 ;
3776
3777// This pattern parses a declaration for a parameter variable or function prototype that is redefining a typedef name,
3778// e.g.:
3779//
3780// typedef int foo;
3781// forall( otype T ) struct foo;
3782// int f( int foo ); // redefine typedef name in new scope
3783//
3784// and allows the C99 array options, which can only appear in a parameter list.
3785
3786type_parameter_redeclarator:
3787 typedef_name attribute_list_opt
3788 { $$ = $1->addQualifiers( $2 ); }
3789 | '&' MUTEX typedef_name attribute_list_opt
3790 { $$ = $3->addPointer( DeclarationNode::newPointer( DeclarationNode::newTypeQualifier( ast::CV::Mutex ), OperKinds::AddressOf ) )->addQualifiers( $4 ); }
3791 | type_parameter_ptr
3792 | type_parameter_array attribute_list_opt
3793 { $$ = $1->addQualifiers( $2 ); }
3794 | type_parameter_function attribute_list_opt
3795 { $$ = $1->addQualifiers( $2 ); }
3796 ;
3797
3798typedef_name:
3799 TYPEDEFname
3800 { $$ = DeclarationNode::newName( $1 ); }
3801 | TYPEGENname
3802 { $$ = DeclarationNode::newName( $1 ); }
3803 ;
3804
3805type_parameter_ptr:
3806 ptrref_operator type_parameter_redeclarator
3807 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
3808 | ptrref_operator type_qualifier_list type_parameter_redeclarator
3809 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
3810 | '(' type_parameter_ptr ')' attribute_list_opt // redundant parenthesis
3811 { $$ = $2->addQualifiers( $4 ); }
3812 ;
3813
3814type_parameter_array:
3815 typedef_name array_parameter_dimension
3816 { $$ = $1->addArray( $2 ); }
3817 | '(' type_parameter_ptr ')' array_parameter_dimension
3818 { $$ = $2->addArray( $4 ); }
3819 ;
3820
3821type_parameter_function:
3822 typedef_name '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
3823 { $$ = $1->addParamList( $3 ); }
3824 | '(' type_parameter_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
3825 { $$ = $2->addParamList( $5 ); }
3826 ;
3827
3828// This pattern parses a declaration of an abstract variable or function prototype, i.e., there is no identifier to
3829// which the type applies, e.g.:
3830//
3831// sizeof( int );
3832// sizeof( int * );
3833// sizeof( int [10] );
3834// sizeof( int (*)() );
3835// sizeof( int () );
3836//
3837// The pattern precludes declaring an array of functions versus a pointer to an array of functions, and returning arrays
3838// and functions versus pointers to arrays and functions.
3839
3840abstract_declarator:
3841 abstract_ptr
3842 | abstract_array attribute_list_opt
3843 { $$ = $1->addQualifiers( $2 ); }
3844 | abstract_function attribute_list_opt
3845 { $$ = $1->addQualifiers( $2 ); }
3846 ;
3847
3848abstract_ptr:
3849 ptrref_operator
3850 { $$ = DeclarationNode::newPointer( nullptr, $1 ); }
3851 | ptrref_operator type_qualifier_list
3852 { $$ = DeclarationNode::newPointer( $2, $1 ); }
3853 | ptrref_operator abstract_declarator
3854 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
3855 | ptrref_operator type_qualifier_list abstract_declarator
3856 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
3857 | '(' abstract_ptr ')' attribute_list_opt
3858 { $$ = $2->addQualifiers( $4 ); }
3859 ;
3860
3861abstract_array:
3862 array_dimension
3863 | '(' abstract_ptr ')' array_dimension
3864 { $$ = $2->addArray( $4 ); }
3865 | '(' abstract_array ')' multi_array_dimension // redundant parenthesis
3866 { $$ = $2->addArray( $4 ); }
3867 | '(' abstract_array ')' // redundant parenthesis
3868 { $$ = $2; }
3869 ;
3870
3871abstract_function:
3872 '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
3873 { $$ = DeclarationNode::newFunction( nullptr, nullptr, $2, nullptr ); }
3874 | '(' abstract_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
3875 { $$ = $2->addParamList( $5 ); }
3876 | '(' abstract_function ')' // redundant parenthesis
3877 { $$ = $2; }
3878 ;
3879
3880array_dimension:
3881 // Only the first dimension can be empty.
3882 '[' ']'
3883 { $$ = DeclarationNode::newArray( nullptr, nullptr, false ); }
3884 | '[' ']' multi_array_dimension
3885 { $$ = DeclarationNode::newArray( nullptr, nullptr, false )->addArray( $3 ); }
3886 // Cannot use constant_expression because of tuples => semantic check
3887 | '[' push assignment_expression pop ',' comma_expression ']' // CFA
3888 { $$ = DeclarationNode::newArray( $3, nullptr, false )->addArray( DeclarationNode::newArray( $6, nullptr, false ) ); }
3889 // { SemanticError( yylloc, "New array dimension is currently unimplemented." ); $$ = nullptr; }
3890 | '[' push array_type_list pop ']' // CFA
3891 { $$ = DeclarationNode::newArray( $3, nullptr, false ); }
3892 | multi_array_dimension
3893 ;
3894
3895array_type_list:
3896 basic_type_name
3897 { $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); }
3898 | type_name
3899 { $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); }
3900 | assignment_expression upupeq assignment_expression
3901 | array_type_list ',' basic_type_name
3902 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); }
3903 | array_type_list ',' type_name
3904 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); }
3905 | array_type_list ',' assignment_expression upupeq assignment_expression
3906 ;
3907
3908upupeq:
3909 '~'
3910 { $$ = OperKinds::LThan; }
3911 | ErangeUpEq
3912 { $$ = OperKinds::LEThan; }
3913 ;
3914
3915multi_array_dimension:
3916 '[' push assignment_expression pop ']'
3917 { $$ = DeclarationNode::newArray( $3, nullptr, false ); }
3918 | '[' push '*' pop ']' // C99
3919 { $$ = DeclarationNode::newVarArray( 0 ); }
3920 | multi_array_dimension '[' push assignment_expression pop ']'
3921 { $$ = $1->addArray( DeclarationNode::newArray( $4, nullptr, false ) ); }
3922 | multi_array_dimension '[' push '*' pop ']' // C99
3923 { $$ = $1->addArray( DeclarationNode::newVarArray( 0 ) ); }
3924 ;
3925
3926// This pattern parses a declaration of a parameter abstract variable or function prototype, i.e., there is no
3927// identifier to which the type applies, e.g.:
3928//
3929// int f( int ); // not handled here
3930// int f( int * ); // abstract function-prototype parameter; no parameter name specified
3931// int f( int (*)() ); // abstract function-prototype parameter; no parameter name specified
3932// int f( int (int) ); // abstract function-prototype parameter; no parameter name specified
3933//
3934// The pattern precludes declaring an array of functions versus a pointer to an array of functions, and returning arrays
3935// and functions versus pointers to arrays and functions. In addition, the pattern handles the
3936// special meaning of parenthesis around a typedef name:
3937//
3938// ISO/IEC 9899:1999 Section 6.7.5.3(11) : "In a parameter declaration, a single typedef name in
3939// parentheses is taken to be an abstract declarator that specifies a function with a single parameter,
3940// not as redundant parentheses around the identifier."
3941//
3942// For example:
3943//
3944// typedef float T;
3945// int f( int ( T [5] ) ); // see abstract_parameter_declarator
3946// int g( int ( T ( int ) ) ); // see abstract_parameter_declarator
3947// int f( int f1( T a[5] ) ); // see identifier_parameter_declarator
3948// int g( int g1( T g2( int p ) ) ); // see identifier_parameter_declarator
3949//
3950// In essence, a '(' immediately to the left of typedef name, T, is interpreted as starting a parameter type list, and
3951// not as redundant parentheses around a redeclaration of T. Finally, the pattern also precludes declaring an array of
3952// functions versus a pointer to an array of functions, and returning arrays and functions versus pointers to arrays and
3953// functions.
3954
3955abstract_parameter_declarator_opt:
3956 // empty
3957 { $$ = nullptr; }
3958 | abstract_parameter_declarator
3959 ;
3960
3961abstract_parameter_declarator:
3962 abstract_parameter_ptr
3963 | '&' MUTEX attribute_list_opt
3964 { $$ = DeclarationNode::newPointer( DeclarationNode::newTypeQualifier( ast::CV::Mutex ), OperKinds::AddressOf )->addQualifiers( $3 ); }
3965 | abstract_parameter_array attribute_list_opt
3966 { $$ = $1->addQualifiers( $2 ); }
3967 | abstract_parameter_function attribute_list_opt
3968 { $$ = $1->addQualifiers( $2 ); }
3969 ;
3970
3971abstract_parameter_ptr:
3972 ptrref_operator
3973 { $$ = DeclarationNode::newPointer( nullptr, $1 ); }
3974 | ptrref_operator type_qualifier_list
3975 { $$ = DeclarationNode::newPointer( $2, $1 ); }
3976 | ptrref_operator abstract_parameter_declarator
3977 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
3978 | ptrref_operator type_qualifier_list abstract_parameter_declarator
3979 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
3980 | '(' abstract_parameter_ptr ')' attribute_list_opt // redundant parenthesis
3981 { $$ = $2->addQualifiers( $4 ); }
3982 ;
3983
3984abstract_parameter_array:
3985 array_parameter_dimension
3986 | '(' abstract_parameter_ptr ')' array_parameter_dimension
3987 { $$ = $2->addArray( $4 ); }
3988 | '(' abstract_parameter_array ')' multi_array_dimension // redundant parenthesis
3989 { $$ = $2->addArray( $4 ); }
3990 | '(' abstract_parameter_array ')' // redundant parenthesis
3991 { $$ = $2; }
3992 ;
3993
3994abstract_parameter_function:
3995 '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
3996 { $$ = DeclarationNode::newFunction( nullptr, nullptr, $2, nullptr ); }
3997 | '(' abstract_parameter_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
3998 { $$ = $2->addParamList( $5 ); }
3999 | '(' abstract_parameter_function ')' // redundant parenthesis
4000 { $$ = $2; }
4001 ;
4002
4003array_parameter_dimension:
4004 // Only the first dimension can be empty or have qualifiers.
4005 array_parameter_1st_dimension
4006 | array_parameter_1st_dimension multi_array_dimension
4007 { $$ = $1->addArray( $2 ); }
4008 | multi_array_dimension
4009 ;
4010
4011// The declaration of an array parameter has additional syntax over arrays in normal variable declarations:
4012//
4013// ISO/IEC 9899:1999 Section 6.7.5.2(1) : "The optional type qualifiers and the keyword static shall appear only in
4014// a declaration of a function parameter with an array type, and then only in the outermost array type derivation."
4015
4016array_parameter_1st_dimension:
4017 '[' ']'
4018 { $$ = DeclarationNode::newArray( nullptr, nullptr, false ); }
4019 // multi_array_dimension handles the '[' '*' ']' case
4020 | '[' push type_qualifier_list '*' pop ']' // remaining C99
4021 { $$ = DeclarationNode::newVarArray( $3 ); }
4022 | '[' push type_qualifier_list pop ']'
4023 { $$ = DeclarationNode::newArray( nullptr, $3, false ); }
4024 // multi_array_dimension handles the '[' assignment_expression ']' case
4025 | '[' push type_qualifier_list assignment_expression pop ']'
4026 { $$ = DeclarationNode::newArray( $4, $3, false ); }
4027 | '[' push STATIC type_qualifier_list_opt assignment_expression pop ']'
4028 { $$ = DeclarationNode::newArray( $5, $4, true ); }
4029 | '[' push type_qualifier_list STATIC assignment_expression pop ']'
4030 { $$ = DeclarationNode::newArray( $5, $3, true ); }
4031 ;
4032
4033// This pattern parses a declaration of an abstract variable, but does not allow "int ()" for a function pointer.
4034//
4035// struct S {
4036// int;
4037// int *;
4038// int [10];
4039// int (*)();
4040// };
4041
4042variable_abstract_declarator:
4043 variable_abstract_ptr
4044 | variable_abstract_array attribute_list_opt
4045 { $$ = $1->addQualifiers( $2 ); }
4046 | variable_abstract_function attribute_list_opt
4047 { $$ = $1->addQualifiers( $2 ); }
4048 ;
4049
4050variable_abstract_ptr:
4051 ptrref_operator
4052 { $$ = DeclarationNode::newPointer( nullptr, $1 ); }
4053 | ptrref_operator type_qualifier_list
4054 { $$ = DeclarationNode::newPointer( $2, $1 ); }
4055 | ptrref_operator variable_abstract_declarator
4056 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
4057 | ptrref_operator type_qualifier_list variable_abstract_declarator
4058 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
4059 | '(' variable_abstract_ptr ')' attribute_list_opt // redundant parenthesis
4060 { $$ = $2->addQualifiers( $4 ); }
4061 ;
4062
4063variable_abstract_array:
4064 array_dimension
4065 | '(' variable_abstract_ptr ')' array_dimension
4066 { $$ = $2->addArray( $4 ); }
4067 | '(' variable_abstract_array ')' multi_array_dimension // redundant parenthesis
4068 { $$ = $2->addArray( $4 ); }
4069 | '(' variable_abstract_array ')' // redundant parenthesis
4070 { $$ = $2; }
4071 ;
4072
4073variable_abstract_function:
4074 '(' variable_abstract_ptr ')' '(' parameter_type_list_opt ')' // empty parameter list OBSOLESCENT (see 3)
4075 { $$ = $2->addParamList( $5 ); }
4076 | '(' variable_abstract_function ')' // redundant parenthesis
4077 { $$ = $2; }
4078 ;
4079
4080// This pattern parses a new-style declaration for a parameter variable or function prototype that is either an
4081// identifier or typedef name and allows the C99 array options, which can only appear in a parameter list.
4082
4083cfa_identifier_parameter_declarator_tuple: // CFA
4084 cfa_identifier_parameter_declarator_no_tuple
4085 | cfa_abstract_tuple
4086 | type_qualifier_list cfa_abstract_tuple
4087 { $$ = $2->addQualifiers( $1 ); }
4088 ;
4089
4090cfa_identifier_parameter_declarator_no_tuple: // CFA
4091 cfa_identifier_parameter_ptr
4092 | cfa_identifier_parameter_array
4093 ;
4094
4095cfa_identifier_parameter_ptr: // CFA
4096 // No SUE declaration in parameter list.
4097 ptrref_operator type_specifier_nobody
4098 { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
4099 | type_qualifier_list ptrref_operator type_specifier_nobody
4100 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
4101 | ptrref_operator cfa_abstract_function
4102 { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
4103 | type_qualifier_list ptrref_operator cfa_abstract_function
4104 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
4105 | ptrref_operator cfa_identifier_parameter_declarator_tuple
4106 { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
4107 | type_qualifier_list ptrref_operator cfa_identifier_parameter_declarator_tuple
4108 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
4109 ;
4110
4111cfa_identifier_parameter_array: // CFA
4112 // Only the first dimension can be empty or have qualifiers. Empty dimension must be factored out due to
4113 // shift/reduce conflict with new-style empty (void) function return type.
4114 '[' ']' type_specifier_nobody
4115 { $$ = $3->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
4116 | cfa_array_parameter_1st_dimension type_specifier_nobody
4117 { $$ = $2->addNewArray( $1 ); }
4118 | '[' ']' multi_array_dimension type_specifier_nobody
4119 { $$ = $4->addNewArray( $3 )->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
4120 | cfa_array_parameter_1st_dimension multi_array_dimension type_specifier_nobody
4121 { $$ = $3->addNewArray( $2 )->addNewArray( $1 ); }
4122 | multi_array_dimension type_specifier_nobody
4123 { $$ = $2->addNewArray( $1 ); }
4124
4125 | '[' ']' cfa_identifier_parameter_ptr
4126 { $$ = $3->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
4127 | cfa_array_parameter_1st_dimension cfa_identifier_parameter_ptr
4128 { $$ = $2->addNewArray( $1 ); }
4129 | '[' ']' multi_array_dimension cfa_identifier_parameter_ptr
4130 { $$ = $4->addNewArray( $3 )->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
4131 | cfa_array_parameter_1st_dimension multi_array_dimension cfa_identifier_parameter_ptr
4132 { $$ = $3->addNewArray( $2 )->addNewArray( $1 ); }
4133 | multi_array_dimension cfa_identifier_parameter_ptr
4134 { $$ = $2->addNewArray( $1 ); }
4135 ;
4136
4137cfa_array_parameter_1st_dimension:
4138 '[' push type_qualifier_list '*' pop ']' // remaining C99
4139 { $$ = DeclarationNode::newVarArray( $3 ); }
4140 | '[' push type_qualifier_list assignment_expression pop ']'
4141 { $$ = DeclarationNode::newArray( $4, $3, false ); }
4142 | '[' push declaration_qualifier_list assignment_expression pop ']'
4143 // declaration_qualifier_list must be used because of shift/reduce conflict with
4144 // assignment_expression, so a semantic check is necessary to preclude them as a type_qualifier cannot
4145 // appear in this context.
4146 { $$ = DeclarationNode::newArray( $4, $3, true ); }
4147 | '[' push declaration_qualifier_list type_qualifier_list assignment_expression pop ']'
4148 { $$ = DeclarationNode::newArray( $5, $4->addQualifiers( $3 ), true ); }
4149 ;
4150
4151// This pattern parses a new-style declaration of an abstract variable or function prototype, i.e., there is no
4152// identifier to which the type applies, e.g.:
4153//
4154// [int] f( int ); // abstract variable parameter; no parameter name specified
4155// [int] f( [int] (int) ); // abstract function-prototype parameter; no parameter name specified
4156//
4157// These rules need LR(3):
4158//
4159// cfa_abstract_tuple identifier_or_type_name
4160// '[' cfa_parameter_list ']' identifier_or_type_name '(' cfa_parameter_ellipsis_list_opt ')'
4161//
4162// since a function return type can be syntactically identical to a tuple type:
4163//
4164// [int, int] t;
4165// [int, int] f( int );
4166//
4167// Therefore, it is necessary to look at the token after identifier_or_type_name to know when to reduce
4168// cfa_abstract_tuple. To make this LR(1), several rules have to be flattened (lengthened) to allow the necessary
4169// lookahead. To accomplish this, cfa_abstract_declarator has an entry point without tuple, and tuple declarations are
4170// duplicated when appearing with cfa_function_specifier.
4171
4172cfa_abstract_declarator_tuple: // CFA
4173 cfa_abstract_tuple
4174 | type_qualifier_list cfa_abstract_tuple
4175 { $$ = $2->addQualifiers( $1 ); }
4176 | cfa_abstract_declarator_no_tuple
4177 ;
4178
4179cfa_abstract_declarator_no_tuple: // CFA
4180 cfa_abstract_ptr
4181 | cfa_abstract_array
4182 ;
4183
4184cfa_abstract_ptr: // CFA
4185 ptrref_operator type_specifier
4186 { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
4187 | type_qualifier_list ptrref_operator type_specifier
4188 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
4189 | ptrref_operator cfa_abstract_function
4190 { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
4191 | type_qualifier_list ptrref_operator cfa_abstract_function
4192 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
4193 | ptrref_operator cfa_abstract_declarator_tuple
4194 { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
4195 | type_qualifier_list ptrref_operator cfa_abstract_declarator_tuple
4196 { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
4197 ;
4198
4199cfa_abstract_array: // CFA
4200 // Only the first dimension can be empty. Empty dimension must be factored out due to shift/reduce conflict with
4201 // empty (void) function return type.
4202 '[' ']' type_specifier
4203 { $$ = $3->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
4204 | '[' ']' multi_array_dimension type_specifier
4205 { $$ = $4->addNewArray( $3 )->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
4206 | multi_array_dimension type_specifier
4207 { $$ = $2->addNewArray( $1 ); }
4208 | '[' ']' cfa_abstract_ptr
4209 { $$ = $3->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
4210 | '[' ']' multi_array_dimension cfa_abstract_ptr
4211 { $$ = $4->addNewArray( $3 )->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
4212 | multi_array_dimension cfa_abstract_ptr
4213 { $$ = $2->addNewArray( $1 ); }
4214 ;
4215
4216cfa_abstract_tuple: // CFA
4217 '[' push cfa_abstract_parameter_list pop ']'
4218 { $$ = DeclarationNode::newTuple( $3 ); }
4219 | '[' push type_specifier_nobody ELLIPSIS pop ']'
4220 { SemanticError( yylloc, "Tuple array currently unimplemented." ); $$ = nullptr; }
4221 | '[' push type_specifier_nobody ELLIPSIS constant_expression pop ']'
4222 { SemanticError( yylloc, "Tuple array currently unimplemented." ); $$ = nullptr; }
4223 ;
4224
4225cfa_abstract_function: // CFA
4226// '[' ']' '(' cfa_parameter_ellipsis_list_opt ')'
4227// { $$ = DeclarationNode::newFunction( nullptr, DeclarationNode::newTuple( nullptr ), $4, nullptr ); }
4228 cfa_abstract_tuple '(' push cfa_parameter_ellipsis_list_opt pop ')'
4229 { $$ = DeclarationNode::newFunction( nullptr, $1, $4, nullptr ); }
4230 | cfa_function_return '(' push cfa_parameter_ellipsis_list_opt pop ')'
4231 { $$ = DeclarationNode::newFunction( nullptr, $1, $4, nullptr ); }
4232 ;
4233
4234// 1) ISO/IEC 9899:1999 Section 6.7.2(2) : "At least one type specifier shall be given in the declaration specifiers in
4235// each declaration, and in the specifier-qualifier list in each structure declaration and type name."
4236//
4237// 2) ISO/IEC 9899:1999 Section 6.11.5(1) : "The placement of a storage-class specifier other than at the beginning of
4238// the declaration specifiers in a declaration is an obsolescent feature."
4239//
4240// 3) ISO/IEC 9899:1999 Section 6.11.6(1) : "The use of function declarators with empty parentheses (not
4241// prototype-format parameter type declarators) is an obsolescent feature."
4242//
4243// 4) ISO/IEC 9899:1999 Section 6.11.7(1) : "The use of function definitions with separate parameter identifier and
4244// declaration lists (not prototype-format parameter type and identifier declarators) is an obsolescent feature.
4245
4246// ************************ MISCELLANEOUS ********************************
4247
4248comma_opt: // redundant comma
4249 // empty
4250 | ','
4251 ;
4252
4253default_initializer_opt:
4254 // empty
4255 { $$ = nullptr; }
4256 | '=' assignment_expression
4257 { $$ = $2; }
4258 ;
4259
4260%%
4261
4262// ----end of grammar----
4263
4264// Local Variables: //
4265// mode: c++ //
4266// tab-width: 4 //
4267// compile-command: "make install" //
4268// End: //
Note: See TracBrowser for help on using the repository browser.