source: src/Parser/parser.yy@ 1ccae59

Last change on this file since 1ccae59 was c6b4432, checked in by Andrew Beach <ajbeach@…>, 23 months ago

Remove BaseSyntaxNode and clean-up.

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