1/*
2//
3// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style license that can be
5// found in the LICENSE file.
6//
7
8This file contains the Yacc grammar for GLSL ES.
9Based on ANSI C Yacc grammar:
10http://www.lysator.liu.se/c/ANSI-C-grammar-y.html
11
12IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
13WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
14*/
15
16%{
17//
18// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
19// Use of this source code is governed by a BSD-style license that can be
20// found in the LICENSE file.
21//
22
23// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
24
25// Ignore errors in auto-generated code.
26#if defined(__GNUC__)
27#pragma GCC diagnostic ignored "-Wunused-function"
28#pragma GCC diagnostic ignored "-Wunused-variable"
29#pragma GCC diagnostic ignored "-Wswitch-enum"
30#elif defined(_MSC_VER)
31#pragma warning(disable: 4065)
32#pragma warning(disable: 4189)
33#pragma warning(disable: 4505)
34#pragma warning(disable: 4701)
35#endif
36
37#include "angle_gl.h"
38#include "compiler/translator/SymbolTable.h"
39#include "compiler/translator/ParseContext.h"
40#include "GLSLANG/ShaderLang.h"
41
42#define YYENABLE_NLS 0
43
44#define YYLEX_PARAM context->scanner
45
46%}
47%expect 1 /* One shift reduce conflict because of if | else */
48%pure-parser
49%parse-param {TParseContext* context}
50%locations
51
52%code requires {
53#define YYLTYPE TSourceLoc
54#define YYLTYPE_IS_DECLARED 1
55}
56
57%union {
58    struct {
59        union {
60            TString *string;
61            float f;
62            int i;
63            unsigned int u;
64            bool b;
65        };
66        TSymbol* symbol;
67    } lex;
68    struct {
69        TOperator op;
70        union {
71            TIntermNode* intermNode;
72            TIntermNodePair nodePair;
73            TIntermTyped* intermTypedNode;
74            TIntermAggregate* intermAggregate;
75        };
76        union {
77            TPublicType type;
78            TPrecision precision;
79            TLayoutQualifier layoutQualifier;
80            TQualifier qualifier;
81            TFunction* function;
82            TParameter param;
83            TField* field;
84            TFieldList* fieldList;
85        };
86    } interm;
87}
88
89%{
90extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner);
91extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason);
92
93#define YYLLOC_DEFAULT(Current, Rhs, N)                      \
94  do {                                                       \
95      if (YYID(N)) {                                         \
96        (Current).first_file = YYRHSLOC(Rhs, 1).first_file;  \
97        (Current).first_line = YYRHSLOC(Rhs, 1).first_line;  \
98        (Current).last_file = YYRHSLOC(Rhs, N).last_file;    \
99        (Current).last_line = YYRHSLOC(Rhs, N).last_line;    \
100      }                                                      \
101      else {                                                 \
102        (Current).first_file = YYRHSLOC(Rhs, 0).last_file;   \
103        (Current).first_line = YYRHSLOC(Rhs, 0).last_line;   \
104        (Current).last_file = YYRHSLOC(Rhs, 0).last_file;    \
105        (Current).last_line = YYRHSLOC(Rhs, 0).last_line;    \
106      }                                                      \
107  } while (0)
108
109#define VERTEX_ONLY(S, L) {  \
110    if (context->shaderType != GL_VERTEX_SHADER) {  \
111        context->error(L, " supported in vertex shaders only ", S);  \
112        context->recover();  \
113    }  \
114}
115
116#define FRAG_ONLY(S, L) {  \
117    if (context->shaderType != GL_FRAGMENT_SHADER) {  \
118        context->error(L, " supported in fragment shaders only ", S);  \
119        context->recover();  \
120    }  \
121}
122
123#define ES2_ONLY(S, L) {  \
124    if (context->shaderVersion != 100) {  \
125        context->error(L, " supported in GLSL ES 1.00 only ", S);  \
126        context->recover();  \
127    }  \
128}
129
130#define ES3_ONLY(TOKEN, LINE, REASON) {  \
131    if (context->shaderVersion != 300) {  \
132        context->error(LINE, REASON " supported in GLSL ES 3.00 only ", TOKEN);  \
133        context->recover();  \
134    }  \
135}
136%}
137
138%token <lex> INVARIANT HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION
139%token <lex> ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE UINT_TYPE
140%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT
141%token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4 UVEC2 UVEC3 UVEC4
142%token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM VARYING
143%token <lex> MATRIX2x3 MATRIX3x2 MATRIX2x4 MATRIX4x2 MATRIX3x4 MATRIX4x3
144%token <lex> CENTROID FLAT SMOOTH
145%token <lex> STRUCT VOID_TYPE WHILE
146%token <lex> SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT SAMPLER2DARRAY
147%token <lex> ISAMPLER2D ISAMPLER3D ISAMPLERCUBE ISAMPLER2DARRAY
148%token <lex> USAMPLER2D USAMPLER3D USAMPLERCUBE USAMPLER2DARRAY
149%token <lex> SAMPLER3D SAMPLER3DRECT SAMPLER2DSHADOW SAMPLERCUBESHADOW SAMPLER2DARRAYSHADOW
150%token <lex> LAYOUT
151
152%token <lex> IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT UINTCONSTANT BOOLCONSTANT
153%token <lex> FIELD_SELECTION
154%token <lex> LEFT_OP RIGHT_OP
155%token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
156%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
157%token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
158%token <lex> SUB_ASSIGN
159
160%token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
161%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
162%token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION
163
164%type <lex> identifier
165%type <interm> assignment_operator unary_operator
166%type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression
167%type <interm.intermTypedNode> expression integer_expression assignment_expression
168%type <interm.intermTypedNode> unary_expression multiplicative_expression additive_expression
169%type <interm.intermTypedNode> relational_expression equality_expression
170%type <interm.intermTypedNode> conditional_expression constant_expression
171%type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression
172%type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression
173%type <interm.intermTypedNode> function_call initializer condition conditionopt
174
175%type <interm.intermNode> translation_unit function_definition
176%type <interm.intermNode> statement simple_statement
177%type <interm.intermAggregate>  statement_list compound_statement
178%type <interm.intermNode> declaration_statement selection_statement expression_statement
179%type <interm.intermNode> declaration external_declaration
180%type <interm.intermNode> for_init_statement compound_statement_no_new_scope
181%type <interm.nodePair> selection_rest_statement for_rest_statement
182%type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope statement_with_scope
183%type <interm> single_declaration init_declarator_list
184
185%type <interm> parameter_declaration parameter_declarator parameter_type_specifier
186%type <interm.qualifier> parameter_qualifier parameter_type_qualifier
187%type <interm.layoutQualifier> layout_qualifier layout_qualifier_id_list layout_qualifier_id
188
189%type <interm.precision> precision_qualifier
190%type <interm.type> type_qualifier fully_specified_type type_specifier storage_qualifier interpolation_qualifier
191%type <interm.type> type_specifier_no_prec type_specifier_nonarray
192%type <interm.type> struct_specifier
193%type <interm.field> struct_declarator
194%type <interm.fieldList> struct_declarator_list struct_declaration struct_declaration_list
195%type <interm.function> function_header function_declarator function_identifier
196%type <interm.function> function_header_with_parameters function_call_header
197%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
198%type <interm> function_call_or_method
199
200%type <lex> enter_struct
201
202%start translation_unit
203%%
204
205identifier
206    : IDENTIFIER
207    | TYPE_NAME
208
209variable_identifier
210    : IDENTIFIER {
211        // The symbol table search was done in the lexical phase
212        const TVariable *variable = context->getNamedVariable(@1, $1.string, $1.symbol);
213
214        if (variable->getType().getQualifier() == EvqConst)
215        {
216            ConstantUnion* constArray = variable->getConstPointer();
217            TType t(variable->getType());
218            $$ = context->intermediate.addConstantUnion(constArray, t, @1);
219        }
220        else
221        {
222            $$ = context->intermediate.addSymbol(variable->getUniqueId(),
223                                                 variable->getName(),
224                                                 variable->getType(),
225                                                 @1);
226        }
227
228        // don't delete $1.string, it's used by error recovery, and the pool
229        // pop will reclaim the memory
230    }
231    ;
232
233primary_expression
234    : variable_identifier {
235        $$ = $1;
236    }
237    | INTCONSTANT {
238        ConstantUnion *unionArray = new ConstantUnion[1];
239        unionArray->setIConst($1.i);
240        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @1);
241    }
242    | UINTCONSTANT {
243        ConstantUnion *unionArray = new ConstantUnion[1];
244        unionArray->setUConst($1.u);
245        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtUInt, EbpUndefined, EvqConst), @1);
246    }
247    | FLOATCONSTANT {
248        ConstantUnion *unionArray = new ConstantUnion[1];
249        unionArray->setFConst($1.f);
250        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1);
251    }
252    | BOOLCONSTANT {
253        ConstantUnion *unionArray = new ConstantUnion[1];
254        unionArray->setBConst($1.b);
255        $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @1);
256    }
257    | LEFT_PAREN expression RIGHT_PAREN {
258        $$ = $2;
259    }
260    ;
261
262postfix_expression
263    : primary_expression {
264        $$ = $1;
265    }
266    | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET {
267        $$ = context->addIndexExpression($1, @2, $3);
268    }
269    | function_call {
270        $$ = $1;
271    }
272    | postfix_expression DOT identifier {
273        $$ = context->addFieldSelectionExpression($1, @2, *$3.string, @3);
274    }
275    | postfix_expression INC_OP {
276        if (context->lValueErrorCheck(@2, "++", $1))
277            context->recover();
278        $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, @2);
279        if ($$ == 0) {
280            context->unaryOpError(@2, "++", $1->getCompleteString());
281            context->recover();
282            $$ = $1;
283        }
284    }
285    | postfix_expression DEC_OP {
286        if (context->lValueErrorCheck(@2, "--", $1))
287            context->recover();
288        $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, @2);
289        if ($$ == 0) {
290            context->unaryOpError(@2, "--", $1->getCompleteString());
291            context->recover();
292            $$ = $1;
293        }
294    }
295    ;
296
297integer_expression
298    : expression {
299        if (context->integerErrorCheck($1, "[]"))
300            context->recover();
301        $$ = $1;
302    }
303    ;
304
305function_call
306    : function_call_or_method {
307        TFunction* fnCall = $1.function;
308        TOperator op = fnCall->getBuiltInOp();
309
310        if (op != EOpNull)
311        {
312            //
313            // Then this should be a constructor.
314            // Don't go through the symbol table for constructors.
315            // Their parameters will be verified algorithmically.
316            //
317            TType type(EbtVoid, EbpUndefined);  // use this to get the type back
318            if (context->constructorErrorCheck(@1, $1.intermNode, *fnCall, op, &type)) {
319                $$ = 0;
320            } else {
321                //
322                // It's a constructor, of type 'type'.
323                //
324                $$ = context->addConstructor($1.intermNode, &type, op, fnCall, @1);
325            }
326
327            if ($$ == 0) {
328                context->recover();
329                $$ = context->intermediate.setAggregateOperator(0, op, @1);
330            }
331            $$->setType(type);
332        } else {
333            //
334            // Not a constructor.  Find it in the symbol table.
335            //
336            const TFunction* fnCandidate;
337            bool builtIn;
338            fnCandidate = context->findFunction(@1, fnCall, context->shaderVersion, &builtIn);
339            if (fnCandidate) {
340                //
341                // A declared function.
342                //
343                if (builtIn && !fnCandidate->getExtension().empty() &&
344                    context->extensionErrorCheck(@1, fnCandidate->getExtension())) {
345                    context->recover();
346                }
347                op = fnCandidate->getBuiltInOp();
348                if (builtIn && op != EOpNull) {
349                    //
350                    // A function call mapped to a built-in operation.
351                    //
352                    if (fnCandidate->getParamCount() == 1) {
353                        //
354                        // Treat it like a built-in unary operator.
355                        //
356                        $$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1);
357                        if ($$ == 0)  {
358                            std::stringstream extraInfoStream;
359                            extraInfoStream << "built in unary operator function.  Type: " << static_cast<TIntermTyped*>($1.intermNode)->getCompleteString();
360                            std::string extraInfo = extraInfoStream.str();
361                            context->error($1.intermNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
362                            YYERROR;
363                        }
364                    } else {
365                        $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1);
366                    }
367                } else {
368                    // This is a real function call
369
370                    $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1);
371                    $$->setType(fnCandidate->getReturnType());
372
373                    // this is how we know whether the given function is a builtIn function or a user defined function
374                    // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
375                    // if builtIn == true, it's definitely a builtIn function with EOpNull
376                    if (!builtIn)
377                        $$->getAsAggregate()->setUserDefined();
378                    $$->getAsAggregate()->setName(fnCandidate->getMangledName());
379
380                    TQualifier qual;
381                    for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) {
382                        qual = fnCandidate->getParam(i).type->getQualifier();
383                        if (qual == EvqOut || qual == EvqInOut) {
384                            if (context->lValueErrorCheck($$->getLine(), "assign", (*($$->getAsAggregate()->getSequence()))[i]->getAsTyped())) {
385                                context->error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
386                                context->recover();
387                            }
388                        }
389                    }
390                }
391                $$->setType(fnCandidate->getReturnType());
392            } else {
393                // error message was put out by PaFindFunction()
394                // Put on a dummy node for error recovery
395                ConstantUnion *unionArray = new ConstantUnion[1];
396                unionArray->setFConst(0.0f);
397                $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1);
398                context->recover();
399            }
400        }
401        delete fnCall;
402    }
403    ;
404
405function_call_or_method
406    : function_call_generic {
407        $$ = $1;
408    }
409    | postfix_expression DOT function_call_generic {
410        context->error(@3, "methods are not supported", "");
411        context->recover();
412        $$ = $3;
413    }
414    ;
415
416function_call_generic
417    : function_call_header_with_parameters RIGHT_PAREN {
418        $$ = $1;
419    }
420    | function_call_header_no_parameters RIGHT_PAREN {
421        $$ = $1;
422    }
423    ;
424
425function_call_header_no_parameters
426    : function_call_header VOID_TYPE {
427        $$.function = $1;
428        $$.intermNode = 0;
429    }
430    | function_call_header {
431        $$.function = $1;
432        $$.intermNode = 0;
433    }
434    ;
435
436function_call_header_with_parameters
437    : function_call_header assignment_expression {
438        TParameter param = { 0, new TType($2->getType()) };
439        $1->addParameter(param);
440        $$.function = $1;
441        $$.intermNode = $2;
442    }
443    | function_call_header_with_parameters COMMA assignment_expression {
444        TParameter param = { 0, new TType($3->getType()) };
445        $1.function->addParameter(param);
446        $$.function = $1.function;
447        $$.intermNode = context->intermediate.growAggregate($1.intermNode, $3, @2);
448    }
449    ;
450
451function_call_header
452    : function_identifier LEFT_PAREN {
453        $$ = $1;
454    }
455    ;
456
457// Grammar Note:  Constructors look like functions, but are recognized as types.
458
459function_identifier
460    : type_specifier_nonarray {
461        $$ = context->addConstructorFunc($1);
462    }
463    | IDENTIFIER {
464        if (context->reservedErrorCheck(@1, *$1.string))
465            context->recover();
466        TType type(EbtVoid, EbpUndefined);
467        TFunction *function = new TFunction($1.string, type);
468        $$ = function;
469    }
470    ;
471
472unary_expression
473    : postfix_expression {
474        $$ = $1;
475    }
476    | INC_OP unary_expression {
477        if (context->lValueErrorCheck(@1, "++", $2))
478            context->recover();
479        $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, @1);
480        if ($$ == 0) {
481            context->unaryOpError(@1, "++", $2->getCompleteString());
482            context->recover();
483            $$ = $2;
484        }
485    }
486    | DEC_OP unary_expression {
487        if (context->lValueErrorCheck(@1, "--", $2))
488            context->recover();
489        $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, @1);
490        if ($$ == 0) {
491            context->unaryOpError(@1, "--", $2->getCompleteString());
492            context->recover();
493            $$ = $2;
494        }
495    }
496    | unary_operator unary_expression {
497        if ($1.op != EOpNull) {
498            $$ = context->intermediate.addUnaryMath($1.op, $2, @1);
499            if ($$ == 0) {
500                const char* errorOp = "";
501                switch($1.op) {
502                case EOpNegative:   errorOp = "-"; break;
503                case EOpLogicalNot: errorOp = "!"; break;
504                default: break;
505                }
506                context->unaryOpError(@1, errorOp, $2->getCompleteString());
507                context->recover();
508                $$ = $2;
509            }
510        } else
511            $$ = $2;
512    }
513    ;
514// Grammar Note:  No traditional style type casts.
515
516unary_operator
517    : PLUS  { $$.op = EOpNull; }
518    | DASH  { $$.op = EOpNegative; }
519    | BANG  { $$.op = EOpLogicalNot; }
520    ;
521// Grammar Note:  No '*' or '&' unary ops.  Pointers are not supported.
522
523multiplicative_expression
524    : unary_expression { $$ = $1; }
525    | multiplicative_expression STAR unary_expression {
526        $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, @2);
527        if ($$ == 0) {
528            context->binaryOpError(@2, "*", $1->getCompleteString(), $3->getCompleteString());
529            context->recover();
530            $$ = $1;
531        }
532    }
533    | multiplicative_expression SLASH unary_expression {
534        $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, @2);
535        if ($$ == 0) {
536            context->binaryOpError(@2, "/", $1->getCompleteString(), $3->getCompleteString());
537            context->recover();
538            $$ = $1;
539        }
540    }
541    ;
542
543additive_expression
544    : multiplicative_expression { $$ = $1; }
545    | additive_expression PLUS multiplicative_expression {
546        $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, @2);
547        if ($$ == 0) {
548            context->binaryOpError(@2, "+", $1->getCompleteString(), $3->getCompleteString());
549            context->recover();
550            $$ = $1;
551        }
552    }
553    | additive_expression DASH multiplicative_expression {
554        $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, @2);
555        if ($$ == 0) {
556            context->binaryOpError(@2, "-", $1->getCompleteString(), $3->getCompleteString());
557            context->recover();
558            $$ = $1;
559        }
560    }
561    ;
562
563shift_expression
564    : additive_expression { $$ = $1; }
565    ;
566
567relational_expression
568    : shift_expression { $$ = $1; }
569    | relational_expression LEFT_ANGLE shift_expression {
570        $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, @2);
571        if ($$ == 0) {
572            context->binaryOpError(@2, "<", $1->getCompleteString(), $3->getCompleteString());
573            context->recover();
574            ConstantUnion *unionArray = new ConstantUnion[1];
575            unionArray->setBConst(false);
576            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
577        }
578    }
579    | relational_expression RIGHT_ANGLE shift_expression  {
580        $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, @2);
581        if ($$ == 0) {
582            context->binaryOpError(@2, ">", $1->getCompleteString(), $3->getCompleteString());
583            context->recover();
584            ConstantUnion *unionArray = new ConstantUnion[1];
585            unionArray->setBConst(false);
586            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
587        }
588    }
589    | relational_expression LE_OP shift_expression  {
590        $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, @2);
591        if ($$ == 0) {
592            context->binaryOpError(@2, "<=", $1->getCompleteString(), $3->getCompleteString());
593            context->recover();
594            ConstantUnion *unionArray = new ConstantUnion[1];
595            unionArray->setBConst(false);
596            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
597        }
598    }
599    | relational_expression GE_OP shift_expression  {
600        $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, @2);
601        if ($$ == 0) {
602            context->binaryOpError(@2, ">=", $1->getCompleteString(), $3->getCompleteString());
603            context->recover();
604            ConstantUnion *unionArray = new ConstantUnion[1];
605            unionArray->setBConst(false);
606            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
607        }
608    }
609    ;
610
611equality_expression
612    : relational_expression { $$ = $1; }
613    | equality_expression EQ_OP relational_expression  {
614        $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, @2);
615        if ($$ == 0) {
616            context->binaryOpError(@2, "==", $1->getCompleteString(), $3->getCompleteString());
617            context->recover();
618            ConstantUnion *unionArray = new ConstantUnion[1];
619            unionArray->setBConst(false);
620            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
621        }
622    }
623    | equality_expression NE_OP relational_expression {
624        $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, @2);
625        if ($$ == 0) {
626            context->binaryOpError(@2, "!=", $1->getCompleteString(), $3->getCompleteString());
627            context->recover();
628            ConstantUnion *unionArray = new ConstantUnion[1];
629            unionArray->setBConst(false);
630            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
631        }
632    }
633    ;
634
635and_expression
636    : equality_expression { $$ = $1; }
637    ;
638
639exclusive_or_expression
640    : and_expression { $$ = $1; }
641    ;
642
643inclusive_or_expression
644    : exclusive_or_expression { $$ = $1; }
645    ;
646
647logical_and_expression
648    : inclusive_or_expression { $$ = $1; }
649    | logical_and_expression AND_OP inclusive_or_expression {
650        $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, @2);
651        if ($$ == 0) {
652            context->binaryOpError(@2, "&&", $1->getCompleteString(), $3->getCompleteString());
653            context->recover();
654            ConstantUnion *unionArray = new ConstantUnion[1];
655            unionArray->setBConst(false);
656            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
657        }
658    }
659    ;
660
661logical_xor_expression
662    : logical_and_expression { $$ = $1; }
663    | logical_xor_expression XOR_OP logical_and_expression  {
664        $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, @2);
665        if ($$ == 0) {
666            context->binaryOpError(@2, "^^", $1->getCompleteString(), $3->getCompleteString());
667            context->recover();
668            ConstantUnion *unionArray = new ConstantUnion[1];
669            unionArray->setBConst(false);
670            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
671        }
672    }
673    ;
674
675logical_or_expression
676    : logical_xor_expression { $$ = $1; }
677    | logical_or_expression OR_OP logical_xor_expression  {
678        $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, @2);
679        if ($$ == 0) {
680            context->binaryOpError(@2, "||", $1->getCompleteString(), $3->getCompleteString());
681            context->recover();
682            ConstantUnion *unionArray = new ConstantUnion[1];
683            unionArray->setBConst(false);
684            $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
685        }
686    }
687    ;
688
689conditional_expression
690    : logical_or_expression { $$ = $1; }
691    | logical_or_expression QUESTION expression COLON assignment_expression {
692       if (context->boolErrorCheck(@2, $1))
693            context->recover();
694
695        $$ = context->intermediate.addSelection($1, $3, $5, @2);
696        if ($3->getType() != $5->getType())
697            $$ = 0;
698
699        if ($$ == 0) {
700            context->binaryOpError(@2, ":", $3->getCompleteString(), $5->getCompleteString());
701            context->recover();
702            $$ = $5;
703        }
704    }
705    ;
706
707assignment_expression
708    : conditional_expression { $$ = $1; }
709    | unary_expression assignment_operator assignment_expression {
710        if (context->lValueErrorCheck(@2, "assign", $1))
711            context->recover();
712        $$ = context->intermediate.addAssign($2.op, $1, $3, @2);
713        if ($$ == 0) {
714            context->assignError(@2, "assign", $1->getCompleteString(), $3->getCompleteString());
715            context->recover();
716            $$ = $1;
717        }
718    }
719    ;
720
721assignment_operator
722    : EQUAL        { $$.op = EOpAssign; }
723    | MUL_ASSIGN   { $$.op = EOpMulAssign; }
724    | DIV_ASSIGN   { $$.op = EOpDivAssign; }
725    | ADD_ASSIGN   { $$.op = EOpAddAssign; }
726    | SUB_ASSIGN   { $$.op = EOpSubAssign; }
727    ;
728
729expression
730    : assignment_expression {
731        $$ = $1;
732    }
733    | expression COMMA assignment_expression {
734        $$ = context->intermediate.addComma($1, $3, @2);
735        if ($$ == 0) {
736            context->binaryOpError(@2, ",", $1->getCompleteString(), $3->getCompleteString());
737            context->recover();
738            $$ = $3;
739        }
740    }
741    ;
742
743constant_expression
744    : conditional_expression {
745        if (context->constErrorCheck($1))
746            context->recover();
747        $$ = $1;
748    }
749    ;
750
751enter_struct
752    : IDENTIFIER LEFT_BRACE {
753        if (context->enterStructDeclaration(@1, *$1.string))
754            context->recover();
755        $$ = $1;
756    }
757    ;
758
759declaration
760    : function_prototype SEMICOLON   {
761        TFunction &function = *($1.function);
762
763        TIntermAggregate *prototype = new TIntermAggregate;
764        prototype->setType(function.getReturnType());
765        prototype->setName(function.getName());
766
767        for (size_t i = 0; i < function.getParamCount(); i++)
768        {
769            const TParameter &param = function.getParam(i);
770            if (param.name != 0)
771            {
772                TVariable variable(param.name, *param.type);
773
774                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), @1), @1);
775            }
776            else
777            {
778                prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, @1), @1);
779            }
780        }
781
782        prototype->setOp(EOpPrototype);
783        $$ = prototype;
784
785        context->symbolTable.pop();
786    }
787    | init_declarator_list SEMICOLON {
788        TIntermAggregate *aggNode = $1.intermAggregate;
789        if (aggNode && aggNode->getOp() == EOpNull)
790            aggNode->setOp(EOpDeclaration);
791        $$ = aggNode;
792    }
793    | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
794        if (($2 == EbpHigh) && (context->shaderType == GL_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) {
795            context->error(@1, "precision is not supported in fragment shader", "highp");
796            context->recover();
797        }
798        if (!context->symbolTable.setDefaultPrecision( $3, $2 )) {
799            context->error(@1, "illegal type argument for default precision qualifier", getBasicString($3.type));
800            context->recover();
801        }
802        $$ = 0;
803    }
804    | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE SEMICOLON {
805        ES3_ONLY(getQualifierString($1.qualifier), @1, "interface blocks");
806        $$ = context->addInterfaceBlock($1, @2, *$2.string, $3, NULL, @$, NULL, @$);
807    }
808    | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON {
809        ES3_ONLY(getQualifierString($1.qualifier), @1, "interface blocks");
810        $$ = context->addInterfaceBlock($1, @2, *$2.string, $3, $5.string, @5, NULL, @$);
811    }
812    | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET SEMICOLON {
813        ES3_ONLY(getQualifierString($1.qualifier), @1, "interface blocks");
814        $$ = context->addInterfaceBlock($1, @2, *$2.string, $3, $5.string, @5, $7, @6);
815    }
816    | type_qualifier SEMICOLON {
817        context->parseGlobalLayoutQualifier($1);
818        $$ = 0;
819    }
820    ;
821
822function_prototype
823    : function_declarator RIGHT_PAREN  {
824        //
825        // Multiple declarations of the same function are allowed.
826        //
827        // If this is a definition, the definition production code will check for redefinitions
828        // (we don't know at this point if it's a definition or not).
829        //
830        // Redeclarations are allowed.  But, return types and parameter qualifiers must match.
831        //
832        TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find($1->getMangledName(), context->shaderVersion));
833        if (prevDec) {
834            if (prevDec->getReturnType() != $1->getReturnType()) {
835                context->error(@2, "overloaded functions must have the same return type", $1->getReturnType().getBasicString());
836                context->recover();
837            }
838            for (size_t i = 0; i < prevDec->getParamCount(); ++i) {
839                if (prevDec->getParam(i).type->getQualifier() != $1->getParam(i).type->getQualifier()) {
840                    context->error(@2, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString());
841                    context->recover();
842                }
843            }
844        }
845
846        //
847        // Check for previously declared variables using the same name.
848        //
849        TSymbol *prevSym = context->symbolTable.find($1->getName(), context->shaderVersion);
850        if (prevSym)
851        {
852            if (!prevSym->isFunction())
853            {
854                context->error(@2, "redefinition", $1->getName().c_str(), "function");
855                context->recover();
856            }
857        }
858        else
859        {
860            // Insert the unmangled name to detect potential future redefinition as a variable.
861            TFunction *function = new TFunction(NewPoolTString($1->getName().c_str()), $1->getReturnType());
862            context->symbolTable.getOuterLevel()->insert(function);
863        }
864
865        //
866        // If this is a redeclaration, it could also be a definition,
867        // in which case, we want to use the variable names from this one, and not the one that's
868        // being redeclared.  So, pass back up this declaration, not the one in the symbol table.
869        //
870        $$.function = $1;
871
872        // We're at the inner scope level of the function's arguments and body statement.
873        // Add the function prototype to the surrounding scope instead.
874        context->symbolTable.getOuterLevel()->insert($$.function);
875    }
876    ;
877
878function_declarator
879    : function_header {
880        $$ = $1;
881    }
882    | function_header_with_parameters {
883        $$ = $1;
884    }
885    ;
886
887
888function_header_with_parameters
889    : function_header parameter_declaration {
890        // Add the parameter
891        $$ = $1;
892        if ($2.param.type->getBasicType() != EbtVoid)
893            $1->addParameter($2.param);
894        else
895            delete $2.param.type;
896    }
897    | function_header_with_parameters COMMA parameter_declaration {
898        //
899        // Only first parameter of one-parameter functions can be void
900        // The check for named parameters not being void is done in parameter_declarator
901        //
902        if ($3.param.type->getBasicType() == EbtVoid) {
903            //
904            // This parameter > first is void
905            //
906            context->error(@2, "cannot be an argument type except for '(void)'", "void");
907            context->recover();
908            delete $3.param.type;
909        } else {
910            // Add the parameter
911            $$ = $1;
912            $1->addParameter($3.param);
913        }
914    }
915    ;
916
917function_header
918    : fully_specified_type IDENTIFIER LEFT_PAREN {
919        if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) {
920            context->error(@2, "no qualifiers allowed for function return", getQualifierString($1.qualifier));
921            context->recover();
922        }
923        // make sure a sampler is not involved as well...
924        if (context->structQualifierErrorCheck(@2, $1))
925            context->recover();
926
927        // Add the function as a prototype after parsing it (we do not support recursion)
928        TFunction *function;
929        TType type($1);
930        function = new TFunction($2.string, type);
931        $$ = function;
932
933        context->symbolTable.push();
934    }
935    ;
936
937parameter_declarator
938    // Type + name
939    : type_specifier identifier {
940        if ($1.type == EbtVoid) {
941            context->error(@2, "illegal use of type 'void'", $2.string->c_str());
942            context->recover();
943        }
944        if (context->reservedErrorCheck(@2, *$2.string))
945            context->recover();
946        TParameter param = {$2.string, new TType($1)};
947        $$.param = param;
948    }
949    | type_specifier identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
950        // Check that we can make an array out of this type
951        if (context->arrayTypeErrorCheck(@3, $1))
952            context->recover();
953
954        if (context->reservedErrorCheck(@2, *$2.string))
955            context->recover();
956
957        int size;
958        if (context->arraySizeErrorCheck(@3, $4, size))
959            context->recover();
960        $1.setArray(true, size);
961
962        TType* type = new TType($1);
963        TParameter param = { $2.string, type };
964        $$.param = param;
965    }
966    ;
967
968parameter_declaration
969    //
970    // The only parameter qualifier a parameter can have are
971    // IN_QUAL, OUT_QUAL, INOUT_QUAL, or CONST.
972    //
973
974    //
975    // Type + name
976    //
977    : parameter_type_qualifier parameter_qualifier parameter_declarator {
978        $$ = $3;
979        if (context->paramErrorCheck(@3, $1, $2, $$.param.type))
980            context->recover();
981    }
982    | parameter_qualifier parameter_declarator {
983        $$ = $2;
984        if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type))
985            context->recover();
986        if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type))
987            context->recover();
988    }
989    //
990    // Only type
991    //
992    | parameter_type_qualifier parameter_qualifier parameter_type_specifier {
993        $$ = $3;
994        if (context->paramErrorCheck(@3, $1, $2, $$.param.type))
995            context->recover();
996    }
997    | parameter_qualifier parameter_type_specifier {
998        $$ = $2;
999        if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type))
1000            context->recover();
1001        if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type))
1002            context->recover();
1003    }
1004    ;
1005
1006parameter_qualifier
1007    : /* empty */ {
1008        $$ = EvqIn;
1009    }
1010    | IN_QUAL {
1011        $$ = EvqIn;
1012    }
1013    | OUT_QUAL {
1014        $$ = EvqOut;
1015    }
1016    | INOUT_QUAL {
1017        $$ = EvqInOut;
1018    }
1019    ;
1020
1021parameter_type_specifier
1022    : type_specifier {
1023        TParameter param = { 0, new TType($1) };
1024        $$.param = param;
1025    }
1026    ;
1027
1028init_declarator_list
1029    : single_declaration {
1030        $$ = $1;
1031    }
1032    | init_declarator_list COMMA identifier {
1033        $$ = $1;
1034        $$.intermAggregate = context->parseDeclarator($$.type, $1.intermAggregate, $3.symbol, @3, *$3.string);
1035    }
1036    | init_declarator_list COMMA identifier LEFT_BRACKET RIGHT_BRACKET {
1037        $$ = $1;
1038        context->parseArrayDeclarator($$.type, @3, *$3.string, @4, NULL, NULL);
1039    }
1040    | init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
1041        $$ = $1;
1042        $$.intermAggregate = context->parseArrayDeclarator($$.type, @3, *$3.string, @4, $1.intermNode, $5);
1043    }
1044    | init_declarator_list COMMA identifier EQUAL initializer {
1045        $$ = $1;
1046        $$.intermAggregate = context->parseInitDeclarator($$.type, $1.intermAggregate, @3, *$3.string, @4, $5);
1047    }
1048    ;
1049
1050single_declaration
1051    : fully_specified_type {
1052        $$.type = $1;
1053        $$.intermAggregate = context->parseSingleDeclaration($$.type, @1, "");
1054    }
1055    | fully_specified_type identifier {
1056        $$.type = $1;
1057        $$.intermAggregate = context->parseSingleDeclaration($$.type, @2, *$2.string);
1058    }
1059    | fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET {
1060        context->error(@2, "unsized array declarations not supported", $2.string->c_str());
1061        context->recover();
1062
1063        $$.type = $1;
1064        $$.intermAggregate = context->parseSingleDeclaration($$.type, @2, *$2.string);
1065    }
1066    | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
1067        $$.type = $1;
1068        $$.intermAggregate = context->parseSingleArrayDeclaration($$.type, @2, *$2.string, @3, $4);
1069    }
1070    | fully_specified_type identifier EQUAL initializer {
1071        $$.type = $1;
1072        $$.intermAggregate = context->parseSingleInitDeclaration($$.type, @2, *$2.string, @3, $4);
1073    }
1074    | INVARIANT IDENTIFIER {
1075        // $$.type is not used in invariant declarations.
1076        $$.intermAggregate = context->parseInvariantDeclaration(@1, @2, $2.string, $2.symbol);
1077    }
1078    ;
1079
1080fully_specified_type
1081    : type_specifier {
1082        $$ = $1;
1083
1084        if ($1.array) {
1085            context->error(@1, "not supported", "first-class array");
1086            context->recover();
1087            $1.setArray(false);
1088        }
1089    }
1090    | type_qualifier type_specifier  {
1091        $$ = context->addFullySpecifiedType($1.qualifier, $1.layoutQualifier, $2);
1092    }
1093    ;
1094
1095interpolation_qualifier
1096    : SMOOTH {
1097        $$.qualifier = EvqSmooth;
1098    }
1099    | FLAT {
1100        $$.qualifier = EvqFlat;
1101    }
1102    ;
1103
1104parameter_type_qualifier
1105    : CONST_QUAL {
1106        $$ = EvqConst;
1107    }
1108    ;
1109
1110type_qualifier
1111    : ATTRIBUTE {
1112        VERTEX_ONLY("attribute", @1);
1113        ES2_ONLY("attribute", @1);
1114        if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "attribute"))
1115            context->recover();
1116        $$.setBasic(EbtVoid, EvqAttribute, @1);
1117    }
1118    | VARYING {
1119        ES2_ONLY("varying", @1);
1120        if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "varying"))
1121            context->recover();
1122        if (context->shaderType == GL_VERTEX_SHADER)
1123            $$.setBasic(EbtVoid, EvqVaryingOut, @1);
1124        else
1125            $$.setBasic(EbtVoid, EvqVaryingIn, @1);
1126    }
1127    | INVARIANT VARYING {
1128        ES2_ONLY("varying", @1);
1129        if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying"))
1130            context->recover();
1131        if (context->shaderType == GL_VERTEX_SHADER)
1132            $$.setBasic(EbtVoid, EvqInvariantVaryingOut, @1);
1133        else
1134            $$.setBasic(EbtVoid, EvqInvariantVaryingIn, @1);
1135    }
1136    | storage_qualifier {
1137        if ($1.qualifier != EvqConst && !context->symbolTable.atGlobalLevel()) {
1138            context->error(@1, "Local variables can only use the const storage qualifier.", getQualifierString($1.qualifier));
1139            context->recover();
1140        } else {
1141            $$.setBasic(EbtVoid, $1.qualifier, @1);
1142        }
1143    }
1144    | interpolation_qualifier storage_qualifier {
1145        $$ = context->joinInterpolationQualifiers(@1, $1.qualifier, @2, $2.qualifier);
1146    }
1147    | interpolation_qualifier {
1148        context->error(@1, "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier", getInterpolationString($1.qualifier));
1149        context->recover();
1150
1151        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1152        $$.setBasic(EbtVoid, qual, @1);
1153    }
1154    | layout_qualifier {
1155        $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1156        $$.layoutQualifier = $1;
1157    }
1158    | layout_qualifier storage_qualifier {
1159        $$.setBasic(EbtVoid, $2.qualifier, @2);
1160        $$.layoutQualifier = $1;
1161    }
1162    ;
1163
1164storage_qualifier
1165    : CONST_QUAL {
1166        $$.qualifier = EvqConst;
1167    }
1168    | IN_QUAL {
1169        ES3_ONLY("in", @1, "storage qualifier");
1170        $$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentIn : EvqVertexIn;
1171    }
1172    | OUT_QUAL {
1173        ES3_ONLY("out", @1, "storage qualifier");
1174        $$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqVertexOut;
1175    }
1176    | CENTROID IN_QUAL {
1177        ES3_ONLY("centroid in", @1, "storage qualifier");
1178        if (context->shaderType == GL_VERTEX_SHADER)
1179        {
1180            context->error(@1, "invalid storage qualifier", "it is an error to use 'centroid in' in the vertex shader");
1181            context->recover();
1182        }
1183        $$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqCentroidIn : EvqVertexIn;
1184    }
1185    | CENTROID OUT_QUAL {
1186        ES3_ONLY("centroid out", @1, "storage qualifier");
1187        if (context->shaderType == GL_FRAGMENT_SHADER)
1188        {
1189            context->error(@1, "invalid storage qualifier", "it is an error to use 'centroid out' in the fragment shader");
1190            context->recover();
1191        }
1192        $$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqCentroidOut;
1193    }
1194    | UNIFORM {
1195        if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "uniform"))
1196            context->recover();
1197        $$.qualifier = EvqUniform;
1198    }
1199    ;
1200
1201type_specifier
1202    : type_specifier_no_prec {
1203        $$ = $1;
1204
1205        if ($$.precision == EbpUndefined) {
1206            $$.precision = context->symbolTable.getDefaultPrecision($1.type);
1207            if (context->precisionErrorCheck(@1, $$.precision, $1.type)) {
1208                context->recover();
1209            }
1210        }
1211    }
1212    | precision_qualifier type_specifier_no_prec {
1213        $$ = $2;
1214        $$.precision = $1;
1215
1216        if (!SupportsPrecision($2.type)) {
1217            context->error(@1, "illegal type for precision qualifier", getBasicString($2.type));
1218            context->recover();
1219        }
1220    }
1221    ;
1222
1223precision_qualifier
1224    : HIGH_PRECISION {
1225        $$ = EbpHigh;
1226    }
1227    | MEDIUM_PRECISION {
1228        $$ = EbpMedium;
1229    }
1230    | LOW_PRECISION  {
1231        $$ = EbpLow;
1232    }
1233    ;
1234
1235layout_qualifier
1236    : LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN {
1237        ES3_ONLY("layout", @1, "qualifier");
1238        $$ = $3;
1239    }
1240    ;
1241
1242layout_qualifier_id_list
1243    : layout_qualifier_id {
1244        $$ = $1;
1245    }
1246    | layout_qualifier_id_list COMMA layout_qualifier_id {
1247        $$ = context->joinLayoutQualifiers($1, $3);
1248    }
1249    ;
1250
1251layout_qualifier_id
1252    : IDENTIFIER {
1253        $$ = context->parseLayoutQualifier(*$1.string, @1);
1254    }
1255    | IDENTIFIER EQUAL INTCONSTANT {
1256        $$ = context->parseLayoutQualifier(*$1.string, @1, *$3.string, $3.i, @3);
1257    }
1258    | IDENTIFIER EQUAL UINTCONSTANT {
1259        $$ = context->parseLayoutQualifier(*$1.string, @1, *$3.string, $3.i, @3);
1260    }
1261    ;
1262
1263type_specifier_no_prec
1264    : type_specifier_nonarray {
1265        $$ = $1;
1266    }
1267    | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET {
1268        $$ = $1;
1269
1270        if (context->arrayTypeErrorCheck(@2, $1))
1271            context->recover();
1272        else {
1273            int size;
1274            if (context->arraySizeErrorCheck(@2, $3, size))
1275                context->recover();
1276            $$.setArray(true, size);
1277        }
1278    }
1279    ;
1280
1281type_specifier_nonarray
1282    : VOID_TYPE {
1283        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1284        $$.setBasic(EbtVoid, qual, @1);
1285    }
1286    | FLOAT_TYPE {
1287        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1288        $$.setBasic(EbtFloat, qual, @1);
1289    }
1290    | INT_TYPE {
1291        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1292        $$.setBasic(EbtInt, qual, @1);
1293    }
1294    | UINT_TYPE {
1295        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1296        $$.setBasic(EbtUInt, qual, @1);
1297    }
1298    | BOOL_TYPE {
1299        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1300        $$.setBasic(EbtBool, qual, @1);
1301    }
1302    | VEC2 {
1303        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1304        $$.setBasic(EbtFloat, qual, @1);
1305        $$.setAggregate(2);
1306    }
1307    | VEC3 {
1308        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1309        $$.setBasic(EbtFloat, qual, @1);
1310        $$.setAggregate(3);
1311    }
1312    | VEC4 {
1313        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1314        $$.setBasic(EbtFloat, qual, @1);
1315        $$.setAggregate(4);
1316    }
1317    | BVEC2 {
1318        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1319        $$.setBasic(EbtBool, qual, @1);
1320        $$.setAggregate(2);
1321    }
1322    | BVEC3 {
1323        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1324        $$.setBasic(EbtBool, qual, @1);
1325        $$.setAggregate(3);
1326    }
1327    | BVEC4 {
1328        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1329        $$.setBasic(EbtBool, qual, @1);
1330        $$.setAggregate(4);
1331    }
1332    | IVEC2 {
1333        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1334        $$.setBasic(EbtInt, qual, @1);
1335        $$.setAggregate(2);
1336    }
1337    | IVEC3 {
1338        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1339        $$.setBasic(EbtInt, qual, @1);
1340        $$.setAggregate(3);
1341    }
1342    | IVEC4 {
1343        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1344        $$.setBasic(EbtInt, qual, @1);
1345        $$.setAggregate(4);
1346    }
1347    | UVEC2 {
1348        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1349        $$.setBasic(EbtUInt, qual, @1);
1350        $$.setAggregate(2);
1351    }
1352    | UVEC3 {
1353        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1354        $$.setBasic(EbtUInt, qual, @1);
1355        $$.setAggregate(3);
1356    }
1357    | UVEC4 {
1358        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1359        $$.setBasic(EbtUInt, qual, @1);
1360        $$.setAggregate(4);
1361    }
1362    | MATRIX2 {
1363        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1364        $$.setBasic(EbtFloat, qual, @1);
1365        $$.setMatrix(2, 2);
1366    }
1367    | MATRIX3 {
1368        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1369        $$.setBasic(EbtFloat, qual, @1);
1370        $$.setMatrix(3, 3);
1371    }
1372    | MATRIX4 {
1373        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1374        $$.setBasic(EbtFloat, qual, @1);
1375        $$.setMatrix(4, 4);
1376    }
1377    | MATRIX2x3 {
1378        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1379        $$.setBasic(EbtFloat, qual, @1);
1380        $$.setMatrix(2, 3);
1381    }
1382    | MATRIX3x2 {
1383        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1384        $$.setBasic(EbtFloat, qual, @1);
1385        $$.setMatrix(3, 2);
1386    }
1387    | MATRIX2x4 {
1388        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1389        $$.setBasic(EbtFloat, qual, @1);
1390        $$.setMatrix(2, 4);
1391    }
1392    | MATRIX4x2 {
1393        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1394        $$.setBasic(EbtFloat, qual, @1);
1395        $$.setMatrix(4, 2);
1396    }
1397    | MATRIX3x4 {
1398        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1399        $$.setBasic(EbtFloat, qual, @1);
1400        $$.setMatrix(3, 4);
1401    }
1402    | MATRIX4x3 {
1403        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1404        $$.setBasic(EbtFloat, qual, @1);
1405        $$.setMatrix(4, 3);
1406    }
1407    | SAMPLER2D {
1408        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1409        $$.setBasic(EbtSampler2D, qual, @1);
1410    }
1411    | SAMPLER3D {
1412        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1413        $$.setBasic(EbtSampler3D, qual, @1);
1414    }
1415    | SAMPLERCUBE {
1416        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1417        $$.setBasic(EbtSamplerCube, qual, @1);
1418    }
1419    | SAMPLER2DARRAY {
1420        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1421        $$.setBasic(EbtSampler2DArray, qual, @1);
1422    }
1423    | ISAMPLER2D {
1424        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1425        $$.setBasic(EbtISampler2D, qual, @1);
1426    }
1427    | ISAMPLER3D {
1428        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1429        $$.setBasic(EbtISampler3D, qual, @1);
1430    }
1431    | ISAMPLERCUBE {
1432        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1433        $$.setBasic(EbtISamplerCube, qual, @1);
1434    }
1435    | ISAMPLER2DARRAY {
1436        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1437        $$.setBasic(EbtISampler2DArray, qual, @1);
1438    }
1439    | USAMPLER2D {
1440        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1441        $$.setBasic(EbtUSampler2D, qual, @1);
1442    }
1443    | USAMPLER3D {
1444        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1445        $$.setBasic(EbtUSampler3D, qual, @1);
1446    }
1447    | USAMPLERCUBE {
1448        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1449        $$.setBasic(EbtUSamplerCube, qual, @1);
1450    }
1451    | USAMPLER2DARRAY {
1452        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1453        $$.setBasic(EbtUSampler2DArray, qual, @1);
1454    }
1455    | SAMPLER2DSHADOW {
1456        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1457        $$.setBasic(EbtSampler2DShadow, qual, @1);
1458    }
1459    | SAMPLERCUBESHADOW {
1460        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1461        $$.setBasic(EbtSamplerCubeShadow, qual, @1);
1462    }
1463    | SAMPLER2DARRAYSHADOW {
1464        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1465        $$.setBasic(EbtSampler2DArrayShadow, qual, @1);
1466    }
1467    | SAMPLER_EXTERNAL_OES {
1468        if (!context->supportsExtension("GL_OES_EGL_image_external")) {
1469            context->error(@1, "unsupported type", "samplerExternalOES");
1470            context->recover();
1471        }
1472        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1473        $$.setBasic(EbtSamplerExternalOES, qual, @1);
1474    }
1475    | SAMPLER2DRECT {
1476        if (!context->supportsExtension("GL_ARB_texture_rectangle")) {
1477            context->error(@1, "unsupported type", "sampler2DRect");
1478            context->recover();
1479        }
1480        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1481        $$.setBasic(EbtSampler2DRect, qual, @1);
1482    }
1483    | struct_specifier {
1484        $$ = $1;
1485        $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1486    }
1487    | TYPE_NAME {
1488        //
1489        // This is for user defined type names.  The lexical phase looked up the
1490        // type.
1491        //
1492        TType& structure = static_cast<TVariable*>($1.symbol)->getType();
1493        TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1494        $$.setBasic(EbtStruct, qual, @1);
1495        $$.userDef = &structure;
1496    }
1497    ;
1498
1499struct_specifier
1500    : STRUCT identifier LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
1501        $$ = context->addStructure(@1, @2, $2.string, $5);
1502    }
1503    | STRUCT LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
1504        $$ = context->addStructure(@1, @$, NewPoolTString(""), $4);
1505    }
1506    ;
1507
1508struct_declaration_list
1509    : struct_declaration {
1510        $$ = $1;
1511    }
1512    | struct_declaration_list struct_declaration {
1513        $$ = $1;
1514        for (size_t i = 0; i < $2->size(); ++i) {
1515            TField* field = (*$2)[i];
1516            for (size_t j = 0; j < $$->size(); ++j) {
1517                if ((*$$)[j]->name() == field->name()) {
1518                    context->error(@2, "duplicate field name in structure:", "struct", field->name().c_str());
1519                    context->recover();
1520                }
1521            }
1522            $$->push_back(field);
1523        }
1524    }
1525    ;
1526
1527struct_declaration
1528    : type_specifier struct_declarator_list SEMICOLON {
1529        $$ = context->addStructDeclaratorList($1, $2);
1530    }
1531    | type_qualifier type_specifier struct_declarator_list SEMICOLON {
1532        // ES3 Only, but errors should be handled elsewhere
1533        $2.qualifier = $1.qualifier;
1534        $2.layoutQualifier = $1.layoutQualifier;
1535        $$ = context->addStructDeclaratorList($2, $3);
1536    }
1537    ;
1538
1539struct_declarator_list
1540    : struct_declarator {
1541        $$ = NewPoolTFieldList();
1542        $$->push_back($1);
1543    }
1544    | struct_declarator_list COMMA struct_declarator {
1545        $$->push_back($3);
1546    }
1547    ;
1548
1549struct_declarator
1550    : identifier {
1551        if (context->reservedErrorCheck(@1, *$1.string))
1552            context->recover();
1553
1554        TType* type = new TType(EbtVoid, EbpUndefined);
1555        $$ = new TField(type, $1.string, @1);
1556    }
1557    | identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
1558        if (context->reservedErrorCheck(@1, *$1.string))
1559            context->recover();
1560
1561        TType* type = new TType(EbtVoid, EbpUndefined);
1562        int size;
1563        if (context->arraySizeErrorCheck(@3, $3, size))
1564            context->recover();
1565        type->setArraySize(size);
1566
1567        $$ = new TField(type, $1.string, @1);
1568    }
1569    ;
1570
1571initializer
1572    : assignment_expression { $$ = $1; }
1573    ;
1574
1575declaration_statement
1576    : declaration { $$ = $1; }
1577    ;
1578
1579statement
1580    : compound_statement  { $$ = $1; }
1581    | simple_statement    { $$ = $1; }
1582    ;
1583
1584// Grammar Note:  No labeled statements; 'goto' is not supported.
1585
1586simple_statement
1587    : declaration_statement { $$ = $1; }
1588    | expression_statement  { $$ = $1; }
1589    | selection_statement   { $$ = $1; }
1590    | iteration_statement   { $$ = $1; }
1591    | jump_statement        { $$ = $1; }
1592    ;
1593
1594compound_statement
1595    : LEFT_BRACE RIGHT_BRACE { $$ = 0; }
1596    | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE {
1597        if ($3 != 0) {
1598            $3->setOp(EOpSequence);
1599            $3->setLine(@$);
1600        }
1601        $$ = $3;
1602    }
1603    ;
1604
1605statement_no_new_scope
1606    : compound_statement_no_new_scope { $$ = $1; }
1607    | simple_statement                { $$ = $1; }
1608    ;
1609
1610statement_with_scope
1611    : { context->symbolTable.push(); } compound_statement_no_new_scope { context->symbolTable.pop(); $$ = $2; }
1612    | { context->symbolTable.push(); } simple_statement                { context->symbolTable.pop(); $$ = $2; }
1613    ;
1614
1615compound_statement_no_new_scope
1616    // Statement that doesn't create a new scope, for selection_statement, iteration_statement
1617    : LEFT_BRACE RIGHT_BRACE {
1618        $$ = 0;
1619    }
1620    | LEFT_BRACE statement_list RIGHT_BRACE {
1621        if ($2) {
1622            $2->setOp(EOpSequence);
1623            $2->setLine(@$);
1624        }
1625        $$ = $2;
1626    }
1627    ;
1628
1629statement_list
1630    : statement {
1631        $$ = context->intermediate.makeAggregate($1, @$);
1632    }
1633    | statement_list statement {
1634        $$ = context->intermediate.growAggregate($1, $2, @$);
1635    }
1636    ;
1637
1638expression_statement
1639    : SEMICOLON  { $$ = 0; }
1640    | expression SEMICOLON  { $$ = static_cast<TIntermNode*>($1); }
1641    ;
1642
1643selection_statement
1644    : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
1645        if (context->boolErrorCheck(@1, $3))
1646            context->recover();
1647        $$ = context->intermediate.addSelection($3, $5, @1);
1648    }
1649    ;
1650
1651selection_rest_statement
1652    : statement_with_scope ELSE statement_with_scope {
1653        $$.node1 = $1;
1654        $$.node2 = $3;
1655    }
1656    | statement_with_scope {
1657        $$.node1 = $1;
1658        $$.node2 = 0;
1659    }
1660    ;
1661
1662// Grammar Note:  No 'switch'.  Switch statements not supported.
1663
1664condition
1665    // In 1996 c++ draft, conditions can include single declarations
1666    : expression {
1667        $$ = $1;
1668        if (context->boolErrorCheck($1->getLine(), $1))
1669            context->recover();
1670    }
1671    | fully_specified_type identifier EQUAL initializer {
1672        TIntermNode* intermNode;
1673        if (context->structQualifierErrorCheck(@2, $1))
1674            context->recover();
1675        if (context->boolErrorCheck(@2, $1))
1676            context->recover();
1677
1678        if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode))
1679            $$ = $4;
1680        else {
1681            context->recover();
1682            $$ = 0;
1683        }
1684    }
1685    ;
1686
1687iteration_statement
1688    : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope {
1689        context->symbolTable.pop();
1690        $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, @1);
1691        --context->loopNestingLevel;
1692    }
1693    | DO { ++context->loopNestingLevel; } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
1694        if (context->boolErrorCheck(@8, $6))
1695            context->recover();
1696
1697        $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, @4);
1698        --context->loopNestingLevel;
1699    }
1700    | FOR LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
1701        context->symbolTable.pop();
1702        $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), $7, @1);
1703        --context->loopNestingLevel;
1704    }
1705    ;
1706
1707for_init_statement
1708    : expression_statement {
1709        $$ = $1;
1710    }
1711    | declaration_statement {
1712        $$ = $1;
1713    }
1714    ;
1715
1716conditionopt
1717    : condition {
1718        $$ = $1;
1719    }
1720    | /* May be null */ {
1721        $$ = 0;
1722    }
1723    ;
1724
1725for_rest_statement
1726    : conditionopt SEMICOLON {
1727        $$.node1 = $1;
1728        $$.node2 = 0;
1729    }
1730    | conditionopt SEMICOLON expression  {
1731        $$.node1 = $1;
1732        $$.node2 = $3;
1733    }
1734    ;
1735
1736jump_statement
1737    : CONTINUE SEMICOLON {
1738        if (context->loopNestingLevel <= 0) {
1739            context->error(@1, "continue statement only allowed in loops", "");
1740            context->recover();
1741        }
1742        $$ = context->intermediate.addBranch(EOpContinue, @1);
1743    }
1744    | BREAK SEMICOLON {
1745        if (context->loopNestingLevel <= 0) {
1746            context->error(@1, "break statement only allowed in loops", "");
1747            context->recover();
1748        }
1749        $$ = context->intermediate.addBranch(EOpBreak, @1);
1750    }
1751    | RETURN SEMICOLON {
1752        $$ = context->intermediate.addBranch(EOpReturn, @1);
1753        if (context->currentFunctionType->getBasicType() != EbtVoid) {
1754            context->error(@1, "non-void function must return a value", "return");
1755            context->recover();
1756        }
1757    }
1758    | RETURN expression SEMICOLON {
1759        $$ = context->intermediate.addBranch(EOpReturn, $2, @1);
1760        context->functionReturnsValue = true;
1761        if (context->currentFunctionType->getBasicType() == EbtVoid) {
1762            context->error(@1, "void function cannot return a value", "return");
1763            context->recover();
1764        } else if (*(context->currentFunctionType) != $2->getType()) {
1765            context->error(@1, "function return is not matching type:", "return");
1766            context->recover();
1767        }
1768    }
1769    | DISCARD SEMICOLON {
1770        FRAG_ONLY("discard", @1);
1771        $$ = context->intermediate.addBranch(EOpKill, @1);
1772    }
1773    ;
1774
1775// Grammar Note:  No 'goto'.  Gotos are not supported.
1776
1777translation_unit
1778    : external_declaration {
1779        $$ = $1;
1780        context->treeRoot = $$;
1781    }
1782    | translation_unit external_declaration {
1783        $$ = context->intermediate.growAggregate($1, $2, @$);
1784        context->treeRoot = $$;
1785    }
1786    ;
1787
1788external_declaration
1789    : function_definition {
1790        $$ = $1;
1791    }
1792    | declaration {
1793        $$ = $1;
1794    }
1795    ;
1796
1797function_definition
1798    : function_prototype {
1799        TFunction* function = $1.function;
1800
1801        const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName(), context->shaderVersion);
1802
1803        if (builtIn)
1804        {
1805            context->error(@1, "built-in functions cannot be redefined", function->getName().c_str());
1806            context->recover();
1807        }
1808
1809        TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find(function->getMangledName(), context->shaderVersion));
1810        //
1811        // Note:  'prevDec' could be 'function' if this is the first time we've seen function
1812        // as it would have just been put in the symbol table.  Otherwise, we're looking up
1813        // an earlier occurance.
1814        //
1815        if (prevDec->isDefined()) {
1816            //
1817            // Then this function already has a body.
1818            //
1819            context->error(@1, "function already has a body", function->getName().c_str());
1820            context->recover();
1821        }
1822        prevDec->setDefined();
1823
1824        //
1825        // Raise error message if main function takes any parameters or return anything other than void
1826        //
1827        if (function->getName() == "main") {
1828            if (function->getParamCount() > 0) {
1829                context->error(@1, "function cannot take any parameter(s)", function->getName().c_str());
1830                context->recover();
1831            }
1832            if (function->getReturnType().getBasicType() != EbtVoid) {
1833                context->error(@1, "", function->getReturnType().getBasicString(), "main function cannot return a value");
1834                context->recover();
1835            }
1836        }
1837
1838        //
1839        // Remember the return type for later checking for RETURN statements.
1840        //
1841        context->currentFunctionType = &(prevDec->getReturnType());
1842        context->functionReturnsValue = false;
1843
1844        //
1845        // Insert parameters into the symbol table.
1846        // If the parameter has no name, it's not an error, just don't insert it
1847        // (could be used for unused args).
1848        //
1849        // Also, accumulate the list of parameters into the HIL, so lower level code
1850        // knows where to find parameters.
1851        //
1852        TIntermAggregate* paramNodes = new TIntermAggregate;
1853        for (size_t i = 0; i < function->getParamCount(); i++) {
1854            const TParameter& param = function->getParam(i);
1855            if (param.name != 0) {
1856                TVariable *variable = new TVariable(param.name, *param.type);
1857                //
1858                // Insert the parameters with name in the symbol table.
1859                //
1860                if (! context->symbolTable.declare(variable)) {
1861                    context->error(@1, "redefinition", variable->getName().c_str());
1862                    context->recover();
1863                    delete variable;
1864                }
1865
1866                //
1867                // Add the parameter to the HIL
1868                //
1869                paramNodes = context->intermediate.growAggregate(
1870                                               paramNodes,
1871                                               context->intermediate.addSymbol(variable->getUniqueId(),
1872                                                                       variable->getName(),
1873                                                                       variable->getType(), @1),
1874                                               @1);
1875            } else {
1876                paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, @1), @1);
1877            }
1878        }
1879        context->intermediate.setAggregateOperator(paramNodes, EOpParameters, @1);
1880        $1.intermAggregate = paramNodes;
1881        context->loopNestingLevel = 0;
1882    }
1883    compound_statement_no_new_scope {
1884        //?? Check that all paths return a value if return type != void ?
1885        //   May be best done as post process phase on intermediate code
1886        if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) {
1887            context->error(@1, "function does not return a value:", "", $1.function->getName().c_str());
1888            context->recover();
1889        }
1890
1891        $$ = context->intermediate.growAggregate($1.intermAggregate, $3, @$);
1892        context->intermediate.setAggregateOperator($$, EOpFunction, @1);
1893        $$->getAsAggregate()->setName($1.function->getMangledName().c_str());
1894        $$->getAsAggregate()->setType($1.function->getReturnType());
1895
1896        // store the pragma information for debug and optimize and other vendor specific
1897        // information. This information can be queried from the parse tree
1898        $$->getAsAggregate()->setOptimize(context->pragma().optimize);
1899        $$->getAsAggregate()->setDebug(context->pragma().debug);
1900
1901        context->symbolTable.pop();
1902    }
1903    ;
1904
1905%%
1906
1907int glslang_parse(TParseContext* context) {
1908    return yyparse(context);
1909}
1910