/**************************************************************************** * * Open Watcom Project * * Copyright (c) 2002-2021 The Open Watcom Contributors. All Rights Reserved. * Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved. * * ======================================================================== * * This file contains Original Code and/or Modifications of Original * Code as defined in and that are subject to the Sybase Open Watcom * Public License version 1.0 (the 'License'). You may not use this file * except in compliance with the License. BY USING THIS FILE YOU AGREE TO * ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is * provided with the Original Code and Modifications, and is also * available at www.sybase.com/developer/opensource. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR * NON-INFRINGEMENT. Please see the License for the specific language * governing rights and limitations under the License. * * ======================================================================== * * Description: PLUSPLUS.Y : description of C++ syntax Modified By Reason -------- -- ------ 92/10/02 Greg Bentz Initial version, shipped as "alpha" Jim Randall Anthony Scian Jim Welch 92/10/02 A.F.Scian changed cast-expression to use MakeNormalCast so we can distinguish programmer specified casts 92/10/15 A.F.Scian added new keywords __stdcall, _Syscall, _Packed, and _Seg16 92/10/16 A.F.Scian - added _Packed semantic actions for OS/2 - added _Seg16 semantic actions for OS/2 - made far16 equivalent to far for 16-bit compiler - made syscall and stdcall equivalent to cdecl for 16-bit compiler 92/10/22 A.F.Scian instead of parsing one global declaration at a time and accepting the tokens, parse all of the global declarations before accepting 92/10/23 A.F.Scian made interrupt a flag instead of a calling convention 92/10/28 A.F.Scian used direct access to standard calling conventions 92/10/29 A.F.Scian - treat exception decls just like arguments - corrected throw to have an optional expr 92/12/01 A.F.Scian added better error messages for missing ';' 92/12/04 A.F.Scian added optional size expression for delete [] 93/01/07 A.F.Scian changed precedence of :> operator to just less than a cast 93/01/27 A.F.Scian added support for '::' 93/01/31 A.F.Scian removed kludge to define class template symbols 93/02/08 A.F.Scian fixed problem with "struct T" followed by id 93/02/09 A.F.Scian added calls to zapTemplateClassDeclSpec (see YYDRIVER.C for explanation) 93/03/11 J.W.Welch New messaging 93/03/16 A.F.Scian streamlined member-declarator to directly call DeclNoInit instead of going through DataInitNoInit 93/03/29 A.F.Scian added semantics for "new (int [x+1])" 5.3.3 "The first array dimension can be a general integral expression even when is used" 93/04/20 A.F.Scian added rules for y_template_scoped_typename to handle nested types inside of templates 93/04/21 A.F.Scian fixed actions for function-declaration to not pop the GS_DECL_SPEC stack until the function body is processed (this allows any linkage on the function symbol to be retained for the entire processing of the function body) 93/07/13 A.F.Scian - added more than one pointer declarator to conversion function ids - fixed concatenation of strings so that the type of the result is correct 93/07/29 A.F.Scian it was impossible to tell the difference between no parms and ( void ) (both had parms == NULL) so code now calls AddExplicitParms which handles the problem by setting a bit in the DECL_INFO 93/08/11 A.F.Scian allow multiple ;'s in member decl lists e.g., struct S { int a;;;; void foo(){};;; }; 93/12/01 A.F.Scian added %ambig directives supported by new YACC 93/12/15 A.F.Scian added operator new []/operator delete [] support 94/03/23 A.F.Scian set up so that class S; doesn't define the class 94/04/18 A.F.Scian added support for "class __export __stdcall X" 94/04/19 A.F.Scian push some calls to FreeDeclInfo into functions that are called before 94/06/08 A.F.Scian improved error message location for missing ';' error messages 94/10/14 A.F.Scian added __declspec( ) 94/10/18 A.F.Scian added kludge to support: typedef struct S { } S, const *CPS; ^^^^^- accept this 94/10/25 A.F.Scian upgrade LHS of assignment-expr so that it accepts casts and pm-exprs 94/11/02 A.F.Scian added support for "class __declspec(dllimport) X" 94/12/07 A.F.Scian added Y_GLOBAL_ID as a valid declarator-id so struct S { friend int ::foo( int ); }; works 95/02/23 A.F.Scian added __builtin_isfloat( ) construct 95/04/28 A.F.Scian added __unaligned modifier 95/05/16 A.F.Scian added class template directives 95/06/28 A.F.Scian added more general offsetof field expressions 96/01/10 A.F.Scian adjusted syntax of __unaligned to match 'const' rather than 'far' 96/02/12 A.F.Scian added support for __declspec( pragma-modifier ) 96/02/26 A.F.Scian added some namespace syntax 96/03/19 A.F.Scian adjusted ++@/--@ grammar as per ISO C++ mtg in Santa Cruz, CA resolutions 96/05/07 A.F.Scian added "using namespace X;" 96/06/07 A.F.Scian added support for multiple ids in __declspec() 96/07/02 A.F.Scian added sizeof 96/07/25 A.F.Scian accept unsigned : 1; as a bitfield 96/10/28 A.F.Scian fixed 96/07/25 so that : 1; still works */ %token Y_IMPOSSIBLE /*** declaration keywords ***/ %token Y_ASM %token Y_AUTO %token Y_BOOL %token Y_CHAR %token Y_CLASS %token Y_CONST %token Y_CONST_CAST %token Y_DELETE %token Y_DOUBLE %token Y_DYNAMIC_CAST %token Y_ELSE %token Y_ENUM %token Y_EXPLICIT %token Y_EXPORT %token Y_EXTERN %token Y_FALSE %token Y_FLOAT %token Y_FOR %token Y_FRIEND %token Y_INLINE %token Y_INT %token Y_LONG %token Y_MUTABLE %token Y_NAMESPACE %token Y_NULLPTR %token Y_NEW %token Y_OPERATOR %token Y_PRIVATE %token Y_PROTECTED %token Y_PUBLIC %token Y_REGISTER %token Y_REINTERPRET_CAST %token Y_SHORT %token Y_SIGNED %token Y_SIZEOF %token Y_STATIC %token Y_STATIC_ASSERT %token Y_STATIC_CAST %token Y_STRUCT %token Y_TEMPLATE %token Y_THIS %token Y_THROW %token Y_TRUE %token Y_TYPEDEF %token Y_TYPEID %token Y_TYPENAME %token Y_UNION %token Y_UNSIGNED %token Y_USING %token Y_VIRTUAL %token Y_VOID %token Y_VOLATILE %token Y_WCHAR_T /*** punctuation and operators ***/ %token Y_COMMA %token Y_QUESTION %token Y_COLON %token Y_SEMI_COLON %token Y_LEFT_PAREN %token Y_RIGHT_PAREN %token Y_LEFT_BRACKET %token Y_RIGHT_BRACKET %token Y_LEFT_BRACE %token Y_RIGHT_BRACE %token Y_TILDE %token Y_EQUAL %token Y_EQ %token Y_EXCLAMATION %token Y_NE %token Y_OR %token Y_OR_EQUAL %token Y_OR_OR %token Y_AND %token Y_AND_EQUAL %token Y_AND_AND %token Y_XOR %token Y_XOR_EQUAL %token Y_GT %token Y_GE %token Y_LT %token Y_LE %token Y_LSHIFT %token Y_LSHIFT_EQUAL %token Y_RSHIFT %token Y_RSHIFT_EQUAL %token Y_PLUS %token Y_PLUS_EQUAL %token Y_PLUS_PLUS %token Y_MINUS %token Y_MINUS_EQUAL %token Y_MINUS_MINUS %token Y_TIMES %token Y_TIMES_EQUAL %token Y_DIV %token Y_DIV_EQUAL %token Y_PERCENT %token Y_PERCENT_EQUAL %token Y_DOT %token Y_DOT_DOT_DOT %token Y_DOT_STAR %token Y_ARROW %token Y_ARROW_STAR %token Y_SEG_OP /*** special lexical tokens ***/ %token Y_ID %token Y_UNKNOWN_ID %token Y_TEMPLATE_ID %token Y_TYPE_NAME %token Y_TEMPLATE_NAME %token Y_NAMESPACE_NAME %token Y_NULLPTR %token Y_CONSTANT %token Y_TRUE %token Y_FALSE %token Y_STRING %token Y_GLOBAL_ID /* :: */ %token Y_GLOBAL_UNKNOWN_ID /* :: */ %token Y_GLOBAL_TEMPLATE_ID /* :: */ %token Y_GLOBAL_TYPE_NAME /* :: */ %token Y_GLOBAL_TEMPLATE_NAME /* :: */ %token Y_GLOBAL_NAMESPACE_NAME /* :: */ %token Y_GLOBAL_OPERATOR /* ::operator */ %token Y_GLOBAL_TILDE /* ::~ */ %token Y_GLOBAL_NEW /* ::new */ %token Y_GLOBAL_DELETE /* ::delete */ /* Y_SCOPED_* tokens must stay in line with Y_TEMPLATE_SCOPED_* tokens */ %token Y_SCOPED_ID /* C:: */ %token Y_SCOPED_UNKNOWN_ID /* C:: */ %token Y_SCOPED_TEMPLATE_ID /* C:: */ %token Y_SCOPED_TYPE_NAME /* C:: */ %token Y_SCOPED_TEMPLATE_NAME /* C:: */ %token Y_SCOPED_NAMESPACE_NAME /* C:: */ %token Y_SCOPED_OPERATOR /* C::operator */ %token Y_SCOPED_TILDE /* C::~ */ %token Y_SCOPED_TIMES /* C::* */ %token Y_TEMPLATE_SCOPED_ID /* T<>:: */ %token Y_TEMPLATE_SCOPED_UNKNOWN_ID/* T<>:: */ %token Y_TEMPLATE_SCOPED_TEMPLATE_ID/* T<>:: */ %token Y_TEMPLATE_SCOPED_TYPE_NAME/* T<>:: */ %token Y_TEMPLATE_SCOPED_TEMPLATE_NAME/* T<>:: */ %token Y_TEMPLATE_SCOPED_NAMESPACE_NAME/* T<>:: */ %token Y_TEMPLATE_SCOPED_OPERATOR/* T<>::operator */ %token Y_TEMPLATE_SCOPED_TILDE /* T<>::~ */ %token Y_TEMPLATE_SCOPED_TIMES /* T<>::* */ /*** leader token for "special" parsing ***/ %token Y_EXPRESSION_SPECIAL %token Y_EXPR_DECL_SPECIAL %token Y_FUNCTION_DECL_SPECIAL %token Y_EXCEPTION_SPECIAL %token Y_MEM_INIT_SPECIAL %token Y_DEFARG_SPECIAL %token Y_TEMPLATE_INT_DEFARG_SPECIAL %token Y_TEMPLATE_TYPE_DEFARG_SPECIAL %token Y_CLASS_INST_SPECIAL /*** terminator tokens for "special" parsing ***/ %token Y_DEFARG_END %token Y_GT_SPECIAL /*** tokens that are never generated by yylex() ***/ %token Y_REDUCE_SPECIAL %token Y_SHIFT_SPECIAL %token Y_DEFARG_GONE_SPECIAL %token Y_TEMPLATE_DEFARG_GONE_SPECIAL %token Y_PURE_FUNCTION_SPECIAL /*** special function names ***/ %token Y_DECLTYPE %token Y___OFFSETOF %token Y___TYPEOF %token Y___BUILTIN_ISFLOAT /*** PC-specific keywords ***/ %token Y___ASM %token Y___BASED %token Y__CDECL %token Y___CDECL %token Y___DECLSPEC %token Y__EXPORT %token Y___EXPORT %token Y___FAR %token Y__FAR16 %token Y___FAR16 %token Y__FASTCALL %token Y___FASTCALL %token Y___FORTRAN %token Y___HUGE %token Y___INLINE %token Y___INT8 %token Y___INT16 %token Y___INT32 %token Y___INT64 %token Y___INTERRUPT %token Y___LOADDS %token Y___NEAR %token Y__OPTLINK %token Y__PACKED %token Y__PASCAL %token Y___PASCAL %token Y___PRAGMA %token Y___SAVEREGS %token Y__SEG16 %token Y___SEGMENT %token Y___SEGNAME %token Y___SELF %token Y___STDCALL %token Y__SYSCALL %token Y___SYSCALL %token Y__SYSTEM %token Y___WATCALL %token Y___UNALIGNED %type segment-cast-opt %type modifier %type access-specifier %type cv-qualifier-seq-opt %type base-qualifiers-opt %type packed-class-opt %type class-key %type template-typename-key %type operator %type class-mod-opt %type class-mod-seq %type class-mod %type ptr-operator %type pragma-modifier %type based-expression %type ptr-mod %type base-specifier base-specifier-list %type ctor-initializer %type defarg-check %type type-specifier-seq %type type-specifier %type typeof-specifier %type decltype-specifier %type arg-decl-specifier-seq %type decl-specifier-seq %type non-type-decl-specifier-seq %type non-type-decl-specifier %type no-declarator-declaration %type basic-type-specifier %type simple-type-specifier %type maybe-type-decl-specifier-seq %type storage-class-specifier %type ms-specific-declspec %type ms-declspec-seq %type function-specifier %type cv-qualifier %type class-specifier %type enum-specifier %type elaborated-type-specifier %type class-substance %type class-body %type qualified-type-specifier %type qualified-class-specifier %type qualified-class-type %type typename-specifier %type function-declaration %type declarator %type comma-declarator %type init-declarator %type comma-init-declarator %type ctor-declarator %type declaring-declarator %type comma-declaring-declarator %type direct-declarator %type ptr-mod-init-declarator %type ptr-mod-declarator %type conversion-declarator %type special-new-abstract-ptr-mod-declarator %type abstract-ptr-mod-declarator %type special-new-abstract-declarator %type abstract-declarator %type special-new-direct-abstract-declarator %type direct-abstract-declarator %type parameter-declaration-clause %type simple-parameter-declaration %type parameter-declaration %type template-parameter %type type-parameter %type type-parameter-no-defarg %type parameter-declaration-list %type actual-exception-declaration %type exception-declaration %type member-declaring-declarator %type member-declarator %type direct-new-declarator %type partial-ptr-declarator %type new-declarator %type dynamic-type-id %type new-type-id %type special-new-type-id %type simple-arg-no-id %type identifier %type boolean-literal %type pointer-literal %type new-keyword %type delete-keyword %type declarator-id %type conversion-type-id %type operator-function-id %type scoped-operator-function-id %type template-scoped-operator-function-id %type conversion-function-id %type scoped-conversion-function-id %type template-scoped-conversion-function-id %type pseudo-destructor-name %type exception-specification-opt %type exception-specification %type expression %type expression-before-semicolon %type expression-list %type expression-list-opt %type assignment-operator %type assignment-expression %type assignment-expression-opt %type conditional-expression %type logical-or-expression %type logical-and-expression %type inclusive-or-expression %type exclusive-or-expression %type and-expression %type equality-expression %type relational-expression %type shift-expression %type additive-expression %type multiplicative-expression %type pm-expression %type cast-expression %type unary-operator %type unary-expression %type offsetof-field %type offsetof-index %type new-expression %type delete-expression %type postfix-expression %type primary-expression %type id-expression %type unqualified-id %type template-scoped-unqualified-id %type qualified-id %type nested-name-specifier %type scoped-nested-name-specifier %type segment-expression %type postfix-expression-before-dot %type postfix-expression-before-arrow %type new-placement %type make-id %type class-name-id %type invalid-class-name-id %type enumerator %type elaborated-type-name %type literal %type string-literal pragma-id %type type-id-list %type type-id %type new-initializer %type new-initializer-opt %type constant-expression %type constant-initializer %type mem-initializer-list %type mem-initializer %type template-id %type scoped-template-id %type template-type %type template-type-instantiation %type scoped-template-type %type scoped-template-type-instantiation %type template-scoped-template-type %type template-scoped-template-type-instantiation %type template-argument %type template-argument-list-opt %type template-argument-list %type qualified-namespace-specifier %type expr-decl-stmt %type goal-symbol %nonassoc Y_LEFT_PAREN %nonassoc Y_FAVOUR_REDUCE_SPECIAL %start goal-symbol %% /* these actions change the token to EOF to force acceptance */ goal-symbol : Y_EXPRESSION_SPECIAL expression { $$ = $2; t = YYEOFTOKEN; } | Y_EXPRESSION_SPECIAL type-specifier-seq declaring-declarator initializer { CheckDeclarationDSpec( state->gstack->u.dspec, GetCurrScope() ); GStackPop( &(state->gstack) ); $$ = $3->id; $3->id = NULL; FreeDeclInfo( $3 ); t = YYEOFTOKEN; } | Y_EXPR_DECL_SPECIAL expr-decl-stmt { $$ = $2; t = YYEOFTOKEN; } | Y_FUNCTION_DECL_SPECIAL decl-specifier-seq declarator { GStackPop( &(state->gstack) ); /* decl-spec */ $$ = (PTREE) $3; t = YYEOFTOKEN; } | Y_FUNCTION_DECL_SPECIAL declarator { $$ = (PTREE) $2; t = YYEOFTOKEN; } | Y_FUNCTION_DECL_SPECIAL decl-specifier-seq ctor-declarator { GStackPop( &(state->gstack) ); /* decl-spec */ $$ = (PTREE) $3; t = YYEOFTOKEN; } | might-restart-declarations { t = YYEOFTOKEN; } | Y_EXCEPTION_SPECIAL exception-declaration { /* treat exception decl like an argument */ $$ = (PTREE) AddArgument( NULL, $2 ); t = YYEOFTOKEN; } | Y_MEM_INIT_SPECIAL mem-initializer-list Y_LEFT_BRACE { $$ = $2; t = YYEOFTOKEN; } | Y_DEFARG_SPECIAL assignment-expression Y_DEFARG_END { $$ = $2; t = YYEOFTOKEN; } | Y_TEMPLATE_INT_DEFARG_SPECIAL logical-or-expression Y_DEFARG_END { $$ = $2; t = YYEOFTOKEN; } | Y_TEMPLATE_TYPE_DEFARG_SPECIAL expect-type-id type-id Y_DEFARG_END { $$ = $3; t = YYEOFTOKEN; } | Y_CLASS_INST_SPECIAL class-specifier { $$ = (PTREE) $2; t = YYEOFTOKEN; } /* I have included this as a stack reset leaves us open to abuse * now we fixed bug 218. All linkage gets reset when we have a * syntax error earlier in the file which screws up closing of the * parser. We only issue an error if we have not reported any * earlier errors as this error comes out badly at the end of a * file */ | Y_RIGHT_BRACE { error_state_t save; CErrCheckpoint( &save ); if( 0 == save ) { SetErrLoc( &yylp[1] ); CErr1( ERR_MISPLACED_RIGHT_BRACE ); what = P_DIAGNOSED; } } | /* nothing */ { if( CurToken != T_EOF ) { CErr1( ERR_SYNTAX ); } what = P_DIAGNOSED; } ; /* error reporting hints */ expect-string-literal : /* nothing */ { state->expect = "string-literal"; } ; expect-identifier : /* nothing */ { state->expect = "identifier"; } ; expect-id-expression : /* nothing */ { state->expect = "id-expression"; } ; expect-type-name : /* nothing */ { state->expect = "type-name"; } ; expect-type-id : /* nothing */ { state->expect = "type-id"; } ; expect-qualified-namespace-specifier : /* nothing */ { state->expect = "qualified-namespace-specifier"; } ; lt-special-init : /* nothing */ { angle_bracket_stack *angle_state; angle_state = VstkPush( &(state->angle_stack) ); angle_state->paren_depth = 0; } ; lt-special : lt-special-init Y_LT ; expr-decl-stmt : expression-before-semicolon Y_SEMI_COLON { $$ = $1; } | local-declaration { $$ = NULL; } ; expression-before-semicolon : expression { $$ = $1; if( t != Y_SEMI_COLON ) { SetErrLoc( &yylocation ); CErr1( ERR_SYNTAX_MISSING_SEMICOLON ); what = P_DIAGNOSED; } } ; /* r/r conflict: * id-expression <- qualified-id (unit production) * access-declaration <- qualified-id */ access-declaration : qualified-id { ClassAccessDeclaration( $1, &yylocation ); } | qualified-type-specifier { ClassAccessTypeDeclaration( $1, &yylocation ); } | Y_SCOPED_UNKNOWN_ID { ClassAccessDeclaration( MakeScopedId( $1 ), &yylocation ); } | nested-name-specifier Y_TEMPLATE_SCOPED_UNKNOWN_ID { PTreeFreeSubtrees( $1 ); ClassAccessDeclaration( MakeScopedId( $2 ), &yylocation ); } ; /* A.2 Lexical conventions [gram.lex] */ identifier : Y_ID | Y_UNKNOWN_ID | Y_TEMPLATE_ID ; literal : Y_CONSTANT /* integer-literal character-literal floating-literal */ | string-literal | boolean-literal | pointer-literal ; string-literal : Y_STRING | string-literal Y_STRING { $$ = PTreeStringLiteralConcat( $1, $2 ); } ; boolean-literal : Y_TRUE | Y_FALSE ; pointer-literal : Y_NULLPTR ; /* A.4 Expressions [gram.expr] */ primary-expression : literal | Y_THIS { $$ = setLocation( PTreeThis(), &yylp[1] ); } | Y_LEFT_PAREN expression Y_RIGHT_PAREN { $$ = $2; } | id-expression ; id-expression : unqualified-id | qualified-id ; unqualified-id : identifier | operator-function-id | conversion-function-id | Y_TILDE expect-type-name Y_TYPE_NAME /* ~ class-name */ { $$ = setLocation( MakeDestructorId( $3 ), &yylp[1] ); } | Y_TILDE expect-type-name Y_UNKNOWN_ID /* ~ id (non-stanard, diagnostics only) */ { $$ = setLocation( MakeDestructorId( $3 ), &yylp[1] ); } | Y_TILDE expect-type-name template-type /* ~ class-name */ { $$ = setLocation( MakeDestructorIdFromType( PTypeClassInstantiation( state->class_colon, $3 ) ), &yylp[1] ); } | template-id ; qualified-id : nested-name-specifier template-scoped-unqualified-id { PTreeFreeSubtrees( $1 ); $$ = $2; } | Y_GLOBAL_ID /* :: identifier */ { $$ = MakeGlobalId( $1 ); } | Y_GLOBAL_TEMPLATE_ID /* :: identifier */ { $$ = MakeGlobalId( $1 ); } | Y_SCOPED_ID { $$ = MakeScopedId( $1 ); } | Y_SCOPED_TEMPLATE_ID { $$ = MakeScopedId( $1 ); } | scoped-operator-function-id | scoped-conversion-function-id | scoped-template-id | pseudo-destructor-name ; /* differs from standard */ nested-name-specifier : template-type | scoped-template-type | template-type scoped-nested-name-specifier { PTreeFreeSubtrees( $1 ); $$ = $2; } | scoped-template-type scoped-nested-name-specifier { PTreeFreeSubtrees( $1 ); $$ = $2; } ; /* non-standard */ scoped-nested-name-specifier : template-scoped-template-type | template-scoped-template-type scoped-nested-name-specifier { PTreeFreeSubtrees( $1 ); $$ = $2; } ; /* non-standard */ template-scoped-unqualified-id : Y_TEMPLATE_SCOPED_ID { $$ = MakeScopedId( $1 ); } | Y_TEMPLATE_SCOPED_TEMPLATE_ID { $$ = MakeScopedId( $1 ); } | Y_TEMPLATE_SCOPED_TEMPLATE_ID lt-special template-argument-list-opt Y_GT_SPECIAL | Y_TEMPLATE_SCOPED_TEMPLATE_NAME lt-special template-argument-list-opt Y_GT_SPECIAL | template-scoped-operator-function-id | template-scoped-conversion-function-id ; postfix-expression : primary-expression | postfix-expression Y_LEFT_BRACKET expression Y_RIGHT_BRACKET { $$ = setLocation( PTreeBinary( CO_INDEX, $1, $3 ), &yylp[2] ); } | postfix-expression Y_LEFT_PAREN expression-list-opt Y_RIGHT_PAREN { $$ = setLocation( PTreeBinary( CO_CALL, $1, $3 ), &yylp[2] ); } | simple-type-specifier Y_LEFT_PAREN expression-list-opt Y_RIGHT_PAREN %ambig 0 Y_LEFT_PAREN { $$ = setLocation( MakeFunctionLikeCast( $1, $3 ), &yylp[2] ); } | typename-specifier Y_LEFT_PAREN expression-list-opt Y_RIGHT_PAREN { $$ = setLocation( MakeFunctionLikeCast( $1, $3 ), &yylp[2] ); } | postfix-expression-before-dot Y_DOT expect-id-expression id-expression { $$ = PTreeReplaceRight( setLocation( $1, &yylp[3] ), $4 ); } | postfix-expression-before-arrow Y_ARROW expect-id-expression id-expression { $$ = PTreeReplaceRight( setLocation( $1, &yylp[3] ), $4 ); } /* id-expression includes pseudo-destructor-name | postfix-expression-before-dot Y_DOT pseudo-destructor-name | postfix-expression-before-arrow Y_ARROW pseudo-destructor-name */ | postfix-expression Y_PLUS_PLUS { $$ = setLocation( PTreeUnary( CO_POST_PLUS_PLUS, $1 ), &yylp[2] ); } | postfix-expression Y_MINUS_MINUS { $$ = setLocation( PTreeUnary( CO_POST_MINUS_MINUS, $1 ), &yylp[2] ); } | Y_DYNAMIC_CAST lt-special expect-type-id type-id Y_GT_SPECIAL Y_LEFT_PAREN expression Y_RIGHT_PAREN { $$ = setLocation( PTreeBinary( CO_DYNAMIC_CAST, $4, $7 ), &yylp[1] ); } | Y_STATIC_CAST lt-special expect-type-id type-id Y_GT_SPECIAL Y_LEFT_PAREN expression Y_RIGHT_PAREN { $$ = setLocation( PTreeBinary( CO_STATIC_CAST, $4, $7 ), &yylp[1] ); } | Y_REINTERPRET_CAST lt-special expect-type-id type-id Y_GT_SPECIAL Y_LEFT_PAREN expression Y_RIGHT_PAREN { $$ = setLocation( PTreeBinary( CO_REINTERPRET_CAST, $4, $7 ), &yylp[1] ); } | Y_CONST_CAST lt-special expect-type-id type-id Y_GT_SPECIAL Y_LEFT_PAREN expression Y_RIGHT_PAREN { $$ = setLocation( PTreeBinary( CO_CONST_CAST, $4, $7 ), &yylp[1] ); } | Y_TYPEID Y_LEFT_PAREN expression Y_RIGHT_PAREN { $$ = setLocation( PTreeUnary( CO_TYPEID_EXPR, $3 ), &yylp[1] ); } | Y_TYPEID Y_LEFT_PAREN type-id Y_RIGHT_PAREN { $$ = setLocation( PTreeUnary( CO_TYPEID_TYPE, $3 ), &yylp[1] ); } /* extension */ | Y___SEGNAME Y_LEFT_PAREN expect-string-literal string-literal Y_RIGHT_PAREN { $$ = setLocation( PTreeUnary( CO_SEGNAME, $4 ), &yylp[1] ); } ; /* non-standard */ postfix-expression-before-dot : postfix-expression { $1 = PTreeTraversePostfix( $1, &AnalyseNode ); if( ($1->flags & PTF_LV_CHECKED) == 0 ) { AnalyseLvalue( &$1 ); } $1 = PTreeTraversePostfix( $1, &setAnalysedFlag ); if( $1->type ) { TYPE cls; cls = TypedefModifierRemoveOnly( $1->type ); if( ( cls != NULL ) && ( cls->id == TYP_POINTER ) && (cls->flag & TF1_REFERENCE) ) { cls = cls->of; } if( cls != NULL ) { cls = BindTemplateClass( cls, &$1->locn, false ); $1->type = BoundTemplateClass( $1->type ); cls = TypedefModifierRemoveOnly( cls ); if( cls->id == TYP_CLASS ) { setTypeMember( state, cls->u.c.scope ); } } } $$ = PTreeBinary( CO_DOT, $1, NULL ); } ; /* non-standard */ postfix-expression-before-arrow : postfix-expression { $1 = PTreeTraversePostfix( $1, &AnalyseNode ); if( ($1->flags & PTF_LV_CHECKED) == 0 ) { AnalyseLvalue( &$1 ); } $$ = PTreeBinary( CO_ARROW, $1, NULL ); $$ = OverloadOperator( $$ ); $$->u.subtree[0] = PTreeTraversePostfix( $$->u.subtree[0], &setAnalysedFlag ); if( $$->u.subtree[0] ) { TYPE cls; cls = TypedefModifierRemoveOnly( $$->u.subtree[0]->type ); if( ( cls != NULL ) && ( cls->id == TYP_POINTER ) && (cls->flag & TF1_REFERENCE) ) { cls = TypedefModifierRemoveOnly( cls->of ); } if( ( cls != NULL ) && cls->id == TYP_POINTER ) { cls = BindTemplateClass( cls->of, &$1->locn, false ); $1->type = BoundTemplateClass( $1->type ); cls = TypedefModifierRemoveOnly( cls ); if( cls->id == TYP_CLASS ) { setTypeMember( state, cls->u.c.scope ); } } } } ; expression-list-opt : /* nothing */ { $$ = NULL; } | expression-list ; expression-list : assignment-expression { $$ = PTreeBinary( CO_LIST, NULL, $1 ); } | expression-list Y_COMMA assignment-expression { $$ = setLocation( PTreeBinary( CO_LIST, $1, $3 ), &yylp[2] ); } ; pseudo-destructor-name : Y_SCOPED_TILDE expect-type-name identifier { $$ = setLocation( MakeScopedDestructorId( $1, $3 ), &yylp[1] ); } | Y_SCOPED_TILDE expect-type-name Y_TYPE_NAME { $$ = setLocation( MakeScopedDestructorId( $1, $3 ), &yylp[1] ); } | nested-name-specifier Y_TEMPLATE_SCOPED_TILDE expect-type-name Y_ID { PTreeFreeSubtrees( $1 ); $$ = setLocation( MakeScopedDestructorId( $2, $4 ), &yylp[2] ); } | nested-name-specifier Y_TEMPLATE_SCOPED_TILDE expect-type-name Y_UNKNOWN_ID { PTreeFreeSubtrees( $1 ); $$ = setLocation( MakeScopedDestructorId( $2, $4 ), &yylp[2] ); } | nested-name-specifier Y_TEMPLATE_SCOPED_TILDE expect-type-name Y_TEMPLATE_NAME { PTreeFreeSubtrees( $1 ); $$ = setLocation( MakeScopedDestructorId( $2, $4 ), &yylp[2] ); } | nested-name-specifier Y_TEMPLATE_SCOPED_TILDE expect-type-name Y_TYPE_NAME { $$ = setLocation( MakeScopedDestructorId( $2, $4 ), &yylp[1] ); } ; unary-expression : postfix-expression | Y_PLUS_PLUS cast-expression { $$ = setLocation( PTreeUnary( CO_PRE_PLUS_PLUS, $2 ), &yylp[1] ); } | Y_MINUS_MINUS cast-expression { $$ = setLocation( PTreeUnary( CO_PRE_MINUS_MINUS, $2 ), &yylp[1] ); } | unary-operator cast-expression { $$ = PTreeReplaceLeft( $1, $2 ); } | Y_SIZEOF unary-expression { $$ = setLocation( PTreeUnary( CO_SIZEOF_EXPR, $2 ), &yylp[1] ); } | Y_SIZEOF Y_LEFT_PAREN type-id Y_RIGHT_PAREN { $$ = setLocation( PTreeUnary( CO_SIZEOF_TYPE, $3 ), &yylp[1] ); } | new-expression | delete-expression /* extension */ | Y_SIZEOF Y_TYPE_NAME { $$ = setLocation( PTreeUnary( CO_SIZEOF_TYPE, PTreeMSSizeofKludge( $2 ) ), &yylp[1] ); } | Y___BUILTIN_ISFLOAT Y_LEFT_PAREN expect-type-id type-id Y_RIGHT_PAREN { $$ = setLocation( MakeBuiltinIsFloat( $4 ), &yylp[1] ); } | Y___OFFSETOF Y_LEFT_PAREN expect-type-id type-id Y_COMMA offsetof-field Y_RIGHT_PAREN { $$ = setLocation( PTreeOffsetof( $4, $6 ), &yylp[5] ); } ; unary-operator : Y_TIMES { $$ = setLocation( PTreeUnary( CO_INDIRECT, NULL ), &yylp[1] ); } | Y_AND { $$ = setLocation( PTreeUnary( CO_ADDR_OF, NULL ), &yylp[1] ); } | Y_PLUS { $$ = setLocation( PTreeUnary( CO_UPLUS, NULL ), &yylp[1] ); } | Y_MINUS { $$ = setLocation( PTreeUnary( CO_UMINUS, NULL ), &yylp[1] ); } | Y_EXCLAMATION { $$ = setLocation( PTreeUnary( CO_EXCLAMATION, NULL ), &yylp[1] ); } | Y_TILDE { $$ = setLocation( PTreeUnary( CO_TILDE, NULL ), &yylp[1] ); } ; new-expression : new-keyword new-modifier-opt new-placement new-type-id new-initializer-opt { $$ = setLocation( MakeNewExpr( $1, $3, $4, $5 ), &$1->locn ); PTreeFreeSubtrees( $1 ); } | new-keyword new-modifier-opt new-type-id new-initializer-opt { $$ = setLocation( MakeNewExpr( $1, NULL, $3, $4 ), &$1->locn ); PTreeFreeSubtrees( $1 ); } | new-keyword new-modifier-opt new-placement Y_LEFT_PAREN special-new-type-id Y_RIGHT_PAREN new-initializer-opt /* TODO */ { $$ = setLocation( MakeNewExpr( $1, $3, $5, $7 ), &$1->locn ); PTreeFreeSubtrees( $1 ); } | new-keyword new-modifier-opt Y_LEFT_PAREN special-new-type-id Y_RIGHT_PAREN new-initializer-opt /* TODO */ { $$ = setLocation( MakeNewExpr( $1, NULL, $4, $6 ), &$1->locn ); PTreeFreeSubtrees( $1 ); } ; /* non-standard */ new-keyword : Y_NEW { $$ = makeUnary( CO_NEW, NULL); } | Y_GLOBAL_NEW ; new-modifier-opt : /* nothing */ | modifier { CheckNewModifier( $1 ); } ; new-placement : Y_LEFT_PAREN expression-list Y_RIGHT_PAREN { $$ = $2; } ; new-type-id : dynamic-type-id | Y_LEFT_PAREN special-new-type-id Y_RIGHT_PAREN { $$ = $2; } ; new-initializer-opt : /* nothing */ { $$ = NULL; } | new-initializer ; new-initializer : Y_LEFT_PAREN Y_RIGHT_PAREN { $$ = NULL; } /* ARM p.61 '()' is syntactic convenience */ | Y_LEFT_PAREN expression-list Y_RIGHT_PAREN { $$ = $2; } ; dynamic-type-id : type-specifier-seq { $$ = MakeNewTypeId( DoDeclSpec( state->gstack->u.dspec ) ); GStackPop( &(state->gstack) ); } | type-specifier-seq new-declarator { $$ = $2; GStackPop( &(state->gstack) ); } ; /* TODO */ new-declarator : partial-ptr-declarator direct-new-declarator { $$ = MakeNewDeclarator( state->gstack->u.dspec, $1, $2 ); } | partial-ptr-declarator { $$ = MakeNewDeclarator( state->gstack->u.dspec, $1, NULL ); } | direct-new-declarator { $$ = MakeNewDeclarator( state->gstack->u.dspec, NULL, $1 ); } ; delete-expression : delete-keyword cast-expression { $$ = setLocation( MakeDeleteExpr( $1, ( $1 == NULL ) ? CO_DELETE : CO_DELETE_G, $2 ), &yylp[1] ); } | delete-keyword Y_LEFT_BRACKET delete-size-expression-opt Y_RIGHT_BRACKET cast-expression { $$ = setLocation( MakeDeleteExpr( $1, ( $1 == NULL ) ? CO_DELETE_ARRAY : CO_DELETE_G_ARRAY, $5 ), &yylp[1] ); } ; /* non-standard */ delete-keyword : Y_DELETE { $$ = NULL; } | Y_GLOBAL_DELETE ; /* non-standard */ delete-size-expression-opt : /* nothing */ | expression { PTreeDeleteSizeExpr( $1 ); } ; cast-expression : unary-expression | Y_LEFT_PAREN type-id Y_RIGHT_PAREN cast-expression { $$ = setLocation( MakeNormalCast( $2, $4 ), &yylp[3] ); } ; /* extension */ segment-expression : cast-expression | segment-expression Y_SEG_OP cast-expression { $$ = setLocation( PTreeBinary( CO_SEG_OP, $1, $3 ), &yylp[2] ); } ; pm-expression : segment-expression | pm-expression Y_DOT_STAR segment-expression { $$ = setLocation( PTreeBinary( CO_DOT_STAR, $1, $3 ), &yylp[2] ); } | pm-expression Y_ARROW_STAR segment-expression { $$ = setLocation( PTreeBinary( CO_ARROW_STAR, $1, $3 ), &yylp[2] ); } ; multiplicative-expression : pm-expression | multiplicative-expression Y_TIMES pm-expression { $$ = setLocation( PTreeBinary( CO_TIMES, $1, $3 ), &yylp[2] ); } | multiplicative-expression Y_DIV pm-expression { $$ = setLocation( PTreeBinary( CO_DIVIDE, $1, $3 ), &yylp[2] ); } | multiplicative-expression Y_PERCENT pm-expression { $$ = setLocation( PTreeBinary( CO_PERCENT, $1, $3 ), &yylp[2] ); } ; additive-expression : multiplicative-expression | additive-expression Y_PLUS multiplicative-expression { $$ = setLocation( PTreeBinary( CO_PLUS, $1, $3 ), &yylp[2] ); } | additive-expression Y_MINUS multiplicative-expression { $$ = setLocation( PTreeBinary( CO_MINUS, $1, $3 ), &yylp[2] ); } ; shift-expression : additive-expression | shift-expression Y_RSHIFT additive-expression { $$ = setLocation( PTreeBinary( CO_RSHIFT, $1, $3 ), &yylp[2] ); } | shift-expression Y_LSHIFT additive-expression { $$ = setLocation( PTreeBinary( CO_LSHIFT, $1, $3 ), &yylp[2] ); } ; relational-expression : shift-expression | relational-expression Y_LT shift-expression { $$ = setLocation( PTreeBinary( CO_LT, $1, $3 ), &yylp[2] ); } | relational-expression Y_LE shift-expression { $$ = setLocation( PTreeBinary( CO_LE, $1, $3 ), &yylp[2] ); } | relational-expression Y_GT shift-expression { $$ = setLocation( PTreeBinary( CO_GT, $1, $3 ), &yylp[2] ); } | relational-expression Y_GE shift-expression { $$ = setLocation( PTreeBinary( CO_GE, $1, $3 ), &yylp[2] ); } ; equality-expression : relational-expression | equality-expression Y_EQ relational-expression { $$ = setLocation( PTreeBinary( CO_EQ, $1, $3 ), &yylp[2] ); } | equality-expression Y_NE relational-expression { $$ = setLocation( PTreeBinary( CO_NE, $1, $3 ), &yylp[2] ); } ; and-expression : equality-expression | and-expression Y_AND equality-expression { $$ = setLocation( PTreeBinary( CO_AND, $1, $3 ), &yylp[2] ); } ; exclusive-or-expression : and-expression | exclusive-or-expression Y_XOR and-expression { $$ = setLocation( PTreeBinary( CO_XOR, $1, $3 ), &yylp[2] ); } ; inclusive-or-expression : exclusive-or-expression | inclusive-or-expression Y_OR exclusive-or-expression { $$ = setLocation( PTreeBinary( CO_OR, $1, $3 ), &yylp[2] ); } ; logical-and-expression : inclusive-or-expression | logical-and-expression Y_AND_AND inclusive-or-expression { $$ = setLocation( PTreeBinary( CO_AND_AND, $1, $3 ), &yylp[2] ); } ; logical-or-expression : logical-and-expression | logical-or-expression Y_OR_OR logical-and-expression { $$ = setLocation( PTreeBinary( CO_OR_OR, $1, $3 ), &yylp[2] ); } ; conditional-expression : logical-or-expression | logical-or-expression Y_QUESTION expression Y_COLON assignment-expression { $3 = setLocation( PTreeBinary( CO_COLON, $3, $5 ), &yylp[4] ); $$ = setLocation( PTreeBinary( CO_QUESTION, $1, $3 ), &yylp[2] ); } ; assignment-expression : conditional-expression | logical-or-expression assignment-operator assignment-expression { $$ = PTreeReplaceLeft( $2, $1 ); $$ = PTreeReplaceRight( $$, $3 ); } | Y_THROW assignment-expression-opt { $$ = setLocation( PTreeUnary( CO_THROW, $2 ), &yylp[1] ); } ; assignment-expression-opt : /* nothing */ { $$ = NULL; } | assignment-expression ; assignment-operator : Y_EQUAL { $$ = setLocation( PTreeBinary( CO_EQUAL, NULL, NULL ), &yylp[1] ); } | Y_TIMES_EQUAL { $$ = setLocation( PTreeBinary( CO_TIMES_EQUAL, NULL, NULL ), &yylp[1] ); } | Y_DIV_EQUAL { $$ = setLocation( PTreeBinary( CO_DIVIDE_EQUAL, NULL, NULL ), &yylp[1] ); } | Y_PERCENT_EQUAL { $$ = setLocation( PTreeBinary( CO_PERCENT_EQUAL, NULL, NULL ), &yylp[1] ); } | Y_PLUS_EQUAL { $$ = setLocation( PTreeBinary( CO_PLUS_EQUAL, NULL, NULL ), &yylp[1] ); } | Y_MINUS_EQUAL { $$ = setLocation( PTreeBinary( CO_MINUS_EQUAL, NULL, NULL ), &yylp[1] ); } | Y_LSHIFT_EQUAL { $$ = setLocation( PTreeBinary( CO_LSHIFT_EQUAL, NULL, NULL ), &yylp[1] ); } | Y_RSHIFT_EQUAL { $$ = setLocation( PTreeBinary( CO_RSHIFT_EQUAL, NULL, NULL ), &yylp[1] ); } | Y_OR_EQUAL { $$ = setLocation( PTreeBinary( CO_OR_EQUAL, NULL, NULL ), &yylp[1] ); } | Y_AND_EQUAL { $$ = setLocation( PTreeBinary( CO_AND_EQUAL, NULL, NULL ), &yylp[1] ); } | Y_XOR_EQUAL { $$ = setLocation( PTreeBinary( CO_XOR_EQUAL, NULL, NULL ), &yylp[1] ); } ; expression : assignment-expression | expression Y_COMMA assignment-expression { $$ = setLocation( PTreeBinary( CO_COMMA, $1, $3 ), &yylp[2] ); } ; constant-expression : conditional-expression { $$ = PTreeNonZeroConstantExpr( $1 ); } ; offsetof-field : make-id { $$ = PTreeBinary( CO_DOT, $1, NULL ); $$ = PTreeBinary( CO_DOT, NULL, $$ ); } | make-id offsetof-index { $$ = PTreeBinary( CO_DOT, $1, $2 ); $$ = PTreeBinary( CO_DOT, NULL, $$ ); } | offsetof-field Y_DOT make-id { $$ = setLocation( PTreeBinary( CO_DOT, $3, NULL ), &yylp[2] ); $$ = setLocation( PTreeBinary( CO_DOT, $1, $$ ), &yylp[2] ); } | offsetof-field Y_DOT make-id offsetof-index { $$ = setLocation( PTreeBinary( CO_DOT, $3, $4 ), &yylp[2] ); $$ = setLocation( PTreeBinary( CO_DOT, $1, $$ ), &yylp[2] ); } ; offsetof-index : Y_LEFT_BRACKET constant-expression Y_RIGHT_BRACKET { $$ = setLocation( PTreeBinary( CO_INDEX, NULL, $2 ), &yylp[1] ); } | offsetof-index Y_LEFT_BRACKET constant-expression Y_RIGHT_BRACKET { $$ = setLocation( PTreeBinary( CO_INDEX, $1, $3 ), &yylp[2] ); } ; partial-ptr-declarator : Y_TIMES cv-qualifier-seq-opt partial-ptr-declarator { $$ = MakeNewPointer( $2, $3, NULL ); } | Y_TIMES cv-qualifier-seq-opt { $$ = MakeNewPointer( $2, NULL, NULL ); } | Y_SCOPED_TIMES cv-qualifier-seq-opt partial-ptr-declarator { $$ = MakeNewPointer( $2, $3, $1 ); } | Y_SCOPED_TIMES cv-qualifier-seq-opt { $$ = MakeNewPointer( $2, NULL, $1 ); } | nested-name-specifier Y_TEMPLATE_SCOPED_TIMES cv-qualifier-seq-opt partial-ptr-declarator { $$ = MakeNewPointer( $3, $4, $2 ); PTreeFreeSubtrees( $1 ); } | nested-name-specifier Y_TEMPLATE_SCOPED_TIMES cv-qualifier-seq-opt { $$ = MakeNewPointer( $3, NULL, $2 ); PTreeFreeSubtrees( $1 ); } ; direct-new-declarator : Y_LEFT_BRACKET expression Y_RIGHT_BRACKET { $$ = MakeNewDynamicArray( $2 ); } | direct-new-declarator Y_LEFT_BRACKET constant-expression Y_RIGHT_BRACKET { $$ = AddArrayDeclarator( $1, $3 ); } ; make-id : Y_ID | Y_UNKNOWN_ID | Y_TEMPLATE_ID | Y_TYPE_NAME | Y_TEMPLATE_NAME | Y_NAMESPACE_NAME ; /* A.5 Statements [gram.stmt] */ /* A.6 Declarations [gram.dcl] */ /* should only be referenced by might-restart-declarations */ declaration-seq : declaration | declaration-seq declaration ; /* slightly differs from standard */ declaration : block-declaration-before-semicolon Y_SEMI_COLON | function-definition | template-declaration /* | explicit-specialization */ | explicit-instantiation | linkage-specification | namespace-definition | Y_SEMI_COLON /* extension */ ; block-declaration-before-semicolon : block-declaration { if( t != Y_SEMI_COLON ) { SetErrLoc( &yylocation ); CErr1( ERR_SYNTAX_MISSING_SEMICOLON ); what = P_DIAGNOSED; } } ; block-declaration : simple-declaration | asm-definition | namespace-alias-definition | using-declaration | using-directive | static_assert-declaration ; simple-declaration : decl-specifier-seq init-declarator-list { CheckDeclarationDSpec( state->gstack->u.dspec, GetCurrScope() ); GStackPop( &(state->gstack) ); } | no-declarator-declaration { CheckDeclarationDSpec( state->gstack->u.dspec, GetCurrScope() ); GStackPop( &(state->gstack) ); } ; static_assert-declaration : Y_STATIC_ASSERT Y_LEFT_PAREN constant-expression Y_COMMA expect-string-literal string-literal Y_RIGHT_PAREN { /* see N1720 -- Proposal to Add Static Assertions to the Core * Language (Revision 3) */ DbgAssert( $3->op == PT_INT_CONSTANT ); DbgAssert( $6->op == PT_STRING_CONSTANT ); if( $3->u.int_constant == 0 ) { CErr2p( ERR_STATIC_ASSERTION_FAILURE, $6->u.string->string ); } PTreeFreeSubtrees( $3 ); PTreeFreeSubtrees( $6 ); } ; /* TODO */ decl-specifier-seq : non-type-decl-specifier-seq type-specifier maybe-type-decl-specifier-seq { $1 = PTypeCombine( $1, $2 ); $$ = PTypeCombine( $1, $3 ); $$ = PTypeDone( $$, t == Y_SEMI_COLON ); pushUserDeclSpec( state, $$ ); } | non-type-decl-specifier-seq type-specifier { $$ = PTypeCombine( $1, $2 ); $$ = PTypeDone( $$, t == Y_SEMI_COLON ); pushUserDeclSpec( state, $$ ); } | type-specifier maybe-type-decl-specifier-seq { $$ = PTypeCombine( $1, $2 ); $$ = PTypeDone( $$, t == Y_SEMI_COLON ); pushUserDeclSpec( state, $$ ); } | type-specifier { $$ = PTypeDone( $1, t == Y_SEMI_COLON ); pushUserDeclSpec( state, $$ ); } | non-type-decl-specifier-seq { $$ = PTypeDone( $1, t == Y_SEMI_COLON ); pushUserDeclSpec( state, $$ ); } ; /* non-standard */ non-type-decl-specifier-seq : non-type-decl-specifier | non-type-decl-specifier-seq non-type-decl-specifier { $$ = PTypeCombine( $1, $2 ); } ; /* non-standard */ maybe-type-decl-specifier-seq : non-type-decl-specifier | basic-type-specifier | maybe-type-decl-specifier-seq non-type-decl-specifier { $$ = PTypeCombine( $1, $2 ); } | maybe-type-decl-specifier-seq basic-type-specifier { $$ = PTypeCombine( $1, $2 ); } ; /* non-standard */ non-type-decl-specifier : storage-class-specifier | function-specifier | cv-qualifier | ms-specific-declspec | Y_FRIEND { $$ = PTypeSpecifier( STY_FRIEND ); } ; /* non-standard */ ms-specific-declspec : Y___DECLSPEC Y_LEFT_PAREN Y_RIGHT_PAREN { $$ = PTypeMSDeclSpec( NULL, NULL ); } | Y___DECLSPEC Y_LEFT_PAREN ms-declspec-seq Y_RIGHT_PAREN { $$ = $3; } ; /* non-standard */ ms-declspec-seq : make-id { $$ = PTypeMSDeclSpec( NULL, $1 ); } | pragma-modifier { $$ = PTypeMSDeclSpecModifier( NULL, $1 ); } | ms-declspec-seq make-id { $$ = PTypeMSDeclSpec( $1, $2 ); } | ms-declspec-seq pragma-modifier { $$ = PTypeMSDeclSpecModifier( $1, $2 ); } ; storage-class-specifier : Y_AUTO { $$ = PTypeStgClass( STG_AUTO ); } | Y_REGISTER { $$ = PTypeStgClass( STG_REGISTER ); } | Y_STATIC { $$ = PTypeStgClass( STG_STATIC ); } | Y_EXTERN { $$ = PTypeStgClass( STG_EXTERN ); } | Y_MUTABLE { $$ = PTypeStgClass( STG_MUTABLE ); } /* extension */ | Y_EXTERN linkage-id { $$ = PTypeLinkage(); } | Y_TYPEDEF { $$ = PTypeStgClass( STG_TYPEDEF ); } ; function-specifier : Y_INLINE { $$ = PTypeSpecifier( STY_INLINE ); } | Y_VIRTUAL { $$ = PTypeSpecifier( STY_VIRTUAL ); } | Y_EXPLICIT { $$ = PTypeSpecifier( STY_EXPLICIT ); } /* extension */ | Y___INLINE { $$ = PTypeSpecifier( STY_INLINE ); } ; type-specifier : simple-type-specifier %prec Y_FAVOUR_REDUCE_SPECIAL %ambig 0 Y_LEFT_PAREN | class-specifier | enum-specifier | elaborated-type-specifier | typename-specifier /* cv-qualifier */ ; simple-type-specifier : Y_TYPE_NAME { $$ = sendType( $1 ); } | qualified-type-specifier | basic-type-specifier /* see N1978 -- Decltype (Revision 5) */ | decltype-specifier /* extension */ | typeof-specifier ; decltype-specifier : Y_DECLTYPE Y_LEFT_PAREN id-expression Y_RIGHT_PAREN { $$ = PTypeDecltypeExpr( $3, true ); } | Y_DECLTYPE Y_LEFT_PAREN expression Y_RIGHT_PAREN { $$ = PTypeDecltypeExpr( $3, false ); } ; /* non-standard */ qualified-type-specifier : Y_GLOBAL_TYPE_NAME { $$ = sendType( $1 ); } | Y_SCOPED_TYPE_NAME { $$ = sendType( $1 ); } | nested-name-specifier { $$ = PTypeClassInstantiation( state->class_colon, $1 ); } | nested-name-specifier Y_TEMPLATE_SCOPED_TYPE_NAME { PTreeFreeSubtrees( $1 ); $$ = sendType( $2 ); } ; enum-specifier : enum-key enum-start enumerator-list Y_COMMA Y_RIGHT_BRACE { $$ = MakeEnumType( &(state->gstack->u.enumdata) ); GStackPop( &(state->gstack) ); // TODO: warning non-standard } | enum-key enum-start enumerator-list Y_RIGHT_BRACE { $$ = MakeEnumType( &(state->gstack->u.enumdata) ); GStackPop( &(state->gstack) ); } | enum-key enum-start Y_RIGHT_BRACE { $$ = MakeEnumType( &(state->gstack->u.enumdata) ); GStackPop( &(state->gstack) ); } ; /* non-standard */ enum-start : Y_LEFT_BRACE { EnumDefine( &(state->gstack->u.enumdata) ); } ; /* non-standard */ enum-key : Y_ENUM make-id { GStackPush( &(state->gstack), GS_ENUM_DATA ); InitEnumState( &(state->gstack->u.enumdata), $2 ); } | Y_ENUM { GStackPush( &(state->gstack), GS_ENUM_DATA ); InitEnumState( &(state->gstack->u.enumdata), NULL ); } ; enumerator-list : enumerator-definition | enumerator-list Y_COMMA enumerator-definition ; /* TODO */ enumerator-definition : enumerator { MakeEnumMember( &(state->gstack->u.enumdata), $1, NULL ); } | enumerator Y_EQUAL constant-expression { MakeEnumMember( &(state->gstack->u.enumdata), $1, $3 ); } ; enumerator : make-id /* identifier */ ; elaborated-type-specifier : Y_ENUM make-id { ENUM_DATA edata; InitEnumState( &edata, $2 ); $$ = EnumReference( &edata ); } | Y_ENUM elaborated-type-name { ENUM_DATA edata; InitEnumState( &edata, $2 ); $$ = EnumReference( &edata ); } ; namespace-definition /* named-namespace-definition | unnamed-namespace-definition */ : namespace-key Y_LEFT_BRACE namespace-body Y_RIGHT_BRACE ; /* non-standard */ namespace-key : Y_NAMESPACE { NameSpaceUnnamed( &yylp[1] ); } | Y_NAMESPACE expect-identifier make-id { NameSpaceNamed( $3 ); } ; namespace-body : /* nothing */ { NameSpaceClose(); } | might-restart-declarations { NameSpaceClose(); } ; namespace-alias-definition : Y_NAMESPACE expect-identifier make-id Y_EQUAL expect-qualified-namespace-specifier qualified-namespace-specifier { NameSpaceAlias( $3, $6 ); } ; qualified-namespace-specifier : Y_NAMESPACE_NAME | Y_GLOBAL_NAMESPACE_NAME | Y_SCOPED_NAMESPACE_NAME ; using-declaration : Y_USING qualified-id { NameSpaceUsingDeclId( $2 ); } | Y_USING qualified-type-specifier { NameSpaceUsingDeclType( $2 ); } | Y_USING Y_GLOBAL_TEMPLATE_NAME { NameSpaceUsingDeclTemplateName( $2 ); } | Y_USING Y_SCOPED_TEMPLATE_NAME { NameSpaceUsingDeclTemplateName( $2 ); } | Y_USING qualified-namespace-specifier { CErr2p( ERR_NAMESPACE_NOT_ALLOWED_IN_USING_DECL, $2 ); PTreeFreeSubtrees( $2 ); } ; using-directive : Y_USING Y_NAMESPACE expect-qualified-namespace-specifier qualified-namespace-specifier { NameSpaceUsingDirective( $4 ); } ; asm-definition : Y_ASM Y_LEFT_PAREN expect-string-literal string-literal Y_RIGHT_PAREN { StringTrash( $4->u.string ); PTreeFree( $4 ); CErr1( WARN_ASM_IGNORED ); } ; linkage-specification : Y_EXTERN linkage-id start-linkage-block linkage-body Y_RIGHT_BRACE { LinkagePop(); } ; linkage-id : string-literal { LinkagePush( $1->u.string->string ); StringTrash( $1->u.string ); PTreeFree( $1 ); if( ! ScopeType( GetCurrScope(), SCOPE_FILE ) ) { CErr1( ERR_ONLY_GLOBAL_LINKAGES ); } } ; start-linkage-block : Y_LEFT_BRACE { LinkageBlock(); } ; linkage-body : /* nothing */ | might-restart-declarations ; /* A.7 Declarators [gram.decl] */ init-declarator-list : init-declarator { tryCtorStyleInit( state, $1 ); } | init-declarator-list Y_COMMA comma-init-declarator { tryCtorStyleInit( state, $3 ); } ; init-declarator : declarator { $$ = InsertDeclInfo( GetCurrScope(), $1 ); GStackPush( &(state->gstack), GS_INIT_DATA ); $$ = DataInitNoInit( &(state->gstack->u.initdata), $$ ); GStackPop( &(state->gstack) ); } | declaring-declarator initializer { $$ = $1; } | ptr-mod-init-declarator { $1 = FinishDeclarator( state->gstack->u.dspec, $1 ); $$ = InsertDeclInfo( GetCurrScope(), $1 ); } | direct-declarator Y_LEFT_PAREN expression-list Y_RIGHT_PAREN { $1 = FinishDeclarator( state->gstack->u.dspec, $1 ); $$ = InsertDeclInfo( GetCurrScope(), $1 ); setInitWithLocn( $$, $3, &yylp[2] ); } ; declarator : ptr-mod-declarator { $$ = FinishDeclarator( state->gstack->u.dspec, $1 ); } | direct-declarator { $$ = FinishDeclarator( state->gstack->u.dspec, $1 ); } ; comma-init-declarator : comma-declarator { $$ = InsertDeclInfo( GetCurrScope(), $1 ); GStackPush( &(state->gstack), GS_INIT_DATA ); $$ = DataInitNoInit( &(state->gstack->u.initdata), $$ ); GStackPop( &(state->gstack) ); } | comma-declaring-declarator initializer { $$ = $1; } | cv-qualifier-seq-opt ptr-mod-init-declarator { $2 = AddMSCVQualifierKludge( $1, $2 ); $2 = FinishDeclarator( state->gstack->u.dspec, $2 ); $$ = InsertDeclInfo( GetCurrScope(), $2 ); } | cv-qualifier-seq-opt direct-declarator Y_LEFT_PAREN expression-list Y_RIGHT_PAREN { $2 = AddMSCVQualifierKludge( $1, $2 ); $2 = FinishDeclarator( state->gstack->u.dspec, $2 ); $$ = InsertDeclInfo( GetCurrScope(), $2 ); setInitWithLocn( $$, $4, &yylp[3] ); } ; declaring-declarator : declarator { $$ = InsertDeclInfo( GetCurrScope(), $1 ); GStackPush( &(state->gstack), GS_DECL_INFO ); state->gstack->u.dinfo = $$; } ; comma-declaring-declarator : comma-declarator { $$ = InsertDeclInfo( GetCurrScope(), $1 ); GStackPush( &(state->gstack), GS_DECL_INFO ); state->gstack->u.dinfo = $$; } ; comma-declarator : cv-qualifier-seq-opt ptr-mod-declarator { $2 = AddMSCVQualifierKludge( $1, $2 ); $$ = FinishDeclarator( state->gstack->u.dspec, $2 ); } | cv-qualifier-seq-opt direct-declarator { $2 = AddMSCVQualifierKludge( $1, $2 ); $$ = FinishDeclarator( state->gstack->u.dspec, $2 ); } ; ptr-mod : modifier { $$ = MakeFlagModifier( $1 ); } | Y___BASED Y_LEFT_PAREN based-expression Y_RIGHT_PAREN { $$ = $3; } | pragma-modifier | ptr-operator ; ptr-mod-init-declarator : ptr-mod ptr-mod-init-declarator { $$ = AddDeclarator( $2, $1 ); } | ptr-mod direct-declarator Y_LEFT_PAREN expression-list Y_RIGHT_PAREN { $$ = AddDeclarator( $2, $1 ); setInitWithLocn( $$, $4, &yylp[3] ); } ; ptr-mod-declarator : ptr-mod ptr-mod-declarator { $$ = AddDeclarator( $2, $1 ); } | ptr-mod direct-declarator { $$ = AddDeclarator( $2, $1 ); } ; direct-declarator : declarator-id { $$ = MakeDeclarator( state->gstack->u.dspec, $1 ); if( $$ == NULL ) { what = P_SYNTAX; } else { if( $$->template_member ) { what = P_CLASS_TEMPLATE; } } } | direct-declarator Y_LEFT_PAREN parameter-declaration-clause Y_RIGHT_PAREN cv-qualifier-seq-opt exception-specification-opt { $$ = AddDeclarator( $1, MakeFnType( &($3), $5, $6 ) ); $$ = AddExplicitParms( $$, $3 ); } | direct-declarator Y_LEFT_BRACKET constant-expression Y_RIGHT_BRACKET { $$ = AddArrayDeclarator( $1, $3 ); } | direct-declarator Y_LEFT_BRACKET Y_RIGHT_BRACKET { $$ = AddArrayDeclarator( $1, NULL ); } | Y_LEFT_PAREN ptr-mod-declarator Y_RIGHT_PAREN { $$ = $2; } | Y_LEFT_PAREN direct-declarator Y_RIGHT_PAREN { $$ = $2; } ; modifier : Y___NEAR { $$ = TF1_NEAR; } | Y___FAR { $$ = TF1_FAR; } | Y__FAR16 { $$ = TF1_SET_FAR16; /* equals TF1_FAR on the 8086 */ } | Y___FAR16 { $$ = TF1_SET_FAR16; /* equals TF1_FAR on the 8086 */ } | Y___HUGE { $$ = TF1_SET_HUGE; /* equals TF1_FAR on the 386 */ } | Y__EXPORT { $$ = TF1_DLLEXPORT | TF1_HUG_FUNCTION; } | Y___EXPORT { $$ = TF1_DLLEXPORT | TF1_HUG_FUNCTION; } | Y___LOADDS { $$ = TF1_LOADDS | TF1_TYP_FUNCTION; } | Y___SAVEREGS { $$ = TF1_SAVEREGS | TF1_TYP_FUNCTION; } | Y___INTERRUPT { $$ = TF1_INTERRUPT | TF1_TYP_FUNCTION; } ; based-expression : segment-cast-opt Y___SEGNAME Y_LEFT_PAREN expect-string-literal string-literal Y_RIGHT_PAREN { $$ = MakeBasedModifier( TF1_BASED_STRING, $1, $5 ); } | segment-cast-opt identifier { $$ = MakeBasedModifier( TF1_NULL, $1, $2 ); } | segment-cast-opt Y_VOID { $$ = MakeBasedModifier( TF1_BASED_VOID, $1, NULL ); } | segment-cast-opt Y___SELF { $$ = MakeBasedModifier( TF1_BASED_SELF, $1, NULL ); } ; segment-cast-opt : /* nothing */ { $$ = false; } | Y_LEFT_PAREN Y___SEGMENT Y_RIGHT_PAREN { $$ = true; } ; pragma-modifier : Y___PRAGMA Y_LEFT_PAREN pragma-id Y_RIGHT_PAREN { $$ = MakePragma( $3->u.string->string ); StringTrash( $3->u.string ); PTreeFree( $3 ); } | Y__CDECL { $$ = MakePragmaMagic( M_CDECL ); } | Y___CDECL { $$ = MakePragmaMagic( M_CDECL ); } | Y__FASTCALL { $$ = MakePragmaMagic( M_FASTCALL ); } | Y___FASTCALL { $$ = MakePragmaMagic( M_FASTCALL ); } | Y___FORTRAN { $$ = MakePragmaMagic( M_FORTRAN ); } | Y__OPTLINK { $$ = MakePragmaMagic( M_OPTLINK ); } | Y__PASCAL { $$ = MakePragmaMagic( M_PASCAL ); } | Y___PASCAL { $$ = MakePragmaMagic( M_PASCAL ); } | Y___STDCALL { $$ = MakePragmaMagic( M_STDCALL ); } | Y__SYSCALL { $$ = MakePragmaMagic( M_SYSCALL ); } | Y___SYSCALL { $$ = MakePragmaMagic( M_SYSCALL ); } | Y__SYSTEM { $$ = MakePragmaMagic( M_SYSTEM ); } | Y___WATCALL { $$ = MakePragmaMagic( M_WATCALL ); } ; pragma-id : string-literal ; ptr-operator : Y_TIMES cv-qualifier-seq-opt { $$ = MakePointerType( TF1_NULL, $2 ); } | Y_AND cv-qualifier-seq-opt { $$ = MakePointerType( TF1_REFERENCE, $2 ); } | Y_SCOPED_TIMES cv-qualifier-seq-opt { $$ = MakeMemberPointer( $1, $2 ); } | nested-name-specifier Y_TEMPLATE_SCOPED_TIMES cv-qualifier-seq-opt { $$ = MakeMemberPointer( $2, $3 ); PTreeFreeSubtrees( $1 ); } /* extension */ | Y_TIMES Y__SEG16 cv-qualifier-seq-opt { $$ = MakeSeg16Pointer( $3 ); } ; cv-qualifier-seq-opt : /* nothing */ { $$ = STY_NULL; } | Y_CONST { $$ = STY_CONST; } | Y_VOLATILE { $$ = STY_VOLATILE; } | Y___UNALIGNED { $$ = STY_UNALIGNED; } | Y_CONST Y_VOLATILE { $$ = STY_CONST | STY_VOLATILE; } | Y_VOLATILE Y_CONST { $$ = STY_CONST | STY_VOLATILE; } | Y_CONST Y___UNALIGNED { $$ = STY_CONST | STY_UNALIGNED; } | Y___UNALIGNED Y_CONST { $$ = STY_CONST | STY_UNALIGNED; } | Y_VOLATILE Y___UNALIGNED { $$ = STY_VOLATILE | STY_UNALIGNED; } | Y___UNALIGNED Y_VOLATILE { $$ = STY_VOLATILE | STY_UNALIGNED; } | Y___UNALIGNED Y_CONST Y_VOLATILE { $$ = STY_CONST | STY_VOLATILE | STY_UNALIGNED; } | Y___UNALIGNED Y_VOLATILE Y_CONST { $$ = STY_CONST | STY_VOLATILE | STY_UNALIGNED; } | Y_VOLATILE Y_CONST Y___UNALIGNED { $$ = STY_CONST | STY_VOLATILE | STY_UNALIGNED; } | Y_VOLATILE Y___UNALIGNED Y_CONST { $$ = STY_CONST | STY_VOLATILE | STY_UNALIGNED; } | Y_CONST Y_VOLATILE Y___UNALIGNED { $$ = STY_CONST | STY_VOLATILE | STY_UNALIGNED; } | Y_CONST Y___UNALIGNED Y_VOLATILE { $$ = STY_CONST | STY_VOLATILE | STY_UNALIGNED; } ; declarator-id : id-expression | Y_TEMPLATE_NAME /* non-standard */ | Y_NAMESPACE_NAME /* non-standard */ | Y_TYPE_NAME /* non-standard */ | Y_GLOBAL_UNKNOWN_ID /* :: identifier */ { $$ = MakeGlobalId( $1 ); } | Y_SCOPED_UNKNOWN_ID { $$ = MakeScopedId( $1 ); } | nested-name-specifier Y_TEMPLATE_SCOPED_UNKNOWN_ID { PTreeFreeSubtrees( $1 ); $$ = MakeScopedId( $2 ); } /* * these Y_TEMPLATE_SCOPED_ cases are needed because of the odd way * template class constructors are parsed. Essentially, a constructor * of the form A::A() gets parsed as a function with A being the * return type and ::A being the declarator-id. zapTemplateClassDeclSpec * then cleans things up by converting it into a constructor. */ | Y_TEMPLATE_SCOPED_ID { $$ = MakeScopedId( $1 ); zapTemplateClassDeclSpec( state ); } | Y_TEMPLATE_SCOPED_UNKNOWN_ID { $$ = MakeScopedId( $1 ); zapTemplateClassDeclSpec( state ); } | Y_TEMPLATE_SCOPED_TILDE make-id { $$ = MakeScopedDestructorId( $1, $2 ); zapTemplateClassDeclSpec( state ); } | template-scoped-conversion-function-id { zapTemplateClassDeclSpec( state ); } | template-scoped-operator-function-id { zapTemplateClassDeclSpec( state ); } ; type-id : type-specifier-seq abstract-declarator { $$ = TypeDeclarator( $2 ); GStackPop( &(state->gstack) ); } | type-specifier-seq { $$ = DoDeclSpec( state->gstack->u.dspec ); GStackPop( &(state->gstack) ); } ; type-specifier-seq : decl-specifier-seq { $$ = CheckTypeSpecifier( $1 ); if( $$ == NULL ) { what = P_SYNTAX; } } ; abstract-declarator : abstract-ptr-mod-declarator { $$ = FinishDeclarator( state->gstack->u.dspec, $1 ); } | direct-abstract-declarator { $$ = FinishDeclarator( state->gstack->u.dspec, $1 ); } ; abstract-ptr-mod-declarator : ptr-mod abstract-ptr-mod-declarator { $$ = AddDeclarator( $2, $1 ); } | ptr-mod direct-abstract-declarator { $$ = AddDeclarator( $2, $1 ); } | ptr-mod { $$ = MakeAbstractDeclarator( $1 ); } ; direct-abstract-declarator : direct-abstract-declarator Y_LEFT_PAREN parameter-declaration-clause Y_RIGHT_PAREN cv-qualifier-seq-opt exception-specification-opt { $$ = AddDeclarator( $1, MakeFnType( &($3), $5, $6 ) ); FreeArgs( $3 ); } | Y_LEFT_PAREN parameter-declaration-clause Y_RIGHT_PAREN cv-qualifier-seq-opt exception-specification-opt { $$ = MakeAbstractDeclarator( MakeFnType( &($2), $4, $5 ) ); FreeArgs( $2 ); } | direct-abstract-declarator Y_LEFT_BRACKET constant-expression Y_RIGHT_BRACKET { $$ = AddArrayDeclarator( $1, $3 ); } | Y_LEFT_BRACKET constant-expression Y_RIGHT_BRACKET { $$ = MakeAbstractDeclarator( NULL ); $$ = AddArrayDeclarator( $$, $2 ); } | direct-abstract-declarator Y_LEFT_BRACKET Y_RIGHT_BRACKET { $$ = AddArrayDeclarator( $1, NULL ); } | Y_LEFT_BRACKET Y_RIGHT_BRACKET { $$ = MakeAbstractDeclarator( NULL ); $$ = AddArrayDeclarator( $$, NULL ); } | Y_LEFT_PAREN direct-abstract-declarator Y_RIGHT_PAREN { $$ = $2; } | Y_LEFT_PAREN abstract-ptr-mod-declarator Y_RIGHT_PAREN { $$ = $2; } ; parameter-declaration-clause : /* nothing */ { $$ = NULL; } | parameter-declaration-list | parameter-declaration-list Y_COMMA Y_DOT_DOT_DOT { $$ = AddEllipseArg( $1 ); } | parameter-declaration-list Y_DOT_DOT_DOT { $$ = AddEllipseArg( $1 ); } | Y_DOT_DOT_DOT { $$ = AddEllipseArg( NULL ); } ; parameter-declaration-list : parameter-declaration { $$ = AddArgument( NULL, $1 ); } | parameter-declaration-list Y_COMMA parameter-declaration { $$ = AddArgument( $1, $3 ); } ; arg-decl-specifier-seq : decl-specifier-seq { $$ = CheckArgDSpec( $1 ); if( $$ == NULL ) { what = P_SYNTAX; } } ; parameter-declaration : simple-parameter-declaration { GStackPop( &(state->gstack) ); } ; /* non standard */ simple-parameter-declaration : arg-decl-specifier-seq { $$ = DeclSpecDeclarator( $1 ); } | arg-decl-specifier-seq simple-arg-no-id defarg-parse-or-copy { $$ = $2; } | arg-decl-specifier-seq declarator { $$ = $2; } | arg-decl-specifier-seq declarator defarg-parse-or-copy { $$ = $2; } | arg-decl-specifier-seq abstract-declarator { $$ = $2; } | arg-decl-specifier-seq abstract-declarator defarg-parse-or-copy { $$ = $2; } ; simple-arg-no-id : /* nothing */ { $$ = DeclSpecDeclarator( $0 ); } ; defarg-parse-or-copy : defarg-check Y_EQUAL assignment-expression { DECL_INFO *dinfo; DbgAssert( $1 == NULL ); dinfo = $0; dinfo->defarg_expr = $3; dinfo->has_defarg = true; TokenLocnAssign( dinfo->init_locn, yylp[2] ); } | defarg-check Y_DEFARG_GONE_SPECIAL { DECL_INFO *dinfo; dinfo = $0; dinfo->defarg_rewrite = $1; dinfo->has_defarg = true; TokenLocnAssign( dinfo->init_locn, yylp[2] ); } ; type-defarg-parse-or-copy : defarg-check Y_EQUAL type-id { DECL_INFO *dinfo; DbgAssert( $1 == NULL ); dinfo = $0; dinfo->defarg_expr = $3; dinfo->has_defarg = true; TokenLocnAssign( dinfo->init_locn, yylp[2] ); } | defarg-check Y_DEFARG_GONE_SPECIAL { DECL_INFO *dinfo; dinfo = $0; dinfo->defarg_rewrite = $1; dinfo->has_defarg = true; TokenLocnAssign( dinfo->init_locn, yylp[2] ); } ; defarg-check : /* nothing */ { if( t != Y_EQUAL ) { what = P_SYNTAX; $$ = NULL; } else { angle_bracket_stack *angle_state; angle_state = VstkTop( &(state->angle_stack) ); if( state->template_decl && ( angle_state != NULL ) && ( angle_state->paren_depth == 0 ) ) { $$ = RewritePackageTemplateDefArg(); t = Y_DEFARG_GONE_SPECIAL; } else if( state->template_decl ) { $$ = RewritePackagePassThrough( currParseStack->template_record_tokens ); t = Y_DEFARG_GONE_SPECIAL; } else if( ClassOKToRewrite() ) { $$ = RewritePackageDefArg( NULL ); t = Y_DEFARG_GONE_SPECIAL; } else { $$ = NULL; } } } ; ctor-declarator : Y_LEFT_PAREN parameter-declaration-clause Y_RIGHT_PAREN cv-qualifier-seq-opt exception-specification-opt { DECL_SPEC *dspec; PTREE id; dspec = state->gstack->u.dspec; id = MakeConstructorId( dspec ); if( id == NULL ) { what = P_SYNTAX; } $$ = MakeDeclarator( dspec, id ); AddDeclarator( $$, MakeFnType( &($2), $4, $5 ) ); $$ = AddExplicitParms( $$, $2 ); if( $$->template_member ) { what = P_CLASS_TEMPLATE; } else { $$ = FinishDeclarator( dspec, $$ ); } } ; function-declaration : decl-specifier-seq declarator ctor-initializer { $2->mem_init = $3; $$ = DeclFunction( state->gstack->u.dspec, $2 ); GStackPush( &(state->gstack), GS_DECL_INFO ); state->gstack->u.dinfo = $$; } | decl-specifier-seq declarator { $$ = DeclFunction( state->gstack->u.dspec, $2 ); GStackPush( &(state->gstack), GS_DECL_INFO ); state->gstack->u.dinfo = $$; } | declarator ctor-initializer { $1->mem_init = $2; $$ = DeclFunction( NULL, $1 ); GStackPush( &(state->gstack), GS_DECL_INFO ); state->gstack->u.dinfo = $$; } | declarator { $$ = DeclFunction( NULL, $1 ); GStackPush( &(state->gstack), GS_DECL_INFO ); state->gstack->u.dinfo = $$; } | decl-specifier-seq ctor-declarator ctor-initializer { $2->mem_init = $3; $$ = DeclFunction( state->gstack->u.dspec, $2 ); GStackPush( &(state->gstack), GS_DECL_INFO ); state->gstack->u.dinfo = $$; } | decl-specifier-seq ctor-declarator { $$ = DeclFunction( state->gstack->u.dspec, $2 ); GStackPush( &(state->gstack), GS_DECL_INFO ); state->gstack->u.dinfo = $$; } ; function-definition : function-declaration function-body { GStackPop( &(state->gstack) ); /* decl-info */ if( $1->has_dspec ) { GStackPop( &(state->gstack) ); /* decl-spec */ } if( $1->body != NULL ) { if( ScopeType( GetCurrScope(), SCOPE_TEMPLATE_DECL ) ) { TemplateFunctionAttachDefn( $1 ); } else if( ( ScopeType( GetCurrScope(), SCOPE_TEMPLATE_INST ) && ! $1->friend_fn ) ) { TemplateMemberAttachDefn( $1, false ); } else if( ( ( ScopeType( GetCurrScope(), SCOPE_CLASS ) && ScopeType( GetCurrScope()->enclosing, SCOPE_TEMPLATE_INST ) ) && ! $1->friend_fn ) ) { if( GetCurrScope()->owner.type->flag & TF1_SPECIFIC ) { ClassStoreInlineFunc( $1 ); } else { TemplateMemberAttachDefn( $1, true ); } } else { ClassStoreInlineFunc( $1 ); } } else { FreeDeclInfo( $1 ); } } ; function-body : check-for-rewrite Y_LEFT_BRACE absorb-body Y_RIGHT_BRACE ; check-for-rewrite : /* nothing */ { /* guards against errors from Q during rewriting: void foo( void ) { Q::blah } */ setNoSuperTokens( state ); } ; absorb-body : /* nothing */ { /* token will be thrown away (see check-for-rewrite) */ ParseFlush(); if( doFnbodyRewrite() ) { REWRITE *rewrite; rewrite = RewritePackageFunction( getMultiToken() ); state->gstack->u.dinfo->body = rewrite; } else { FunctionBody( state->gstack->u.dinfo ); } what = P_RELEX; } ; initializer : init-start assignment-expression { DataInitSimple( $2 ); GStackPop( &(state->gstack) ); } | init-start braced-initializer { GStackPop( &(state->gstack) ); } ; init-start : Y_EQUAL { DECL_INFO *dinfo; dinfo = state->gstack->u.dinfo; reuseGStack( state, GS_INIT_DATA ); DataInitStart( &(state->gstack->u.initdata), dinfo ); DataInitSimpleLocn( &yylp[1] ); } ; initializer-list : assignment-expression { DataInitExpr( $1 ); } | initializer-list Y_COMMA assignment-expression { DataInitExpr( $3 ); } | braced-initializer | initializer-list Y_COMMA braced-initializer ; /* A.8 Classes [gram.class] */ /* r/r conflict: * class-specifier <- class-key class-name * start-class <- */ start-class : /* nothing */ { ClassStart(); pushDefaultDeclSpec( state ); } ; invalid-class-name-id : Y_GLOBAL_UNKNOWN_ID | Y_SCOPED_UNKNOWN_ID ; class-name-id : Y_ID | Y_UNKNOWN_ID | Y_TEMPLATE_ID | Y_TYPE_NAME | Y_TEMPLATE_NAME | Y_NAMESPACE_NAME | Y_GLOBAL_ID | Y_GLOBAL_TYPE_NAME | Y_SCOPED_ID | Y_SCOPED_TYPE_NAME | invalid-class-name-id { CErr2p( ERR_QUALIFIED_NAME_NOT_CLASS, $1 ); $$ = PTreeErrorNode( $1 ); } ; class-name : class-name-id { CLASS_DECL decl_type; CLNAME_STATE after_name; decl_type = CLASS_REFERENCE; switch( t ) { case Y_LEFT_BRACE: case Y_COLON: decl_type = CLASS_DEFINITION; break; case Y_SEMI_COLON: decl_type = CLASS_DECLARATION; break; } after_name = ClassName( $1, decl_type ); switch( after_name ) { case CLNAME_CONTINUE: what = P_RELEX; break; case CLNAME_PROBLEM: what = P_DIAGNOSED; break; } } | nested-name-specifier { CLASS_DECL decl_type; tc_directive tcd_control; tcd_control = TCD_NULL; decl_type = CLASS_REFERENCE; switch( t ) { case Y_LEFT_BRACE: case Y_COLON: decl_type = CLASS_DEFINITION; break; case Y_SEMI_COLON: if( state->template_extern ) { tcd_control |= TCD_EXTERN; } else if( state->template_instantiate ) { tcd_control |= TCD_INSTANTIATE; } decl_type = CLASS_DECLARATION; break; } ClassSpecificInstantiation( $1, decl_type, tcd_control ); what = P_RELEX; } ; class-specifier : class-key class-name { $$ = ClassRefDef(); GStackPop( &(state->gstack) ); } | class-key class-name base-clause class-body { $$ = $4; } | class-key class-name class-body { $$ = $3; } | class-key no-class-name base-clause class-body { $$ = $4; } | class-key no-class-name class-body { $$ = $3; } ; class-key : packed-class-opt Y_CLASS class-mod-opt { pushClassData( state, TF1_NULL, $1, $3 ); } | packed-class-opt Y_STRUCT class-mod-opt { pushClassData( state, TF1_STRUCT, $1, $3 ); } | packed-class-opt Y_UNION class-mod-opt { pushClassData( state, TF1_UNION, $1, $3 ); } ; class-body : class-substance Y_RIGHT_BRACE { GStackPop( &(state->gstack) ); GStackPop( &(state->gstack) ); $$ = $1; } ; class-substance : start-class Y_LEFT_BRACE member-specification-opt { $$ = ClassEnd(); what = P_RELEX; } ; no-class-name : /* nothing */ { ClassName( NULL, CLASS_DEFINITION ); } ; packed-class-opt : /* nothing */ { $$ = CLINIT_NULL; } | Y__PACKED { $$ = CLINIT_PACKED; } ; class-mod-opt : /* nothing */ { $$ = NULL; } | class-mod-seq ; class-mod : pragma-modifier | modifier { $$ = MakeFlagModifier( $1 ); } | ms-specific-declspec { $$ = MakeClassModDeclSpec( $1 ); } ; class-mod-seq : class-mod | class-mod-seq class-mod { $$ = TypeClassModCombine( $1, $2 ); } ; member-specification-opt : /* nothing */ | member-specification ; member-specification : member-specification-opt member-declaration | member-specification-opt access-specifier Y_COLON { ClassPermission( $2 ); } ; member-declaration : simple-member-declaration-before-semicolon Y_SEMI_COLON | function-definition | access-declaration Y_SEMI_COLON | static_assert-declaration Y_SEMI_COLON | template-declaration | Y_SEMI_COLON { SetErrLoc( &yylp[1] ); CErr1( WARN_EMPTY_MEMBER_DECL ); } ; simple-member-declaration-before-semicolon : simple-member-declaration { if( t != Y_SEMI_COLON ) { SetErrLoc( &yylocation ); CErr1( ERR_SYNTAX_MISSING_SEMICOLON ); what = P_DIAGNOSED; } } ; simple-member-declaration : decl-specifier-seq member-declarator-list { GStackPop( &(state->gstack) ); } | member-declarator-list { } | decl-specifier-seq { $1 = CheckNoDeclarator( $1 ); if( $1 == NULL ) { what = P_SYNTAX; } GStackPop( &(state->gstack) ); } | decl-specifier-seq ctor-declarator { InsertDeclInfo( GetCurrScope(), $2 ); FreeDeclInfo( $2 ); GStackPop( &(state->gstack) ); } | using-declaration ; member-declarator-list : member-declarator { VerifyMemberFunction( state->gstack->u.dspec, $1 ); } | member-declarator-list Y_COMMA member-declarator { VerifyMemberFunction( state->gstack->u.dspec, $3 ); } ; member-declarator : member-declaring-declarator constant-initializer { $$ = $1; $$->sym->flags |= SYMF_IN_CLASS_INIT; DataInitSimple( $2 ); GStackPop( &(state->gstack) ); } | member-declaring-declarator Y_PURE_FUNCTION_SPECIAL Y_CONSTANT { if( $3->op != PT_INT_CONSTANT || $3->u.int_constant != 0 ) { CErr1( ERR_MUST_BE_ZERO ); } PTreeFree( $3 ); $$ = $1; } | member-declaring-declarator { $$ = $1; DeclNoInit( $$ ); } | Y_COLON constant-expression { ClassBitfield( state->gstack->u.dspec, NULL, $2 ); $$ = NULL; } | declarator-id Y_COLON constant-expression { ClassBitfield( state->gstack->u.dspec, $1, $3 ); $$ = NULL; } ; member-declaring-declarator : declarator { if( t == Y_EQUAL ) { if( VerifyPureFunction( $1 ) ) { t = Y_PURE_FUNCTION_SPECIAL; } } $$ = InsertDeclInfo( GetCurrScope(), $1 ); if( t == Y_EQUAL ) { if( ! SymIsStaticMember( $$->sym ) || ! SymIsConstant( $$->sym ) ) { CErr1( ERR_MUST_BE_CONST_STATIC_INTEGRAL ); } GStackPush( &(state->gstack), GS_DECL_INFO ); state->gstack->u.dinfo = $$; reuseGStack( state, GS_INIT_DATA ); DataInitStart( &(state->gstack->u.initdata), $$ ); DataInitSimpleLocn( &yylp[1] ); } } ; constant-initializer : Y_EQUAL constant-expression { $$ = $2; } ; /* A.9 Derived classes [gram.derived] */ base-clause : Y_COLON base-specifier-list { ClassBaseClause( $2 ); } ; base-specifier-list : base-specifier { $$ = ClassBaseList( NULL, $1 ); } | base-specifier-list Y_COMMA base-specifier { $$ = ClassBaseList( $1, $3 ); } ; base-specifier : base-qualifiers-opt qualified-class-specifier { $$ = ClassBaseSpecifier( $1, $2 ); } ; base-qualifiers-opt : /* nothing */ { $$ = IN_NULL; } | base-qualifiers-opt Y_PRIVATE { $$ = ClassBaseQualifiers( $1, IN_PRIVATE ); } | base-qualifiers-opt Y_PUBLIC { $$ = ClassBaseQualifiers( $1, IN_PUBLIC ); } | base-qualifiers-opt Y_PROTECTED { $$ = ClassBaseQualifiers( $1, IN_PROTECTED ); } | base-qualifiers-opt Y_VIRTUAL { $$ = ClassBaseQualifiers( $1, IN_VIRTUAL ); } ; access-specifier : Y_PRIVATE { $$ = SYMF_PRIVATE; } | Y_PROTECTED { $$ = SYMF_PROTECTED; } | Y_PUBLIC { $$ = SYMF_NONE; } ; /* A.10 Special member functions [gram.special] */ conversion-function-id : Y_OPERATOR conversion-type-id { $$ = setLocation( $2, &yylp[1] ); } ; scoped-conversion-function-id : Y_SCOPED_OPERATOR conversion-type-id { $$ = setLocation( MakeScopedUserConversionId( $1, $2 ), &yylp[1] ); ScopeQualifyPop(); } | Y_GLOBAL_OPERATOR conversion-type-id { $$ = setLocation( $2, &yylp[1] ); } ; template-scoped-conversion-function-id : Y_TEMPLATE_SCOPED_OPERATOR conversion-type-id { $$ = setLocation( MakeScopedUserConversionId( $1, $2 ), &yylp[1] ); ScopeQualifyPop(); } ; conversion-type-id : type-specifier-seq { $$ = MakeUserConversionId( $1, NULL ); GStackPop( &(state->gstack) ); } | type-specifier-seq conversion-declarator { $$ = MakeUserConversionId( $1, $2 ); GStackPop( &(state->gstack) ); } ; conversion-declarator : ptr-operator { $$ = MakeAbstractDeclarator( $1 ); } | ptr-operator conversion-declarator { $$ = AddDeclarator( $2, $1 ); } ; ctor-initializer : Y_COLON { if( state->template_record_tokens != NULL ) { PTreeFreeSubtrees( getMultiToken() ); recordTemplateCtorInitializer( state ); $$ = NULL; } else { $$ = RewritePackageMemInit( getMultiToken() ); } what = P_RELEX; } ; mem-initializer-list : mem-initializer { $$ = PTreeBinary( CO_LIST, NULL, $1 ); } | mem-initializer-list Y_COMMA mem-initializer { $$ = PTreeBinary( CO_LIST, $1, $3 ); } ; mem-initializer : qualified-class-specifier Y_LEFT_PAREN expression-list-opt Y_RIGHT_PAREN { $$ = MakeMemInitItem( $1, NULL, $3, &yylp[2] ); } | identifier Y_LEFT_PAREN expression-list-opt Y_RIGHT_PAREN { $$ = MakeMemInitItem( NULL, $1, $3, &yylp[2] ); } ; /* non-standard */ qualified-class-specifier : qualified-class-type { if( $$ == NULL ) { what = P_DIAGNOSED; } } ; /* non-standard */ qualified-class-type : Y_TYPE_NAME { $$ = sendClass( $1 ); } | Y_GLOBAL_TYPE_NAME { $$ = sendClass( $1 ); } | Y_SCOPED_TYPE_NAME { $$ = sendClass( $1 ); } | nested-name-specifier { $$ = PTypeClassInstantiation( state->class_colon, $1 ); if( ClassType( $$->partial ) == NULL ) { CErr2p( ERR_EXPECTED_CLASS_TYPE, $$->partial ); PTypeRelease( $$ ); $$ = NULL; } } | nested-name-specifier Y_TEMPLATE_SCOPED_TYPE_NAME { PTreeFreeSubtrees( $1 ); $$ = sendClass( $2 ); } ; /* A.11 Overloading [gram.over] */ /* TODO */ operator-function-id : Y_OPERATOR operator { $$ = setLocation( MakeOperatorId( $2 ), &yylp[1] ); } ; scoped-operator-function-id : Y_SCOPED_OPERATOR operator { $$ = setLocation( MakeScopedOperatorId( $1, $2 ), &yylp[1] ); ScopeQualifyPop(); } | Y_GLOBAL_OPERATOR operator { $$ = setLocation( MakeGlobalOperatorId( $1, $2 ), &yylp[1] ); ScopeQualifyPop(); } ; template-scoped-operator-function-id : Y_TEMPLATE_SCOPED_OPERATOR operator { $$ = setLocation( MakeScopedOperatorId( $1, $2 ), &yylp[1] ); ScopeQualifyPop(); } ; operator : Y_NEW { $$ = CO_NEW; } | Y_DELETE { $$ = CO_DELETE; } | Y_NEW Y_LEFT_BRACKET Y_RIGHT_BRACKET { $$ = CO_NEW_ARRAY; } | Y_DELETE Y_LEFT_BRACKET Y_RIGHT_BRACKET { $$ = CO_DELETE_ARRAY; } | Y_PLUS { $$ = CO_PLUS; } | Y_MINUS { $$ = CO_MINUS; } | Y_TIMES { $$ = CO_TIMES; } | Y_DIV { $$ = CO_DIVIDE; } | Y_PERCENT { $$ = CO_PERCENT; } | Y_XOR { $$ = CO_XOR; } | Y_AND { $$ = CO_AND; } | Y_OR { $$ = CO_OR; } | Y_TILDE { $$ = CO_TILDE; } | Y_EXCLAMATION { $$ = CO_EXCLAMATION; } | Y_EQUAL { $$ = CO_EQUAL; } | Y_TIMES_EQUAL { $$ = CO_TIMES_EQUAL; } | Y_DIV_EQUAL { $$ = CO_DIVIDE_EQUAL; } | Y_PERCENT_EQUAL { $$ = CO_PERCENT_EQUAL; } | Y_PLUS_EQUAL { $$ = CO_PLUS_EQUAL; } | Y_MINUS_EQUAL { $$ = CO_MINUS_EQUAL; } | Y_LSHIFT_EQUAL { $$ = CO_LSHIFT_EQUAL; } | Y_RSHIFT_EQUAL { $$ = CO_RSHIFT_EQUAL; } | Y_OR_EQUAL { $$ = CO_OR_EQUAL; } | Y_AND_EQUAL { $$ = CO_AND_EQUAL; } | Y_XOR_EQUAL { $$ = CO_XOR_EQUAL; } | Y_LSHIFT { $$ = CO_LSHIFT; } | Y_RSHIFT { $$ = CO_RSHIFT; } | Y_EQ { $$ = CO_EQ; } | Y_NE { $$ = CO_NE; } | Y_LE { $$ = CO_LE; } | Y_GE { $$ = CO_GE; } | Y_LT { $$ = CO_LT; } | Y_GT { $$ = CO_GT; } | Y_AND_AND { $$ = CO_AND_AND; } | Y_OR_OR { $$ = CO_OR_OR; } | Y_PLUS_PLUS { $$ = CO_PRE_PLUS_PLUS; } | Y_MINUS_MINUS { $$ = CO_PRE_MINUS_MINUS; } | Y_COMMA { $$ = CO_COMMA; } | Y_ARROW_STAR { $$ = CO_ARROW_STAR; } | Y_ARROW { $$ = CO_ARROW; } | Y_LEFT_PAREN Y_RIGHT_PAREN { $$ = CO_CALL; } | Y_LEFT_BRACKET Y_RIGHT_BRACKET { $$ = CO_INDEX; } | Y_SEG_OP { $$ = CO_SEG_OP; } ; /* A.12 Templates [gram.temp] */ /* differs from standard */ template-declaration : template-declaration-before-semicolon Y_SEMI_COLON | template-function-declaration ; /* differs from standard */ template-declaration-start : template-key template-declaration-init lt-special template-parameter-list-opt Y_GT_SPECIAL ; /* differs from standard */ simple-template-declaration-before-semicolon : block-declaration-before-semicolon | simple-member-declaration-before-semicolon ; template-declaration-before-semicolon : template-declaration-start simple-template-declaration-before-semicolon { RewriteFree( ParseGetRecordingInProgress( NULL ) ); state->template_decl = false; GStackPop( &(state->gstack) ); /* GS_DECL_SPEC */ GStackPop( &(state->gstack) ); /* GS_TEMPLATE_DATA */ } | Y_EXPORT template-declaration-start simple-template-declaration-before-semicolon { CErr1( WARN_UNSUPPORTED_TEMPLATE_EXPORT ); RewriteFree( ParseGetRecordingInProgress( NULL ) ); state->template_decl = false; GStackPop( &(state->gstack) ); /* GS_DECL_SPEC */ GStackPop( &(state->gstack) ); /* GS_TEMPLATE_DATA */ } ; template-function-declaration : template-declaration-start function-definition { RewriteFree( ParseGetRecordingInProgress( NULL ) ); state->template_decl = false; GStackPop( &(state->gstack) ); /* GS_DECL_SPEC */ GStackPop( &(state->gstack) ); /* GS_TEMPLATE_DATA */ } | Y_EXPORT template-declaration-start function-definition { CErr1( WARN_UNSUPPORTED_TEMPLATE_EXPORT ); RewriteFree( ParseGetRecordingInProgress( NULL ) ); state->template_decl = false; GStackPop( &(state->gstack) ); /* GS_DECL_SPEC */ GStackPop( &(state->gstack) ); /* GS_TEMPLATE_DATA */ } ; /* non standard */ template-declaration-init : /* nothing */ { GStackPush( &(state->gstack), GS_TEMPLATE_DATA ); TemplateDeclInit( &(state->gstack->u.templatedata) ); } ; /* non standard */ template-parameter-list-opt : /* nothing */ { pushDefaultDeclSpec( state ); state->template_record_tokens = RewriteRecordInit( &(state->template_record_locn) ); } | template-parameter-list { pushDefaultDeclSpec( state ); state->template_record_tokens = RewriteRecordInit( &(state->template_record_locn) ); } ; template-parameter-list : template-parameter { TemplateDeclAddArgument( $1 ); } | template-parameter-list Y_COMMA template-parameter { TemplateDeclAddArgument( $3 ); } ; template-parameter : type-parameter | parameter-declaration ; type-parameter : type-parameter-no-defarg | type-parameter-no-defarg type-defarg-parse-or-copy ; /* non standard */ type-parameter-no-defarg : template-typename-key { DECL_SPEC *dspec; pushClassData( state, TF1_NULL, CLINIT_NULL, NULL ); ClassName( NULL, CLASS_GENERIC ); dspec = ClassRefDef(); GStackPop( &(state->gstack) ); $$ = DeclSpecDeclarator( dspec ); PTypeRelease( dspec ); } | template-typename-key make-id { DECL_SPEC *dspec; pushClassData( state, TF1_NULL, CLINIT_NULL, NULL ); ClassName( $2, CLASS_GENERIC ); dspec = ClassRefDef(); GStackPop( &(state->gstack) ); $$ = DeclSpecDeclarator( dspec ); PTypeRelease( dspec ); } ; /* non standard */ template-typename-key : Y_TYPENAME { } | Y_CLASS { } ; template-id : Y_TEMPLATE_ID lt-special template-argument-list-opt Y_GT_SPECIAL { $3 = NodeReverseArgs( NULL, $3 ); $3->flags |= PTF_ALREADY_ANALYSED; $$ = PTreeBinary( CO_TEMPLATE, $1, $3 ); } ; scoped-template-id : Y_SCOPED_TEMPLATE_ID lt-special template-argument-list-opt Y_GT_SPECIAL { $3 = NodeReverseArgs( NULL, $3 ); $3->flags |= PTF_ALREADY_ANALYSED; $$ = PTreeBinary( CO_TEMPLATE, MakeScopedId( $1 ), $3 ); } | Y_GLOBAL_TEMPLATE_ID lt-special template-argument-list-opt Y_GT_SPECIAL { $3 = NodeReverseArgs( NULL, $3 ); $3->flags |= PTF_ALREADY_ANALYSED; $$ = PTreeBinary( CO_TEMPLATE, MakeScopedId( $1 ), $3 ); } ; template-argument-list : template-argument { $$ = PTreeBinary( CO_LIST, NULL, $1 ); } | template-argument-list Y_COMMA template-argument { $$ = setLocation( PTreeBinary( CO_LIST, $1, $3 ), &yylp[2] ); } ; template-argument : assignment-expression { $1 = AnalyseRawExpr( $1 ); if( $1->op == PT_SYMBOL ) { SYMBOL sym = $1->u.symcg.symbol; if( SymIsConstantInt( sym ) ) { PTreeFreeSubtrees( $1 ); $1 = PTreeIntConstant( sym->u.sval, TYP_SINT ); } } $$ = $1; } | type-id ; /* TODO */ typename-specifier : typename-special nested-name-specifier Y_TEMPLATE_SCOPED_TYPE_NAME { $$ = sendType( $3 ); PTreeFreeSubtrees( $2 ); } | typename-special nested-name-specifier { $$ = sendType( $2 ); } | typename-special Y_SCOPED_TYPE_NAME { $$ = sendType( $2 ); } ; /* non-standard */ explicit-instantiation-special : Y_TEMPLATE { state->template_instantiate = true; } | Y_EXTERN Y_TEMPLATE { state->template_extern = true; } ; explicit-instantiation : Y_EXTERN Y_TEMPLATE template-class-directive-extern Y_SEMI_COLON { CErr1( WARN_MISSING_KEYWORD_IN_EXPLICT_INSTANTIATION ); } | Y_TEMPLATE template-class-directive-instantiate Y_SEMI_COLON { CErr1( WARN_MISSING_KEYWORD_IN_EXPLICT_INSTANTIATION ); } | explicit-instantiation-special block-declaration-before-semicolon Y_SEMI_COLON { state->template_instantiate = false; state->template_extern = false; } ; template-key : Y_TEMPLATE { if( state->template_decl ) { CErr1( ERR_NO_NESTED_TEMPLATES ); } else if( ! ScopeType( GetCurrScope(), SCOPE_FILE ) && ! ScopeType( GetCurrScope(), SCOPE_CLASS ) ) { CErr1( ERR_ONLY_GLOBAL_TEMPLATES ); } state->template_decl = true; } ; template-argument-list-opt : /* nothing */ { $$ = PTreeBinary( CO_LIST, NULL, NULL ); } | template-argument-list { $$ = $1; } ; template-class-directive-extern : nested-name-specifier { TYPE type = NodeIsBinaryOp( $1, CO_STORAGE ) ? $1->u.subtree[1]->type : $1->type; TemplateClassDirective( type, &($1->locn), TCD_EXTERN ); NodeFreeDupedExpr( $1 ); } ; template-class-directive-instantiate : nested-name-specifier { TYPE type = NodeIsBinaryOp( $1, CO_STORAGE ) ? $1->u.subtree[1]->type : $1->type; TemplateClassDirective( type, &($1->locn), TCD_INSTANTIATE ); NodeFreeDupedExpr( $1 ); } ; template-type : template-type-instantiation Y_GT_SPECIAL ; template-type-instantiation : Y_TEMPLATE_NAME lt-special template-argument-list-opt { TYPE inst_type; inst_type = TemplateClassReference( $1, $3 ); setWatchColonColon( state, $1, inst_type ); $$ = $1; if( inst_type != NULL ) { $$->type = inst_type; } } ; scoped-template-type : scoped-template-type-instantiation Y_GT_SPECIAL ; scoped-template-type-instantiation : Y_SCOPED_TEMPLATE_NAME lt-special template-argument-list-opt { TYPE inst_type; inst_type = TemplateClassReference( $1, $3 ); setWatchColonColon( state, $1, inst_type ); $$ = $1; if( inst_type == NULL ) { DbgAssert( ( $$->op == PT_BINARY ) && ( $$->cgop == CO_STORAGE ) ); $$->u.subtree[1] = PTreeBinary( CO_TEMPLATE, $$->u.subtree[1], $3 ); } else { $$->u.subtree[1]->type = inst_type; } } | Y_GLOBAL_TEMPLATE_NAME lt-special template-argument-list-opt { TYPE inst_type; inst_type = TemplateClassReference( $1, $3 ); setWatchColonColon( state, $1, inst_type ); $$ = $1; if( inst_type == NULL ) { DbgAssert( ( $$->op == PT_BINARY ) && ( $$->cgop == CO_STORAGE ) ); $$->u.subtree[1] = PTreeBinary( CO_TEMPLATE, $$->u.subtree[1], $3 ); } else { $$->u.subtree[1]->type = inst_type; } } ; template-scoped-template-type : template-scoped-template-type-instantiation Y_GT_SPECIAL ; template-scoped-template-type-instantiation : Y_TEMPLATE_SCOPED_TEMPLATE_NAME lt-special template-argument-list-opt { TYPE inst_type; inst_type = TemplateClassReference( $1, $3 ); setWatchColonColon( state, $1, inst_type ); $$ = $1; if( inst_type == NULL ) { DbgAssert( ( $$->op == PT_BINARY ) && ( $$->cgop == CO_STORAGE ) ); $$->u.subtree[1] = PTreeBinary( CO_TEMPLATE, $$->u.subtree[1], $3 ); } else { $$->u.subtree[1]->type = inst_type; } } ; /* A.13 Exception handling [gram.except] */ exception-declaration : actual-exception-declaration { $$ = $1; GStackPop( &(state->gstack) ); } ; actual-exception-declaration : type-specifier-seq declarator { $$ = $2; } | type-specifier-seq abstract-declarator { $$ = $2; } | type-specifier-seq { $$ = DeclSpecDeclarator( state->gstack->u.dspec ); } ; exception-specification-opt : /* nothing */ { $$ = ThrowsAnything(); } | exception-specification ; exception-specification : Y_THROW Y_LEFT_PAREN type-id-list Y_RIGHT_PAREN { $$ = $3; } | Y_THROW Y_LEFT_PAREN Y_RIGHT_PAREN { $$ = NULL; } ; type-id-list : expect-type-id type-id { $$ = $2; } | type-id-list Y_COMMA expect-type-id type-id { $$ = PTreeTListAppend( $1, $4 ); } ; /*** declaration syntax ***/ might-restart-declarations : start-restart-declarations { popRestartDecl( state ); } | start-restart-declarations declaration-seq { popRestartDecl( state ); } ; start-restart-declarations : /* nothing */ { pushRestartDecl( state ); } ; local-declaration : block-declaration-before-semicolon Y_SEMI_COLON ; no-declarator-declaration : decl-specifier-seq { $$ = CheckNoDeclarator( $1 ); if( $$ == NULL ) { what = P_SYNTAX; } } ; /* extension */ typeof-specifier : Y___TYPEOF Y_LEFT_PAREN expression Y_RIGHT_PAREN { $$ = PTypeExpr( $3 ); } | Y___TYPEOF Y_LEFT_PAREN type-id Y_RIGHT_PAREN { $$ = PTypeTypeid( $3 ); } ; cv-qualifier : Y_CONST { $$ = PTypeSpecifier( STY_CONST ); } | Y_VOLATILE { $$ = PTypeSpecifier( STY_VOLATILE ); } | Y___UNALIGNED { $$ = PTypeSpecifier( STY_UNALIGNED ); } ; /* non-standard */ basic-type-specifier : Y_CHAR { $$ = PTypeScalar( STM_CHAR ); } | Y_WCHAR_T { $$ = PTypeScalar( STM_WCHAR ); } | Y_BOOL { $$ = PTypeScalar( STM_BOOL ); } | Y_SHORT { $$ = PTypeScalar( STM_SHORT ); } | Y_INT { $$ = PTypeScalar( STM_INT ); } | Y_LONG { $$ = PTypeScalar( STM_LONG ); } | Y_SIGNED { $$ = PTypeScalar( STM_SIGNED ); } | Y_UNSIGNED { $$ = PTypeScalar( STM_UNSIGNED ); } | Y_FLOAT { $$ = PTypeScalar( STM_FLOAT ); } | Y_DOUBLE { $$ = PTypeScalar( STM_DOUBLE ); } | Y_VOID { $$ = PTypeScalar( STM_VOID ); } /* extension */ | Y___SEGMENT { $$ = PTypeScalar( STM_SEGMENT ); } | Y___INT8 { $$ = PTypeScalar( STM_CHAR ); } | Y___INT16 { $$ = PTypeScalar( STM_SHORT ); } | Y___INT32 { $$ = PTypeScalar( STM_INT32 ); } | Y___INT64 { $$ = PTypeScalar( STM_INT64 ); } ; elaborated-type-name : Y_GLOBAL_ID | Y_GLOBAL_TEMPLATE_ID | Y_GLOBAL_TYPE_NAME | Y_SCOPED_ID | Y_SCOPED_TEMPLATE_ID | Y_SCOPED_TYPE_NAME ; braced-initializer : brace-start initializer-list Y_COMMA Y_RIGHT_BRACE { DataInitPop(); } | brace-start initializer-list Y_RIGHT_BRACE { DataInitPop(); } ; brace-start : Y_LEFT_BRACE { DataInitPush(); } ; typename-special : typename-special-init Y_TYPENAME { if( ! ScopeType( GetCurrScope(), SCOPE_TEMPLATE_DECL ) && ! IsTemplateInstantiationActive() ) { SetErrLoc( &yylp[2] ); CErr1( ERR_TYPENAME_OUTSIDE_TEMPLATE ); } } ; typename-special-init : /* nothing */ { state->special_typename = true; } ; special-new-type-id : type-specifier-seq special-new-abstract-declarator { $$ = $2; GStackPop( &(state->gstack) ); } | type-specifier-seq { $$ = MakeNewTypeId( DoDeclSpec( state->gstack->u.dspec ) ); GStackPop( &(state->gstack) ); } ; special-new-abstract-declarator : special-new-abstract-ptr-mod-declarator { $$ = FinishDeclarator( state->gstack->u.dspec, $1 ); } | special-new-direct-abstract-declarator { $$ = FinishDeclarator( state->gstack->u.dspec, $1 ); } ; special-new-abstract-ptr-mod-declarator : ptr-mod special-new-abstract-ptr-mod-declarator { $$ = AddDeclarator( $2, $1 ); } | ptr-mod special-new-direct-abstract-declarator { $$ = AddDeclarator( $2, $1 ); } | ptr-mod { $$ = MakeAbstractDeclarator( $1 ); } ; special-new-direct-abstract-declarator : special-new-direct-abstract-declarator Y_LEFT_PAREN parameter-declaration-clause Y_RIGHT_PAREN cv-qualifier-seq-opt exception-specification-opt { $$ = AddDeclarator( $1, MakeFnType( &($3), $5, $6 ) ); FreeArgs( $3 ); } | Y_LEFT_PAREN parameter-declaration-clause Y_RIGHT_PAREN cv-qualifier-seq-opt exception-specification-opt { $$ = MakeAbstractDeclarator( MakeFnType( &($2), $4, $5 ) ); FreeArgs( $2 ); } | special-new-direct-abstract-declarator Y_LEFT_BRACKET constant-expression Y_RIGHT_BRACKET { $$ = AddArrayDeclarator( $1, $3 ); } | Y_LEFT_BRACKET expression Y_RIGHT_BRACKET { $$ = MakeNewDynamicArray( $2 ); } | special-new-direct-abstract-declarator Y_LEFT_BRACKET Y_RIGHT_BRACKET { $$ = AddArrayDeclarator( $1, NULL ); } | Y_LEFT_BRACKET Y_RIGHT_BRACKET { $$ = MakeAbstractDeclarator( NULL ); $$ = AddArrayDeclarator( $$, NULL ); } | Y_LEFT_PAREN special-new-direct-abstract-declarator Y_RIGHT_PAREN { $$ = $2; } | Y_LEFT_PAREN special-new-abstract-ptr-mod-declarator Y_RIGHT_PAREN { $$ = $2; } ; %%