gfx/angle/src/compiler/glslang.y

Thu, 15 Jan 2015 15:55:04 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:55:04 +0100
branch
TOR_BUG_9701
changeset 9
a63d609f5ebe
permissions
-rw-r--r--

Back out 97036ab72558 which inappropriately compared turds to third parties.

     1 /*
     2 //
     3 // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
     4 // Use of this source code is governed by a BSD-style license that can be
     5 // found in the LICENSE file.
     6 //
     8 This file contains the Yacc grammar for GLSL ES.
     9 Based on ANSI C Yacc grammar:
    10 http://www.lysator.liu.se/c/ANSI-C-grammar-y.html
    12 IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
    13 WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
    14 */
    16 %{
    17 //
    18 // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
    19 // Use of this source code is governed by a BSD-style license that can be
    20 // found in the LICENSE file.
    21 //
    23 // This file is auto-generated by generate_parser.sh. DO NOT EDIT!
    25 // Ignore errors in auto-generated code.
    26 #if defined(__GNUC__)
    27 #pragma GCC diagnostic ignored "-Wunused-function"
    28 #pragma GCC diagnostic ignored "-Wunused-variable"
    29 #pragma GCC diagnostic ignored "-Wswitch-enum"
    30 #elif defined(_MSC_VER)
    31 #pragma warning(disable: 4065)
    32 #pragma warning(disable: 4189)
    33 #pragma warning(disable: 4505)
    34 #pragma warning(disable: 4701)
    35 #endif
    37 #include "compiler/SymbolTable.h"
    38 #include "compiler/ParseHelper.h"
    39 #include "GLSLANG/ShaderLang.h"
    41 #define YYENABLE_NLS 0
    43 #define YYLEX_PARAM context->scanner
    44 %}
    46 %expect 1 /* One shift reduce conflict because of if | else */
    47 %pure-parser
    48 %parse-param {TParseContext* context}
    49 %locations
    51 %code requires {
    52 #define YYLTYPE TSourceLoc
    53 #define YYLTYPE_IS_DECLARED 1
    54 }
    56 %union {
    57     struct {
    58         union {
    59             TString *string;
    60             float f;
    61             int i;
    62             bool b;
    63         };
    64         TSymbol* symbol;
    65     } lex;
    66     struct {
    67         TOperator op;
    68         union {
    69             TIntermNode* intermNode;
    70             TIntermNodePair nodePair;
    71             TIntermTyped* intermTypedNode;
    72             TIntermAggregate* intermAggregate;
    73         };
    74         union {
    75             TPublicType type;
    76             TPrecision precision;
    77             TQualifier qualifier;
    78             TFunction* function;
    79             TParameter param;
    80             TField* field;
    81             TFieldList* fieldList;
    82         };
    83     } interm;
    84 }
    86 %{
    87 extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner);
    88 static void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason);
    90 #define YYLLOC_DEFAULT(Current, Rhs, N)                      \
    91   do {                                                       \
    92       if (YYID(N)) {                                         \
    93         (Current).first_file = YYRHSLOC(Rhs, 1).first_file;  \
    94         (Current).first_line = YYRHSLOC(Rhs, 1).first_line;  \
    95         (Current).last_file = YYRHSLOC(Rhs, N).last_file;    \
    96         (Current).last_line = YYRHSLOC(Rhs, N).last_line;    \
    97       }                                                      \
    98       else {                                                 \
    99         (Current).first_file = YYRHSLOC(Rhs, 0).last_file;   \
   100         (Current).first_line = YYRHSLOC(Rhs, 0).last_line;   \
   101         (Current).last_file = YYRHSLOC(Rhs, 0).last_file;    \
   102         (Current).last_line = YYRHSLOC(Rhs, 0).last_line;    \
   103       }                                                      \
   104   } while (0)
   106 #define VERTEX_ONLY(S, L) {  \
   107     if (context->shaderType != SH_VERTEX_SHADER) {  \
   108         context->error(L, " supported in vertex shaders only ", S);  \
   109         context->recover();  \
   110     }  \
   111 }
   113 #define FRAG_ONLY(S, L) {  \
   114     if (context->shaderType != SH_FRAGMENT_SHADER) {  \
   115         context->error(L, " supported in fragment shaders only ", S);  \
   116         context->recover();  \
   117     }  \
   118 }
   119 %}
   121 %token <lex> INVARIANT HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION
   122 %token <lex> ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE
   123 %token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN
   124 %token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4
   125 %token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM VARYING
   126 %token <lex> STRUCT VOID_TYPE WHILE
   127 %token <lex> SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT
   129 %token <lex> IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT BOOLCONSTANT
   130 %token <lex> LEFT_OP RIGHT_OP
   131 %token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
   132 %token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
   133 %token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
   134 %token <lex> SUB_ASSIGN
   136 %token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
   137 %token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
   138 %token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION
   140 %type <lex> identifier
   141 %type <interm> assignment_operator unary_operator
   142 %type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression
   143 %type <interm.intermTypedNode> expression integer_expression assignment_expression
   144 %type <interm.intermTypedNode> unary_expression multiplicative_expression additive_expression
   145 %type <interm.intermTypedNode> relational_expression equality_expression
   146 %type <interm.intermTypedNode> conditional_expression constant_expression
   147 %type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression
   148 %type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression
   149 %type <interm.intermTypedNode> function_call initializer condition conditionopt
   151 %type <interm.intermNode> translation_unit function_definition
   152 %type <interm.intermNode> statement simple_statement
   153 %type <interm.intermAggregate>  statement_list compound_statement
   154 %type <interm.intermNode> declaration_statement selection_statement expression_statement
   155 %type <interm.intermNode> declaration external_declaration
   156 %type <interm.intermNode> for_init_statement compound_statement_no_new_scope
   157 %type <interm.nodePair> selection_rest_statement for_rest_statement
   158 %type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope statement_with_scope
   159 %type <interm> single_declaration init_declarator_list
   161 %type <interm> parameter_declaration parameter_declarator parameter_type_specifier
   162 %type <interm.qualifier> parameter_qualifier
   164 %type <interm.precision> precision_qualifier
   165 %type <interm.type> type_qualifier fully_specified_type type_specifier
   166 %type <interm.type> type_specifier_no_prec type_specifier_nonarray
   167 %type <interm.type> struct_specifier
   168 %type <interm.field> struct_declarator
   169 %type <interm.fieldList> struct_declarator_list struct_declaration struct_declaration_list
   170 %type <interm.function> function_header function_declarator function_identifier
   171 %type <interm.function> function_header_with_parameters function_call_header
   172 %type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
   173 %type <interm> function_call_or_method
   175 %start translation_unit
   176 %%
   178 identifier
   179     : IDENTIFIER
   180     | TYPE_NAME
   182 variable_identifier
   183     : IDENTIFIER {
   184         // The symbol table search was done in the lexical phase
   185         const TSymbol* symbol = $1.symbol;
   186         const TVariable* variable;
   187         if (symbol == 0) {
   188             context->error(@1, "undeclared identifier", $1.string->c_str());
   189             context->recover();
   190             TType type(EbtFloat, EbpUndefined);
   191             TVariable* fakeVariable = new TVariable($1.string, type);
   192             context->symbolTable.insert(*fakeVariable);
   193             variable = fakeVariable;
   194         } else {
   195             // This identifier can only be a variable type symbol
   196             if (! symbol->isVariable()) {
   197                 context->error(@1, "variable expected", $1.string->c_str());
   198                 context->recover();
   199             }
   201             variable = static_cast<const TVariable*>(symbol);
   203             if (context->symbolTable.findBuiltIn(variable->getName()) &&
   204                 !variable->getExtension().empty() &&
   205                 context->extensionErrorCheck(@1, variable->getExtension())) {
   206                 context->recover();
   207             }
   208         }
   210         // don't delete $1.string, it's used by error recovery, and the pool
   211         // pop will reclaim the memory
   213         if (variable->getType().getQualifier() == EvqConst ) {
   214             ConstantUnion* constArray = variable->getConstPointer();
   215             TType t(variable->getType());
   216             $$ = context->intermediate.addConstantUnion(constArray, t, @1);
   217         } else
   218             $$ = context->intermediate.addSymbol(variable->getUniqueId(),
   219                                                  variable->getName(),
   220                                                  variable->getType(),
   221                                                  @1);
   222     }
   223     ;
   225 primary_expression
   226     : variable_identifier {
   227         $$ = $1;
   228     }
   229     | INTCONSTANT {
   230         //
   231         // INT_TYPE is only 16-bit plus sign bit for vertex/fragment shaders,
   232         // check for overflow for constants
   233         //
   234         if (abs($1.i) >= (1 << 16)) {
   235             context->error(@1, " integer constant overflow", "");
   236             context->recover();
   237         }
   238         ConstantUnion *unionArray = new ConstantUnion[1];
   239         unionArray->setIConst($1.i);
   240         $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @1);
   241     }
   242     | FLOATCONSTANT {
   243         ConstantUnion *unionArray = new ConstantUnion[1];
   244         unionArray->setFConst($1.f);
   245         $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1);
   246     }
   247     | BOOLCONSTANT {
   248         ConstantUnion *unionArray = new ConstantUnion[1];
   249         unionArray->setBConst($1.b);
   250         $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @1);
   251     }
   252     | LEFT_PAREN expression RIGHT_PAREN {
   253         $$ = $2;
   254     }
   255     ;
   257 postfix_expression
   258     : primary_expression {
   259         $$ = $1;
   260     }
   261     | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET {
   262         $$ = context->addIndexExpression($1, @2, $3);
   263     }
   264     | function_call {
   265         $$ = $1;
   266     }
   267     | postfix_expression DOT identifier {
   268         if ($1->isArray()) {
   269             context->error(@3, "cannot apply dot operator to an array", ".");
   270             context->recover();
   271         }
   273         if ($1->isVector()) {
   274             TVectorFields fields;
   275             if (! context->parseVectorFields(*$3.string, $1->getNominalSize(), fields, @3)) {
   276                 fields.num = 1;
   277                 fields.offsets[0] = 0;
   278                 context->recover();
   279             }
   281             if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields
   282                 $$ = context->addConstVectorNode(fields, $1, @3);
   283                 if ($$ == 0) {
   284                     context->recover();
   285                     $$ = $1;
   286                 }
   287                 else
   288                     $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, (int) (*$3.string).size()));
   289             } else {
   290                 TString vectorString = *$3.string;
   291                 TIntermTyped* index = context->intermediate.addSwizzle(fields, @3);
   292                 $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, @2);
   293                 $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, (int) vectorString.size()));
   294             }
   295         } else if ($1->isMatrix()) {
   296             TMatrixFields fields;
   297             if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, @3)) {
   298                 fields.wholeRow = false;
   299                 fields.wholeCol = false;
   300                 fields.row = 0;
   301                 fields.col = 0;
   302                 context->recover();
   303             }
   305             if (fields.wholeRow || fields.wholeCol) {
   306                 context->error(@2, " non-scalar fields not implemented yet", ".");
   307                 context->recover();
   308                 ConstantUnion *unionArray = new ConstantUnion[1];
   309                 unionArray->setIConst(0);
   310                 TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3);
   311                 $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2);
   312                 $$->setType(TType($1->getBasicType(), $1->getPrecision(),EvqTemporary, $1->getNominalSize()));
   313             } else {
   314                 ConstantUnion *unionArray = new ConstantUnion[1];
   315                 unionArray->setIConst(fields.col * $1->getNominalSize() + fields.row);
   316                 TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3);
   317                 $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2);
   318                 $$->setType(TType($1->getBasicType(), $1->getPrecision()));
   319             }
   320         } else if ($1->getBasicType() == EbtStruct) {
   321             bool fieldFound = false;
   322             const TFieldList& fields = $1->getType().getStruct()->fields();
   323             unsigned int i;
   324             for (i = 0; i < fields.size(); ++i) {
   325                 if (fields[i]->name() == *$3.string) {
   326                     fieldFound = true;
   327                     break;
   328                 }
   329             }
   330             if (fieldFound) {
   331                 if ($1->getType().getQualifier() == EvqConst) {
   332                     $$ = context->addConstStruct(*$3.string, $1, @2);
   333                     if ($$ == 0) {
   334                         context->recover();
   335                         $$ = $1;
   336                     }
   337                     else {
   338                         $$->setType(*fields[i]->type());
   339                         // change the qualifier of the return type, not of the structure field
   340                         // as the structure definition is shared between various structures.
   341                         $$->getTypePointer()->setQualifier(EvqConst);
   342                     }
   343                 } else {
   344                     ConstantUnion *unionArray = new ConstantUnion[1];
   345                     unionArray->setIConst(i);
   346                     TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *fields[i]->type(), @3);
   347                     $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, @2);
   348                     $$->setType(*fields[i]->type());
   349                 }
   350             } else {
   351                 context->error(@2, " no such field in structure", $3.string->c_str());
   352                 context->recover();
   353                 $$ = $1;
   354             }
   355         } else {
   356             context->error(@2, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str());
   357             context->recover();
   358             $$ = $1;
   359         }
   360         // don't delete $3.string, it's from the pool
   361     }
   362     | postfix_expression INC_OP {
   363         if (context->lValueErrorCheck(@2, "++", $1))
   364             context->recover();
   365         $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, @2, context->symbolTable);
   366         if ($$ == 0) {
   367             context->unaryOpError(@2, "++", $1->getCompleteString());
   368             context->recover();
   369             $$ = $1;
   370         }
   371     }
   372     | postfix_expression DEC_OP {
   373         if (context->lValueErrorCheck(@2, "--", $1))
   374             context->recover();
   375         $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, @2, context->symbolTable);
   376         if ($$ == 0) {
   377             context->unaryOpError(@2, "--", $1->getCompleteString());
   378             context->recover();
   379             $$ = $1;
   380         }
   381     }
   382     ;
   384 integer_expression
   385     : expression {
   386         if (context->integerErrorCheck($1, "[]"))
   387             context->recover();
   388         $$ = $1;
   389     }
   390     ;
   392 function_call
   393     : function_call_or_method {
   394         TFunction* fnCall = $1.function;
   395         TOperator op = fnCall->getBuiltInOp();
   397         if (op != EOpNull)
   398         {
   399             //
   400             // Then this should be a constructor.
   401             // Don't go through the symbol table for constructors.
   402             // Their parameters will be verified algorithmically.
   403             //
   404             TType type(EbtVoid, EbpUndefined);  // use this to get the type back
   405             if (context->constructorErrorCheck(@1, $1.intermNode, *fnCall, op, &type)) {
   406                 $$ = 0;
   407             } else {
   408                 //
   409                 // It's a constructor, of type 'type'.
   410                 //
   411                 $$ = context->addConstructor($1.intermNode, &type, op, fnCall, @1);
   412             }
   414             if ($$ == 0) {
   415                 context->recover();
   416                 $$ = context->intermediate.setAggregateOperator(0, op, @1);
   417             }
   418             $$->setType(type);
   419         } else {
   420             //
   421             // Not a constructor.  Find it in the symbol table.
   422             //
   423             const TFunction* fnCandidate;
   424             bool builtIn;
   425             fnCandidate = context->findFunction(@1, fnCall, &builtIn);
   426             if (fnCandidate) {
   427                 //
   428                 // A declared function.
   429                 //
   430                 if (builtIn && !fnCandidate->getExtension().empty() &&
   431                     context->extensionErrorCheck(@1, fnCandidate->getExtension())) {
   432                     context->recover();
   433                 }
   434                 op = fnCandidate->getBuiltInOp();
   435                 if (builtIn && op != EOpNull) {
   436                     //
   437                     // A function call mapped to a built-in operation.
   438                     //
   439                     if (fnCandidate->getParamCount() == 1) {
   440                         //
   441                         // Treat it like a built-in unary operator.
   442                         //
   443                         $$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1, context->symbolTable);
   444                         if ($$ == 0)  {
   445                             std::stringstream extraInfoStream;
   446                             extraInfoStream << "built in unary operator function.  Type: " << static_cast<TIntermTyped*>($1.intermNode)->getCompleteString();
   447                             std::string extraInfo = extraInfoStream.str();
   448                             context->error($1.intermNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
   449                             YYERROR;
   450                         }
   451                     } else {
   452                         $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1);
   453                     }
   454                 } else {
   455                     // This is a real function call
   457                     $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1);
   458                     $$->setType(fnCandidate->getReturnType());
   460                     // this is how we know whether the given function is a builtIn function or a user defined function
   461                     // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
   462                     // if builtIn == true, it's definitely a builtIn function with EOpNull
   463                     if (!builtIn)
   464                         $$->getAsAggregate()->setUserDefined();
   465                     $$->getAsAggregate()->setName(fnCandidate->getMangledName());
   467                     TQualifier qual;
   468                     for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) {
   469                         qual = fnCandidate->getParam(i).type->getQualifier();
   470                         if (qual == EvqOut || qual == EvqInOut) {
   471                             if (context->lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) {
   472                                 context->error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
   473                                 context->recover();
   474                             }
   475                         }
   476                     }
   477                 }
   478                 $$->setType(fnCandidate->getReturnType());
   479             } else {
   480                 // error message was put out by PaFindFunction()
   481                 // Put on a dummy node for error recovery
   482                 ConstantUnion *unionArray = new ConstantUnion[1];
   483                 unionArray->setFConst(0.0f);
   484                 $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1);
   485                 context->recover();
   486             }
   487         }
   488         delete fnCall;
   489     }
   490     ;
   492 function_call_or_method
   493     : function_call_generic {
   494         $$ = $1;
   495     }
   496     | postfix_expression DOT function_call_generic {
   497         context->error(@3, "methods are not supported", "");
   498         context->recover();
   499         $$ = $3;
   500     }
   501     ;
   503 function_call_generic
   504     : function_call_header_with_parameters RIGHT_PAREN {
   505         $$ = $1;
   506     }
   507     | function_call_header_no_parameters RIGHT_PAREN {
   508         $$ = $1;
   509     }
   510     ;
   512 function_call_header_no_parameters
   513     : function_call_header VOID_TYPE {
   514         $$.function = $1;
   515         $$.intermNode = 0;
   516     }
   517     | function_call_header {
   518         $$.function = $1;
   519         $$.intermNode = 0;
   520     }
   521     ;
   523 function_call_header_with_parameters
   524     : function_call_header assignment_expression {
   525         TParameter param = { 0, new TType($2->getType()) };
   526         $1->addParameter(param);
   527         $$.function = $1;
   528         $$.intermNode = $2;
   529     }
   530     | function_call_header_with_parameters COMMA assignment_expression {
   531         TParameter param = { 0, new TType($3->getType()) };
   532         $1.function->addParameter(param);
   533         $$.function = $1.function;
   534         $$.intermNode = context->intermediate.growAggregate($1.intermNode, $3, @2);
   535     }
   536     ;
   538 function_call_header
   539     : function_identifier LEFT_PAREN {
   540         $$ = $1;
   541     }
   542     ;
   544 // Grammar Note:  Constructors look like functions, but are recognized as types.
   546 function_identifier
   547     : type_specifier_nonarray {
   548         //
   549         // Constructor
   550         //
   551         TOperator op = EOpNull;
   552         if ($1.userDef) {
   553             op = EOpConstructStruct;
   554         } else {
   555             switch ($1.type) {
   556             case EbtFloat:
   557                 if ($1.matrix) {
   558                     switch($1.size) {
   559                     case 2: op = EOpConstructMat2;  break;
   560                     case 3: op = EOpConstructMat3;  break;
   561                     case 4: op = EOpConstructMat4;  break;
   562                     }
   563                 } else {
   564                     switch($1.size) {
   565                     case 1: op = EOpConstructFloat; break;
   566                     case 2: op = EOpConstructVec2;  break;
   567                     case 3: op = EOpConstructVec3;  break;
   568                     case 4: op = EOpConstructVec4;  break;
   569                     }
   570                 }
   571                 break;
   572             case EbtInt:
   573                 switch($1.size) {
   574                 case 1: op = EOpConstructInt;   break;
   575                 case 2: op = EOpConstructIVec2; break;
   576                 case 3: op = EOpConstructIVec3; break;
   577                 case 4: op = EOpConstructIVec4; break;
   578                 }
   579                 break;
   580             case EbtBool:
   581                 switch($1.size) {
   582                 case 1: op = EOpConstructBool;  break;
   583                 case 2: op = EOpConstructBVec2; break;
   584                 case 3: op = EOpConstructBVec3; break;
   585                 case 4: op = EOpConstructBVec4; break;
   586                 }
   587                 break;
   588             default: break;
   589             }
   590             if (op == EOpNull) {
   591                 context->error(@1, "cannot construct this type", getBasicString($1.type));
   592                 context->recover();
   593                 $1.type = EbtFloat;
   594                 op = EOpConstructFloat;
   595             }
   596         }
   597         TString tempString;
   598         TType type($1);
   599         TFunction *function = new TFunction(&tempString, type, op);
   600         $$ = function;
   601     }
   602     | IDENTIFIER {
   603         if (context->reservedErrorCheck(@1, *$1.string))
   604             context->recover();
   605         TType type(EbtVoid, EbpUndefined);
   606         TFunction *function = new TFunction($1.string, type);
   607         $$ = function;
   608     }
   609     ;
   611 unary_expression
   612     : postfix_expression {
   613         $$ = $1;
   614     }
   615     | INC_OP unary_expression {
   616         if (context->lValueErrorCheck(@1, "++", $2))
   617             context->recover();
   618         $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, @1, context->symbolTable);
   619         if ($$ == 0) {
   620             context->unaryOpError(@1, "++", $2->getCompleteString());
   621             context->recover();
   622             $$ = $2;
   623         }
   624     }
   625     | DEC_OP unary_expression {
   626         if (context->lValueErrorCheck(@1, "--", $2))
   627             context->recover();
   628         $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, @1, context->symbolTable);
   629         if ($$ == 0) {
   630             context->unaryOpError(@1, "--", $2->getCompleteString());
   631             context->recover();
   632             $$ = $2;
   633         }
   634     }
   635     | unary_operator unary_expression {
   636         if ($1.op != EOpNull) {
   637             $$ = context->intermediate.addUnaryMath($1.op, $2, @1, context->symbolTable);
   638             if ($$ == 0) {
   639                 const char* errorOp = "";
   640                 switch($1.op) {
   641                 case EOpNegative:   errorOp = "-"; break;
   642                 case EOpLogicalNot: errorOp = "!"; break;
   643                 default: break;
   644                 }
   645                 context->unaryOpError(@1, errorOp, $2->getCompleteString());
   646                 context->recover();
   647                 $$ = $2;
   648             }
   649         } else
   650             $$ = $2;
   651     }
   652     ;
   653 // Grammar Note:  No traditional style type casts.
   655 unary_operator
   656     : PLUS  { $$.op = EOpNull; }
   657     | DASH  { $$.op = EOpNegative; }
   658     | BANG  { $$.op = EOpLogicalNot; }
   659     ;
   660 // Grammar Note:  No '*' or '&' unary ops.  Pointers are not supported.
   662 multiplicative_expression
   663     : unary_expression { $$ = $1; }
   664     | multiplicative_expression STAR unary_expression {
   665         $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, @2, context->symbolTable);
   666         if ($$ == 0) {
   667             context->binaryOpError(@2, "*", $1->getCompleteString(), $3->getCompleteString());
   668             context->recover();
   669             $$ = $1;
   670         }
   671     }
   672     | multiplicative_expression SLASH unary_expression {
   673         $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, @2, context->symbolTable);
   674         if ($$ == 0) {
   675             context->binaryOpError(@2, "/", $1->getCompleteString(), $3->getCompleteString());
   676             context->recover();
   677             $$ = $1;
   678         }
   679     }
   680     ;
   682 additive_expression
   683     : multiplicative_expression { $$ = $1; }
   684     | additive_expression PLUS multiplicative_expression {
   685         $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, @2, context->symbolTable);
   686         if ($$ == 0) {
   687             context->binaryOpError(@2, "+", $1->getCompleteString(), $3->getCompleteString());
   688             context->recover();
   689             $$ = $1;
   690         }
   691     }
   692     | additive_expression DASH multiplicative_expression {
   693         $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, @2, context->symbolTable);
   694         if ($$ == 0) {
   695             context->binaryOpError(@2, "-", $1->getCompleteString(), $3->getCompleteString());
   696             context->recover();
   697             $$ = $1;
   698         }
   699     }
   700     ;
   702 shift_expression
   703     : additive_expression { $$ = $1; }
   704     ;
   706 relational_expression
   707     : shift_expression { $$ = $1; }
   708     | relational_expression LEFT_ANGLE shift_expression {
   709         $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, @2, context->symbolTable);
   710         if ($$ == 0) {
   711             context->binaryOpError(@2, "<", $1->getCompleteString(), $3->getCompleteString());
   712             context->recover();
   713             ConstantUnion *unionArray = new ConstantUnion[1];
   714             unionArray->setBConst(false);
   715             $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
   716         }
   717     }
   718     | relational_expression RIGHT_ANGLE shift_expression  {
   719         $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, @2, context->symbolTable);
   720         if ($$ == 0) {
   721             context->binaryOpError(@2, ">", $1->getCompleteString(), $3->getCompleteString());
   722             context->recover();
   723             ConstantUnion *unionArray = new ConstantUnion[1];
   724             unionArray->setBConst(false);
   725             $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
   726         }
   727     }
   728     | relational_expression LE_OP shift_expression  {
   729         $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, @2, context->symbolTable);
   730         if ($$ == 0) {
   731             context->binaryOpError(@2, "<=", $1->getCompleteString(), $3->getCompleteString());
   732             context->recover();
   733             ConstantUnion *unionArray = new ConstantUnion[1];
   734             unionArray->setBConst(false);
   735             $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
   736         }
   737     }
   738     | relational_expression GE_OP shift_expression  {
   739         $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, @2, context->symbolTable);
   740         if ($$ == 0) {
   741             context->binaryOpError(@2, ">=", $1->getCompleteString(), $3->getCompleteString());
   742             context->recover();
   743             ConstantUnion *unionArray = new ConstantUnion[1];
   744             unionArray->setBConst(false);
   745             $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
   746         }
   747     }
   748     ;
   750 equality_expression
   751     : relational_expression { $$ = $1; }
   752     | equality_expression EQ_OP relational_expression  {
   753         $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, @2, context->symbolTable);
   754         if ($$ == 0) {
   755             context->binaryOpError(@2, "==", $1->getCompleteString(), $3->getCompleteString());
   756             context->recover();
   757             ConstantUnion *unionArray = new ConstantUnion[1];
   758             unionArray->setBConst(false);
   759             $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
   760         }
   761     }
   762     | equality_expression NE_OP relational_expression {
   763         $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, @2, context->symbolTable);
   764         if ($$ == 0) {
   765             context->binaryOpError(@2, "!=", $1->getCompleteString(), $3->getCompleteString());
   766             context->recover();
   767             ConstantUnion *unionArray = new ConstantUnion[1];
   768             unionArray->setBConst(false);
   769             $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
   770         }
   771     }
   772     ;
   774 and_expression
   775     : equality_expression { $$ = $1; }
   776     ;
   778 exclusive_or_expression
   779     : and_expression { $$ = $1; }
   780     ;
   782 inclusive_or_expression
   783     : exclusive_or_expression { $$ = $1; }
   784     ;
   786 logical_and_expression
   787     : inclusive_or_expression { $$ = $1; }
   788     | logical_and_expression AND_OP inclusive_or_expression {
   789         $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, @2, context->symbolTable);
   790         if ($$ == 0) {
   791             context->binaryOpError(@2, "&&", $1->getCompleteString(), $3->getCompleteString());
   792             context->recover();
   793             ConstantUnion *unionArray = new ConstantUnion[1];
   794             unionArray->setBConst(false);
   795             $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
   796         }
   797     }
   798     ;
   800 logical_xor_expression
   801     : logical_and_expression { $$ = $1; }
   802     | logical_xor_expression XOR_OP logical_and_expression  {
   803         $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, @2, context->symbolTable);
   804         if ($$ == 0) {
   805             context->binaryOpError(@2, "^^", $1->getCompleteString(), $3->getCompleteString());
   806             context->recover();
   807             ConstantUnion *unionArray = new ConstantUnion[1];
   808             unionArray->setBConst(false);
   809             $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
   810         }
   811     }
   812     ;
   814 logical_or_expression
   815     : logical_xor_expression { $$ = $1; }
   816     | logical_or_expression OR_OP logical_xor_expression  {
   817         $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, @2, context->symbolTable);
   818         if ($$ == 0) {
   819             context->binaryOpError(@2, "||", $1->getCompleteString(), $3->getCompleteString());
   820             context->recover();
   821             ConstantUnion *unionArray = new ConstantUnion[1];
   822             unionArray->setBConst(false);
   823             $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
   824         }
   825     }
   826     ;
   828 conditional_expression
   829     : logical_or_expression { $$ = $1; }
   830     | logical_or_expression QUESTION expression COLON assignment_expression {
   831        if (context->boolErrorCheck(@2, $1))
   832             context->recover();
   834         $$ = context->intermediate.addSelection($1, $3, $5, @2);
   835         if ($3->getType() != $5->getType())
   836             $$ = 0;
   838         if ($$ == 0) {
   839             context->binaryOpError(@2, ":", $3->getCompleteString(), $5->getCompleteString());
   840             context->recover();
   841             $$ = $5;
   842         }
   843     }
   844     ;
   846 assignment_expression
   847     : conditional_expression { $$ = $1; }
   848     | unary_expression assignment_operator assignment_expression {
   849         if (context->lValueErrorCheck(@2, "assign", $1))
   850             context->recover();
   851         $$ = context->intermediate.addAssign($2.op, $1, $3, @2);
   852         if ($$ == 0) {
   853             context->assignError(@2, "assign", $1->getCompleteString(), $3->getCompleteString());
   854             context->recover();
   855             $$ = $1;
   856         }
   857     }
   858     ;
   860 assignment_operator
   861     : EQUAL        { $$.op = EOpAssign; }
   862     | MUL_ASSIGN   { $$.op = EOpMulAssign; }
   863     | DIV_ASSIGN   { $$.op = EOpDivAssign; }
   864     | ADD_ASSIGN   { $$.op = EOpAddAssign; }
   865     | SUB_ASSIGN   { $$.op = EOpSubAssign; }
   866     ;
   868 expression
   869     : assignment_expression {
   870         $$ = $1;
   871     }
   872     | expression COMMA assignment_expression {
   873         $$ = context->intermediate.addComma($1, $3, @2);
   874         if ($$ == 0) {
   875             context->binaryOpError(@2, ",", $1->getCompleteString(), $3->getCompleteString());
   876             context->recover();
   877             $$ = $3;
   878         }
   879     }
   880     ;
   882 constant_expression
   883     : conditional_expression {
   884         if (context->constErrorCheck($1))
   885             context->recover();
   886         $$ = $1;
   887     }
   888     ;
   890 declaration
   891     : function_prototype SEMICOLON   {
   892         TFunction &function = *($1.function);
   894         TIntermAggregate *prototype = new TIntermAggregate;
   895         prototype->setType(function.getReturnType());
   896         prototype->setName(function.getName());
   898         for (size_t i = 0; i < function.getParamCount(); i++)
   899         {
   900             const TParameter &param = function.getParam(i);
   901             if (param.name != 0)
   902             {
   903                 TVariable variable(param.name, *param.type);
   905                 prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), @1), @1);
   906             }
   907             else
   908             {
   909                 prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, @1), @1);
   910             }
   911         }
   913         prototype->setOp(EOpPrototype);
   914         $$ = prototype;
   916         context->symbolTable.pop();
   917     }
   918     | init_declarator_list SEMICOLON {
   919         if ($1.intermAggregate)
   920             $1.intermAggregate->setOp(EOpDeclaration);
   921         $$ = $1.intermAggregate;
   922     }
   923     | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
   924         if (($2 == EbpHigh) && (context->shaderType == SH_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) {
   925             context->error(@1, "precision is not supported in fragment shader", "highp");
   926             context->recover();
   927         }
   928         if (!context->symbolTable.setDefaultPrecision( $3, $2 )) {
   929             context->error(@1, "illegal type argument for default precision qualifier", getBasicString($3.type));
   930             context->recover();
   931         }
   932         $$ = 0;
   933     }
   934     ;
   936 function_prototype
   937     : function_declarator RIGHT_PAREN  {
   938         //
   939         // Multiple declarations of the same function are allowed.
   940         //
   941         // If this is a definition, the definition production code will check for redefinitions
   942         // (we don't know at this point if it's a definition or not).
   943         //
   944         // Redeclarations are allowed.  But, return types and parameter qualifiers must match.
   945         //
   946         TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find($1->getMangledName()));
   947         if (prevDec) {
   948             if (prevDec->getReturnType() != $1->getReturnType()) {
   949                 context->error(@2, "overloaded functions must have the same return type", $1->getReturnType().getBasicString());
   950                 context->recover();
   951             }
   952             for (size_t i = 0; i < prevDec->getParamCount(); ++i) {
   953                 if (prevDec->getParam(i).type->getQualifier() != $1->getParam(i).type->getQualifier()) {
   954                     context->error(@2, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString());
   955                     context->recover();
   956                 }
   957             }
   958         }
   960         //
   961         // Check for previously declared variables using the same name.
   962         //
   963         TSymbol *prevSym = context->symbolTable.find($1->getName());
   964         if (prevSym)
   965         {
   966             if (!prevSym->isFunction())
   967             {
   968                 context->error(@2, "redefinition", $1->getName().c_str(), "function");
   969                 context->recover();
   970             }
   971         }
   972         else
   973         {
   974             // Insert the unmangled name to detect potential future redefinition as a variable.
   975             context->symbolTable.getOuterLevel()->insert($1->getName(), *$1);
   976         }
   978         //
   979         // If this is a redeclaration, it could also be a definition,
   980         // in which case, we want to use the variable names from this one, and not the one that's
   981         // being redeclared.  So, pass back up this declaration, not the one in the symbol table.
   982         //
   983         $$.function = $1;
   985         // We're at the inner scope level of the function's arguments and body statement.
   986         // Add the function prototype to the surrounding scope instead.
   987         context->symbolTable.getOuterLevel()->insert(*$$.function);
   988     }
   989     ;
   991 function_declarator
   992     : function_header {
   993         $$ = $1;
   994     }
   995     | function_header_with_parameters {
   996         $$ = $1;
   997     }
   998     ;
  1001 function_header_with_parameters
  1002     : function_header parameter_declaration {
  1003         // Add the parameter
  1004         $$ = $1;
  1005         if ($2.param.type->getBasicType() != EbtVoid)
  1006             $1->addParameter($2.param);
  1007         else
  1008             delete $2.param.type;
  1010     | function_header_with_parameters COMMA parameter_declaration {
  1011         //
  1012         // Only first parameter of one-parameter functions can be void
  1013         // The check for named parameters not being void is done in parameter_declarator
  1014         //
  1015         if ($3.param.type->getBasicType() == EbtVoid) {
  1016             //
  1017             // This parameter > first is void
  1018             //
  1019             context->error(@2, "cannot be an argument type except for '(void)'", "void");
  1020             context->recover();
  1021             delete $3.param.type;
  1022         } else {
  1023             // Add the parameter
  1024             $$ = $1;
  1025             $1->addParameter($3.param);
  1030 function_header
  1031     : fully_specified_type IDENTIFIER LEFT_PAREN {
  1032         if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) {
  1033             context->error(@2, "no qualifiers allowed for function return", getQualifierString($1.qualifier));
  1034             context->recover();
  1036         // make sure a sampler is not involved as well...
  1037         if (context->structQualifierErrorCheck(@2, $1))
  1038             context->recover();
  1040         // Add the function as a prototype after parsing it (we do not support recursion)
  1041         TFunction *function;
  1042         TType type($1);
  1043         function = new TFunction($2.string, type);
  1044         $$ = function;
  1046         context->symbolTable.push();
  1050 parameter_declarator
  1051     // Type + name
  1052     : type_specifier identifier {
  1053         if ($1.type == EbtVoid) {
  1054             context->error(@2, "illegal use of type 'void'", $2.string->c_str());
  1055             context->recover();
  1057         if (context->reservedErrorCheck(@2, *$2.string))
  1058             context->recover();
  1059         TParameter param = {$2.string, new TType($1)};
  1060         $$.param = param;
  1062     | type_specifier identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
  1063         // Check that we can make an array out of this type
  1064         if (context->arrayTypeErrorCheck(@3, $1))
  1065             context->recover();
  1067         if (context->reservedErrorCheck(@2, *$2.string))
  1068             context->recover();
  1070         int size;
  1071         if (context->arraySizeErrorCheck(@3, $4, size))
  1072             context->recover();
  1073         $1.setArray(true, size);
  1075         TType* type = new TType($1);
  1076         TParameter param = { $2.string, type };
  1077         $$.param = param;
  1081 parameter_declaration
  1082     //
  1083     // The only parameter qualifier a parameter can have are
  1084     // IN_QUAL, OUT_QUAL, INOUT_QUAL, or CONST.
  1085     //
  1087     //
  1088     // Type + name
  1089     //
  1090     : type_qualifier parameter_qualifier parameter_declarator {
  1091         $$ = $3;
  1092         if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type))
  1093             context->recover();
  1095     | parameter_qualifier parameter_declarator {
  1096         $$ = $2;
  1097         if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type))
  1098             context->recover();
  1099         if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type))
  1100             context->recover();
  1102     //
  1103     // Only type
  1104     //
  1105     | type_qualifier parameter_qualifier parameter_type_specifier {
  1106         $$ = $3;
  1107         if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type))
  1108             context->recover();
  1110     | parameter_qualifier parameter_type_specifier {
  1111         $$ = $2;
  1112         if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type))
  1113             context->recover();
  1114         if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type))
  1115             context->recover();
  1119 parameter_qualifier
  1120     : /* empty */ {
  1121         $$ = EvqIn;
  1123     | IN_QUAL {
  1124         $$ = EvqIn;
  1126     | OUT_QUAL {
  1127         $$ = EvqOut;
  1129     | INOUT_QUAL {
  1130         $$ = EvqInOut;
  1134 parameter_type_specifier
  1135     : type_specifier {
  1136         TParameter param = { 0, new TType($1) };
  1137         $$.param = param;
  1141 init_declarator_list
  1142     : single_declaration {
  1143         $$ = $1;
  1145     | init_declarator_list COMMA identifier {
  1146         if ($1.type.type == EbtInvariant && !$3.symbol)
  1148             context->error(@3, "undeclared identifier declared as invariant", $3.string->c_str());
  1149             context->recover();
  1152         TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$3.string, TType($1.type), @3);
  1153         $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, symbol, @3);
  1155         if (context->structQualifierErrorCheck(@3, $$.type))
  1156             context->recover();
  1158         if (context->nonInitConstErrorCheck(@3, *$3.string, $$.type, false))
  1159             context->recover();
  1161         TVariable* variable = 0;
  1162         if (context->nonInitErrorCheck(@3, *$3.string, $$.type, variable))
  1163             context->recover();
  1164         if (symbol && variable)
  1165             symbol->setId(variable->getUniqueId());
  1167     | init_declarator_list COMMA identifier LEFT_BRACKET RIGHT_BRACKET {
  1168         if (context->structQualifierErrorCheck(@3, $1.type))
  1169             context->recover();
  1171         if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true))
  1172             context->recover();
  1174         $$ = $1;
  1176         if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type))
  1177             context->recover();
  1178         else {
  1179             $1.type.setArray(true);
  1180             TVariable* variable;
  1181             if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable))
  1182                 context->recover();
  1185     | init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
  1186         if (context->structQualifierErrorCheck(@3, $1.type))
  1187             context->recover();
  1189         if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true))
  1190             context->recover();
  1192         $$ = $1;
  1194         if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type))
  1195             context->recover();
  1196         else {
  1197             int size;
  1198             if (context->arraySizeErrorCheck(@4, $5, size))
  1199                 context->recover();
  1200             $1.type.setArray(true, size);
  1201             TVariable* variable = 0;
  1202             if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable))
  1203                 context->recover();
  1204             TType type = TType($1.type);
  1205             type.setArraySize(size);
  1206             $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, @3), @3);
  1209     | init_declarator_list COMMA identifier EQUAL initializer {
  1210         if (context->structQualifierErrorCheck(@3, $1.type))
  1211             context->recover();
  1213         $$ = $1;
  1215         TIntermNode* intermNode;
  1216         if (!context->executeInitializer(@3, *$3.string, $1.type, $5, intermNode)) {
  1217             //
  1218             // build the intermediate representation
  1219             //
  1220             if (intermNode)
  1221         $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, intermNode, @4);
  1222             else
  1223                 $$.intermAggregate = $1.intermAggregate;
  1224         } else {
  1225             context->recover();
  1226             $$.intermAggregate = 0;
  1231 single_declaration
  1232     : fully_specified_type {
  1233         $$.type = $1;
  1234         $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), @1), @1);
  1236     | fully_specified_type identifier {
  1237         TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2);
  1238         $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2);
  1240         if (context->structQualifierErrorCheck(@2, $$.type))
  1241             context->recover();
  1243         if (context->nonInitConstErrorCheck(@2, *$2.string, $$.type, false))
  1244             context->recover();
  1246             $$.type = $1;
  1248         TVariable* variable = 0;
  1249         if (context->nonInitErrorCheck(@2, *$2.string, $$.type, variable))
  1250             context->recover();
  1251         if (variable && symbol)
  1252             symbol->setId(variable->getUniqueId());
  1254     | fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET {
  1255         context->error(@2, "unsized array declarations not supported", $2.string->c_str());
  1256         context->recover();
  1258         TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2);
  1259         $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2);
  1260         $$.type = $1;
  1262     | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
  1263         TType type = TType($1);
  1264         int size;
  1265         if (context->arraySizeErrorCheck(@2, $4, size))
  1266             context->recover();
  1267         type.setArraySize(size);
  1268         TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, @2);
  1269         $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2);
  1271         if (context->structQualifierErrorCheck(@2, $1))
  1272             context->recover();
  1274         if (context->nonInitConstErrorCheck(@2, *$2.string, $1, true))
  1275             context->recover();
  1277         $$.type = $1;
  1279         if (context->arrayTypeErrorCheck(@3, $1) || context->arrayQualifierErrorCheck(@3, $1))
  1280             context->recover();
  1281         else {
  1282             int size;
  1283             if (context->arraySizeErrorCheck(@3, $4, size))
  1284                 context->recover();
  1286             $1.setArray(true, size);
  1287             TVariable* variable = 0;
  1288             if (context->arrayErrorCheck(@3, *$2.string, $1, variable))
  1289                 context->recover();
  1290             if (variable && symbol)
  1291                 symbol->setId(variable->getUniqueId());
  1294     | fully_specified_type identifier EQUAL initializer {
  1295         if (context->structQualifierErrorCheck(@2, $1))
  1296             context->recover();
  1298         $$.type = $1;
  1300         TIntermNode* intermNode;
  1301         if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode)) {
  1302         //
  1303         // Build intermediate representation
  1304         //
  1305             if(intermNode)
  1306                 $$.intermAggregate = context->intermediate.makeAggregate(intermNode, @3);
  1307             else
  1308                 $$.intermAggregate = 0;
  1309         } else {
  1310             context->recover();
  1311             $$.intermAggregate = 0;
  1314     | INVARIANT IDENTIFIER {
  1315         VERTEX_ONLY("invariant declaration", @1);
  1316         if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying"))
  1317             context->recover();
  1318         $$.type.setBasic(EbtInvariant, EvqInvariantVaryingOut, @2);
  1319         if (!$2.symbol)
  1321             context->error(@2, "undeclared identifier declared as invariant", $2.string->c_str());
  1322             context->recover();
  1324             $$.intermAggregate = 0;
  1326         else
  1328             TIntermSymbol *symbol = context->intermediate.addSymbol(0, *$2.string, TType($$.type), @2);
  1329             $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2);
  1334 fully_specified_type
  1335     : type_specifier {
  1336         $$ = $1;
  1338         if ($1.array) {
  1339             context->error(@1, "not supported", "first-class array");
  1340             context->recover();
  1341             $1.setArray(false);
  1344     | type_qualifier type_specifier  {
  1345         if ($2.array) {
  1346             context->error(@2, "not supported", "first-class array");
  1347             context->recover();
  1348             $2.setArray(false);
  1351         if ($1.qualifier == EvqAttribute &&
  1352             ($2.type == EbtBool || $2.type == EbtInt)) {
  1353             context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier));
  1354             context->recover();
  1356         if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) &&
  1357             ($2.type == EbtBool || $2.type == EbtInt)) {
  1358             context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier));
  1359             context->recover();
  1361         $$ = $2;
  1362         $$.qualifier = $1.qualifier;
  1366 type_qualifier
  1367     : CONST_QUAL {
  1368         $$.setBasic(EbtVoid, EvqConst, @1);
  1370     | ATTRIBUTE {
  1371         VERTEX_ONLY("attribute", @1);
  1372         if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "attribute"))
  1373             context->recover();
  1374         $$.setBasic(EbtVoid, EvqAttribute, @1);
  1376     | VARYING {
  1377         if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "varying"))
  1378             context->recover();
  1379         if (context->shaderType == SH_VERTEX_SHADER)
  1380             $$.setBasic(EbtVoid, EvqVaryingOut, @1);
  1381         else
  1382             $$.setBasic(EbtVoid, EvqVaryingIn, @1);
  1384     | INVARIANT VARYING {
  1385         if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying"))
  1386             context->recover();
  1387         if (context->shaderType == SH_VERTEX_SHADER)
  1388             $$.setBasic(EbtVoid, EvqInvariantVaryingOut, @1);
  1389         else
  1390             $$.setBasic(EbtVoid, EvqInvariantVaryingIn, @1);
  1392     | UNIFORM {
  1393         if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "uniform"))
  1394             context->recover();
  1395         $$.setBasic(EbtVoid, EvqUniform, @1);
  1399 type_specifier
  1400     : type_specifier_no_prec {
  1401         $$ = $1;
  1403         if ($$.precision == EbpUndefined) {
  1404             $$.precision = context->symbolTable.getDefaultPrecision($1.type);
  1405             if (context->precisionErrorCheck(@1, $$.precision, $1.type)) {
  1406                 context->recover();
  1410     | precision_qualifier type_specifier_no_prec {
  1411         $$ = $2;
  1412         $$.precision = $1;
  1416 precision_qualifier
  1417     : HIGH_PRECISION {
  1418         $$ = EbpHigh;
  1420     | MEDIUM_PRECISION {
  1421         $$ = EbpMedium;
  1423     | LOW_PRECISION  {
  1424         $$ = EbpLow;
  1428 type_specifier_no_prec
  1429     : type_specifier_nonarray {
  1430         $$ = $1;
  1432     | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET {
  1433         $$ = $1;
  1435         if (context->arrayTypeErrorCheck(@2, $1))
  1436             context->recover();
  1437         else {
  1438             int size;
  1439             if (context->arraySizeErrorCheck(@2, $3, size))
  1440                 context->recover();
  1441             $$.setArray(true, size);
  1446 type_specifier_nonarray
  1447     : VOID_TYPE {
  1448         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1449         $$.setBasic(EbtVoid, qual, @1);
  1451     | FLOAT_TYPE {
  1452         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1453         $$.setBasic(EbtFloat, qual, @1);
  1455     | INT_TYPE {
  1456         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1457         $$.setBasic(EbtInt, qual, @1);
  1459     | BOOL_TYPE {
  1460         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1461         $$.setBasic(EbtBool, qual, @1);
  1463     | VEC2 {
  1464         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1465         $$.setBasic(EbtFloat, qual, @1);
  1466         $$.setAggregate(2);
  1468     | VEC3 {
  1469         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1470         $$.setBasic(EbtFloat, qual, @1);
  1471         $$.setAggregate(3);
  1473     | VEC4 {
  1474         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1475         $$.setBasic(EbtFloat, qual, @1);
  1476         $$.setAggregate(4);
  1478     | BVEC2 {
  1479         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1480         $$.setBasic(EbtBool, qual, @1);
  1481         $$.setAggregate(2);
  1483     | BVEC3 {
  1484         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1485         $$.setBasic(EbtBool, qual, @1);
  1486         $$.setAggregate(3);
  1488     | BVEC4 {
  1489         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1490         $$.setBasic(EbtBool, qual, @1);
  1491         $$.setAggregate(4);
  1493     | IVEC2 {
  1494         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1495         $$.setBasic(EbtInt, qual, @1);
  1496         $$.setAggregate(2);
  1498     | IVEC3 {
  1499         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1500         $$.setBasic(EbtInt, qual, @1);
  1501         $$.setAggregate(3);
  1503     | IVEC4 {
  1504         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1505         $$.setBasic(EbtInt, qual, @1);
  1506         $$.setAggregate(4);
  1508     | MATRIX2 {
  1509         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1510         $$.setBasic(EbtFloat, qual, @1);
  1511         $$.setAggregate(2, true);
  1513     | MATRIX3 {
  1514         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1515         $$.setBasic(EbtFloat, qual, @1);
  1516         $$.setAggregate(3, true);
  1518     | MATRIX4 {
  1519         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1520         $$.setBasic(EbtFloat, qual, @1);
  1521         $$.setAggregate(4, true);
  1523     | SAMPLER2D {
  1524         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1525         $$.setBasic(EbtSampler2D, qual, @1);
  1527     | SAMPLERCUBE {
  1528         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1529         $$.setBasic(EbtSamplerCube, qual, @1);
  1531     | SAMPLER_EXTERNAL_OES {
  1532         if (!context->supportsExtension("GL_OES_EGL_image_external")) {
  1533             context->error(@1, "unsupported type", "samplerExternalOES");
  1534             context->recover();
  1536         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1537         $$.setBasic(EbtSamplerExternalOES, qual, @1);
  1539     | SAMPLER2DRECT {
  1540         if (!context->supportsExtension("GL_ARB_texture_rectangle")) {
  1541             context->error(@1, "unsupported type", "sampler2DRect");
  1542             context->recover();
  1544         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1545         $$.setBasic(EbtSampler2DRect, qual, @1);
  1547     | struct_specifier {
  1548         $$ = $1;
  1549         $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1551     | TYPE_NAME {
  1552         //
  1553         // This is for user defined type names.  The lexical phase looked up the
  1554         // type.
  1555         //
  1556         TType& structure = static_cast<TVariable*>($1.symbol)->getType();
  1557         TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1558         $$.setBasic(EbtStruct, qual, @1);
  1559         $$.userDef = &structure;
  1563 struct_specifier
  1564     : STRUCT identifier LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
  1565         if (context->reservedErrorCheck(@2, *$2.string))
  1566             context->recover();
  1568         TType* structure = new TType(new TStructure($2.string, $5));
  1569         TVariable* userTypeDef = new TVariable($2.string, *structure, true);
  1570         if (! context->symbolTable.insert(*userTypeDef)) {
  1571             context->error(@2, "redefinition", $2.string->c_str(), "struct");
  1572             context->recover();
  1574         $$.setBasic(EbtStruct, EvqTemporary, @1);
  1575         $$.userDef = structure;
  1576         context->exitStructDeclaration();
  1578     | STRUCT LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
  1579         TType* structure = new TType(new TStructure(NewPoolTString(""), $4));
  1580         $$.setBasic(EbtStruct, EvqTemporary, @1);
  1581         $$.userDef = structure;
  1582         context->exitStructDeclaration();
  1586 struct_declaration_list
  1587     : struct_declaration {
  1588         $$ = $1;
  1590     | struct_declaration_list struct_declaration {
  1591         $$ = $1;
  1592         for (size_t i = 0; i < $2->size(); ++i) {
  1593             TField* field = (*$2)[i];
  1594             for (size_t j = 0; j < $$->size(); ++j) {
  1595                 if ((*$$)[j]->name() == field->name()) {
  1596                     context->error(@2, "duplicate field name in structure:", "struct", field->name().c_str());
  1597                     context->recover();
  1600             $$->push_back(field);
  1605 struct_declaration
  1606     : type_specifier struct_declarator_list SEMICOLON {
  1607         $$ = $2;
  1609         if (context->voidErrorCheck(@1, (*$2)[0]->name(), $1)) {
  1610             context->recover();
  1612         for (unsigned int i = 0; i < $$->size(); ++i) {
  1613             //
  1614             // Careful not to replace already known aspects of type, like array-ness
  1615             //
  1616             TType* type = (*$$)[i]->type();
  1617             type->setBasicType($1.type);
  1618             type->setNominalSize($1.size);
  1619             type->setMatrix($1.matrix);
  1620             type->setPrecision($1.precision);
  1622             // don't allow arrays of arrays
  1623             if (type->isArray()) {
  1624                 if (context->arrayTypeErrorCheck(@1, $1))
  1625                     context->recover();
  1627             if ($1.array)
  1628                 type->setArraySize($1.arraySize);
  1629             if ($1.userDef)
  1630                 type->setStruct($1.userDef->getStruct());
  1632             if (context->structNestingErrorCheck(@1, *(*$$)[i]))
  1633                 context->recover();
  1638 struct_declarator_list
  1639     : struct_declarator {
  1640         $$ = NewPoolTFieldList();
  1641         $$->push_back($1);
  1643     | struct_declarator_list COMMA struct_declarator {
  1644         $$->push_back($3);
  1648 struct_declarator
  1649     : identifier {
  1650         if (context->reservedErrorCheck(@1, *$1.string))
  1651             context->recover();
  1653         TType* type = new TType(EbtVoid, EbpUndefined);
  1654         $$ = new TField(type, $1.string);
  1656     | identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
  1657         if (context->reservedErrorCheck(@1, *$1.string))
  1658             context->recover();
  1660         TType* type = new TType(EbtVoid, EbpUndefined);
  1661         int size = 0;
  1662         if (context->arraySizeErrorCheck(@3, $3, size))
  1663             context->recover();
  1664         type->setArraySize(size);
  1666         $$ = new TField(type, $1.string);
  1670 initializer
  1671     : assignment_expression { $$ = $1; }
  1674 declaration_statement
  1675     : declaration { $$ = $1; }
  1678 statement
  1679     : compound_statement  { $$ = $1; }
  1680     | simple_statement    { $$ = $1; }
  1683 // Grammar Note:  No labeled statements; 'goto' is not supported.
  1685 simple_statement
  1686     : declaration_statement { $$ = $1; }
  1687     | expression_statement  { $$ = $1; }
  1688     | selection_statement   { $$ = $1; }
  1689     | iteration_statement   { $$ = $1; }
  1690     | jump_statement        { $$ = $1; }
  1693 compound_statement
  1694     : LEFT_BRACE RIGHT_BRACE { $$ = 0; }
  1695     | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE {
  1696         if ($3 != 0) {
  1697             $3->setOp(EOpSequence);
  1698             $3->setLine(@$);
  1700         $$ = $3;
  1704 statement_no_new_scope
  1705     : compound_statement_no_new_scope { $$ = $1; }
  1706     | simple_statement                { $$ = $1; }
  1709 statement_with_scope
  1710     : { context->symbolTable.push(); } compound_statement_no_new_scope { context->symbolTable.pop(); $$ = $2; }
  1711     | { context->symbolTable.push(); } simple_statement                { context->symbolTable.pop(); $$ = $2; }
  1714 compound_statement_no_new_scope
  1715     // Statement that doesn't create a new scope, for selection_statement, iteration_statement
  1716     : LEFT_BRACE RIGHT_BRACE {
  1717         $$ = 0;
  1719     | LEFT_BRACE statement_list RIGHT_BRACE {
  1720         if ($2) {
  1721             $2->setOp(EOpSequence);
  1722             $2->setLine(@$);
  1724         $$ = $2;
  1728 statement_list
  1729     : statement {
  1730         $$ = context->intermediate.makeAggregate($1, @$);
  1732     | statement_list statement {
  1733         $$ = context->intermediate.growAggregate($1, $2, @$);
  1737 expression_statement
  1738     : SEMICOLON  { $$ = 0; }
  1739     | expression SEMICOLON  { $$ = static_cast<TIntermNode*>($1); }
  1742 selection_statement
  1743     : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
  1744         if (context->boolErrorCheck(@1, $3))
  1745             context->recover();
  1746         $$ = context->intermediate.addSelection($3, $5, @1);
  1750 selection_rest_statement
  1751     : statement_with_scope ELSE statement_with_scope {
  1752         $$.node1 = $1;
  1753         $$.node2 = $3;
  1755     | statement_with_scope {
  1756         $$.node1 = $1;
  1757         $$.node2 = 0;
  1761 // Grammar Note:  No 'switch'.  Switch statements not supported.
  1763 condition
  1764     // In 1996 c++ draft, conditions can include single declarations
  1765     : expression {
  1766         $$ = $1;
  1767         if (context->boolErrorCheck($1->getLine(), $1))
  1768             context->recover();
  1770     | fully_specified_type identifier EQUAL initializer {
  1771         TIntermNode* intermNode;
  1772         if (context->structQualifierErrorCheck(@2, $1))
  1773             context->recover();
  1774         if (context->boolErrorCheck(@2, $1))
  1775             context->recover();
  1777         if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode))
  1778             $$ = $4;
  1779         else {
  1780             context->recover();
  1781             $$ = 0;
  1786 iteration_statement
  1787     : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope {
  1788         context->symbolTable.pop();
  1789         $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, @1);
  1790         --context->loopNestingLevel;
  1792     | DO { ++context->loopNestingLevel; } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
  1793         if (context->boolErrorCheck(@8, $6))
  1794             context->recover();
  1796         $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, @4);
  1797         --context->loopNestingLevel;
  1799     | FOR LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
  1800         context->symbolTable.pop();
  1801         $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), $7, @1);
  1802         --context->loopNestingLevel;
  1806 for_init_statement
  1807     : expression_statement {
  1808         $$ = $1;
  1810     | declaration_statement {
  1811         $$ = $1;
  1815 conditionopt
  1816     : condition {
  1817         $$ = $1;
  1819     | /* May be null */ {
  1820         $$ = 0;
  1824 for_rest_statement
  1825     : conditionopt SEMICOLON {
  1826         $$.node1 = $1;
  1827         $$.node2 = 0;
  1829     | conditionopt SEMICOLON expression  {
  1830         $$.node1 = $1;
  1831         $$.node2 = $3;
  1835 jump_statement
  1836     : CONTINUE SEMICOLON {
  1837         if (context->loopNestingLevel <= 0) {
  1838             context->error(@1, "continue statement only allowed in loops", "");
  1839             context->recover();
  1841         $$ = context->intermediate.addBranch(EOpContinue, @1);
  1843     | BREAK SEMICOLON {
  1844         if (context->loopNestingLevel <= 0) {
  1845             context->error(@1, "break statement only allowed in loops", "");
  1846             context->recover();
  1848         $$ = context->intermediate.addBranch(EOpBreak, @1);
  1850     | RETURN SEMICOLON {
  1851         $$ = context->intermediate.addBranch(EOpReturn, @1);
  1852         if (context->currentFunctionType->getBasicType() != EbtVoid) {
  1853             context->error(@1, "non-void function must return a value", "return");
  1854             context->recover();
  1857     | RETURN expression SEMICOLON {
  1858         $$ = context->intermediate.addBranch(EOpReturn, $2, @1);
  1859         context->functionReturnsValue = true;
  1860         if (context->currentFunctionType->getBasicType() == EbtVoid) {
  1861             context->error(@1, "void function cannot return a value", "return");
  1862             context->recover();
  1863         } else if (*(context->currentFunctionType) != $2->getType()) {
  1864             context->error(@1, "function return is not matching type:", "return");
  1865             context->recover();
  1868     | DISCARD SEMICOLON {
  1869         FRAG_ONLY("discard", @1);
  1870         $$ = context->intermediate.addBranch(EOpKill, @1);
  1874 // Grammar Note:  No 'goto'.  Gotos are not supported.
  1876 translation_unit
  1877     : external_declaration {
  1878         $$ = $1;
  1879         context->treeRoot = $$;
  1881     | translation_unit external_declaration {
  1882         $$ = context->intermediate.growAggregate($1, $2, @$);
  1883         context->treeRoot = $$;
  1887 external_declaration
  1888     : function_definition {
  1889         $$ = $1;
  1891     | declaration {
  1892         $$ = $1;
  1896 function_definition
  1897     : function_prototype {
  1898         TFunction* function = $1.function;
  1900         const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName());
  1902         if (builtIn)
  1904             context->error(@1, "built-in functions cannot be redefined", function->getName().c_str());
  1905             context->recover();
  1908         TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find(function->getMangledName()));
  1909         //
  1910         // Note:  'prevDec' could be 'function' if this is the first time we've seen function
  1911         // as it would have just been put in the symbol table.  Otherwise, we're looking up
  1912         // an earlier occurance.
  1913         //
  1914         if (prevDec->isDefined()) {
  1915             //
  1916             // Then this function already has a body.
  1917             //
  1918             context->error(@1, "function already has a body", function->getName().c_str());
  1919             context->recover();
  1921         prevDec->setDefined();
  1923         //
  1924         // Raise error message if main function takes any parameters or return anything other than void
  1925         //
  1926         if (function->getName() == "main") {
  1927             if (function->getParamCount() > 0) {
  1928                 context->error(@1, "function cannot take any parameter(s)", function->getName().c_str());
  1929                 context->recover();
  1931             if (function->getReturnType().getBasicType() != EbtVoid) {
  1932                 context->error(@1, "", function->getReturnType().getBasicString(), "main function cannot return a value");
  1933                 context->recover();
  1937         //
  1938         // Remember the return type for later checking for RETURN statements.
  1939         //
  1940         context->currentFunctionType = &(prevDec->getReturnType());
  1941         context->functionReturnsValue = false;
  1943         //
  1944         // Insert parameters into the symbol table.
  1945         // If the parameter has no name, it's not an error, just don't insert it
  1946         // (could be used for unused args).
  1947         //
  1948         // Also, accumulate the list of parameters into the HIL, so lower level code
  1949         // knows where to find parameters.
  1950         //
  1951         TIntermAggregate* paramNodes = new TIntermAggregate;
  1952         for (size_t i = 0; i < function->getParamCount(); i++) {
  1953             const TParameter& param = function->getParam(i);
  1954             if (param.name != 0) {
  1955                 TVariable *variable = new TVariable(param.name, *param.type);
  1956                 //
  1957                 // Insert the parameters with name in the symbol table.
  1958                 //
  1959                 if (! context->symbolTable.insert(*variable)) {
  1960                     context->error(@1, "redefinition", variable->getName().c_str());
  1961                     context->recover();
  1962                     delete variable;
  1965                 //
  1966                 // Add the parameter to the HIL
  1967                 //
  1968                 paramNodes = context->intermediate.growAggregate(
  1969                                                paramNodes,
  1970                                                context->intermediate.addSymbol(variable->getUniqueId(),
  1971                                                                                variable->getName(),
  1972                                                                                variable->getType(),
  1973                                                                                @1),
  1974                                                @1);
  1975             } else {
  1976                 paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, @1), @1);
  1979         context->intermediate.setAggregateOperator(paramNodes, EOpParameters, @1);
  1980         $1.intermAggregate = paramNodes;
  1981         context->loopNestingLevel = 0;
  1983     compound_statement_no_new_scope {
  1984         //?? Check that all paths return a value if return type != void ?
  1985         //   May be best done as post process phase on intermediate code
  1986         if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) {
  1987             context->error(@1, "function does not return a value:", "", $1.function->getName().c_str());
  1988             context->recover();
  1991         $$ = context->intermediate.growAggregate($1.intermAggregate, $3, @$);
  1992         context->intermediate.setAggregateOperator($$, EOpFunction, @1);
  1993         $$->getAsAggregate()->setName($1.function->getMangledName().c_str());
  1994         $$->getAsAggregate()->setType($1.function->getReturnType());
  1996         // store the pragma information for debug and optimize and other vendor specific
  1997         // information. This information can be queried from the parse tree
  1998         $$->getAsAggregate()->setOptimize(context->pragma().optimize);
  1999         $$->getAsAggregate()->setDebug(context->pragma().debug);
  2001         context->symbolTable.pop();
  2005 %%
  2007 void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason) {
  2008     context->error(*yylloc, reason, "");
  2009     context->recover();
  2012 int glslang_parse(TParseContext* context) {
  2013     return yyparse(context);

mercurial