gfx/angle/src/compiler/glslang.y

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/angle/src/compiler/glslang.y	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2014 @@
     1.4 +/*
     1.5 +//
     1.6 +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
     1.7 +// Use of this source code is governed by a BSD-style license that can be
     1.8 +// found in the LICENSE file.
     1.9 +//
    1.10 +
    1.11 +This file contains the Yacc grammar for GLSL ES.
    1.12 +Based on ANSI C Yacc grammar:
    1.13 +http://www.lysator.liu.se/c/ANSI-C-grammar-y.html
    1.14 +
    1.15 +IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
    1.16 +WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
    1.17 +*/
    1.18 +
    1.19 +%{
    1.20 +//
    1.21 +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
    1.22 +// Use of this source code is governed by a BSD-style license that can be
    1.23 +// found in the LICENSE file.
    1.24 +//
    1.25 +
    1.26 +// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
    1.27 +
    1.28 +// Ignore errors in auto-generated code.
    1.29 +#if defined(__GNUC__)
    1.30 +#pragma GCC diagnostic ignored "-Wunused-function"
    1.31 +#pragma GCC diagnostic ignored "-Wunused-variable"
    1.32 +#pragma GCC diagnostic ignored "-Wswitch-enum"
    1.33 +#elif defined(_MSC_VER)
    1.34 +#pragma warning(disable: 4065)
    1.35 +#pragma warning(disable: 4189)
    1.36 +#pragma warning(disable: 4505)
    1.37 +#pragma warning(disable: 4701)
    1.38 +#endif
    1.39 +
    1.40 +#include "compiler/SymbolTable.h"
    1.41 +#include "compiler/ParseHelper.h"
    1.42 +#include "GLSLANG/ShaderLang.h"
    1.43 +
    1.44 +#define YYENABLE_NLS 0
    1.45 +
    1.46 +#define YYLEX_PARAM context->scanner
    1.47 +%}
    1.48 +
    1.49 +%expect 1 /* One shift reduce conflict because of if | else */
    1.50 +%pure-parser
    1.51 +%parse-param {TParseContext* context}
    1.52 +%locations
    1.53 +
    1.54 +%code requires {
    1.55 +#define YYLTYPE TSourceLoc
    1.56 +#define YYLTYPE_IS_DECLARED 1
    1.57 +}
    1.58 +
    1.59 +%union {
    1.60 +    struct {
    1.61 +        union {
    1.62 +            TString *string;
    1.63 +            float f;
    1.64 +            int i;
    1.65 +            bool b;
    1.66 +        };
    1.67 +        TSymbol* symbol;
    1.68 +    } lex;
    1.69 +    struct {
    1.70 +        TOperator op;
    1.71 +        union {
    1.72 +            TIntermNode* intermNode;
    1.73 +            TIntermNodePair nodePair;
    1.74 +            TIntermTyped* intermTypedNode;
    1.75 +            TIntermAggregate* intermAggregate;
    1.76 +        };
    1.77 +        union {
    1.78 +            TPublicType type;
    1.79 +            TPrecision precision;
    1.80 +            TQualifier qualifier;
    1.81 +            TFunction* function;
    1.82 +            TParameter param;
    1.83 +            TField* field;
    1.84 +            TFieldList* fieldList;
    1.85 +        };
    1.86 +    } interm;
    1.87 +}
    1.88 +
    1.89 +%{
    1.90 +extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner);
    1.91 +static void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason);
    1.92 +
    1.93 +#define YYLLOC_DEFAULT(Current, Rhs, N)                      \
    1.94 +  do {                                                       \
    1.95 +      if (YYID(N)) {                                         \
    1.96 +        (Current).first_file = YYRHSLOC(Rhs, 1).first_file;  \
    1.97 +        (Current).first_line = YYRHSLOC(Rhs, 1).first_line;  \
    1.98 +        (Current).last_file = YYRHSLOC(Rhs, N).last_file;    \
    1.99 +        (Current).last_line = YYRHSLOC(Rhs, N).last_line;    \
   1.100 +      }                                                      \
   1.101 +      else {                                                 \
   1.102 +        (Current).first_file = YYRHSLOC(Rhs, 0).last_file;   \
   1.103 +        (Current).first_line = YYRHSLOC(Rhs, 0).last_line;   \
   1.104 +        (Current).last_file = YYRHSLOC(Rhs, 0).last_file;    \
   1.105 +        (Current).last_line = YYRHSLOC(Rhs, 0).last_line;    \
   1.106 +      }                                                      \
   1.107 +  } while (0)
   1.108 +
   1.109 +#define VERTEX_ONLY(S, L) {  \
   1.110 +    if (context->shaderType != SH_VERTEX_SHADER) {  \
   1.111 +        context->error(L, " supported in vertex shaders only ", S);  \
   1.112 +        context->recover();  \
   1.113 +    }  \
   1.114 +}
   1.115 +
   1.116 +#define FRAG_ONLY(S, L) {  \
   1.117 +    if (context->shaderType != SH_FRAGMENT_SHADER) {  \
   1.118 +        context->error(L, " supported in fragment shaders only ", S);  \
   1.119 +        context->recover();  \
   1.120 +    }  \
   1.121 +}
   1.122 +%}
   1.123 +
   1.124 +%token <lex> INVARIANT HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION
   1.125 +%token <lex> ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE
   1.126 +%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN
   1.127 +%token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4
   1.128 +%token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM VARYING
   1.129 +%token <lex> STRUCT VOID_TYPE WHILE
   1.130 +%token <lex> SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT
   1.131 +
   1.132 +%token <lex> IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT BOOLCONSTANT
   1.133 +%token <lex> LEFT_OP RIGHT_OP
   1.134 +%token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
   1.135 +%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
   1.136 +%token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
   1.137 +%token <lex> SUB_ASSIGN
   1.138 +
   1.139 +%token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
   1.140 +%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
   1.141 +%token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION
   1.142 +
   1.143 +%type <lex> identifier
   1.144 +%type <interm> assignment_operator unary_operator
   1.145 +%type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression
   1.146 +%type <interm.intermTypedNode> expression integer_expression assignment_expression
   1.147 +%type <interm.intermTypedNode> unary_expression multiplicative_expression additive_expression
   1.148 +%type <interm.intermTypedNode> relational_expression equality_expression
   1.149 +%type <interm.intermTypedNode> conditional_expression constant_expression
   1.150 +%type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression
   1.151 +%type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression
   1.152 +%type <interm.intermTypedNode> function_call initializer condition conditionopt
   1.153 +
   1.154 +%type <interm.intermNode> translation_unit function_definition
   1.155 +%type <interm.intermNode> statement simple_statement
   1.156 +%type <interm.intermAggregate>  statement_list compound_statement
   1.157 +%type <interm.intermNode> declaration_statement selection_statement expression_statement
   1.158 +%type <interm.intermNode> declaration external_declaration
   1.159 +%type <interm.intermNode> for_init_statement compound_statement_no_new_scope
   1.160 +%type <interm.nodePair> selection_rest_statement for_rest_statement
   1.161 +%type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope statement_with_scope
   1.162 +%type <interm> single_declaration init_declarator_list
   1.163 +
   1.164 +%type <interm> parameter_declaration parameter_declarator parameter_type_specifier
   1.165 +%type <interm.qualifier> parameter_qualifier
   1.166 +
   1.167 +%type <interm.precision> precision_qualifier
   1.168 +%type <interm.type> type_qualifier fully_specified_type type_specifier
   1.169 +%type <interm.type> type_specifier_no_prec type_specifier_nonarray
   1.170 +%type <interm.type> struct_specifier
   1.171 +%type <interm.field> struct_declarator
   1.172 +%type <interm.fieldList> struct_declarator_list struct_declaration struct_declaration_list
   1.173 +%type <interm.function> function_header function_declarator function_identifier
   1.174 +%type <interm.function> function_header_with_parameters function_call_header
   1.175 +%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
   1.176 +%type <interm> function_call_or_method
   1.177 +
   1.178 +%start translation_unit
   1.179 +%%
   1.180 +
   1.181 +identifier
   1.182 +    : IDENTIFIER
   1.183 +    | TYPE_NAME
   1.184 +
   1.185 +variable_identifier
   1.186 +    : IDENTIFIER {
   1.187 +        // The symbol table search was done in the lexical phase
   1.188 +        const TSymbol* symbol = $1.symbol;
   1.189 +        const TVariable* variable;
   1.190 +        if (symbol == 0) {
   1.191 +            context->error(@1, "undeclared identifier", $1.string->c_str());
   1.192 +            context->recover();
   1.193 +            TType type(EbtFloat, EbpUndefined);
   1.194 +            TVariable* fakeVariable = new TVariable($1.string, type);
   1.195 +            context->symbolTable.insert(*fakeVariable);
   1.196 +            variable = fakeVariable;
   1.197 +        } else {
   1.198 +            // This identifier can only be a variable type symbol
   1.199 +            if (! symbol->isVariable()) {
   1.200 +                context->error(@1, "variable expected", $1.string->c_str());
   1.201 +                context->recover();
   1.202 +            }
   1.203 +            
   1.204 +            variable = static_cast<const TVariable*>(symbol);
   1.205 +
   1.206 +            if (context->symbolTable.findBuiltIn(variable->getName()) &&
   1.207 +                !variable->getExtension().empty() &&
   1.208 +                context->extensionErrorCheck(@1, variable->getExtension())) {
   1.209 +                context->recover();
   1.210 +            }
   1.211 +        }
   1.212 +
   1.213 +        // don't delete $1.string, it's used by error recovery, and the pool
   1.214 +        // pop will reclaim the memory
   1.215 +
   1.216 +        if (variable->getType().getQualifier() == EvqConst ) {
   1.217 +            ConstantUnion* constArray = variable->getConstPointer();
   1.218 +            TType t(variable->getType());
   1.219 +            $$ = context->intermediate.addConstantUnion(constArray, t, @1);
   1.220 +        } else
   1.221 +            $$ = context->intermediate.addSymbol(variable->getUniqueId(),
   1.222 +                                                 variable->getName(),
   1.223 +                                                 variable->getType(),
   1.224 +                                                 @1);
   1.225 +    }
   1.226 +    ;
   1.227 +
   1.228 +primary_expression
   1.229 +    : variable_identifier {
   1.230 +        $$ = $1;
   1.231 +    }
   1.232 +    | INTCONSTANT {
   1.233 +        //
   1.234 +        // INT_TYPE is only 16-bit plus sign bit for vertex/fragment shaders,
   1.235 +        // check for overflow for constants
   1.236 +        //
   1.237 +        if (abs($1.i) >= (1 << 16)) {
   1.238 +            context->error(@1, " integer constant overflow", "");
   1.239 +            context->recover();
   1.240 +        }
   1.241 +        ConstantUnion *unionArray = new ConstantUnion[1];
   1.242 +        unionArray->setIConst($1.i);
   1.243 +        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @1);
   1.244 +    }
   1.245 +    | FLOATCONSTANT {
   1.246 +        ConstantUnion *unionArray = new ConstantUnion[1];
   1.247 +        unionArray->setFConst($1.f);
   1.248 +        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1);
   1.249 +    }
   1.250 +    | BOOLCONSTANT {
   1.251 +        ConstantUnion *unionArray = new ConstantUnion[1];
   1.252 +        unionArray->setBConst($1.b);
   1.253 +        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @1);
   1.254 +    }
   1.255 +    | LEFT_PAREN expression RIGHT_PAREN {
   1.256 +        $$ = $2;
   1.257 +    }
   1.258 +    ;
   1.259 +
   1.260 +postfix_expression
   1.261 +    : primary_expression {
   1.262 +        $$ = $1;
   1.263 +    }
   1.264 +    | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET {
   1.265 +        $$ = context->addIndexExpression($1, @2, $3);
   1.266 +    }
   1.267 +    | function_call {
   1.268 +        $$ = $1;
   1.269 +    }
   1.270 +    | postfix_expression DOT identifier {
   1.271 +        if ($1->isArray()) {
   1.272 +            context->error(@3, "cannot apply dot operator to an array", ".");
   1.273 +            context->recover();
   1.274 +        }
   1.275 +
   1.276 +        if ($1->isVector()) {
   1.277 +            TVectorFields fields;
   1.278 +            if (! context->parseVectorFields(*$3.string, $1->getNominalSize(), fields, @3)) {
   1.279 +                fields.num = 1;
   1.280 +                fields.offsets[0] = 0;
   1.281 +                context->recover();
   1.282 +            }
   1.283 +
   1.284 +            if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields
   1.285 +                $$ = context->addConstVectorNode(fields, $1, @3);
   1.286 +                if ($$ == 0) {
   1.287 +                    context->recover();
   1.288 +                    $$ = $1;
   1.289 +                }
   1.290 +                else
   1.291 +                    $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, (int) (*$3.string).size()));
   1.292 +            } else {
   1.293 +                TString vectorString = *$3.string;
   1.294 +                TIntermTyped* index = context->intermediate.addSwizzle(fields, @3);
   1.295 +                $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, @2);
   1.296 +                $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, (int) vectorString.size()));
   1.297 +            }
   1.298 +        } else if ($1->isMatrix()) {
   1.299 +            TMatrixFields fields;
   1.300 +            if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, @3)) {
   1.301 +                fields.wholeRow = false;
   1.302 +                fields.wholeCol = false;
   1.303 +                fields.row = 0;
   1.304 +                fields.col = 0;
   1.305 +                context->recover();
   1.306 +            }
   1.307 +
   1.308 +            if (fields.wholeRow || fields.wholeCol) {
   1.309 +                context->error(@2, " non-scalar fields not implemented yet", ".");
   1.310 +                context->recover();
   1.311 +                ConstantUnion *unionArray = new ConstantUnion[1];
   1.312 +                unionArray->setIConst(0);
   1.313 +                TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3);
   1.314 +                $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2);
   1.315 +                $$->setType(TType($1->getBasicType(), $1->getPrecision(),EvqTemporary, $1->getNominalSize()));
   1.316 +            } else {
   1.317 +                ConstantUnion *unionArray = new ConstantUnion[1];
   1.318 +                unionArray->setIConst(fields.col * $1->getNominalSize() + fields.row);
   1.319 +                TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3);
   1.320 +                $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2);
   1.321 +                $$->setType(TType($1->getBasicType(), $1->getPrecision()));
   1.322 +            }
   1.323 +        } else if ($1->getBasicType() == EbtStruct) {
   1.324 +            bool fieldFound = false;
   1.325 +            const TFieldList& fields = $1->getType().getStruct()->fields();
   1.326 +            unsigned int i;
   1.327 +            for (i = 0; i < fields.size(); ++i) {
   1.328 +                if (fields[i]->name() == *$3.string) {
   1.329 +                    fieldFound = true;
   1.330 +                    break;
   1.331 +                }
   1.332 +            }
   1.333 +            if (fieldFound) {
   1.334 +                if ($1->getType().getQualifier() == EvqConst) {
   1.335 +                    $$ = context->addConstStruct(*$3.string, $1, @2);
   1.336 +                    if ($$ == 0) {
   1.337 +                        context->recover();
   1.338 +                        $$ = $1;
   1.339 +                    }
   1.340 +                    else {
   1.341 +                        $$->setType(*fields[i]->type());
   1.342 +                        // change the qualifier of the return type, not of the structure field
   1.343 +                        // as the structure definition is shared between various structures.
   1.344 +                        $$->getTypePointer()->setQualifier(EvqConst);
   1.345 +                    }
   1.346 +                } else {
   1.347 +                    ConstantUnion *unionArray = new ConstantUnion[1];
   1.348 +                    unionArray->setIConst(i);
   1.349 +                    TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *fields[i]->type(), @3);
   1.350 +                    $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, @2);
   1.351 +                    $$->setType(*fields[i]->type());
   1.352 +                }
   1.353 +            } else {
   1.354 +                context->error(@2, " no such field in structure", $3.string->c_str());
   1.355 +                context->recover();
   1.356 +                $$ = $1;
   1.357 +            }
   1.358 +        } else {
   1.359 +            context->error(@2, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str());
   1.360 +            context->recover();
   1.361 +            $$ = $1;
   1.362 +        }
   1.363 +        // don't delete $3.string, it's from the pool
   1.364 +    }
   1.365 +    | postfix_expression INC_OP {
   1.366 +        if (context->lValueErrorCheck(@2, "++", $1))
   1.367 +            context->recover();
   1.368 +        $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, @2, context->symbolTable);
   1.369 +        if ($$ == 0) {
   1.370 +            context->unaryOpError(@2, "++", $1->getCompleteString());
   1.371 +            context->recover();
   1.372 +            $$ = $1;
   1.373 +        }
   1.374 +    }
   1.375 +    | postfix_expression DEC_OP {
   1.376 +        if (context->lValueErrorCheck(@2, "--", $1))
   1.377 +            context->recover();
   1.378 +        $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, @2, context->symbolTable);
   1.379 +        if ($$ == 0) {
   1.380 +            context->unaryOpError(@2, "--", $1->getCompleteString());
   1.381 +            context->recover();
   1.382 +            $$ = $1;
   1.383 +        }
   1.384 +    }
   1.385 +    ;
   1.386 +
   1.387 +integer_expression
   1.388 +    : expression {
   1.389 +        if (context->integerErrorCheck($1, "[]"))
   1.390 +            context->recover();
   1.391 +        $$ = $1;
   1.392 +    }
   1.393 +    ;
   1.394 +
   1.395 +function_call
   1.396 +    : function_call_or_method {
   1.397 +        TFunction* fnCall = $1.function;
   1.398 +        TOperator op = fnCall->getBuiltInOp();
   1.399 +
   1.400 +        if (op != EOpNull)
   1.401 +        {
   1.402 +            //
   1.403 +            // Then this should be a constructor.
   1.404 +            // Don't go through the symbol table for constructors.
   1.405 +            // Their parameters will be verified algorithmically.
   1.406 +            //
   1.407 +            TType type(EbtVoid, EbpUndefined);  // use this to get the type back
   1.408 +            if (context->constructorErrorCheck(@1, $1.intermNode, *fnCall, op, &type)) {
   1.409 +                $$ = 0;
   1.410 +            } else {
   1.411 +                //
   1.412 +                // It's a constructor, of type 'type'.
   1.413 +                //
   1.414 +                $$ = context->addConstructor($1.intermNode, &type, op, fnCall, @1);
   1.415 +            }
   1.416 +
   1.417 +            if ($$ == 0) {
   1.418 +                context->recover();
   1.419 +                $$ = context->intermediate.setAggregateOperator(0, op, @1);
   1.420 +            }
   1.421 +            $$->setType(type);
   1.422 +        } else {
   1.423 +            //
   1.424 +            // Not a constructor.  Find it in the symbol table.
   1.425 +            //
   1.426 +            const TFunction* fnCandidate;
   1.427 +            bool builtIn;
   1.428 +            fnCandidate = context->findFunction(@1, fnCall, &builtIn);
   1.429 +            if (fnCandidate) {
   1.430 +                //
   1.431 +                // A declared function.
   1.432 +                //
   1.433 +                if (builtIn && !fnCandidate->getExtension().empty() &&
   1.434 +                    context->extensionErrorCheck(@1, fnCandidate->getExtension())) {
   1.435 +                    context->recover();
   1.436 +                }
   1.437 +                op = fnCandidate->getBuiltInOp();
   1.438 +                if (builtIn && op != EOpNull) {
   1.439 +                    //
   1.440 +                    // A function call mapped to a built-in operation.
   1.441 +                    //
   1.442 +                    if (fnCandidate->getParamCount() == 1) {
   1.443 +                        //
   1.444 +                        // Treat it like a built-in unary operator.
   1.445 +                        //
   1.446 +                        $$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1, context->symbolTable);
   1.447 +                        if ($$ == 0)  {
   1.448 +                            std::stringstream extraInfoStream;
   1.449 +                            extraInfoStream << "built in unary operator function.  Type: " << static_cast<TIntermTyped*>($1.intermNode)->getCompleteString();
   1.450 +                            std::string extraInfo = extraInfoStream.str();
   1.451 +                            context->error($1.intermNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
   1.452 +                            YYERROR;
   1.453 +                        }
   1.454 +                    } else {
   1.455 +                        $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1);
   1.456 +                    }
   1.457 +                } else {
   1.458 +                    // This is a real function call
   1.459 +
   1.460 +                    $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1);
   1.461 +                    $$->setType(fnCandidate->getReturnType());
   1.462 +
   1.463 +                    // this is how we know whether the given function is a builtIn function or a user defined function
   1.464 +                    // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
   1.465 +                    // if builtIn == true, it's definitely a builtIn function with EOpNull
   1.466 +                    if (!builtIn)
   1.467 +                        $$->getAsAggregate()->setUserDefined();
   1.468 +                    $$->getAsAggregate()->setName(fnCandidate->getMangledName());
   1.469 +
   1.470 +                    TQualifier qual;
   1.471 +                    for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) {
   1.472 +                        qual = fnCandidate->getParam(i).type->getQualifier();
   1.473 +                        if (qual == EvqOut || qual == EvqInOut) {
   1.474 +                            if (context->lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) {
   1.475 +                                context->error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
   1.476 +                                context->recover();
   1.477 +                            }
   1.478 +                        }
   1.479 +                    }
   1.480 +                }
   1.481 +                $$->setType(fnCandidate->getReturnType());
   1.482 +            } else {
   1.483 +                // error message was put out by PaFindFunction()
   1.484 +                // Put on a dummy node for error recovery
   1.485 +                ConstantUnion *unionArray = new ConstantUnion[1];
   1.486 +                unionArray->setFConst(0.0f);
   1.487 +                $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1);
   1.488 +                context->recover();
   1.489 +            }
   1.490 +        }
   1.491 +        delete fnCall;
   1.492 +    }
   1.493 +    ;
   1.494 +
   1.495 +function_call_or_method
   1.496 +    : function_call_generic {
   1.497 +        $$ = $1;
   1.498 +    }
   1.499 +    | postfix_expression DOT function_call_generic {
   1.500 +        context->error(@3, "methods are not supported", "");
   1.501 +        context->recover();
   1.502 +        $$ = $3;
   1.503 +    }
   1.504 +    ;
   1.505 +
   1.506 +function_call_generic
   1.507 +    : function_call_header_with_parameters RIGHT_PAREN {
   1.508 +        $$ = $1;
   1.509 +    }
   1.510 +    | function_call_header_no_parameters RIGHT_PAREN {
   1.511 +        $$ = $1;
   1.512 +    }
   1.513 +    ;
   1.514 +
   1.515 +function_call_header_no_parameters
   1.516 +    : function_call_header VOID_TYPE {
   1.517 +        $$.function = $1;
   1.518 +        $$.intermNode = 0;
   1.519 +    }
   1.520 +    | function_call_header {
   1.521 +        $$.function = $1;
   1.522 +        $$.intermNode = 0;
   1.523 +    }
   1.524 +    ;
   1.525 +
   1.526 +function_call_header_with_parameters
   1.527 +    : function_call_header assignment_expression {
   1.528 +        TParameter param = { 0, new TType($2->getType()) };
   1.529 +        $1->addParameter(param);
   1.530 +        $$.function = $1;
   1.531 +        $$.intermNode = $2;
   1.532 +    }
   1.533 +    | function_call_header_with_parameters COMMA assignment_expression {
   1.534 +        TParameter param = { 0, new TType($3->getType()) };
   1.535 +        $1.function->addParameter(param);
   1.536 +        $$.function = $1.function;
   1.537 +        $$.intermNode = context->intermediate.growAggregate($1.intermNode, $3, @2);
   1.538 +    }
   1.539 +    ;
   1.540 +
   1.541 +function_call_header
   1.542 +    : function_identifier LEFT_PAREN {
   1.543 +        $$ = $1;
   1.544 +    }
   1.545 +    ;
   1.546 +
   1.547 +// Grammar Note:  Constructors look like functions, but are recognized as types.
   1.548 +
   1.549 +function_identifier
   1.550 +    : type_specifier_nonarray {
   1.551 +        //
   1.552 +        // Constructor
   1.553 +        //
   1.554 +        TOperator op = EOpNull;
   1.555 +        if ($1.userDef) {
   1.556 +            op = EOpConstructStruct;
   1.557 +        } else {
   1.558 +            switch ($1.type) {
   1.559 +            case EbtFloat:
   1.560 +                if ($1.matrix) {
   1.561 +                    switch($1.size) {
   1.562 +                    case 2: op = EOpConstructMat2;  break;
   1.563 +                    case 3: op = EOpConstructMat3;  break;
   1.564 +                    case 4: op = EOpConstructMat4;  break;
   1.565 +                    }
   1.566 +                } else {
   1.567 +                    switch($1.size) {
   1.568 +                    case 1: op = EOpConstructFloat; break;
   1.569 +                    case 2: op = EOpConstructVec2;  break;
   1.570 +                    case 3: op = EOpConstructVec3;  break;
   1.571 +                    case 4: op = EOpConstructVec4;  break;
   1.572 +                    }
   1.573 +                }
   1.574 +                break;
   1.575 +            case EbtInt:
   1.576 +                switch($1.size) {
   1.577 +                case 1: op = EOpConstructInt;   break;
   1.578 +                case 2: op = EOpConstructIVec2; break;
   1.579 +                case 3: op = EOpConstructIVec3; break;
   1.580 +                case 4: op = EOpConstructIVec4; break;
   1.581 +                }
   1.582 +                break;
   1.583 +            case EbtBool:
   1.584 +                switch($1.size) {
   1.585 +                case 1: op = EOpConstructBool;  break;
   1.586 +                case 2: op = EOpConstructBVec2; break;
   1.587 +                case 3: op = EOpConstructBVec3; break;
   1.588 +                case 4: op = EOpConstructBVec4; break;
   1.589 +                }
   1.590 +                break;
   1.591 +            default: break;
   1.592 +            }
   1.593 +            if (op == EOpNull) {
   1.594 +                context->error(@1, "cannot construct this type", getBasicString($1.type));
   1.595 +                context->recover();
   1.596 +                $1.type = EbtFloat;
   1.597 +                op = EOpConstructFloat;
   1.598 +            }
   1.599 +        }
   1.600 +        TString tempString;
   1.601 +        TType type($1);
   1.602 +        TFunction *function = new TFunction(&tempString, type, op);
   1.603 +        $$ = function;
   1.604 +    }
   1.605 +    | IDENTIFIER {
   1.606 +        if (context->reservedErrorCheck(@1, *$1.string))
   1.607 +            context->recover();
   1.608 +        TType type(EbtVoid, EbpUndefined);
   1.609 +        TFunction *function = new TFunction($1.string, type);
   1.610 +        $$ = function;
   1.611 +    }
   1.612 +    ;
   1.613 +
   1.614 +unary_expression
   1.615 +    : postfix_expression {
   1.616 +        $$ = $1;
   1.617 +    }
   1.618 +    | INC_OP unary_expression {
   1.619 +        if (context->lValueErrorCheck(@1, "++", $2))
   1.620 +            context->recover();
   1.621 +        $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, @1, context->symbolTable);
   1.622 +        if ($$ == 0) {
   1.623 +            context->unaryOpError(@1, "++", $2->getCompleteString());
   1.624 +            context->recover();
   1.625 +            $$ = $2;
   1.626 +        }
   1.627 +    }
   1.628 +    | DEC_OP unary_expression {
   1.629 +        if (context->lValueErrorCheck(@1, "--", $2))
   1.630 +            context->recover();
   1.631 +        $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, @1, context->symbolTable);
   1.632 +        if ($$ == 0) {
   1.633 +            context->unaryOpError(@1, "--", $2->getCompleteString());
   1.634 +            context->recover();
   1.635 +            $$ = $2;
   1.636 +        }
   1.637 +    }
   1.638 +    | unary_operator unary_expression {
   1.639 +        if ($1.op != EOpNull) {
   1.640 +            $$ = context->intermediate.addUnaryMath($1.op, $2, @1, context->symbolTable);
   1.641 +            if ($$ == 0) {
   1.642 +                const char* errorOp = "";
   1.643 +                switch($1.op) {
   1.644 +                case EOpNegative:   errorOp = "-"; break;
   1.645 +                case EOpLogicalNot: errorOp = "!"; break;
   1.646 +                default: break;
   1.647 +                }
   1.648 +                context->unaryOpError(@1, errorOp, $2->getCompleteString());
   1.649 +                context->recover();
   1.650 +                $$ = $2;
   1.651 +            }
   1.652 +        } else
   1.653 +            $$ = $2;
   1.654 +    }
   1.655 +    ;
   1.656 +// Grammar Note:  No traditional style type casts.
   1.657 +
   1.658 +unary_operator
   1.659 +    : PLUS  { $$.op = EOpNull; }
   1.660 +    | DASH  { $$.op = EOpNegative; }
   1.661 +    | BANG  { $$.op = EOpLogicalNot; }
   1.662 +    ;
   1.663 +// Grammar Note:  No '*' or '&' unary ops.  Pointers are not supported.
   1.664 +
   1.665 +multiplicative_expression
   1.666 +    : unary_expression { $$ = $1; }
   1.667 +    | multiplicative_expression STAR unary_expression {
   1.668 +        $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, @2, context->symbolTable);
   1.669 +        if ($$ == 0) {
   1.670 +            context->binaryOpError(@2, "*", $1->getCompleteString(), $3->getCompleteString());
   1.671 +            context->recover();
   1.672 +            $$ = $1;
   1.673 +        }
   1.674 +    }
   1.675 +    | multiplicative_expression SLASH unary_expression {
   1.676 +        $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, @2, context->symbolTable);
   1.677 +        if ($$ == 0) {
   1.678 +            context->binaryOpError(@2, "/", $1->getCompleteString(), $3->getCompleteString());
   1.679 +            context->recover();
   1.680 +            $$ = $1;
   1.681 +        }
   1.682 +    }
   1.683 +    ;
   1.684 +
   1.685 +additive_expression
   1.686 +    : multiplicative_expression { $$ = $1; }
   1.687 +    | additive_expression PLUS multiplicative_expression {
   1.688 +        $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, @2, context->symbolTable);
   1.689 +        if ($$ == 0) {
   1.690 +            context->binaryOpError(@2, "+", $1->getCompleteString(), $3->getCompleteString());
   1.691 +            context->recover();
   1.692 +            $$ = $1;
   1.693 +        }
   1.694 +    }
   1.695 +    | additive_expression DASH multiplicative_expression {
   1.696 +        $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, @2, context->symbolTable);
   1.697 +        if ($$ == 0) {
   1.698 +            context->binaryOpError(@2, "-", $1->getCompleteString(), $3->getCompleteString());
   1.699 +            context->recover();
   1.700 +            $$ = $1;
   1.701 +        }
   1.702 +    }
   1.703 +    ;
   1.704 +
   1.705 +shift_expression
   1.706 +    : additive_expression { $$ = $1; }
   1.707 +    ;
   1.708 +
   1.709 +relational_expression
   1.710 +    : shift_expression { $$ = $1; }
   1.711 +    | relational_expression LEFT_ANGLE shift_expression {
   1.712 +        $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, @2, context->symbolTable);
   1.713 +        if ($$ == 0) {
   1.714 +            context->binaryOpError(@2, "<", $1->getCompleteString(), $3->getCompleteString());
   1.715 +            context->recover();
   1.716 +            ConstantUnion *unionArray = new ConstantUnion[1];
   1.717 +            unionArray->setBConst(false);
   1.718 +            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
   1.719 +        }
   1.720 +    }
   1.721 +    | relational_expression RIGHT_ANGLE shift_expression  {
   1.722 +        $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, @2, context->symbolTable);
   1.723 +        if ($$ == 0) {
   1.724 +            context->binaryOpError(@2, ">", $1->getCompleteString(), $3->getCompleteString());
   1.725 +            context->recover();
   1.726 +            ConstantUnion *unionArray = new ConstantUnion[1];
   1.727 +            unionArray->setBConst(false);
   1.728 +            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
   1.729 +        }
   1.730 +    }
   1.731 +    | relational_expression LE_OP shift_expression  {
   1.732 +        $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, @2, context->symbolTable);
   1.733 +        if ($$ == 0) {
   1.734 +            context->binaryOpError(@2, "<=", $1->getCompleteString(), $3->getCompleteString());
   1.735 +            context->recover();
   1.736 +            ConstantUnion *unionArray = new ConstantUnion[1];
   1.737 +            unionArray->setBConst(false);
   1.738 +            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
   1.739 +        }
   1.740 +    }
   1.741 +    | relational_expression GE_OP shift_expression  {
   1.742 +        $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, @2, context->symbolTable);
   1.743 +        if ($$ == 0) {
   1.744 +            context->binaryOpError(@2, ">=", $1->getCompleteString(), $3->getCompleteString());
   1.745 +            context->recover();
   1.746 +            ConstantUnion *unionArray = new ConstantUnion[1];
   1.747 +            unionArray->setBConst(false);
   1.748 +            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
   1.749 +        }
   1.750 +    }
   1.751 +    ;
   1.752 +
   1.753 +equality_expression
   1.754 +    : relational_expression { $$ = $1; }
   1.755 +    | equality_expression EQ_OP relational_expression  {
   1.756 +        $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, @2, context->symbolTable);
   1.757 +        if ($$ == 0) {
   1.758 +            context->binaryOpError(@2, "==", $1->getCompleteString(), $3->getCompleteString());
   1.759 +            context->recover();
   1.760 +            ConstantUnion *unionArray = new ConstantUnion[1];
   1.761 +            unionArray->setBConst(false);
   1.762 +            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
   1.763 +        }
   1.764 +    }
   1.765 +    | equality_expression NE_OP relational_expression {
   1.766 +        $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, @2, context->symbolTable);
   1.767 +        if ($$ == 0) {
   1.768 +            context->binaryOpError(@2, "!=", $1->getCompleteString(), $3->getCompleteString());
   1.769 +            context->recover();
   1.770 +            ConstantUnion *unionArray = new ConstantUnion[1];
   1.771 +            unionArray->setBConst(false);
   1.772 +            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
   1.773 +        }
   1.774 +    }
   1.775 +    ;
   1.776 +
   1.777 +and_expression
   1.778 +    : equality_expression { $$ = $1; }
   1.779 +    ;
   1.780 +
   1.781 +exclusive_or_expression
   1.782 +    : and_expression { $$ = $1; }
   1.783 +    ;
   1.784 +
   1.785 +inclusive_or_expression
   1.786 +    : exclusive_or_expression { $$ = $1; }
   1.787 +    ;
   1.788 +
   1.789 +logical_and_expression
   1.790 +    : inclusive_or_expression { $$ = $1; }
   1.791 +    | logical_and_expression AND_OP inclusive_or_expression {
   1.792 +        $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, @2, context->symbolTable);
   1.793 +        if ($$ == 0) {
   1.794 +            context->binaryOpError(@2, "&&", $1->getCompleteString(), $3->getCompleteString());
   1.795 +            context->recover();
   1.796 +            ConstantUnion *unionArray = new ConstantUnion[1];
   1.797 +            unionArray->setBConst(false);
   1.798 +            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
   1.799 +        }
   1.800 +    }
   1.801 +    ;
   1.802 +
   1.803 +logical_xor_expression
   1.804 +    : logical_and_expression { $$ = $1; }
   1.805 +    | logical_xor_expression XOR_OP logical_and_expression  {
   1.806 +        $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, @2, context->symbolTable);
   1.807 +        if ($$ == 0) {
   1.808 +            context->binaryOpError(@2, "^^", $1->getCompleteString(), $3->getCompleteString());
   1.809 +            context->recover();
   1.810 +            ConstantUnion *unionArray = new ConstantUnion[1];
   1.811 +            unionArray->setBConst(false);
   1.812 +            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
   1.813 +        }
   1.814 +    }
   1.815 +    ;
   1.816 +
   1.817 +logical_or_expression
   1.818 +    : logical_xor_expression { $$ = $1; }
   1.819 +    | logical_or_expression OR_OP logical_xor_expression  {
   1.820 +        $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, @2, context->symbolTable);
   1.821 +        if ($$ == 0) {
   1.822 +            context->binaryOpError(@2, "||", $1->getCompleteString(), $3->getCompleteString());
   1.823 +            context->recover();
   1.824 +            ConstantUnion *unionArray = new ConstantUnion[1];
   1.825 +            unionArray->setBConst(false);
   1.826 +            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
   1.827 +        }
   1.828 +    }
   1.829 +    ;
   1.830 +
   1.831 +conditional_expression
   1.832 +    : logical_or_expression { $$ = $1; }
   1.833 +    | logical_or_expression QUESTION expression COLON assignment_expression {
   1.834 +       if (context->boolErrorCheck(@2, $1))
   1.835 +            context->recover();
   1.836 +
   1.837 +        $$ = context->intermediate.addSelection($1, $3, $5, @2);
   1.838 +        if ($3->getType() != $5->getType())
   1.839 +            $$ = 0;
   1.840 +
   1.841 +        if ($$ == 0) {
   1.842 +            context->binaryOpError(@2, ":", $3->getCompleteString(), $5->getCompleteString());
   1.843 +            context->recover();
   1.844 +            $$ = $5;
   1.845 +        }
   1.846 +    }
   1.847 +    ;
   1.848 +
   1.849 +assignment_expression
   1.850 +    : conditional_expression { $$ = $1; }
   1.851 +    | unary_expression assignment_operator assignment_expression {
   1.852 +        if (context->lValueErrorCheck(@2, "assign", $1))
   1.853 +            context->recover();
   1.854 +        $$ = context->intermediate.addAssign($2.op, $1, $3, @2);
   1.855 +        if ($$ == 0) {
   1.856 +            context->assignError(@2, "assign", $1->getCompleteString(), $3->getCompleteString());
   1.857 +            context->recover();
   1.858 +            $$ = $1;
   1.859 +        }
   1.860 +    }
   1.861 +    ;
   1.862 +
   1.863 +assignment_operator
   1.864 +    : EQUAL        { $$.op = EOpAssign; }
   1.865 +    | MUL_ASSIGN   { $$.op = EOpMulAssign; }
   1.866 +    | DIV_ASSIGN   { $$.op = EOpDivAssign; }
   1.867 +    | ADD_ASSIGN   { $$.op = EOpAddAssign; }
   1.868 +    | SUB_ASSIGN   { $$.op = EOpSubAssign; }
   1.869 +    ;
   1.870 +
   1.871 +expression
   1.872 +    : assignment_expression {
   1.873 +        $$ = $1;
   1.874 +    }
   1.875 +    | expression COMMA assignment_expression {
   1.876 +        $$ = context->intermediate.addComma($1, $3, @2);
   1.877 +        if ($$ == 0) {
   1.878 +            context->binaryOpError(@2, ",", $1->getCompleteString(), $3->getCompleteString());
   1.879 +            context->recover();
   1.880 +            $$ = $3;
   1.881 +        }
   1.882 +    }
   1.883 +    ;
   1.884 +
   1.885 +constant_expression
   1.886 +    : conditional_expression {
   1.887 +        if (context->constErrorCheck($1))
   1.888 +            context->recover();
   1.889 +        $$ = $1;
   1.890 +    }
   1.891 +    ;
   1.892 +
   1.893 +declaration
   1.894 +    : function_prototype SEMICOLON   {
   1.895 +        TFunction &function = *($1.function);
   1.896 +        
   1.897 +        TIntermAggregate *prototype = new TIntermAggregate;
   1.898 +        prototype->setType(function.getReturnType());
   1.899 +        prototype->setName(function.getName());
   1.900 +        
   1.901 +        for (size_t i = 0; i < function.getParamCount(); i++)
   1.902 +        {
   1.903 +            const TParameter &param = function.getParam(i);
   1.904 +            if (param.name != 0)
   1.905 +            {
   1.906 +                TVariable variable(param.name, *param.type);
   1.907 +                
   1.908 +                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), @1), @1);
   1.909 +            }
   1.910 +            else
   1.911 +            {
   1.912 +                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, @1), @1);
   1.913 +            }
   1.914 +        }
   1.915 +        
   1.916 +        prototype->setOp(EOpPrototype);
   1.917 +        $$ = prototype;
   1.918 +
   1.919 +        context->symbolTable.pop();
   1.920 +    }
   1.921 +    | init_declarator_list SEMICOLON {
   1.922 +        if ($1.intermAggregate)
   1.923 +            $1.intermAggregate->setOp(EOpDeclaration);
   1.924 +        $$ = $1.intermAggregate;
   1.925 +    }
   1.926 +    | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
   1.927 +        if (($2 == EbpHigh) && (context->shaderType == SH_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) {
   1.928 +            context->error(@1, "precision is not supported in fragment shader", "highp");
   1.929 +            context->recover();
   1.930 +        }
   1.931 +        if (!context->symbolTable.setDefaultPrecision( $3, $2 )) {
   1.932 +            context->error(@1, "illegal type argument for default precision qualifier", getBasicString($3.type));
   1.933 +            context->recover();
   1.934 +        }
   1.935 +        $$ = 0;
   1.936 +    }
   1.937 +    ;
   1.938 +
   1.939 +function_prototype
   1.940 +    : function_declarator RIGHT_PAREN  {
   1.941 +        //
   1.942 +        // Multiple declarations of the same function are allowed.
   1.943 +        //
   1.944 +        // If this is a definition, the definition production code will check for redefinitions
   1.945 +        // (we don't know at this point if it's a definition or not).
   1.946 +        //
   1.947 +        // Redeclarations are allowed.  But, return types and parameter qualifiers must match.
   1.948 +        //
   1.949 +        TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find($1->getMangledName()));
   1.950 +        if (prevDec) {
   1.951 +            if (prevDec->getReturnType() != $1->getReturnType()) {
   1.952 +                context->error(@2, "overloaded functions must have the same return type", $1->getReturnType().getBasicString());
   1.953 +                context->recover();
   1.954 +            }
   1.955 +            for (size_t i = 0; i < prevDec->getParamCount(); ++i) {
   1.956 +                if (prevDec->getParam(i).type->getQualifier() != $1->getParam(i).type->getQualifier()) {
   1.957 +                    context->error(@2, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString());
   1.958 +                    context->recover();
   1.959 +                }
   1.960 +            }
   1.961 +        }
   1.962 +
   1.963 +        //
   1.964 +        // Check for previously declared variables using the same name.
   1.965 +        //
   1.966 +        TSymbol *prevSym = context->symbolTable.find($1->getName());
   1.967 +        if (prevSym)
   1.968 +        {
   1.969 +            if (!prevSym->isFunction())
   1.970 +            {
   1.971 +                context->error(@2, "redefinition", $1->getName().c_str(), "function");
   1.972 +                context->recover();
   1.973 +            }
   1.974 +        }
   1.975 +        else
   1.976 +        {
   1.977 +            // Insert the unmangled name to detect potential future redefinition as a variable.
   1.978 +            context->symbolTable.getOuterLevel()->insert($1->getName(), *$1);
   1.979 +        }
   1.980 +
   1.981 +        //
   1.982 +        // If this is a redeclaration, it could also be a definition,
   1.983 +        // in which case, we want to use the variable names from this one, and not the one that's
   1.984 +        // being redeclared.  So, pass back up this declaration, not the one in the symbol table.
   1.985 +        //
   1.986 +        $$.function = $1;
   1.987 +
   1.988 +        // We're at the inner scope level of the function's arguments and body statement.
   1.989 +        // Add the function prototype to the surrounding scope instead.
   1.990 +        context->symbolTable.getOuterLevel()->insert(*$$.function);
   1.991 +    }
   1.992 +    ;
   1.993 +
   1.994 +function_declarator
   1.995 +    : function_header {
   1.996 +        $$ = $1;
   1.997 +    }
   1.998 +    | function_header_with_parameters {
   1.999 +        $$ = $1;
  1.1000 +    }
  1.1001 +    ;
  1.1002 +
  1.1003 +
  1.1004 +function_header_with_parameters
  1.1005 +    : function_header parameter_declaration {
  1.1006 +        // Add the parameter
  1.1007 +        $$ = $1;
  1.1008 +        if ($2.param.type->getBasicType() != EbtVoid)
  1.1009 +            $1->addParameter($2.param);
  1.1010 +        else
  1.1011 +            delete $2.param.type;
  1.1012 +    }
  1.1013 +    | function_header_with_parameters COMMA parameter_declaration {
  1.1014 +        //
  1.1015 +        // Only first parameter of one-parameter functions can be void
  1.1016 +        // The check for named parameters not being void is done in parameter_declarator
  1.1017 +        //
  1.1018 +        if ($3.param.type->getBasicType() == EbtVoid) {
  1.1019 +            //
  1.1020 +            // This parameter > first is void
  1.1021 +            //
  1.1022 +            context->error(@2, "cannot be an argument type except for '(void)'", "void");
  1.1023 +            context->recover();
  1.1024 +            delete $3.param.type;
  1.1025 +        } else {
  1.1026 +            // Add the parameter
  1.1027 +            $$ = $1;
  1.1028 +            $1->addParameter($3.param);
  1.1029 +        }
  1.1030 +    }
  1.1031 +    ;
  1.1032 +
  1.1033 +function_header
  1.1034 +    : fully_specified_type IDENTIFIER LEFT_PAREN {
  1.1035 +        if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) {
  1.1036 +            context->error(@2, "no qualifiers allowed for function return", getQualifierString($1.qualifier));
  1.1037 +            context->recover();
  1.1038 +        }
  1.1039 +        // make sure a sampler is not involved as well...
  1.1040 +        if (context->structQualifierErrorCheck(@2, $1))
  1.1041 +            context->recover();
  1.1042 +
  1.1043 +        // Add the function as a prototype after parsing it (we do not support recursion)
  1.1044 +        TFunction *function;
  1.1045 +        TType type($1);
  1.1046 +        function = new TFunction($2.string, type);
  1.1047 +        $$ = function;
  1.1048 +        
  1.1049 +        context->symbolTable.push();
  1.1050 +    }
  1.1051 +    ;
  1.1052 +
  1.1053 +parameter_declarator
  1.1054 +    // Type + name
  1.1055 +    : type_specifier identifier {
  1.1056 +        if ($1.type == EbtVoid) {
  1.1057 +            context->error(@2, "illegal use of type 'void'", $2.string->c_str());
  1.1058 +            context->recover();
  1.1059 +        }
  1.1060 +        if (context->reservedErrorCheck(@2, *$2.string))
  1.1061 +            context->recover();
  1.1062 +        TParameter param = {$2.string, new TType($1)};
  1.1063 +        $$.param = param;
  1.1064 +    }
  1.1065 +    | type_specifier identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
  1.1066 +        // Check that we can make an array out of this type
  1.1067 +        if (context->arrayTypeErrorCheck(@3, $1))
  1.1068 +            context->recover();
  1.1069 +
  1.1070 +        if (context->reservedErrorCheck(@2, *$2.string))
  1.1071 +            context->recover();
  1.1072 +
  1.1073 +        int size;
  1.1074 +        if (context->arraySizeErrorCheck(@3, $4, size))
  1.1075 +            context->recover();
  1.1076 +        $1.setArray(true, size);
  1.1077 +
  1.1078 +        TType* type = new TType($1);
  1.1079 +        TParameter param = { $2.string, type };
  1.1080 +        $$.param = param;
  1.1081 +    }
  1.1082 +    ;
  1.1083 +
  1.1084 +parameter_declaration
  1.1085 +    //
  1.1086 +    // The only parameter qualifier a parameter can have are
  1.1087 +    // IN_QUAL, OUT_QUAL, INOUT_QUAL, or CONST.
  1.1088 +    //
  1.1089 +
  1.1090 +    //
  1.1091 +    // Type + name
  1.1092 +    //
  1.1093 +    : type_qualifier parameter_qualifier parameter_declarator {
  1.1094 +        $$ = $3;
  1.1095 +        if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type))
  1.1096 +            context->recover();
  1.1097 +    }
  1.1098 +    | parameter_qualifier parameter_declarator {
  1.1099 +        $$ = $2;
  1.1100 +        if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type))
  1.1101 +            context->recover();
  1.1102 +        if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type))
  1.1103 +            context->recover();
  1.1104 +    }
  1.1105 +    //
  1.1106 +    // Only type
  1.1107 +    //
  1.1108 +    | type_qualifier parameter_qualifier parameter_type_specifier {
  1.1109 +        $$ = $3;
  1.1110 +        if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type))
  1.1111 +            context->recover();
  1.1112 +    }
  1.1113 +    | parameter_qualifier parameter_type_specifier {
  1.1114 +        $$ = $2;
  1.1115 +        if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type))
  1.1116 +            context->recover();
  1.1117 +        if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type))
  1.1118 +            context->recover();
  1.1119 +    }
  1.1120 +    ;
  1.1121 +
  1.1122 +parameter_qualifier
  1.1123 +    : /* empty */ {
  1.1124 +        $$ = EvqIn;
  1.1125 +    }
  1.1126 +    | IN_QUAL {
  1.1127 +        $$ = EvqIn;
  1.1128 +    }
  1.1129 +    | OUT_QUAL {
  1.1130 +        $$ = EvqOut;
  1.1131 +    }
  1.1132 +    | INOUT_QUAL {
  1.1133 +        $$ = EvqInOut;
  1.1134 +    }
  1.1135 +    ;
  1.1136 +
  1.1137 +parameter_type_specifier
  1.1138 +    : type_specifier {
  1.1139 +        TParameter param = { 0, new TType($1) };
  1.1140 +        $$.param = param;
  1.1141 +    }
  1.1142 +    ;
  1.1143 +
  1.1144 +init_declarator_list
  1.1145 +    : single_declaration {
  1.1146 +        $$ = $1;
  1.1147 +    }
  1.1148 +    | init_declarator_list COMMA identifier {
  1.1149 +        if ($1.type.type == EbtInvariant && !$3.symbol)
  1.1150 +        {
  1.1151 +            context->error(@3, "undeclared identifier declared as invariant", $3.string->c_str());
  1.1152 +            context->recover();
  1.1153 +        }
  1.1154 +
  1.1155 +        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$3.string, TType($1.type), @3);
  1.1156 +        $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, symbol, @3);
  1.1157 +        
  1.1158 +        if (context->structQualifierErrorCheck(@3, $$.type))
  1.1159 +            context->recover();
  1.1160 +
  1.1161 +        if (context->nonInitConstErrorCheck(@3, *$3.string, $$.type, false))
  1.1162 +            context->recover();
  1.1163 +
  1.1164 +        TVariable* variable = 0;
  1.1165 +        if (context->nonInitErrorCheck(@3, *$3.string, $$.type, variable))
  1.1166 +            context->recover();
  1.1167 +        if (symbol && variable)
  1.1168 +            symbol->setId(variable->getUniqueId());
  1.1169 +    }
  1.1170 +    | init_declarator_list COMMA identifier LEFT_BRACKET RIGHT_BRACKET {
  1.1171 +        if (context->structQualifierErrorCheck(@3, $1.type))
  1.1172 +            context->recover();
  1.1173 +
  1.1174 +        if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true))
  1.1175 +            context->recover();
  1.1176 +
  1.1177 +        $$ = $1;
  1.1178 +
  1.1179 +        if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type))
  1.1180 +            context->recover();
  1.1181 +        else {
  1.1182 +            $1.type.setArray(true);
  1.1183 +            TVariable* variable;
  1.1184 +            if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable))
  1.1185 +                context->recover();
  1.1186 +        }
  1.1187 +    }
  1.1188 +    | init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
  1.1189 +        if (context->structQualifierErrorCheck(@3, $1.type))
  1.1190 +            context->recover();
  1.1191 +
  1.1192 +        if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true))
  1.1193 +            context->recover();
  1.1194 +
  1.1195 +        $$ = $1;
  1.1196 +
  1.1197 +        if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type))
  1.1198 +            context->recover();
  1.1199 +        else {
  1.1200 +            int size;
  1.1201 +            if (context->arraySizeErrorCheck(@4, $5, size))
  1.1202 +                context->recover();
  1.1203 +            $1.type.setArray(true, size);
  1.1204 +            TVariable* variable = 0;
  1.1205 +            if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable))
  1.1206 +                context->recover();
  1.1207 +            TType type = TType($1.type);
  1.1208 +            type.setArraySize(size);
  1.1209 +            $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, @3), @3);
  1.1210 +        }
  1.1211 +    }
  1.1212 +    | init_declarator_list COMMA identifier EQUAL initializer {
  1.1213 +        if (context->structQualifierErrorCheck(@3, $1.type))
  1.1214 +            context->recover();
  1.1215 +
  1.1216 +        $$ = $1;
  1.1217 +
  1.1218 +        TIntermNode* intermNode;
  1.1219 +        if (!context->executeInitializer(@3, *$3.string, $1.type, $5, intermNode)) {
  1.1220 +            //
  1.1221 +            // build the intermediate representation
  1.1222 +            //
  1.1223 +            if (intermNode)
  1.1224 +        $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, intermNode, @4);
  1.1225 +            else
  1.1226 +                $$.intermAggregate = $1.intermAggregate;
  1.1227 +        } else {
  1.1228 +            context->recover();
  1.1229 +            $$.intermAggregate = 0;
  1.1230 +        }
  1.1231 +    }
  1.1232 +    ;
  1.1233 +
  1.1234 +single_declaration
  1.1235 +    : fully_specified_type {
  1.1236 +        $$.type = $1;
  1.1237 +        $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), @1), @1);
  1.1238 +    }
  1.1239 +    | fully_specified_type identifier {
  1.1240 +        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2);
  1.1241 +        $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2);
  1.1242 +        
  1.1243 +        if (context->structQualifierErrorCheck(@2, $$.type))
  1.1244 +            context->recover();
  1.1245 +
  1.1246 +        if (context->nonInitConstErrorCheck(@2, *$2.string, $$.type, false))
  1.1247 +            context->recover();
  1.1248 +            
  1.1249 +            $$.type = $1;
  1.1250 +
  1.1251 +        TVariable* variable = 0;
  1.1252 +        if (context->nonInitErrorCheck(@2, *$2.string, $$.type, variable))
  1.1253 +            context->recover();
  1.1254 +        if (variable && symbol)
  1.1255 +            symbol->setId(variable->getUniqueId());
  1.1256 +    }
  1.1257 +    | fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET {
  1.1258 +        context->error(@2, "unsized array declarations not supported", $2.string->c_str());
  1.1259 +        context->recover();
  1.1260 +
  1.1261 +        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2);
  1.1262 +        $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2);
  1.1263 +        $$.type = $1;
  1.1264 +    }
  1.1265 +    | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
  1.1266 +        TType type = TType($1);
  1.1267 +        int size;
  1.1268 +        if (context->arraySizeErrorCheck(@2, $4, size))
  1.1269 +            context->recover();
  1.1270 +        type.setArraySize(size);
  1.1271 +        TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, @2);
  1.1272 +        $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2);
  1.1273 +        
  1.1274 +        if (context->structQualifierErrorCheck(@2, $1))
  1.1275 +            context->recover();
  1.1276 +
  1.1277 +        if (context->nonInitConstErrorCheck(@2, *$2.string, $1, true))
  1.1278 +            context->recover();
  1.1279 +
  1.1280 +        $$.type = $1;
  1.1281 +
  1.1282 +        if (context->arrayTypeErrorCheck(@3, $1) || context->arrayQualifierErrorCheck(@3, $1))
  1.1283 +            context->recover();
  1.1284 +        else {
  1.1285 +            int size;
  1.1286 +            if (context->arraySizeErrorCheck(@3, $4, size))
  1.1287 +                context->recover();
  1.1288 +
  1.1289 +            $1.setArray(true, size);
  1.1290 +            TVariable* variable = 0;
  1.1291 +            if (context->arrayErrorCheck(@3, *$2.string, $1, variable))
  1.1292 +                context->recover();
  1.1293 +            if (variable && symbol)
  1.1294 +                symbol->setId(variable->getUniqueId());
  1.1295 +        }
  1.1296 +    }
  1.1297 +    | fully_specified_type identifier EQUAL initializer {
  1.1298 +        if (context->structQualifierErrorCheck(@2, $1))
  1.1299 +            context->recover();
  1.1300 +
  1.1301 +        $$.type = $1;
  1.1302 +
  1.1303 +        TIntermNode* intermNode;
  1.1304 +        if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode)) {
  1.1305 +        //
  1.1306 +        // Build intermediate representation
  1.1307 +        //
  1.1308 +            if(intermNode)
  1.1309 +                $$.intermAggregate = context->intermediate.makeAggregate(intermNode, @3);
  1.1310 +            else
  1.1311 +                $$.intermAggregate = 0;
  1.1312 +        } else {
  1.1313 +            context->recover();
  1.1314 +            $$.intermAggregate = 0;
  1.1315 +        }
  1.1316 +    }
  1.1317 +    | INVARIANT IDENTIFIER {
  1.1318 +        VERTEX_ONLY("invariant declaration", @1);
  1.1319 +        if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying"))
  1.1320 +            context->recover();
  1.1321 +        $$.type.setBasic(EbtInvariant, EvqInvariantVaryingOut, @2);
  1.1322 +        if (!$2.symbol)
  1.1323 +        {
  1.1324 +            context->error(@2, "undeclared identifier declared as invariant", $2.string->c_str());
  1.1325 +            context->recover();
  1.1326 +            
  1.1327 +            $$.intermAggregate = 0;
  1.1328 +        }
  1.1329 +        else
  1.1330 +        {
  1.1331 +            TIntermSymbol *symbol = context->intermediate.addSymbol(0, *$2.string, TType($$.type), @2);
  1.1332 +            $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2);
  1.1333 +        }
  1.1334 +    }
  1.1335 +    ;
  1.1336 +
  1.1337 +fully_specified_type
  1.1338 +    : type_specifier {
  1.1339 +        $$ = $1;
  1.1340 +
  1.1341 +        if ($1.array) {
  1.1342 +            context->error(@1, "not supported", "first-class array");
  1.1343 +            context->recover();
  1.1344 +            $1.setArray(false);
  1.1345 +        }
  1.1346 +    }
  1.1347 +    | type_qualifier type_specifier  {
  1.1348 +        if ($2.array) {
  1.1349 +            context->error(@2, "not supported", "first-class array");
  1.1350 +            context->recover();
  1.1351 +            $2.setArray(false);
  1.1352 +        }
  1.1353 +
  1.1354 +        if ($1.qualifier == EvqAttribute &&
  1.1355 +            ($2.type == EbtBool || $2.type == EbtInt)) {
  1.1356 +            context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier));
  1.1357 +            context->recover();
  1.1358 +        }
  1.1359 +        if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) &&
  1.1360 +            ($2.type == EbtBool || $2.type == EbtInt)) {
  1.1361 +            context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier));
  1.1362 +            context->recover();
  1.1363 +        }
  1.1364 +        $$ = $2;
  1.1365 +        $$.qualifier = $1.qualifier;
  1.1366 +    }
  1.1367 +    ;
  1.1368 +
  1.1369 +type_qualifier
  1.1370 +    : CONST_QUAL {
  1.1371 +        $$.setBasic(EbtVoid, EvqConst, @1);
  1.1372 +    }
  1.1373 +    | ATTRIBUTE {
  1.1374 +        VERTEX_ONLY("attribute", @1);
  1.1375 +        if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "attribute"))
  1.1376 +            context->recover();
  1.1377 +        $$.setBasic(EbtVoid, EvqAttribute, @1);
  1.1378 +    }
  1.1379 +    | VARYING {
  1.1380 +        if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "varying"))
  1.1381 +            context->recover();
  1.1382 +        if (context->shaderType == SH_VERTEX_SHADER)
  1.1383 +            $$.setBasic(EbtVoid, EvqVaryingOut, @1);
  1.1384 +        else
  1.1385 +            $$.setBasic(EbtVoid, EvqVaryingIn, @1);
  1.1386 +    }
  1.1387 +    | INVARIANT VARYING {
  1.1388 +        if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying"))
  1.1389 +            context->recover();
  1.1390 +        if (context->shaderType == SH_VERTEX_SHADER)
  1.1391 +            $$.setBasic(EbtVoid, EvqInvariantVaryingOut, @1);
  1.1392 +        else
  1.1393 +            $$.setBasic(EbtVoid, EvqInvariantVaryingIn, @1);
  1.1394 +    }
  1.1395 +    | UNIFORM {
  1.1396 +        if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "uniform"))
  1.1397 +            context->recover();
  1.1398 +        $$.setBasic(EbtVoid, EvqUniform, @1);
  1.1399 +    }
  1.1400 +    ;
  1.1401 +
  1.1402 +type_specifier
  1.1403 +    : type_specifier_no_prec {
  1.1404 +        $$ = $1;
  1.1405 +
  1.1406 +        if ($$.precision == EbpUndefined) {
  1.1407 +            $$.precision = context->symbolTable.getDefaultPrecision($1.type);
  1.1408 +            if (context->precisionErrorCheck(@1, $$.precision, $1.type)) {
  1.1409 +                context->recover();
  1.1410 +            }
  1.1411 +        }
  1.1412 +    }
  1.1413 +    | precision_qualifier type_specifier_no_prec {
  1.1414 +        $$ = $2;
  1.1415 +        $$.precision = $1;
  1.1416 +    }
  1.1417 +    ;
  1.1418 +
  1.1419 +precision_qualifier
  1.1420 +    : HIGH_PRECISION {
  1.1421 +        $$ = EbpHigh;
  1.1422 +    }
  1.1423 +    | MEDIUM_PRECISION {
  1.1424 +        $$ = EbpMedium;
  1.1425 +    }
  1.1426 +    | LOW_PRECISION  {
  1.1427 +        $$ = EbpLow;
  1.1428 +    }
  1.1429 +    ;
  1.1430 +
  1.1431 +type_specifier_no_prec
  1.1432 +    : type_specifier_nonarray {
  1.1433 +        $$ = $1;
  1.1434 +    }
  1.1435 +    | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET {
  1.1436 +        $$ = $1;
  1.1437 +
  1.1438 +        if (context->arrayTypeErrorCheck(@2, $1))
  1.1439 +            context->recover();
  1.1440 +        else {
  1.1441 +            int size;
  1.1442 +            if (context->arraySizeErrorCheck(@2, $3, size))
  1.1443 +                context->recover();
  1.1444 +            $$.setArray(true, size);
  1.1445 +        }
  1.1446 +    }
  1.1447 +    ;
  1.1448 +
  1.1449 +type_specifier_nonarray
  1.1450 +    : VOID_TYPE {
  1.1451 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1452 +        $$.setBasic(EbtVoid, qual, @1);
  1.1453 +    }
  1.1454 +    | FLOAT_TYPE {
  1.1455 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1456 +        $$.setBasic(EbtFloat, qual, @1);
  1.1457 +    }
  1.1458 +    | INT_TYPE {
  1.1459 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1460 +        $$.setBasic(EbtInt, qual, @1);
  1.1461 +    }
  1.1462 +    | BOOL_TYPE {
  1.1463 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1464 +        $$.setBasic(EbtBool, qual, @1);
  1.1465 +    }
  1.1466 +    | VEC2 {
  1.1467 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1468 +        $$.setBasic(EbtFloat, qual, @1);
  1.1469 +        $$.setAggregate(2);
  1.1470 +    }
  1.1471 +    | VEC3 {
  1.1472 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1473 +        $$.setBasic(EbtFloat, qual, @1);
  1.1474 +        $$.setAggregate(3);
  1.1475 +    }
  1.1476 +    | VEC4 {
  1.1477 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1478 +        $$.setBasic(EbtFloat, qual, @1);
  1.1479 +        $$.setAggregate(4);
  1.1480 +    }
  1.1481 +    | BVEC2 {
  1.1482 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1483 +        $$.setBasic(EbtBool, qual, @1);
  1.1484 +        $$.setAggregate(2);
  1.1485 +    }
  1.1486 +    | BVEC3 {
  1.1487 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1488 +        $$.setBasic(EbtBool, qual, @1);
  1.1489 +        $$.setAggregate(3);
  1.1490 +    }
  1.1491 +    | BVEC4 {
  1.1492 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1493 +        $$.setBasic(EbtBool, qual, @1);
  1.1494 +        $$.setAggregate(4);
  1.1495 +    }
  1.1496 +    | IVEC2 {
  1.1497 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1498 +        $$.setBasic(EbtInt, qual, @1);
  1.1499 +        $$.setAggregate(2);
  1.1500 +    }
  1.1501 +    | IVEC3 {
  1.1502 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1503 +        $$.setBasic(EbtInt, qual, @1);
  1.1504 +        $$.setAggregate(3);
  1.1505 +    }
  1.1506 +    | IVEC4 {
  1.1507 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1508 +        $$.setBasic(EbtInt, qual, @1);
  1.1509 +        $$.setAggregate(4);
  1.1510 +    }
  1.1511 +    | MATRIX2 {
  1.1512 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1513 +        $$.setBasic(EbtFloat, qual, @1);
  1.1514 +        $$.setAggregate(2, true);
  1.1515 +    }
  1.1516 +    | MATRIX3 {
  1.1517 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1518 +        $$.setBasic(EbtFloat, qual, @1);
  1.1519 +        $$.setAggregate(3, true);
  1.1520 +    }
  1.1521 +    | MATRIX4 {
  1.1522 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1523 +        $$.setBasic(EbtFloat, qual, @1);
  1.1524 +        $$.setAggregate(4, true);
  1.1525 +    }
  1.1526 +    | SAMPLER2D {
  1.1527 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1528 +        $$.setBasic(EbtSampler2D, qual, @1);
  1.1529 +    }
  1.1530 +    | SAMPLERCUBE {
  1.1531 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1532 +        $$.setBasic(EbtSamplerCube, qual, @1);
  1.1533 +    }
  1.1534 +    | SAMPLER_EXTERNAL_OES {
  1.1535 +        if (!context->supportsExtension("GL_OES_EGL_image_external")) {
  1.1536 +            context->error(@1, "unsupported type", "samplerExternalOES");
  1.1537 +            context->recover();
  1.1538 +        }
  1.1539 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1540 +        $$.setBasic(EbtSamplerExternalOES, qual, @1);
  1.1541 +    }
  1.1542 +    | SAMPLER2DRECT {
  1.1543 +        if (!context->supportsExtension("GL_ARB_texture_rectangle")) {
  1.1544 +            context->error(@1, "unsupported type", "sampler2DRect");
  1.1545 +            context->recover();
  1.1546 +        }
  1.1547 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1548 +        $$.setBasic(EbtSampler2DRect, qual, @1);
  1.1549 +    }
  1.1550 +    | struct_specifier {
  1.1551 +        $$ = $1;
  1.1552 +        $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1553 +    }
  1.1554 +    | TYPE_NAME {
  1.1555 +        //
  1.1556 +        // This is for user defined type names.  The lexical phase looked up the
  1.1557 +        // type.
  1.1558 +        //
  1.1559 +        TType& structure = static_cast<TVariable*>($1.symbol)->getType();
  1.1560 +        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
  1.1561 +        $$.setBasic(EbtStruct, qual, @1);
  1.1562 +        $$.userDef = &structure;
  1.1563 +    }
  1.1564 +    ;
  1.1565 +
  1.1566 +struct_specifier
  1.1567 +    : STRUCT identifier LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
  1.1568 +        if (context->reservedErrorCheck(@2, *$2.string))
  1.1569 +            context->recover();
  1.1570 +
  1.1571 +        TType* structure = new TType(new TStructure($2.string, $5));
  1.1572 +        TVariable* userTypeDef = new TVariable($2.string, *structure, true);
  1.1573 +        if (! context->symbolTable.insert(*userTypeDef)) {
  1.1574 +            context->error(@2, "redefinition", $2.string->c_str(), "struct");
  1.1575 +            context->recover();
  1.1576 +        }
  1.1577 +        $$.setBasic(EbtStruct, EvqTemporary, @1);
  1.1578 +        $$.userDef = structure;
  1.1579 +        context->exitStructDeclaration();
  1.1580 +    }
  1.1581 +    | STRUCT LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
  1.1582 +        TType* structure = new TType(new TStructure(NewPoolTString(""), $4));
  1.1583 +        $$.setBasic(EbtStruct, EvqTemporary, @1);
  1.1584 +        $$.userDef = structure;
  1.1585 +        context->exitStructDeclaration();
  1.1586 +    }
  1.1587 +    ;
  1.1588 +
  1.1589 +struct_declaration_list
  1.1590 +    : struct_declaration {
  1.1591 +        $$ = $1;
  1.1592 +    }
  1.1593 +    | struct_declaration_list struct_declaration {
  1.1594 +        $$ = $1;
  1.1595 +        for (size_t i = 0; i < $2->size(); ++i) {
  1.1596 +            TField* field = (*$2)[i];
  1.1597 +            for (size_t j = 0; j < $$->size(); ++j) {
  1.1598 +                if ((*$$)[j]->name() == field->name()) {
  1.1599 +                    context->error(@2, "duplicate field name in structure:", "struct", field->name().c_str());
  1.1600 +                    context->recover();
  1.1601 +                }
  1.1602 +            }
  1.1603 +            $$->push_back(field);
  1.1604 +        }
  1.1605 +    }
  1.1606 +    ;
  1.1607 +
  1.1608 +struct_declaration
  1.1609 +    : type_specifier struct_declarator_list SEMICOLON {
  1.1610 +        $$ = $2;
  1.1611 +
  1.1612 +        if (context->voidErrorCheck(@1, (*$2)[0]->name(), $1)) {
  1.1613 +            context->recover();
  1.1614 +        }
  1.1615 +        for (unsigned int i = 0; i < $$->size(); ++i) {
  1.1616 +            //
  1.1617 +            // Careful not to replace already known aspects of type, like array-ness
  1.1618 +            //
  1.1619 +            TType* type = (*$$)[i]->type();
  1.1620 +            type->setBasicType($1.type);
  1.1621 +            type->setNominalSize($1.size);
  1.1622 +            type->setMatrix($1.matrix);
  1.1623 +            type->setPrecision($1.precision);
  1.1624 +
  1.1625 +            // don't allow arrays of arrays
  1.1626 +            if (type->isArray()) {
  1.1627 +                if (context->arrayTypeErrorCheck(@1, $1))
  1.1628 +                    context->recover();
  1.1629 +            }
  1.1630 +            if ($1.array)
  1.1631 +                type->setArraySize($1.arraySize);
  1.1632 +            if ($1.userDef)
  1.1633 +                type->setStruct($1.userDef->getStruct());
  1.1634 +
  1.1635 +            if (context->structNestingErrorCheck(@1, *(*$$)[i]))
  1.1636 +                context->recover();
  1.1637 +        }
  1.1638 +    }
  1.1639 +    ;
  1.1640 +
  1.1641 +struct_declarator_list
  1.1642 +    : struct_declarator {
  1.1643 +        $$ = NewPoolTFieldList();
  1.1644 +        $$->push_back($1);
  1.1645 +    }
  1.1646 +    | struct_declarator_list COMMA struct_declarator {
  1.1647 +        $$->push_back($3);
  1.1648 +    }
  1.1649 +    ;
  1.1650 +
  1.1651 +struct_declarator
  1.1652 +    : identifier {
  1.1653 +        if (context->reservedErrorCheck(@1, *$1.string))
  1.1654 +            context->recover();
  1.1655 +
  1.1656 +        TType* type = new TType(EbtVoid, EbpUndefined);
  1.1657 +        $$ = new TField(type, $1.string);
  1.1658 +    }
  1.1659 +    | identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
  1.1660 +        if (context->reservedErrorCheck(@1, *$1.string))
  1.1661 +            context->recover();
  1.1662 +
  1.1663 +        TType* type = new TType(EbtVoid, EbpUndefined);
  1.1664 +        int size = 0;
  1.1665 +        if (context->arraySizeErrorCheck(@3, $3, size))
  1.1666 +            context->recover();
  1.1667 +        type->setArraySize(size);
  1.1668 +
  1.1669 +        $$ = new TField(type, $1.string);
  1.1670 +    }
  1.1671 +    ;
  1.1672 +
  1.1673 +initializer
  1.1674 +    : assignment_expression { $$ = $1; }
  1.1675 +    ;
  1.1676 +
  1.1677 +declaration_statement
  1.1678 +    : declaration { $$ = $1; }
  1.1679 +    ;
  1.1680 +
  1.1681 +statement
  1.1682 +    : compound_statement  { $$ = $1; }
  1.1683 +    | simple_statement    { $$ = $1; }
  1.1684 +    ;
  1.1685 +
  1.1686 +// Grammar Note:  No labeled statements; 'goto' is not supported.
  1.1687 +
  1.1688 +simple_statement
  1.1689 +    : declaration_statement { $$ = $1; }
  1.1690 +    | expression_statement  { $$ = $1; }
  1.1691 +    | selection_statement   { $$ = $1; }
  1.1692 +    | iteration_statement   { $$ = $1; }
  1.1693 +    | jump_statement        { $$ = $1; }
  1.1694 +    ;
  1.1695 +
  1.1696 +compound_statement
  1.1697 +    : LEFT_BRACE RIGHT_BRACE { $$ = 0; }
  1.1698 +    | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE {
  1.1699 +        if ($3 != 0) {
  1.1700 +            $3->setOp(EOpSequence);
  1.1701 +            $3->setLine(@$);
  1.1702 +        }
  1.1703 +        $$ = $3;
  1.1704 +    }
  1.1705 +    ;
  1.1706 +
  1.1707 +statement_no_new_scope
  1.1708 +    : compound_statement_no_new_scope { $$ = $1; }
  1.1709 +    | simple_statement                { $$ = $1; }
  1.1710 +    ;
  1.1711 +
  1.1712 +statement_with_scope
  1.1713 +    : { context->symbolTable.push(); } compound_statement_no_new_scope { context->symbolTable.pop(); $$ = $2; }
  1.1714 +    | { context->symbolTable.push(); } simple_statement                { context->symbolTable.pop(); $$ = $2; }
  1.1715 +    ;
  1.1716 +
  1.1717 +compound_statement_no_new_scope
  1.1718 +    // Statement that doesn't create a new scope, for selection_statement, iteration_statement
  1.1719 +    : LEFT_BRACE RIGHT_BRACE {
  1.1720 +        $$ = 0;
  1.1721 +    }
  1.1722 +    | LEFT_BRACE statement_list RIGHT_BRACE {
  1.1723 +        if ($2) {
  1.1724 +            $2->setOp(EOpSequence);
  1.1725 +            $2->setLine(@$);
  1.1726 +        }
  1.1727 +        $$ = $2;
  1.1728 +    }
  1.1729 +    ;
  1.1730 +
  1.1731 +statement_list
  1.1732 +    : statement {
  1.1733 +        $$ = context->intermediate.makeAggregate($1, @$);
  1.1734 +    }
  1.1735 +    | statement_list statement {
  1.1736 +        $$ = context->intermediate.growAggregate($1, $2, @$);
  1.1737 +    }
  1.1738 +    ;
  1.1739 +
  1.1740 +expression_statement
  1.1741 +    : SEMICOLON  { $$ = 0; }
  1.1742 +    | expression SEMICOLON  { $$ = static_cast<TIntermNode*>($1); }
  1.1743 +    ;
  1.1744 +
  1.1745 +selection_statement
  1.1746 +    : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
  1.1747 +        if (context->boolErrorCheck(@1, $3))
  1.1748 +            context->recover();
  1.1749 +        $$ = context->intermediate.addSelection($3, $5, @1);
  1.1750 +    }
  1.1751 +    ;
  1.1752 +
  1.1753 +selection_rest_statement
  1.1754 +    : statement_with_scope ELSE statement_with_scope {
  1.1755 +        $$.node1 = $1;
  1.1756 +        $$.node2 = $3;
  1.1757 +    }
  1.1758 +    | statement_with_scope {
  1.1759 +        $$.node1 = $1;
  1.1760 +        $$.node2 = 0;
  1.1761 +    }
  1.1762 +    ;
  1.1763 +
  1.1764 +// Grammar Note:  No 'switch'.  Switch statements not supported.
  1.1765 +
  1.1766 +condition
  1.1767 +    // In 1996 c++ draft, conditions can include single declarations
  1.1768 +    : expression {
  1.1769 +        $$ = $1;
  1.1770 +        if (context->boolErrorCheck($1->getLine(), $1))
  1.1771 +            context->recover();
  1.1772 +    }
  1.1773 +    | fully_specified_type identifier EQUAL initializer {
  1.1774 +        TIntermNode* intermNode;
  1.1775 +        if (context->structQualifierErrorCheck(@2, $1))
  1.1776 +            context->recover();
  1.1777 +        if (context->boolErrorCheck(@2, $1))
  1.1778 +            context->recover();
  1.1779 +
  1.1780 +        if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode))
  1.1781 +            $$ = $4;
  1.1782 +        else {
  1.1783 +            context->recover();
  1.1784 +            $$ = 0;
  1.1785 +        }
  1.1786 +    }
  1.1787 +    ;
  1.1788 +
  1.1789 +iteration_statement
  1.1790 +    : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope {
  1.1791 +        context->symbolTable.pop();
  1.1792 +        $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, @1);
  1.1793 +        --context->loopNestingLevel;
  1.1794 +    }
  1.1795 +    | DO { ++context->loopNestingLevel; } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
  1.1796 +        if (context->boolErrorCheck(@8, $6))
  1.1797 +            context->recover();
  1.1798 +
  1.1799 +        $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, @4);
  1.1800 +        --context->loopNestingLevel;
  1.1801 +    }
  1.1802 +    | FOR LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
  1.1803 +        context->symbolTable.pop();
  1.1804 +        $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), $7, @1);
  1.1805 +        --context->loopNestingLevel;
  1.1806 +    }
  1.1807 +    ;
  1.1808 +
  1.1809 +for_init_statement
  1.1810 +    : expression_statement {
  1.1811 +        $$ = $1;
  1.1812 +    }
  1.1813 +    | declaration_statement {
  1.1814 +        $$ = $1;
  1.1815 +    }
  1.1816 +    ;
  1.1817 +
  1.1818 +conditionopt
  1.1819 +    : condition {
  1.1820 +        $$ = $1;
  1.1821 +    }
  1.1822 +    | /* May be null */ {
  1.1823 +        $$ = 0;
  1.1824 +    }
  1.1825 +    ;
  1.1826 +
  1.1827 +for_rest_statement
  1.1828 +    : conditionopt SEMICOLON {
  1.1829 +        $$.node1 = $1;
  1.1830 +        $$.node2 = 0;
  1.1831 +    }
  1.1832 +    | conditionopt SEMICOLON expression  {
  1.1833 +        $$.node1 = $1;
  1.1834 +        $$.node2 = $3;
  1.1835 +    }
  1.1836 +    ;
  1.1837 +
  1.1838 +jump_statement
  1.1839 +    : CONTINUE SEMICOLON {
  1.1840 +        if (context->loopNestingLevel <= 0) {
  1.1841 +            context->error(@1, "continue statement only allowed in loops", "");
  1.1842 +            context->recover();
  1.1843 +        }
  1.1844 +        $$ = context->intermediate.addBranch(EOpContinue, @1);
  1.1845 +    }
  1.1846 +    | BREAK SEMICOLON {
  1.1847 +        if (context->loopNestingLevel <= 0) {
  1.1848 +            context->error(@1, "break statement only allowed in loops", "");
  1.1849 +            context->recover();
  1.1850 +        }
  1.1851 +        $$ = context->intermediate.addBranch(EOpBreak, @1);
  1.1852 +    }
  1.1853 +    | RETURN SEMICOLON {
  1.1854 +        $$ = context->intermediate.addBranch(EOpReturn, @1);
  1.1855 +        if (context->currentFunctionType->getBasicType() != EbtVoid) {
  1.1856 +            context->error(@1, "non-void function must return a value", "return");
  1.1857 +            context->recover();
  1.1858 +        }
  1.1859 +    }
  1.1860 +    | RETURN expression SEMICOLON {
  1.1861 +        $$ = context->intermediate.addBranch(EOpReturn, $2, @1);
  1.1862 +        context->functionReturnsValue = true;
  1.1863 +        if (context->currentFunctionType->getBasicType() == EbtVoid) {
  1.1864 +            context->error(@1, "void function cannot return a value", "return");
  1.1865 +            context->recover();
  1.1866 +        } else if (*(context->currentFunctionType) != $2->getType()) {
  1.1867 +            context->error(@1, "function return is not matching type:", "return");
  1.1868 +            context->recover();
  1.1869 +        }
  1.1870 +    }
  1.1871 +    | DISCARD SEMICOLON {
  1.1872 +        FRAG_ONLY("discard", @1);
  1.1873 +        $$ = context->intermediate.addBranch(EOpKill, @1);
  1.1874 +    }
  1.1875 +    ;
  1.1876 +
  1.1877 +// Grammar Note:  No 'goto'.  Gotos are not supported.
  1.1878 +
  1.1879 +translation_unit
  1.1880 +    : external_declaration {
  1.1881 +        $$ = $1;
  1.1882 +        context->treeRoot = $$;
  1.1883 +    }
  1.1884 +    | translation_unit external_declaration {
  1.1885 +        $$ = context->intermediate.growAggregate($1, $2, @$);
  1.1886 +        context->treeRoot = $$;
  1.1887 +    }
  1.1888 +    ;
  1.1889 +
  1.1890 +external_declaration
  1.1891 +    : function_definition {
  1.1892 +        $$ = $1;
  1.1893 +    }
  1.1894 +    | declaration {
  1.1895 +        $$ = $1;
  1.1896 +    }
  1.1897 +    ;
  1.1898 +
  1.1899 +function_definition
  1.1900 +    : function_prototype {
  1.1901 +        TFunction* function = $1.function;
  1.1902 +        
  1.1903 +        const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName());
  1.1904 +        
  1.1905 +        if (builtIn)
  1.1906 +        {
  1.1907 +            context->error(@1, "built-in functions cannot be redefined", function->getName().c_str());
  1.1908 +            context->recover();
  1.1909 +        }
  1.1910 +        
  1.1911 +        TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find(function->getMangledName()));
  1.1912 +        //
  1.1913 +        // Note:  'prevDec' could be 'function' if this is the first time we've seen function
  1.1914 +        // as it would have just been put in the symbol table.  Otherwise, we're looking up
  1.1915 +        // an earlier occurance.
  1.1916 +        //
  1.1917 +        if (prevDec->isDefined()) {
  1.1918 +            //
  1.1919 +            // Then this function already has a body.
  1.1920 +            //
  1.1921 +            context->error(@1, "function already has a body", function->getName().c_str());
  1.1922 +            context->recover();
  1.1923 +        }
  1.1924 +        prevDec->setDefined();
  1.1925 +
  1.1926 +        //
  1.1927 +        // Raise error message if main function takes any parameters or return anything other than void
  1.1928 +        //
  1.1929 +        if (function->getName() == "main") {
  1.1930 +            if (function->getParamCount() > 0) {
  1.1931 +                context->error(@1, "function cannot take any parameter(s)", function->getName().c_str());
  1.1932 +                context->recover();
  1.1933 +            }
  1.1934 +            if (function->getReturnType().getBasicType() != EbtVoid) {
  1.1935 +                context->error(@1, "", function->getReturnType().getBasicString(), "main function cannot return a value");
  1.1936 +                context->recover();
  1.1937 +            }
  1.1938 +        }
  1.1939 +
  1.1940 +        //
  1.1941 +        // Remember the return type for later checking for RETURN statements.
  1.1942 +        //
  1.1943 +        context->currentFunctionType = &(prevDec->getReturnType());
  1.1944 +        context->functionReturnsValue = false;
  1.1945 +
  1.1946 +        //
  1.1947 +        // Insert parameters into the symbol table.
  1.1948 +        // If the parameter has no name, it's not an error, just don't insert it
  1.1949 +        // (could be used for unused args).
  1.1950 +        //
  1.1951 +        // Also, accumulate the list of parameters into the HIL, so lower level code
  1.1952 +        // knows where to find parameters.
  1.1953 +        //
  1.1954 +        TIntermAggregate* paramNodes = new TIntermAggregate;
  1.1955 +        for (size_t i = 0; i < function->getParamCount(); i++) {
  1.1956 +            const TParameter& param = function->getParam(i);
  1.1957 +            if (param.name != 0) {
  1.1958 +                TVariable *variable = new TVariable(param.name, *param.type);
  1.1959 +                //
  1.1960 +                // Insert the parameters with name in the symbol table.
  1.1961 +                //
  1.1962 +                if (! context->symbolTable.insert(*variable)) {
  1.1963 +                    context->error(@1, "redefinition", variable->getName().c_str());
  1.1964 +                    context->recover();
  1.1965 +                    delete variable;
  1.1966 +                }
  1.1967 +
  1.1968 +                //
  1.1969 +                // Add the parameter to the HIL
  1.1970 +                //
  1.1971 +                paramNodes = context->intermediate.growAggregate(
  1.1972 +                                               paramNodes,
  1.1973 +                                               context->intermediate.addSymbol(variable->getUniqueId(),
  1.1974 +                                                                               variable->getName(),
  1.1975 +                                                                               variable->getType(),
  1.1976 +                                                                               @1),
  1.1977 +                                               @1);
  1.1978 +            } else {
  1.1979 +                paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, @1), @1);
  1.1980 +            }
  1.1981 +        }
  1.1982 +        context->intermediate.setAggregateOperator(paramNodes, EOpParameters, @1);
  1.1983 +        $1.intermAggregate = paramNodes;
  1.1984 +        context->loopNestingLevel = 0;
  1.1985 +    }
  1.1986 +    compound_statement_no_new_scope {
  1.1987 +        //?? Check that all paths return a value if return type != void ?
  1.1988 +        //   May be best done as post process phase on intermediate code
  1.1989 +        if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) {
  1.1990 +            context->error(@1, "function does not return a value:", "", $1.function->getName().c_str());
  1.1991 +            context->recover();
  1.1992 +        }
  1.1993 +        
  1.1994 +        $$ = context->intermediate.growAggregate($1.intermAggregate, $3, @$);
  1.1995 +        context->intermediate.setAggregateOperator($$, EOpFunction, @1);
  1.1996 +        $$->getAsAggregate()->setName($1.function->getMangledName().c_str());
  1.1997 +        $$->getAsAggregate()->setType($1.function->getReturnType());
  1.1998 +
  1.1999 +        // store the pragma information for debug and optimize and other vendor specific
  1.2000 +        // information. This information can be queried from the parse tree
  1.2001 +        $$->getAsAggregate()->setOptimize(context->pragma().optimize);
  1.2002 +        $$->getAsAggregate()->setDebug(context->pragma().debug);
  1.2003 +
  1.2004 +        context->symbolTable.pop();
  1.2005 +    }
  1.2006 +    ;
  1.2007 +
  1.2008 +%%
  1.2009 +
  1.2010 +void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason) {
  1.2011 +    context->error(*yylloc, reason, "");
  1.2012 +    context->recover();
  1.2013 +}
  1.2014 +
  1.2015 +int glslang_parse(TParseContext* context) {
  1.2016 +    return yyparse(context);
  1.2017 +}

mercurial