/
*
Open Watcom Project
*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 <type-id> 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_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_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 YOFFSETOF
%token YTYPEOF
%token Y___BUILTIN_ISFLOAT
/ PC-specific keywords /
%token YASM
%token YBASED
%token YCDECL
%token YCDECL
%token YDECLSPEC
%token YEXPORT
%token YEXPORT
%token YFAR
%token YFAR16
%token YFAR16
%token YFASTCALL
%token YFASTCALL
%token YFORTRAN
%token YHUGE
%token YINLINE
%token YINT8
%token YINT16
%token YINT32
%token YINT64
%token YINTERRUPT
%token YLOADDS
%token YNEAR
%token YOPTLINK
%token YPACKED
%token YPASCAL
%token YPASCAL
%token YPRAGMA
%token YSAVEREGS
%token YSEG16
%token YSEGMENT
%token YSEGNAME
%token YSELF
%token YSTDCALL
%token YSYSCALL
%token YSYSCALL
%token YSYSTEM
%token YWATCALL
%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 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 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:
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
;
string-literal
: Y_STRING
| string-literal Y_STRING
{ $$ = PTreeStringLiteralConcat( $1, $2 ); }
;
boolean-literal
: Y_TRUE
| Y_FALSE
;
/ 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 ) ) {
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 ) ) {
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, StringBytes( $6->u.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) */
| Y_DECLTYPE Y_LEFT_PAREN expression Y_RIGHT_PAREN
{ $$ = PTypeExpr( $3 ); }
/* extension */
| typeof-specifier
;
/ 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
{ $$ = MakeIndexPragma( M_CDECL ); }
| Y___CDECL
{ $$ = MakeIndexPragma( M_CDECL ); }
| Y__FASTCALL
{ $$ = MakeIndexPragma( M_FASTCALL ); }
| Y___FASTCALL
{ $$ = MakeIndexPragma( M_FASTCALL ); }
| Y___FORTRAN
{ $$ = MakeIndexPragma( M_FORTRAN ); }
| Y__OPTLINK
{ $$ = MakeIndexPragma( M_OPTLINK ); }
| Y__PASCAL
{ $$ = MakeIndexPragma( M_PASCAL ); }
| Y___PASCAL
{ $$ = MakeIndexPragma( M_PASCAL ); }
| Y___STDCALL
{ $$ = MakeIndexPragma( M_STDCALL ); }
| Y__SYSCALL
{ $$ = MakeIndexPragma( M_SYSCALL ); }
| Y___SYSCALL
{ $$ = MakeIndexPragma( M_SYSCALL ); }
| Y__SYSTEM
{ $$ = MakeIndexPragma( M_SYSTEM ); }
| Y___WATCALL
{ $$ = MakeIndexPragma( 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<T>::A() gets parsed as a function with A<T> 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( $<dspec>0 ); }
;
defarg-parse-or-copy
: defarg-check Y_EQUAL assignment-expression
{
DECL_INFO *dinfo;
DbgAssert( $1 == NULL );
dinfo = $<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 = $<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 = $<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 = $<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:
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->flag |= SF_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
{ $$ = SF_PRIVATE; }
| Y_PROTECTED
{ $$ = SF_PROTECTED; }
| Y_PUBLIC
{ $$ = SF_NULL; }
;
/ 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( StructType( $$->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; }
;
%%