Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / compiler / translator / glslang.y
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
8 This file contains the Yacc grammar for GLSL ES.
9 Based on ANSI C Yacc grammar:
10 http://www.lysator.liu.se/c/ANSI-C-grammar-y.html
11
12 IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
13 WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
14 */
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 %{
90 extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner);
91 extern 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
205 identifier
206     : IDENTIFIER
207     | TYPE_NAME
208
209 variable_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
233 primary_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
262 postfix_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
297 integer_expression
298     : expression {
299         if (context->integerErrorCheck($1, "[]"))
300             context->recover();
301         $$ = $1;
302     }
303     ;
304
305 function_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
405 function_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
416 function_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
425 function_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
436 function_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
451 function_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
459 function_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
472 unary_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
516 unary_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
523 multiplicative_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
543 additive_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
563 shift_expression
564     : additive_expression { $$ = $1; }
565     ;
566
567 relational_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
611 equality_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
635 and_expression
636     : equality_expression { $$ = $1; }
637     ;
638
639 exclusive_or_expression
640     : and_expression { $$ = $1; }
641     ;
642
643 inclusive_or_expression
644     : exclusive_or_expression { $$ = $1; }
645     ;
646
647 logical_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
661 logical_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
675 logical_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
689 conditional_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
707 assignment_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
721 assignment_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
729 expression
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
743 constant_expression
744     : conditional_expression {
745         if (context->constErrorCheck($1))
746             context->recover();
747         $$ = $1;
748     }
749     ;
750
751 enter_struct
752     : IDENTIFIER LEFT_BRACE {
753         if (context->enterStructDeclaration(@1, *$1.string))
754             context->recover();
755         $$ = $1;
756     }
757     ;
758
759 declaration
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
822 function_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
878 function_declarator
879     : function_header {
880         $$ = $1;
881     }
882     | function_header_with_parameters {
883         $$ = $1;
884     }
885     ;
886
887
888 function_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
917 function_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
937 parameter_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
968 parameter_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
1006 parameter_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
1021 parameter_type_specifier
1022     : type_specifier {
1023         TParameter param = { 0, new TType($1) };
1024         $$.param = param;
1025     }
1026     ;
1027
1028 init_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
1050 single_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
1080 fully_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
1095 interpolation_qualifier
1096     : SMOOTH {
1097         $$.qualifier = EvqSmooth;
1098     }
1099     | FLAT {
1100         $$.qualifier = EvqFlat;
1101     }
1102     ;
1103
1104 parameter_type_qualifier
1105     : CONST_QUAL {
1106         $$ = EvqConst;
1107     }
1108     ;
1109
1110 type_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
1164 storage_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
1201 type_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
1223 precision_qualifier
1224     : HIGH_PRECISION {
1225         $$ = EbpHigh;
1226     }
1227     | MEDIUM_PRECISION {
1228         $$ = EbpMedium;
1229     }
1230     | LOW_PRECISION  {
1231         $$ = EbpLow;
1232     }
1233     ;
1234
1235 layout_qualifier
1236     : LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN {
1237         ES3_ONLY("layout", @1, "qualifier");
1238         $$ = $3;
1239     }
1240     ;
1241
1242 layout_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
1251 layout_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
1263 type_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
1281 type_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
1499 struct_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
1508 struct_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
1527 struct_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
1539 struct_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
1549 struct_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
1571 initializer
1572     : assignment_expression { $$ = $1; }
1573     ;
1574
1575 declaration_statement
1576     : declaration { $$ = $1; }
1577     ;
1578
1579 statement
1580     : compound_statement  { $$ = $1; }
1581     | simple_statement    { $$ = $1; }
1582     ;
1583
1584 // Grammar Note:  No labeled statements; 'goto' is not supported.
1585
1586 simple_statement
1587     : declaration_statement { $$ = $1; }
1588     | expression_statement  { $$ = $1; }
1589     | selection_statement   { $$ = $1; }
1590     | iteration_statement   { $$ = $1; }
1591     | jump_statement        { $$ = $1; }
1592     ;
1593
1594 compound_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
1605 statement_no_new_scope
1606     : compound_statement_no_new_scope { $$ = $1; }
1607     | simple_statement                { $$ = $1; }
1608     ;
1609
1610 statement_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
1615 compound_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
1629 statement_list
1630     : statement {
1631         $$ = context->intermediate.makeAggregate($1, @$);
1632     }
1633     | statement_list statement {
1634         $$ = context->intermediate.growAggregate($1, $2, @$);
1635     }
1636     ;
1637
1638 expression_statement
1639     : SEMICOLON  { $$ = 0; }
1640     | expression SEMICOLON  { $$ = static_cast<TIntermNode*>($1); }
1641     ;
1642
1643 selection_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
1651 selection_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
1664 condition
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
1687 iteration_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
1707 for_init_statement
1708     : expression_statement {
1709         $$ = $1;
1710     }
1711     | declaration_statement {
1712         $$ = $1;
1713     }
1714     ;
1715
1716 conditionopt
1717     : condition {
1718         $$ = $1;
1719     }
1720     | /* May be null */ {
1721         $$ = 0;
1722     }
1723     ;
1724
1725 for_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
1736 jump_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
1777 translation_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
1788 external_declaration
1789     : function_definition {
1790         $$ = $1;
1791     }
1792     | declaration {
1793         $$ = $1;
1794     }
1795     ;
1796
1797 function_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
1907 int glslang_parse(TParseContext* context) {
1908     return yyparse(context);
1909 }