d0d29df45132f45ff904d86dbdf7089ca5acb099
[WebKit.git] / Source / ThirdParty / ANGLE / src / compiler / glslang.y
1 //
2 // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 /**
8  * This is bison grammar and production code for parsing the OpenGL 2.0 shading
9  * languages.
10  */
11 %{
12
13 /* Based on:
14 ANSI C Yacc grammar
15
16 In 1985, Jeff Lee published his Yacc grammar (which is accompanied by a
17 matching Lex specification) for the April 30, 1985 draft version of the
18 ANSI C standard.  Tom Stockfisch reposted it to net.sources in 1987; that
19 original, as mentioned in the answer to question 17.25 of the comp.lang.c
20 FAQ, can be ftp'ed from ftp.uu.net, file usenet/net.sources/ansi.c.grammar.Z.
21
22 I intend to keep this version as close to the current C Standard grammar as
23 possible; please let me know if you discover discrepancies.
24
25 Jutta Degener, 1995
26 */
27
28 #include "compiler/SymbolTable.h"
29 #include "compiler/ParseHelper.h"
30 #include "GLSLANG/ShaderLang.h"
31
32 #define YYPARSE_PARAM parseContextLocal
33 /*
34 TODO(alokp): YYPARSE_PARAM_DECL is only here to support old bison.exe in
35 compiler/tools. Remove it when we can exclusively use the newer version.
36 */
37 #define YYPARSE_PARAM_DECL void*
38 #define parseContext ((TParseContext*)(parseContextLocal))
39 #define YYLEX_PARAM parseContextLocal
40 #define YY_DECL int yylex(YYSTYPE* pyylval, void* parseContextLocal)
41 extern void yyerror(const char*);
42
43 #define FRAG_VERT_ONLY(S, L) {                                                  \
44     if (parseContext->language != EShLangFragment &&                             \
45         parseContext->language != EShLangVertex) {                               \
46         parseContext->error(L, " supported in vertex/fragment shaders only ", S, "", "");   \
47         parseContext->recover();                                                            \
48     }                                                                           \
49 }
50
51 #define VERTEX_ONLY(S, L) {                                                     \
52     if (parseContext->language != EShLangVertex) {                               \
53         parseContext->error(L, " supported in vertex shaders only ", S, "", "");            \
54         parseContext->recover();                                                            \
55     }                                                                           \
56 }
57
58 #define FRAG_ONLY(S, L) {                                                       \
59     if (parseContext->language != EShLangFragment) {                             \
60         parseContext->error(L, " supported in fragment shaders only ", S, "", "");          \
61         parseContext->recover();                                                            \
62     }                                                                           \
63 }
64
65 #define PACK_ONLY(S, L) {                                                       \
66     if (parseContext->language != EShLangPack) {                                 \
67         parseContext->error(L, " supported in pack shaders only ", S, "", "");              \
68         parseContext->recover();                                                            \
69     }                                                                           \
70 }
71
72 #define UNPACK_ONLY(S, L) {                                                     \
73     if (parseContext->language != EShLangUnpack) {                               \
74         parseContext->error(L, " supported in unpack shaders only ", S, "", "");            \
75         parseContext->recover();                                                            \
76     }                                                                           \
77 }
78
79 #define PACK_UNPACK_ONLY(S, L) {                                                \
80     if (parseContext->language != EShLangUnpack &&                               \
81         parseContext->language != EShLangPack) {                                 \
82         parseContext->error(L, " supported in pack/unpack shaders only ", S, "", "");       \
83         parseContext->recover();                                                            \
84     }                                                                           \
85 }
86 %}
87 %union {
88     struct {
89         TSourceLoc line;
90         union {
91             TString *string;
92             float f;
93             int i;
94             bool b;
95         };
96         TSymbol* symbol;
97     } lex;
98     struct {
99         TSourceLoc line;
100         TOperator op;
101         union {
102             TIntermNode* intermNode;
103             TIntermNodePair nodePair;
104             TIntermTyped* intermTypedNode;
105             TIntermAggregate* intermAggregate;
106         };
107         union {
108             TPublicType type;
109             TPrecision precision;
110             TQualifier qualifier;
111             TFunction* function;
112             TParameter param;
113             TTypeLine typeLine;
114             TTypeList* typeList;
115         };
116     } interm;
117 }
118
119 %{
120     extern int yylex(YYSTYPE*, void*);
121 %}
122
123 %pure_parser /* Just in case is called from multiple threads */
124 %expect 1 /* One shift reduce conflict because of if | else */
125 %token <lex> INVARIANT HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION
126 %token <lex> ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE
127 %token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN
128 %token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4
129 %token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM VARYING
130 %token <lex> STRUCT VOID_TYPE WHILE
131 %token <lex> SAMPLER2D SAMPLERCUBE
132
133 %token <lex> IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT BOOLCONSTANT
134 %token <lex> FIELD_SELECTION
135 %token <lex> LEFT_OP RIGHT_OP
136 %token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
137 %token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
138 %token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
139 %token <lex> SUB_ASSIGN
140
141 %token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
142 %token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
143 %token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION
144
145 %type <interm> assignment_operator unary_operator
146 %type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression
147 %type <interm.intermTypedNode> expression integer_expression assignment_expression
148 %type <interm.intermTypedNode> unary_expression multiplicative_expression additive_expression
149 %type <interm.intermTypedNode> relational_expression equality_expression
150 %type <interm.intermTypedNode> conditional_expression constant_expression
151 %type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression
152 %type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression
153 %type <interm.intermTypedNode> function_call initializer condition conditionopt
154
155 %type <interm.intermNode> translation_unit function_definition
156 %type <interm.intermNode> statement simple_statement
157 %type <interm.intermAggregate>  statement_list compound_statement
158 %type <interm.intermNode> declaration_statement selection_statement expression_statement
159 %type <interm.intermNode> declaration external_declaration
160 %type <interm.intermNode> for_init_statement compound_statement_no_new_scope
161 %type <interm.nodePair> selection_rest_statement for_rest_statement
162 %type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope
163 %type <interm> single_declaration init_declarator_list
164
165 %type <interm> parameter_declaration parameter_declarator parameter_type_specifier
166 %type <interm.qualifier> parameter_qualifier
167
168 %type <interm.precision> precision_qualifier
169 %type <interm.type> type_qualifier fully_specified_type type_specifier
170 %type <interm.type> type_specifier_no_prec type_specifier_nonarray
171 %type <interm.type> struct_specifier
172 %type <interm.typeLine> struct_declarator
173 %type <interm.typeList> struct_declarator_list struct_declaration struct_declaration_list
174 %type <interm.function> function_header function_declarator function_identifier
175 %type <interm.function> function_header_with_parameters function_call_header
176 %type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
177 %type <interm> function_call_or_method
178
179 %start translation_unit
180 %%
181
182 variable_identifier
183     : IDENTIFIER {
184         // The symbol table search was done in the lexical phase
185         const TSymbol* symbol = $1.symbol;
186         const TVariable* variable;
187         if (symbol == 0) {
188             parseContext->error($1.line, "undeclared identifier", $1.string->c_str(), "");
189             parseContext->recover();
190             TType type(EbtFloat, EbpUndefined);
191             TVariable* fakeVariable = new TVariable($1.string, type);
192             parseContext->symbolTable.insert(*fakeVariable);
193             variable = fakeVariable;
194         } else {
195             // This identifier can only be a variable type symbol
196             if (! symbol->isVariable()) {
197                 parseContext->error($1.line, "variable expected", $1.string->c_str(), "");
198                 parseContext->recover();
199             }
200             variable = static_cast<const TVariable*>(symbol);
201         }
202
203         // don't delete $1.string, it's used by error recovery, and the pool
204         // pop will reclaim the memory
205
206         if (variable->getType().getQualifier() == EvqConst ) {
207             ConstantUnion* constArray = variable->getConstPointer();
208             TType t(variable->getType());
209             $$ = parseContext->intermediate.addConstantUnion(constArray, t, $1.line);
210         } else
211             $$ = parseContext->intermediate.addSymbol(variable->getUniqueId(),
212                                                      variable->getName(),
213                                                      variable->getType(), $1.line);
214     }
215     ;
216
217 primary_expression
218     : variable_identifier {
219         $$ = $1;
220     }
221     | INTCONSTANT {
222         //
223         // INT_TYPE is only 16-bit plus sign bit for vertex/fragment shaders,
224         // check for overflow for constants
225         //
226         if (abs($1.i) >= (1 << 16)) {
227             parseContext->error($1.line, " integer constant overflow", "", "");
228             parseContext->recover();
229         }
230         ConstantUnion *unionArray = new ConstantUnion[1];
231         unionArray->setIConst($1.i);
232         $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $1.line);
233     }
234     | FLOATCONSTANT {
235         ConstantUnion *unionArray = new ConstantUnion[1];
236         unionArray->setFConst($1.f);
237         $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line);
238     }
239     | BOOLCONSTANT {
240         ConstantUnion *unionArray = new ConstantUnion[1];
241         unionArray->setBConst($1.b);
242         $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $1.line);
243     }
244     | LEFT_PAREN expression RIGHT_PAREN {
245         $$ = $2;
246     }
247     ;
248
249 postfix_expression
250     : primary_expression {
251         $$ = $1;
252     }
253     | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET {
254         if (!$1->isArray() && !$1->isMatrix() && !$1->isVector()) {
255             if ($1->getAsSymbolNode())
256                 parseContext->error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str(), "");
257             else
258                 parseContext->error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression", "");
259             parseContext->recover();
260         }
261         if ($1->getType().getQualifier() == EvqConst && $3->getQualifier() == EvqConst) {
262             if ($1->isArray()) { // constant folding for arrays
263                 $$ = parseContext->addConstArrayNode($3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), $1, $2.line);
264             } else if ($1->isVector()) {  // constant folding for vectors
265                 TVectorFields fields;
266                 fields.num = 1;
267                 fields.offsets[0] = $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(); // need to do it this way because v.xy sends fields integer array
268                 $$ = parseContext->addConstVectorNode(fields, $1, $2.line);
269             } else if ($1->isMatrix()) { // constant folding for matrices
270                 $$ = parseContext->addConstMatrixNode($3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), $1, $2.line);
271             }
272         } else {
273             if ($3->getQualifier() == EvqConst) {
274                 if (($1->isVector() || $1->isMatrix()) && $1->getType().getNominalSize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() && !$1->isArray() ) {
275                     parseContext->error($2.line, "", "[", "field selection out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst());
276                     parseContext->recover();
277                 } else {
278                     if ($1->isArray()) {
279                         if ($1->getType().getArraySize() == 0) {
280                             if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()) {
281                                 if (parseContext->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), true, $2.line))
282                                     parseContext->recover();
283                             } else {
284                                 if (parseContext->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line))
285                                     parseContext->recover();
286                             }
287                         } else if ( $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() >= $1->getType().getArraySize()) {
288                             parseContext->error($2.line, "", "[", "array index out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst());
289                             parseContext->recover();
290                         }
291                     }
292                     $$ = parseContext->intermediate.addIndex(EOpIndexDirect, $1, $3, $2.line);
293                 }
294             } else {
295                 if ($1->isArray() && $1->getType().getArraySize() == 0) {
296                     parseContext->error($2.line, "", "[", "array must be redeclared with a size before being indexed with a variable");
297                     parseContext->recover();
298                 }
299
300                 $$ = parseContext->intermediate.addIndex(EOpIndexIndirect, $1, $3, $2.line);
301             }
302         }
303         if ($$ == 0) {
304             ConstantUnion *unionArray = new ConstantUnion[1];
305             unionArray->setFConst(0.0f);
306             $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), $2.line);
307         } else if ($1->isArray()) {
308             if ($1->getType().getStruct())
309                 $$->setType(TType($1->getType().getStruct(), $1->getType().getTypeName()));
310             else
311                 $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize(), $1->isMatrix()));
312
313             if ($1->getType().getQualifier() == EvqConst)
314                 $$->getTypePointer()->setQualifier(EvqConst);
315         } else if ($1->isMatrix() && $1->getType().getQualifier() == EvqConst)
316             $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, $1->getNominalSize()));
317         else if ($1->isMatrix())
318             $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize()));
319         else if ($1->isVector() && $1->getType().getQualifier() == EvqConst)
320             $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst));
321         else if ($1->isVector())
322             $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary));
323         else
324             $$->setType($1->getType());
325     }
326     | function_call {
327         $$ = $1;
328     }
329     | postfix_expression DOT FIELD_SELECTION {
330         if ($1->isArray()) {
331             parseContext->error($3.line, "cannot apply dot operator to an array", ".", "");
332             parseContext->recover();
333         }
334
335         if ($1->isVector()) {
336             TVectorFields fields;
337             if (! parseContext->parseVectorFields(*$3.string, $1->getNominalSize(), fields, $3.line)) {
338                 fields.num = 1;
339                 fields.offsets[0] = 0;
340                 parseContext->recover();
341             }
342
343             if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields
344                 $$ = parseContext->addConstVectorNode(fields, $1, $3.line);
345                 if ($$ == 0) {
346                     parseContext->recover();
347                     $$ = $1;
348                 }
349                 else
350                     $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, (int) (*$3.string).size()));
351             } else {
352                 if (fields.num == 1) {
353                     ConstantUnion *unionArray = new ConstantUnion[1];
354                     unionArray->setIConst(fields.offsets[0]);
355                     TIntermTyped* index = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line);
356                     $$ = parseContext->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
357                     $$->setType(TType($1->getBasicType(), $1->getPrecision()));
358                 } else {
359                     TString vectorString = *$3.string;
360                     TIntermTyped* index = parseContext->intermediate.addSwizzle(fields, $3.line);
361                     $$ = parseContext->intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line);
362                     $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, (int) vectorString.size()));
363                 }
364             }
365         } else if ($1->isMatrix()) {
366             TMatrixFields fields;
367             if (! parseContext->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, $3.line)) {
368                 fields.wholeRow = false;
369                 fields.wholeCol = false;
370                 fields.row = 0;
371                 fields.col = 0;
372                 parseContext->recover();
373             }
374
375             if (fields.wholeRow || fields.wholeCol) {
376                 parseContext->error($2.line, " non-scalar fields not implemented yet", ".", "");
377                 parseContext->recover();
378                 ConstantUnion *unionArray = new ConstantUnion[1];
379                 unionArray->setIConst(0);
380                 TIntermTyped* index = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line);
381                 $$ = parseContext->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
382                 $$->setType(TType($1->getBasicType(), $1->getPrecision(),EvqTemporary, $1->getNominalSize()));
383             } else {
384                 ConstantUnion *unionArray = new ConstantUnion[1];
385                 unionArray->setIConst(fields.col * $1->getNominalSize() + fields.row);
386                 TIntermTyped* index = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line);
387                 $$ = parseContext->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
388                 $$->setType(TType($1->getBasicType(), $1->getPrecision()));
389             }
390         } else if ($1->getBasicType() == EbtStruct) {
391             bool fieldFound = false;
392             const TTypeList* fields = $1->getType().getStruct();
393             if (fields == 0) {
394                 parseContext->error($2.line, "structure has no fields", "Internal Error", "");
395                 parseContext->recover();
396                 $$ = $1;
397             } else {
398                 unsigned int i;
399                 for (i = 0; i < fields->size(); ++i) {
400                     if ((*fields)[i].type->getFieldName() == *$3.string) {
401                         fieldFound = true;
402                         break;
403                     }
404                 }
405                 if (fieldFound) {
406                     if ($1->getType().getQualifier() == EvqConst) {
407                         $$ = parseContext->addConstStruct(*$3.string, $1, $2.line);
408                         if ($$ == 0) {
409                             parseContext->recover();
410                             $$ = $1;
411                         }
412                         else {
413                             $$->setType(*(*fields)[i].type);
414                             // change the qualifier of the return type, not of the structure field
415                             // as the structure definition is shared between various structures.
416                             $$->getTypePointer()->setQualifier(EvqConst);
417                         }
418                     } else {
419                         ConstantUnion *unionArray = new ConstantUnion[1];
420                         unionArray->setIConst(i);
421                         TIntermTyped* index = parseContext->intermediate.addConstantUnion(unionArray, *(*fields)[i].type, $3.line);
422                         $$ = parseContext->intermediate.addIndex(EOpIndexDirectStruct, $1, index, $2.line);
423                         $$->setType(*(*fields)[i].type);
424                     }
425                 } else {
426                     parseContext->error($2.line, " no such field in structure", $3.string->c_str(), "");
427                     parseContext->recover();
428                     $$ = $1;
429                 }
430             }
431         } else {
432             parseContext->error($2.line, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str(), "");
433             parseContext->recover();
434             $$ = $1;
435         }
436         // don't delete $3.string, it's from the pool
437     }
438     | postfix_expression INC_OP {
439         if (parseContext->lValueErrorCheck($2.line, "++", $1))
440             parseContext->recover();
441         $$ = parseContext->intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line, parseContext->symbolTable);
442         if ($$ == 0) {
443             parseContext->unaryOpError($2.line, "++", $1->getCompleteString());
444             parseContext->recover();
445             $$ = $1;
446         }
447     }
448     | postfix_expression DEC_OP {
449         if (parseContext->lValueErrorCheck($2.line, "--", $1))
450             parseContext->recover();
451         $$ = parseContext->intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line, parseContext->symbolTable);
452         if ($$ == 0) {
453             parseContext->unaryOpError($2.line, "--", $1->getCompleteString());
454             parseContext->recover();
455             $$ = $1;
456         }
457     }
458     ;
459
460 integer_expression
461     : expression {
462         if (parseContext->integerErrorCheck($1, "[]"))
463             parseContext->recover();
464         $$ = $1;
465     }
466     ;
467
468 function_call
469     : function_call_or_method {
470         TFunction* fnCall = $1.function;
471         TOperator op = fnCall->getBuiltInOp();
472
473         if (op != EOpNull)
474         {
475             //
476             // Then this should be a constructor.
477             // Don't go through the symbol table for constructors.
478             // Their parameters will be verified algorithmically.
479             //
480             TType type(EbtVoid, EbpUndefined);  // use this to get the type back
481             if (parseContext->constructorErrorCheck($1.line, $1.intermNode, *fnCall, op, &type)) {
482                 $$ = 0;
483             } else {
484                 //
485                 // It's a constructor, of type 'type'.
486                 //
487                 $$ = parseContext->addConstructor($1.intermNode, &type, op, fnCall, $1.line);
488             }
489
490             if ($$ == 0) {
491                 parseContext->recover();
492                 $$ = parseContext->intermediate.setAggregateOperator(0, op, $1.line);
493             }
494             $$->setType(type);
495         } else {
496             //
497             // Not a constructor.  Find it in the symbol table.
498             //
499             const TFunction* fnCandidate;
500             bool builtIn;
501             fnCandidate = parseContext->findFunction($1.line, fnCall, &builtIn);
502             if (fnCandidate) {
503                 //
504                 // A declared function.  But, it might still map to a built-in
505                 // operation.
506                 //
507                 op = fnCandidate->getBuiltInOp();
508                 if (builtIn && op != EOpNull) {
509                     //
510                     // A function call mapped to a built-in operation.
511                     //
512                     if (fnCandidate->getParamCount() == 1) {
513                         //
514                         // Treat it like a built-in unary operator.
515                         //
516                         $$ = parseContext->intermediate.addUnaryMath(op, $1.intermNode, 0, parseContext->symbolTable);
517                         if ($$ == 0)  {
518                             parseContext->error($1.intermNode->getLine(), " wrong operand type", "Internal Error",
519                                 "built in unary operator function.  Type: %s",
520                                 static_cast<TIntermTyped*>($1.intermNode)->getCompleteString().c_str());
521                             YYERROR;
522                         }
523                     } else {
524                         $$ = parseContext->intermediate.setAggregateOperator($1.intermAggregate, op, $1.line);
525                     }
526                 } else {
527                     // This is a real function call
528
529                     $$ = parseContext->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, $1.line);
530                     $$->setType(fnCandidate->getReturnType());
531
532                     // this is how we know whether the given function is a builtIn function or a user defined function
533                     // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
534                     // if builtIn == true, it's definitely a builtIn function with EOpNull
535                     if (!builtIn)
536                         $$->getAsAggregate()->setUserDefined();
537                     $$->getAsAggregate()->setName(fnCandidate->getMangledName());
538
539                     TQualifier qual;
540                     TQualifierList& qualifierList = $$->getAsAggregate()->getQualifier();
541                     for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
542                         qual = (*fnCandidate)[i].type->getQualifier();
543                         if (qual == EvqOut || qual == EvqInOut) {
544                             if (parseContext->lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) {
545                                 parseContext->error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error", "");
546                                 parseContext->recover();
547                             }
548                         }
549                         qualifierList.push_back(qual);
550                     }
551                 }
552                 $$->setType(fnCandidate->getReturnType());
553             } else {
554                 // error message was put out by PaFindFunction()
555                 // Put on a dummy node for error recovery
556                 ConstantUnion *unionArray = new ConstantUnion[1];
557                 unionArray->setFConst(0.0f);
558                 $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line);
559                 parseContext->recover();
560             }
561         }
562         delete fnCall;
563     }
564     ;
565
566 function_call_or_method
567     : function_call_generic {
568         $$ = $1;
569     }
570     | postfix_expression DOT function_call_generic {
571         parseContext->error($3.line, "methods are not supported", "", "");
572         parseContext->recover();
573         $$ = $3;
574     }
575     ;
576
577 function_call_generic
578     : function_call_header_with_parameters RIGHT_PAREN {
579         $$ = $1;
580         $$.line = $2.line;
581     }
582     | function_call_header_no_parameters RIGHT_PAREN {
583         $$ = $1;
584         $$.line = $2.line;
585     }
586     ;
587
588 function_call_header_no_parameters
589     : function_call_header VOID_TYPE {
590         $$.function = $1;
591         $$.intermNode = 0;
592     }
593     | function_call_header {
594         $$.function = $1;
595         $$.intermNode = 0;
596     }
597     ;
598
599 function_call_header_with_parameters
600     : function_call_header assignment_expression {
601         TParameter param = { 0, new TType($2->getType()) };
602         $1->addParameter(param);
603         $$.function = $1;
604         $$.intermNode = $2;
605     }
606     | function_call_header_with_parameters COMMA assignment_expression {
607         TParameter param = { 0, new TType($3->getType()) };
608         $1.function->addParameter(param);
609         $$.function = $1.function;
610         $$.intermNode = parseContext->intermediate.growAggregate($1.intermNode, $3, $2.line);
611     }
612     ;
613
614 function_call_header
615     : function_identifier LEFT_PAREN {
616         $$ = $1;
617     }
618     ;
619
620 // Grammar Note:  Constructors look like functions, but are recognized as types.
621
622 function_identifier
623     : type_specifier {
624         //
625         // Constructor
626         //
627         if ($1.array) {
628             if (parseContext->extensionErrorCheck($1.line, "GL_3DL_array_objects")) {
629                 parseContext->recover();
630                 $1.setArray(false);
631             }
632         }
633
634         if ($1.userDef) {
635             TString tempString = "";
636             TType type($1);
637             TFunction *function = new TFunction(&tempString, type, EOpConstructStruct);
638             $$ = function;
639         } else {
640             TOperator op = EOpNull;
641             switch ($1.type) {
642             case EbtFloat:
643                 if ($1.matrix) {
644                     switch($1.size) {
645                     case 2:                                     op = EOpConstructMat2;  break;
646                     case 3:                                     op = EOpConstructMat3;  break;
647                     case 4:                                     op = EOpConstructMat4;  break;
648                     }
649                 } else {
650                     switch($1.size) {
651                     case 1:                                     op = EOpConstructFloat; break;
652                     case 2:                                     op = EOpConstructVec2;  break;
653                     case 3:                                     op = EOpConstructVec3;  break;
654                     case 4:                                     op = EOpConstructVec4;  break;
655                     }
656                 }
657                 break;
658             case EbtInt:
659                 switch($1.size) {
660                 case 1:                                         op = EOpConstructInt;   break;
661                 case 2:       FRAG_VERT_ONLY("ivec2", $1.line); op = EOpConstructIVec2; break;
662                 case 3:       FRAG_VERT_ONLY("ivec3", $1.line); op = EOpConstructIVec3; break;
663                 case 4:       FRAG_VERT_ONLY("ivec4", $1.line); op = EOpConstructIVec4; break;
664                 }
665                 break;
666             case EbtBool:
667                 switch($1.size) {
668                 case 1:                                         op = EOpConstructBool;  break;
669                 case 2:       FRAG_VERT_ONLY("bvec2", $1.line); op = EOpConstructBVec2; break;
670                 case 3:       FRAG_VERT_ONLY("bvec3", $1.line); op = EOpConstructBVec3; break;
671                 case 4:       FRAG_VERT_ONLY("bvec4", $1.line); op = EOpConstructBVec4; break;
672                 }
673                 break;
674             }
675             if (op == EOpNull) {
676                 parseContext->error($1.line, "cannot construct this type", getBasicString($1.type), "");
677                 parseContext->recover();
678                 $1.type = EbtFloat;
679                 op = EOpConstructFloat;
680             }
681             TString tempString = "";
682             TType type($1);
683             TFunction *function = new TFunction(&tempString, type, op);
684             $$ = function;
685         }
686     }
687     | IDENTIFIER {
688         if (parseContext->reservedErrorCheck($1.line, *$1.string))
689             parseContext->recover();
690         TType type(EbtVoid, EbpUndefined);
691         TFunction *function = new TFunction($1.string, type);
692         $$ = function;
693     }
694     | FIELD_SELECTION {
695         if (parseContext->reservedErrorCheck($1.line, *$1.string))
696             parseContext->recover();
697         TType type(EbtVoid, EbpUndefined);
698         TFunction *function = new TFunction($1.string, type);
699         $$ = function;
700     }
701     ;
702
703 unary_expression
704     : postfix_expression {
705         $$ = $1;
706     }
707     | INC_OP unary_expression {
708         if (parseContext->lValueErrorCheck($1.line, "++", $2))
709             parseContext->recover();
710         $$ = parseContext->intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line, parseContext->symbolTable);
711         if ($$ == 0) {
712             parseContext->unaryOpError($1.line, "++", $2->getCompleteString());
713             parseContext->recover();
714             $$ = $2;
715         }
716     }
717     | DEC_OP unary_expression {
718         if (parseContext->lValueErrorCheck($1.line, "--", $2))
719             parseContext->recover();
720         $$ = parseContext->intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line, parseContext->symbolTable);
721         if ($$ == 0) {
722             parseContext->unaryOpError($1.line, "--", $2->getCompleteString());
723             parseContext->recover();
724             $$ = $2;
725         }
726     }
727     | unary_operator unary_expression {
728         if ($1.op != EOpNull) {
729             $$ = parseContext->intermediate.addUnaryMath($1.op, $2, $1.line, parseContext->symbolTable);
730             if ($$ == 0) {
731                 const char* errorOp = "";
732                 switch($1.op) {
733                 case EOpNegative:   errorOp = "-"; break;
734                 case EOpLogicalNot: errorOp = "!"; break;
735                 default: break;
736                 }
737                 parseContext->unaryOpError($1.line, errorOp, $2->getCompleteString());
738                 parseContext->recover();
739                 $$ = $2;
740             }
741         } else
742             $$ = $2;
743     }
744     ;
745 // Grammar Note:  No traditional style type casts.
746
747 unary_operator
748     : PLUS  { $$.line = $1.line; $$.op = EOpNull; }
749     | DASH  { $$.line = $1.line; $$.op = EOpNegative; }
750     | BANG  { $$.line = $1.line; $$.op = EOpLogicalNot; }
751     ;
752 // Grammar Note:  No '*' or '&' unary ops.  Pointers are not supported.
753
754 multiplicative_expression
755     : unary_expression { $$ = $1; }
756     | multiplicative_expression STAR unary_expression {
757         FRAG_VERT_ONLY("*", $2.line);
758         $$ = parseContext->intermediate.addBinaryMath(EOpMul, $1, $3, $2.line, parseContext->symbolTable);
759         if ($$ == 0) {
760             parseContext->binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString());
761             parseContext->recover();
762             $$ = $1;
763         }
764     }
765     | multiplicative_expression SLASH unary_expression {
766         FRAG_VERT_ONLY("/", $2.line);
767         $$ = parseContext->intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line, parseContext->symbolTable);
768         if ($$ == 0) {
769             parseContext->binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString());
770             parseContext->recover();
771             $$ = $1;
772         }
773     }
774     ;
775
776 additive_expression
777     : multiplicative_expression { $$ = $1; }
778     | additive_expression PLUS multiplicative_expression {
779         $$ = parseContext->intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line, parseContext->symbolTable);
780         if ($$ == 0) {
781             parseContext->binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString());
782             parseContext->recover();
783             $$ = $1;
784         }
785     }
786     | additive_expression DASH multiplicative_expression {
787         $$ = parseContext->intermediate.addBinaryMath(EOpSub, $1, $3, $2.line, parseContext->symbolTable);
788         if ($$ == 0) {
789             parseContext->binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString());
790             parseContext->recover();
791             $$ = $1;
792         }
793     }
794     ;
795
796 shift_expression
797     : additive_expression { $$ = $1; }
798     ;
799
800 relational_expression
801     : shift_expression { $$ = $1; }
802     | relational_expression LEFT_ANGLE shift_expression {
803         $$ = parseContext->intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line, parseContext->symbolTable);
804         if ($$ == 0) {
805             parseContext->binaryOpError($2.line, "<", $1->getCompleteString(), $3->getCompleteString());
806             parseContext->recover();
807             ConstantUnion *unionArray = new ConstantUnion[1];
808             unionArray->setBConst(false);
809             $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
810         }
811     }
812     | relational_expression RIGHT_ANGLE shift_expression  {
813         $$ = parseContext->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line, parseContext->symbolTable);
814         if ($$ == 0) {
815             parseContext->binaryOpError($2.line, ">", $1->getCompleteString(), $3->getCompleteString());
816             parseContext->recover();
817             ConstantUnion *unionArray = new ConstantUnion[1];
818             unionArray->setBConst(false);
819             $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
820         }
821     }
822     | relational_expression LE_OP shift_expression  {
823         $$ = parseContext->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line, parseContext->symbolTable);
824         if ($$ == 0) {
825             parseContext->binaryOpError($2.line, "<=", $1->getCompleteString(), $3->getCompleteString());
826             parseContext->recover();
827             ConstantUnion *unionArray = new ConstantUnion[1];
828             unionArray->setBConst(false);
829             $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
830         }
831     }
832     | relational_expression GE_OP shift_expression  {
833         $$ = parseContext->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line, parseContext->symbolTable);
834         if ($$ == 0) {
835             parseContext->binaryOpError($2.line, ">=", $1->getCompleteString(), $3->getCompleteString());
836             parseContext->recover();
837             ConstantUnion *unionArray = new ConstantUnion[1];
838             unionArray->setBConst(false);
839             $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
840         }
841     }
842     ;
843
844 equality_expression
845     : relational_expression { $$ = $1; }
846     | equality_expression EQ_OP relational_expression  {
847         $$ = parseContext->intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line, parseContext->symbolTable);
848         if ($$ == 0) {
849             parseContext->binaryOpError($2.line, "==", $1->getCompleteString(), $3->getCompleteString());
850             parseContext->recover();
851             ConstantUnion *unionArray = new ConstantUnion[1];
852             unionArray->setBConst(false);
853             $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
854         } else if (($1->isArray() || $3->isArray()) && parseContext->extensionErrorCheck($2.line, "GL_3DL_array_objects"))
855             parseContext->recover();
856     }
857     | equality_expression NE_OP relational_expression {
858         $$ = parseContext->intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line, parseContext->symbolTable);
859         if ($$ == 0) {
860             parseContext->binaryOpError($2.line, "!=", $1->getCompleteString(), $3->getCompleteString());
861             parseContext->recover();
862             ConstantUnion *unionArray = new ConstantUnion[1];
863             unionArray->setBConst(false);
864             $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
865         } else if (($1->isArray() || $3->isArray()) && parseContext->extensionErrorCheck($2.line, "GL_3DL_array_objects"))
866             parseContext->recover();
867     }
868     ;
869
870 and_expression
871     : equality_expression { $$ = $1; }
872     ;
873
874 exclusive_or_expression
875     : and_expression { $$ = $1; }
876     ;
877
878 inclusive_or_expression
879     : exclusive_or_expression { $$ = $1; }
880     ;
881
882 logical_and_expression
883     : inclusive_or_expression { $$ = $1; }
884     | logical_and_expression AND_OP inclusive_or_expression {
885         $$ = parseContext->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line, parseContext->symbolTable);
886         if ($$ == 0) {
887             parseContext->binaryOpError($2.line, "&&", $1->getCompleteString(), $3->getCompleteString());
888             parseContext->recover();
889             ConstantUnion *unionArray = new ConstantUnion[1];
890             unionArray->setBConst(false);
891             $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
892         }
893     }
894     ;
895
896 logical_xor_expression
897     : logical_and_expression { $$ = $1; }
898     | logical_xor_expression XOR_OP logical_and_expression  {
899         $$ = parseContext->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line, parseContext->symbolTable);
900         if ($$ == 0) {
901             parseContext->binaryOpError($2.line, "^^", $1->getCompleteString(), $3->getCompleteString());
902             parseContext->recover();
903             ConstantUnion *unionArray = new ConstantUnion[1];
904             unionArray->setBConst(false);
905             $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
906         }
907     }
908     ;
909
910 logical_or_expression
911     : logical_xor_expression { $$ = $1; }
912     | logical_or_expression OR_OP logical_xor_expression  {
913         $$ = parseContext->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line, parseContext->symbolTable);
914         if ($$ == 0) {
915             parseContext->binaryOpError($2.line, "||", $1->getCompleteString(), $3->getCompleteString());
916             parseContext->recover();
917             ConstantUnion *unionArray = new ConstantUnion[1];
918             unionArray->setBConst(false);
919             $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
920         }
921     }
922     ;
923
924 conditional_expression
925     : logical_or_expression { $$ = $1; }
926     | logical_or_expression QUESTION expression COLON assignment_expression {
927        if (parseContext->boolErrorCheck($2.line, $1))
928             parseContext->recover();
929
930         $$ = parseContext->intermediate.addSelection($1, $3, $5, $2.line);
931         if ($3->getType() != $5->getType())
932             $$ = 0;
933
934         if ($$ == 0) {
935             parseContext->binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString());
936             parseContext->recover();
937             $$ = $5;
938         }
939     }
940     ;
941
942 assignment_expression
943     : conditional_expression { $$ = $1; }
944     | unary_expression assignment_operator assignment_expression {
945         if (parseContext->lValueErrorCheck($2.line, "assign", $1))
946             parseContext->recover();
947         $$ = parseContext->intermediate.addAssign($2.op, $1, $3, $2.line);
948         if ($$ == 0) {
949             parseContext->assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString());
950             parseContext->recover();
951             $$ = $1;
952         } else if (($1->isArray() || $3->isArray()) && parseContext->extensionErrorCheck($2.line, "GL_3DL_array_objects"))
953             parseContext->recover();
954     }
955     ;
956
957 assignment_operator
958     : EQUAL        {                                    $$.line = $1.line; $$.op = EOpAssign; }
959     | MUL_ASSIGN   { FRAG_VERT_ONLY("*=", $1.line);     $$.line = $1.line; $$.op = EOpMulAssign; }
960     | DIV_ASSIGN   { FRAG_VERT_ONLY("/=", $1.line);     $$.line = $1.line; $$.op = EOpDivAssign; }
961     | ADD_ASSIGN   {                                    $$.line = $1.line; $$.op = EOpAddAssign; }
962     | SUB_ASSIGN   {                                    $$.line = $1.line; $$.op = EOpSubAssign; }
963     ;
964
965 expression
966     : assignment_expression {
967         $$ = $1;
968     }
969     | expression COMMA assignment_expression {
970         $$ = parseContext->intermediate.addComma($1, $3, $2.line);
971         if ($$ == 0) {
972             parseContext->binaryOpError($2.line, ",", $1->getCompleteString(), $3->getCompleteString());
973             parseContext->recover();
974             $$ = $3;
975         }
976     }
977     ;
978
979 constant_expression
980     : conditional_expression {
981         if (parseContext->constErrorCheck($1))
982             parseContext->recover();
983         $$ = $1;
984     }
985     ;
986
987 declaration
988     : function_prototype SEMICOLON   {
989         TFunction &function = *($1.function);
990         
991         TIntermAggregate *prototype = new TIntermAggregate;
992         prototype->setType(function.getReturnType());
993         prototype->setName(function.getName());
994         
995         for (int i = 0; i < function.getParamCount(); i++)
996         {
997             TParameter &param = function[i];
998             if (param.name != 0)
999             {
1000                 TVariable *variable = new TVariable(param.name, *param.type);
1001                 
1002                 prototype = parseContext->intermediate.growAggregate(prototype, parseContext->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), $1.line), $1.line);
1003             }
1004             else
1005             {
1006                 prototype = parseContext->intermediate.growAggregate(prototype, parseContext->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line);
1007             }
1008         }
1009         
1010         prototype->setOp(EOpPrototype);
1011         $$ = prototype;
1012     }
1013     | init_declarator_list SEMICOLON {
1014         if ($1.intermAggregate)
1015             $1.intermAggregate->setOp(EOpDeclaration);
1016         $$ = $1.intermAggregate;
1017     }
1018     | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
1019         parseContext->symbolTable.setDefaultPrecision( $3.type, $2 );
1020         $$ = 0;
1021     }
1022     ;
1023
1024 function_prototype
1025     : function_declarator RIGHT_PAREN  {
1026         //
1027         // Multiple declarations of the same function are allowed.
1028         //
1029         // If this is a definition, the definition production code will check for redefinitions
1030         // (we don't know at this point if it's a definition or not).
1031         //
1032         // Redeclarations are allowed.  But, return types and parameter qualifiers must match.
1033         //
1034         TFunction* prevDec = static_cast<TFunction*>(parseContext->symbolTable.find($1->getMangledName()));
1035         if (prevDec) {
1036             if (prevDec->getReturnType() != $1->getReturnType()) {
1037                 parseContext->error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getBasicString(), "");
1038                 parseContext->recover();
1039             }
1040             for (int i = 0; i < prevDec->getParamCount(); ++i) {
1041                 if ((*prevDec)[i].type->getQualifier() != (*$1)[i].type->getQualifier()) {
1042                     parseContext->error($2.line, "overloaded functions must have the same parameter qualifiers", (*$1)[i].type->getQualifierString(), "");
1043                     parseContext->recover();
1044                 }
1045             }
1046         }
1047
1048         //
1049         // If this is a redeclaration, it could also be a definition,
1050         // in which case, we want to use the variable names from this one, and not the one that's
1051         // being redeclared.  So, pass back up this declaration, not the one in the symbol table.
1052         //
1053         $$.function = $1;
1054         $$.line = $2.line;
1055
1056         parseContext->symbolTable.insert(*$$.function);
1057     }
1058     ;
1059
1060 function_declarator
1061     : function_header {
1062         $$ = $1;
1063     }
1064     | function_header_with_parameters {
1065         $$ = $1;
1066     }
1067     ;
1068
1069
1070 function_header_with_parameters
1071     : function_header parameter_declaration {
1072         // Add the parameter
1073         $$ = $1;
1074         if ($2.param.type->getBasicType() != EbtVoid)
1075             $1->addParameter($2.param);
1076         else
1077             delete $2.param.type;
1078     }
1079     | function_header_with_parameters COMMA parameter_declaration {
1080         //
1081         // Only first parameter of one-parameter functions can be void
1082         // The check for named parameters not being void is done in parameter_declarator
1083         //
1084         if ($3.param.type->getBasicType() == EbtVoid) {
1085             //
1086             // This parameter > first is void
1087             //
1088             parseContext->error($2.line, "cannot be an argument type except for '(void)'", "void", "");
1089             parseContext->recover();
1090             delete $3.param.type;
1091         } else {
1092             // Add the parameter
1093             $$ = $1;
1094             $1->addParameter($3.param);
1095         }
1096     }
1097     ;
1098
1099 function_header
1100     : fully_specified_type IDENTIFIER LEFT_PAREN {
1101         if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) {
1102             parseContext->error($2.line, "no qualifiers allowed for function return", getQualifierString($1.qualifier), "");
1103             parseContext->recover();
1104         }
1105         // make sure a sampler is not involved as well...
1106         if (parseContext->structQualifierErrorCheck($2.line, $1))
1107             parseContext->recover();
1108
1109         // Add the function as a prototype after parsing it (we do not support recursion)
1110         TFunction *function;
1111         TType type($1);
1112         function = new TFunction($2.string, type);
1113         $$ = function;
1114     }
1115     ;
1116
1117 parameter_declarator
1118     // Type + name
1119     : type_specifier IDENTIFIER {
1120         if ($1.type == EbtVoid) {
1121             parseContext->error($2.line, "illegal use of type 'void'", $2.string->c_str(), "");
1122             parseContext->recover();
1123         }
1124         if (parseContext->reservedErrorCheck($2.line, *$2.string))
1125             parseContext->recover();
1126         TParameter param = {$2.string, new TType($1)};
1127         $$.line = $2.line;
1128         $$.param = param;
1129     }
1130     | type_specifier IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
1131         // Check that we can make an array out of this type
1132         if (parseContext->arrayTypeErrorCheck($3.line, $1))
1133             parseContext->recover();
1134
1135         if (parseContext->reservedErrorCheck($2.line, *$2.string))
1136             parseContext->recover();
1137
1138         int size;
1139         if (parseContext->arraySizeErrorCheck($3.line, $4, size))
1140             parseContext->recover();
1141         $1.setArray(true, size);
1142
1143         TType* type = new TType($1);
1144         TParameter param = { $2.string, type };
1145         $$.line = $2.line;
1146         $$.param = param;
1147     }
1148     ;
1149
1150 parameter_declaration
1151     //
1152     // The only parameter qualifier a parameter can have are
1153     // IN_QUAL, OUT_QUAL, INOUT_QUAL, or CONST.
1154     //
1155
1156     //
1157     // Type + name
1158     //
1159     : type_qualifier parameter_qualifier parameter_declarator {
1160         $$ = $3;
1161         if (parseContext->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type))
1162             parseContext->recover();
1163     }
1164     | parameter_qualifier parameter_declarator {
1165         $$ = $2;
1166         if (parseContext->parameterSamplerErrorCheck($2.line, $1, *$2.param.type))
1167             parseContext->recover();
1168         if (parseContext->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type))
1169             parseContext->recover();
1170     }
1171     //
1172     // Only type
1173     //
1174     | type_qualifier parameter_qualifier parameter_type_specifier {
1175         $$ = $3;
1176         if (parseContext->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type))
1177             parseContext->recover();
1178     }
1179     | parameter_qualifier parameter_type_specifier {
1180         $$ = $2;
1181         if (parseContext->parameterSamplerErrorCheck($2.line, $1, *$2.param.type))
1182             parseContext->recover();
1183         if (parseContext->paramErrorCheck($2.line, EvqTemporary, $1, $$.param.type))
1184             parseContext->recover();
1185     }
1186     ;
1187
1188 parameter_qualifier
1189     : /* empty */ {
1190         $$ = EvqIn;
1191     }
1192     | IN_QUAL {
1193         $$ = EvqIn;
1194     }
1195     | OUT_QUAL {
1196         $$ = EvqOut;
1197     }
1198     | INOUT_QUAL {
1199         $$ = EvqInOut;
1200     }
1201     ;
1202
1203 parameter_type_specifier
1204     : type_specifier {
1205         TParameter param = { 0, new TType($1) };
1206         $$.param = param;
1207     }
1208     ;
1209
1210 init_declarator_list
1211     : single_declaration {
1212         $$ = $1;
1213         
1214         if ($$.type.precision == EbpUndefined) {
1215             $$.type.precision = parseContext->symbolTable.getDefaultPrecision($1.type.type);
1216             if (parseContext->precisionErrorCheck($1.line, $$.type.precision, $1.type.type)) {
1217                 parseContext->recover();
1218             }
1219         }
1220     }
1221     | init_declarator_list COMMA IDENTIFIER {
1222         $$.intermAggregate = parseContext->intermediate.growAggregate($1.intermNode, parseContext->intermediate.addSymbol(0, *$3.string, TType($1.type), $3.line), $3.line);
1223         
1224         if (parseContext->structQualifierErrorCheck($3.line, $$.type))
1225             parseContext->recover();
1226
1227         if (parseContext->nonInitConstErrorCheck($3.line, *$3.string, $$.type))
1228             parseContext->recover();
1229
1230         if (parseContext->nonInitErrorCheck($3.line, *$3.string, $$.type))
1231             parseContext->recover();
1232     }
1233     | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
1234         if (parseContext->structQualifierErrorCheck($3.line, $1.type))
1235             parseContext->recover();
1236
1237         if (parseContext->nonInitConstErrorCheck($3.line, *$3.string, $1.type))
1238             parseContext->recover();
1239
1240         $$ = $1;
1241
1242         if (parseContext->arrayTypeErrorCheck($4.line, $1.type) || parseContext->arrayQualifierErrorCheck($4.line, $1.type))
1243             parseContext->recover();
1244         else {
1245             $1.type.setArray(true);
1246             TVariable* variable;
1247             if (parseContext->arrayErrorCheck($4.line, *$3.string, $1.type, variable))
1248                 parseContext->recover();
1249         }
1250     }
1251     | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
1252         if (parseContext->structQualifierErrorCheck($3.line, $1.type))
1253             parseContext->recover();
1254
1255         if (parseContext->nonInitConstErrorCheck($3.line, *$3.string, $1.type))
1256             parseContext->recover();
1257
1258         $$ = $1;
1259
1260         if (parseContext->arrayTypeErrorCheck($4.line, $1.type) || parseContext->arrayQualifierErrorCheck($4.line, $1.type))
1261             parseContext->recover();
1262         else {
1263             int size;
1264             if (parseContext->arraySizeErrorCheck($4.line, $5, size))
1265                 parseContext->recover();
1266             $1.type.setArray(true, size);
1267             TVariable* variable;
1268             if (parseContext->arrayErrorCheck($4.line, *$3.string, $1.type, variable))
1269                 parseContext->recover();
1270             TType type = TType($1.type);
1271             type.setArraySize(size);
1272             $$.intermAggregate = parseContext->intermediate.growAggregate($1.intermNode, parseContext->intermediate.addSymbol(0, *$3.string, type, $3.line), $3.line);
1273         }
1274     }
1275     | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET EQUAL initializer {
1276         if (parseContext->structQualifierErrorCheck($3.line, $1.type))
1277             parseContext->recover();
1278
1279         $$ = $1;
1280
1281         TVariable* variable = 0;
1282         if (parseContext->arrayTypeErrorCheck($4.line, $1.type) || parseContext->arrayQualifierErrorCheck($4.line, $1.type))
1283             parseContext->recover();
1284         else {
1285             $1.type.setArray(true, $7->getType().getArraySize());
1286             if (parseContext->arrayErrorCheck($4.line, *$3.string, $1.type, variable))
1287                 parseContext->recover();
1288         }
1289
1290         if (parseContext->extensionErrorCheck($$.line, "GL_3DL_array_objects"))
1291             parseContext->recover();
1292         else {
1293             TIntermNode* intermNode;
1294             if (!parseContext->executeInitializer($3.line, *$3.string, $1.type, $7, intermNode, variable)) {
1295                 //
1296                 // build the intermediate representation
1297                 //
1298                 if (intermNode)
1299                     $$.intermAggregate = parseContext->intermediate.growAggregate($1.intermNode, intermNode, $6.line);
1300                 else
1301                     $$.intermAggregate = $1.intermAggregate;
1302             } else {
1303                 parseContext->recover();
1304                 $$.intermAggregate = 0;
1305             }
1306         }
1307     }
1308     | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer {
1309         if (parseContext->structQualifierErrorCheck($3.line, $1.type))
1310             parseContext->recover();
1311
1312         $$ = $1;
1313
1314         TVariable* variable = 0;
1315         if (parseContext->arrayTypeErrorCheck($4.line, $1.type) || parseContext->arrayQualifierErrorCheck($4.line, $1.type))
1316             parseContext->recover();
1317         else {
1318             int size;
1319             if (parseContext->arraySizeErrorCheck($4.line, $5, size))
1320                 parseContext->recover();
1321             $1.type.setArray(true, size);
1322             if (parseContext->arrayErrorCheck($4.line, *$3.string, $1.type, variable))
1323                 parseContext->recover();
1324         }
1325
1326         if (parseContext->extensionErrorCheck($$.line, "GL_3DL_array_objects"))
1327             parseContext->recover();
1328         else {
1329             TIntermNode* intermNode;
1330             if (!parseContext->executeInitializer($3.line, *$3.string, $1.type, $8, intermNode, variable)) {
1331                 //
1332                 // build the intermediate representation
1333                 //
1334                 if (intermNode)
1335                     $$.intermAggregate = parseContext->intermediate.growAggregate($1.intermNode, intermNode, $7.line);
1336                 else
1337                     $$.intermAggregate = $1.intermAggregate;
1338             } else {
1339                 parseContext->recover();
1340                 $$.intermAggregate = 0;
1341             }
1342         }
1343     }
1344     | init_declarator_list COMMA IDENTIFIER EQUAL initializer {
1345         if (parseContext->structQualifierErrorCheck($3.line, $1.type))
1346             parseContext->recover();
1347
1348         $$ = $1;
1349
1350         TIntermNode* intermNode;
1351         if (!parseContext->executeInitializer($3.line, *$3.string, $1.type, $5, intermNode)) {
1352             //
1353             // build the intermediate representation
1354             //
1355             if (intermNode)
1356         $$.intermAggregate = parseContext->intermediate.growAggregate($1.intermNode, intermNode, $4.line);
1357             else
1358                 $$.intermAggregate = $1.intermAggregate;
1359         } else {
1360             parseContext->recover();
1361             $$.intermAggregate = 0;
1362         }
1363     }
1364     ;
1365
1366 single_declaration
1367     : fully_specified_type {
1368         $$.type = $1;
1369         $$.intermAggregate = parseContext->intermediate.makeAggregate(parseContext->intermediate.addSymbol(0, "", TType($1), $1.line), $1.line);
1370     }
1371     | fully_specified_type IDENTIFIER {
1372         $$.intermAggregate = parseContext->intermediate.makeAggregate(parseContext->intermediate.addSymbol(0, *$2.string, TType($1), $2.line), $2.line);
1373         
1374         if (parseContext->structQualifierErrorCheck($2.line, $$.type))
1375             parseContext->recover();
1376
1377         if (parseContext->nonInitConstErrorCheck($2.line, *$2.string, $$.type))
1378             parseContext->recover();
1379             
1380             $$.type = $1;
1381
1382         if (parseContext->nonInitErrorCheck($2.line, *$2.string, $$.type))
1383             parseContext->recover();
1384     }
1385     | fully_specified_type IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
1386         $$.intermAggregate = parseContext->intermediate.makeAggregate(parseContext->intermediate.addSymbol(0, *$2.string, TType($1), $2.line), $2.line);
1387         
1388         if (parseContext->structQualifierErrorCheck($2.line, $1))
1389             parseContext->recover();
1390
1391         if (parseContext->nonInitConstErrorCheck($2.line, *$2.string, $1))
1392             parseContext->recover();
1393
1394         $$.type = $1;
1395
1396         if (parseContext->arrayTypeErrorCheck($3.line, $1) || parseContext->arrayQualifierErrorCheck($3.line, $1))
1397             parseContext->recover();
1398         else {
1399             $1.setArray(true);
1400             TVariable* variable;
1401             if (parseContext->arrayErrorCheck($3.line, *$2.string, $1, variable))
1402                 parseContext->recover();
1403         }
1404     }
1405     | fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
1406         TType type = TType($1);
1407         int size;
1408         if (parseContext->arraySizeErrorCheck($2.line, $4, size))
1409             parseContext->recover();
1410         type.setArraySize(size);
1411         $$.intermAggregate = parseContext->intermediate.makeAggregate(parseContext->intermediate.addSymbol(0, *$2.string, type, $2.line), $2.line);
1412         
1413         if (parseContext->structQualifierErrorCheck($2.line, $1))
1414             parseContext->recover();
1415
1416         if (parseContext->nonInitConstErrorCheck($2.line, *$2.string, $1))
1417             parseContext->recover();
1418
1419         $$.type = $1;
1420
1421         if (parseContext->arrayTypeErrorCheck($3.line, $1) || parseContext->arrayQualifierErrorCheck($3.line, $1))
1422             parseContext->recover();
1423         else {
1424             int size;
1425             if (parseContext->arraySizeErrorCheck($3.line, $4, size))
1426                 parseContext->recover();
1427
1428             $1.setArray(true, size);
1429             TVariable* variable;
1430             if (parseContext->arrayErrorCheck($3.line, *$2.string, $1, variable))
1431                 parseContext->recover();
1432         }
1433     }
1434     | fully_specified_type IDENTIFIER EQUAL initializer {
1435         if (parseContext->structQualifierErrorCheck($2.line, $1))
1436             parseContext->recover();
1437
1438         $$.type = $1;
1439
1440         TIntermNode* intermNode;
1441         if (!parseContext->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) {
1442         //
1443         // Build intermediate representation
1444         //
1445             if(intermNode)
1446                 $$.intermAggregate = parseContext->intermediate.makeAggregate(intermNode, $3.line);
1447             else
1448                 $$.intermAggregate = 0;
1449         } else {
1450             parseContext->recover();
1451             $$.intermAggregate = 0;
1452         }
1453     }
1454     | INVARIANT IDENTIFIER {
1455         VERTEX_ONLY("invariant declaration", $1.line);
1456         $$.qualifier = EvqInvariantVaryingOut;
1457         $$.intermAggregate = 0;
1458     }
1459
1460 //
1461 // Place holder for the pack/unpack languages.
1462 //
1463 //    | buffer_specifier {
1464 //        $$.intermAggregate = 0;
1465 //    }
1466     ;
1467
1468 // Grammar Note:  No 'enum', or 'typedef'.
1469
1470 //
1471 // Place holder for the pack/unpack languages.
1472 //
1473 //%type <interm> buffer_declaration
1474 //%type <interm.type> buffer_specifier input_or_output buffer_declaration_list
1475 //buffer_specifier
1476 //    : input_or_output LEFT_BRACE buffer_declaration_list RIGHT_BRACE {
1477 //    }
1478 //    ;
1479 //
1480 //input_or_output
1481 //    : INPUT {
1482 //        if (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "input"))
1483 //            parseContext->recover();
1484 //        UNPACK_ONLY("input", $1.line);
1485 //        $$.qualifier = EvqInput;
1486 //    }
1487 //    | OUTPUT {
1488 //        if (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "output"))
1489 //            parseContext->recover();
1490 //        PACK_ONLY("output", $1.line);
1491 //        $$.qualifier = EvqOutput;
1492 //    }
1493 //    ;
1494
1495 //
1496 // Place holder for the pack/unpack languages.
1497 //
1498 //buffer_declaration_list
1499 //    : buffer_declaration {
1500 //    }
1501 //    | buffer_declaration_list buffer_declaration {
1502 //    }
1503 //    ;
1504
1505 //
1506 // Input/output semantics:
1507 //   float must be 16 or 32 bits
1508 //   float alignment restrictions?
1509 //   check for only one input and only one output
1510 //   sum of bitfields has to be multiple of 32
1511 //
1512
1513 //
1514 // Place holder for the pack/unpack languages.
1515 //
1516 //buffer_declaration
1517 //    : type_specifier IDENTIFIER COLON constant_expression SEMICOLON {
1518 //        if (parseContext->reservedErrorCheck($2.line, *$2.string, parseContext))
1519 //            parseContext->recover();
1520 //        $$.variable = new TVariable($2.string, $1);
1521 //        if (! parseContext->symbolTable.insert(*$$.variable)) {
1522 //            parseContext->error($2.line, "redefinition", $$.variable->getName().c_str(), "");
1523 //            parseContext->recover();
1524 //            // don't have to delete $$.variable, the pool pop will take care of it
1525 //        }
1526 //    }
1527 //    ;
1528
1529 fully_specified_type
1530     : type_specifier {
1531         $$ = $1;
1532
1533         if ($1.array) {
1534             if (parseContext->extensionErrorCheck($1.line, "GL_3DL_array_objects")) {
1535                 parseContext->recover();
1536                 $1.setArray(false);
1537             }
1538         }
1539     }
1540     | type_qualifier type_specifier  {
1541         if ($2.array && parseContext->extensionErrorCheck($2.line, "GL_3DL_array_objects")) {
1542             parseContext->recover();
1543             $2.setArray(false);
1544         }
1545         if ($2.array && parseContext->arrayQualifierErrorCheck($2.line, $1)) {
1546             parseContext->recover();
1547             $2.setArray(false);
1548         }
1549
1550         if ($1.qualifier == EvqAttribute &&
1551             ($2.type == EbtBool || $2.type == EbtInt)) {
1552             parseContext->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), "");
1553             parseContext->recover();
1554         }
1555         if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) &&
1556             ($2.type == EbtBool || $2.type == EbtInt)) {
1557             parseContext->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier), "");
1558             parseContext->recover();
1559         }
1560         $$ = $2;
1561         $$.qualifier = $1.qualifier;
1562     }
1563     ;
1564
1565 type_qualifier
1566     : CONST_QUAL {
1567         $$.setBasic(EbtVoid, EvqConst, $1.line);
1568     }
1569     | ATTRIBUTE {
1570         VERTEX_ONLY("attribute", $1.line);
1571         if (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "attribute"))
1572             parseContext->recover();
1573         $$.setBasic(EbtVoid, EvqAttribute, $1.line);
1574     }
1575     | VARYING {
1576         if (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "varying"))
1577             parseContext->recover();
1578         if (parseContext->language == EShLangVertex)
1579             $$.setBasic(EbtVoid, EvqVaryingOut, $1.line);
1580         else
1581             $$.setBasic(EbtVoid, EvqVaryingIn, $1.line);
1582     }
1583     | INVARIANT VARYING {
1584         if (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "invariant varying"))
1585             parseContext->recover();
1586         if (parseContext->language == EShLangVertex)
1587             $$.setBasic(EbtVoid, EvqInvariantVaryingOut, $1.line);
1588         else
1589             $$.setBasic(EbtVoid, EvqInvariantVaryingIn, $1.line);
1590     }
1591     | UNIFORM {
1592         if (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "uniform"))
1593             parseContext->recover();
1594         $$.setBasic(EbtVoid, EvqUniform, $1.line);
1595     }
1596     ;
1597
1598 type_specifier
1599     : type_specifier_no_prec {
1600         $$ = $1;
1601     }
1602     | precision_qualifier type_specifier_no_prec {
1603         $$ = $2;
1604         $$.precision = $1;
1605     }
1606     ;
1607
1608 precision_qualifier
1609     : HIGH_PRECISION {
1610         $$ = EbpHigh;
1611     }
1612     | MEDIUM_PRECISION {
1613         $$ = EbpMedium;
1614     }
1615     | LOW_PRECISION  {
1616         $$ = EbpLow;
1617     }
1618     ;
1619
1620 type_specifier_no_prec
1621     : type_specifier_nonarray {
1622         $$ = $1;
1623     }
1624     | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET {
1625         $$ = $1;
1626
1627         if (parseContext->arrayTypeErrorCheck($2.line, $1))
1628             parseContext->recover();
1629         else {
1630             int size;
1631             if (parseContext->arraySizeErrorCheck($2.line, $3, size))
1632                 parseContext->recover();
1633             $$.setArray(true, size);
1634         }
1635     }
1636     ;
1637
1638 type_specifier_nonarray
1639     : VOID_TYPE {
1640         TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1641         $$.setBasic(EbtVoid, qual, $1.line);
1642     }
1643     | FLOAT_TYPE {
1644         TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1645         $$.setBasic(EbtFloat, qual, $1.line);
1646     }
1647     | INT_TYPE {
1648         TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1649         $$.setBasic(EbtInt, qual, $1.line);
1650     }
1651     | BOOL_TYPE {
1652         TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1653         $$.setBasic(EbtBool, qual, $1.line);
1654     }
1655 //    | UNSIGNED INT_TYPE {
1656 //        PACK_UNPACK_ONLY("unsigned", $1.line);
1657 //        TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1658 //        $$.setBasic(EbtInt, qual, $1.line);
1659 //    }
1660     | VEC2 {
1661         TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1662         $$.setBasic(EbtFloat, qual, $1.line);
1663         $$.setAggregate(2);
1664     }
1665     | VEC3 {
1666         TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1667         $$.setBasic(EbtFloat, qual, $1.line);
1668         $$.setAggregate(3);
1669     }
1670     | VEC4 {
1671         TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1672         $$.setBasic(EbtFloat, qual, $1.line);
1673         $$.setAggregate(4);
1674     }
1675     | BVEC2 {
1676         TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1677         $$.setBasic(EbtBool, qual, $1.line);
1678         $$.setAggregate(2);
1679     }
1680     | BVEC3 {
1681         TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1682         $$.setBasic(EbtBool, qual, $1.line);
1683         $$.setAggregate(3);
1684     }
1685     | BVEC4 {
1686         TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1687         $$.setBasic(EbtBool, qual, $1.line);
1688         $$.setAggregate(4);
1689     }
1690     | IVEC2 {
1691         TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1692         $$.setBasic(EbtInt, qual, $1.line);
1693         $$.setAggregate(2);
1694     }
1695     | IVEC3 {
1696         TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1697         $$.setBasic(EbtInt, qual, $1.line);
1698         $$.setAggregate(3);
1699     }
1700     | IVEC4 {
1701         TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1702         $$.setBasic(EbtInt, qual, $1.line);
1703         $$.setAggregate(4);
1704     }
1705     | MATRIX2 {
1706         FRAG_VERT_ONLY("mat2", $1.line);
1707         TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1708         $$.setBasic(EbtFloat, qual, $1.line);
1709         $$.setAggregate(2, true);
1710     }
1711     | MATRIX3 {
1712         FRAG_VERT_ONLY("mat3", $1.line);
1713         TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1714         $$.setBasic(EbtFloat, qual, $1.line);
1715         $$.setAggregate(3, true);
1716     }
1717     | MATRIX4 {
1718         FRAG_VERT_ONLY("mat4", $1.line);
1719         TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1720         $$.setBasic(EbtFloat, qual, $1.line);
1721         $$.setAggregate(4, true);
1722     }
1723     | SAMPLER2D {
1724         FRAG_VERT_ONLY("sampler2D", $1.line);
1725         TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1726         $$.setBasic(EbtSampler2D, qual, $1.line);
1727     }
1728     | SAMPLERCUBE {
1729         FRAG_VERT_ONLY("samplerCube", $1.line);
1730         TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1731         $$.setBasic(EbtSamplerCube, qual, $1.line);
1732     }
1733     | struct_specifier {
1734         FRAG_VERT_ONLY("struct", $1.line);
1735         $$ = $1;
1736         $$.qualifier = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1737     }
1738     | TYPE_NAME {
1739         //
1740         // This is for user defined type names.  The lexical phase looked up the
1741         // type.
1742         //
1743         TType& structure = static_cast<TVariable*>($1.symbol)->getType();
1744         TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1745         $$.setBasic(EbtStruct, qual, $1.line);
1746         $$.userDef = &structure;
1747     }
1748     ;
1749
1750 struct_specifier
1751     : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE {
1752         if (parseContext->reservedErrorCheck($2.line, *$2.string))
1753             parseContext->recover();
1754
1755         TType* structure = new TType($4, *$2.string);
1756         TVariable* userTypeDef = new TVariable($2.string, *structure, true);
1757         if (! parseContext->symbolTable.insert(*userTypeDef)) {
1758             parseContext->error($2.line, "redefinition", $2.string->c_str(), "struct");
1759             parseContext->recover();
1760         }
1761         $$.setBasic(EbtStruct, EvqTemporary, $1.line);
1762         $$.userDef = structure;
1763     }
1764     | STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE {
1765         TType* structure = new TType($3, TString(""));
1766         $$.setBasic(EbtStruct, EvqTemporary, $1.line);
1767         $$.userDef = structure;
1768     }
1769     ;
1770
1771 struct_declaration_list
1772     : struct_declaration {
1773         $$ = $1;
1774     }
1775     | struct_declaration_list struct_declaration {
1776         $$ = $1;
1777         for (unsigned int i = 0; i < $2->size(); ++i) {
1778             for (unsigned int j = 0; j < $$->size(); ++j) {
1779                 if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) {
1780                     parseContext->error((*$2)[i].line, "duplicate field name in structure:", "struct", (*$2)[i].type->getFieldName().c_str());
1781                     parseContext->recover();
1782                 }
1783             }
1784             $$->push_back((*$2)[i]);
1785         }
1786     }
1787     ;
1788
1789 struct_declaration
1790     : type_specifier struct_declarator_list SEMICOLON {
1791         $$ = $2;
1792
1793         if (parseContext->voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) {
1794             parseContext->recover();
1795         }
1796         for (unsigned int i = 0; i < $$->size(); ++i) {
1797             //
1798             // Careful not to replace already known aspects of type, like array-ness
1799             //
1800             TType* type = (*$$)[i].type;
1801             type->setBasicType($1.type);
1802             type->setNominalSize($1.size);
1803             type->setMatrix($1.matrix);
1804
1805             // don't allow arrays of arrays
1806             if (type->isArray()) {
1807                 if (parseContext->arrayTypeErrorCheck($1.line, $1))
1808                     parseContext->recover();
1809             }
1810             if ($1.array)
1811                 type->setArraySize($1.arraySize);
1812             if ($1.userDef) {
1813                 type->setStruct($1.userDef->getStruct());
1814                 type->setTypeName($1.userDef->getTypeName());
1815             }
1816         }
1817     }
1818     ;
1819
1820 struct_declarator_list
1821     : struct_declarator {
1822         $$ = NewPoolTTypeList();
1823         $$->push_back($1);
1824     }
1825     | struct_declarator_list COMMA struct_declarator {
1826         $$->push_back($3);
1827     }
1828     ;
1829
1830 struct_declarator
1831     : IDENTIFIER {
1832         if (parseContext->reservedErrorCheck($1.line, *$1.string))
1833             parseContext->recover();
1834
1835         $$.type = new TType(EbtVoid, EbpUndefined);
1836         $$.line = $1.line;
1837         $$.type->setFieldName(*$1.string);
1838     }
1839     | IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
1840         if (parseContext->reservedErrorCheck($1.line, *$1.string))
1841             parseContext->recover();
1842
1843         $$.type = new TType(EbtVoid, EbpUndefined);
1844         $$.line = $1.line;
1845         $$.type->setFieldName(*$1.string);
1846
1847         int size;
1848         if (parseContext->arraySizeErrorCheck($2.line, $3, size))
1849             parseContext->recover();
1850         $$.type->setArraySize(size);
1851     }
1852     ;
1853
1854 initializer
1855     : assignment_expression { $$ = $1; }
1856     ;
1857
1858 declaration_statement
1859     : declaration { $$ = $1; }
1860     ;
1861
1862 statement
1863     : compound_statement  { $$ = $1; }
1864     | simple_statement    { $$ = $1; }
1865     ;
1866
1867 // Grammar Note:  No labeled statements; 'goto' is not supported.
1868
1869 simple_statement
1870     : declaration_statement { $$ = $1; }
1871     | expression_statement  { $$ = $1; }
1872     | selection_statement   { $$ = $1; }
1873     | iteration_statement   { $$ = $1; }
1874     | jump_statement        { $$ = $1; }
1875     ;
1876
1877 compound_statement
1878     : LEFT_BRACE RIGHT_BRACE { $$ = 0; }
1879     | LEFT_BRACE { parseContext->symbolTable.push(); } statement_list { parseContext->symbolTable.pop(); } RIGHT_BRACE {
1880         if ($3 != 0)
1881             $3->setOp(EOpSequence);
1882         $$ = $3;
1883     }
1884     ;
1885
1886 statement_no_new_scope
1887     : compound_statement_no_new_scope { $$ = $1; }
1888     | simple_statement                { $$ = $1; }
1889     ;
1890
1891 compound_statement_no_new_scope
1892     // Statement that doesn't create a new scope, for selection_statement, iteration_statement
1893     : LEFT_BRACE RIGHT_BRACE {
1894         $$ = 0;
1895     }
1896     | LEFT_BRACE statement_list RIGHT_BRACE {
1897         if ($2)
1898             $2->setOp(EOpSequence);
1899         $$ = $2;
1900     }
1901     ;
1902
1903 statement_list
1904     : statement {
1905         $$ = parseContext->intermediate.makeAggregate($1, 0);
1906     }
1907     | statement_list statement {
1908         $$ = parseContext->intermediate.growAggregate($1, $2, 0);
1909     }
1910     ;
1911
1912 expression_statement
1913     : SEMICOLON  { $$ = 0; }
1914     | expression SEMICOLON  { $$ = static_cast<TIntermNode*>($1); }
1915     ;
1916
1917 selection_statement
1918     : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
1919         if (parseContext->boolErrorCheck($1.line, $3))
1920             parseContext->recover();
1921         $$ = parseContext->intermediate.addSelection($3, $5, $1.line);
1922     }
1923     ;
1924
1925 selection_rest_statement
1926     : statement ELSE statement {
1927         $$.node1 = $1;
1928         $$.node2 = $3;
1929     }
1930     | statement {
1931         $$.node1 = $1;
1932         $$.node2 = 0;
1933     }
1934     ;
1935
1936 // Grammar Note:  No 'switch'.  Switch statements not supported.
1937
1938 condition
1939     // In 1996 c++ draft, conditions can include single declarations
1940     : expression {
1941         $$ = $1;
1942         if (parseContext->boolErrorCheck($1->getLine(), $1))
1943             parseContext->recover();
1944     }
1945     | fully_specified_type IDENTIFIER EQUAL initializer {
1946         TIntermNode* intermNode;
1947         if (parseContext->structQualifierErrorCheck($2.line, $1))
1948             parseContext->recover();
1949         if (parseContext->boolErrorCheck($2.line, $1))
1950             parseContext->recover();
1951
1952         if (!parseContext->executeInitializer($2.line, *$2.string, $1, $4, intermNode))
1953             $$ = $4;
1954         else {
1955             parseContext->recover();
1956             $$ = 0;
1957         }
1958     }
1959     ;
1960
1961 iteration_statement
1962     : WHILE LEFT_PAREN { parseContext->symbolTable.push(); ++parseContext->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope {
1963         parseContext->symbolTable.pop();
1964         $$ = parseContext->intermediate.addLoop(0, $6, $4, 0, true, $1.line);
1965         --parseContext->loopNestingLevel;
1966     }
1967     | DO { ++parseContext->loopNestingLevel; } statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
1968         if (parseContext->boolErrorCheck($8.line, $6))
1969             parseContext->recover();
1970
1971         $$ = parseContext->intermediate.addLoop(0, $3, $6, 0, false, $4.line);
1972         --parseContext->loopNestingLevel;
1973     }
1974     | FOR LEFT_PAREN { parseContext->symbolTable.push(); ++parseContext->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
1975         parseContext->symbolTable.pop();
1976         $$ = parseContext->intermediate.addLoop($4, $7, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), true, $1.line);
1977         --parseContext->loopNestingLevel;
1978     }
1979     ;
1980
1981 for_init_statement
1982     : expression_statement {
1983         $$ = $1;
1984     }
1985     | declaration_statement {
1986         $$ = $1;
1987     }
1988     ;
1989
1990 conditionopt
1991     : condition {
1992         $$ = $1;
1993     }
1994     | /* May be null */ {
1995         $$ = 0;
1996     }
1997     ;
1998
1999 for_rest_statement
2000     : conditionopt SEMICOLON {
2001         $$.node1 = $1;
2002         $$.node2 = 0;
2003     }
2004     | conditionopt SEMICOLON expression  {
2005         $$.node1 = $1;
2006         $$.node2 = $3;
2007     }
2008     ;
2009
2010 jump_statement
2011     : CONTINUE SEMICOLON {
2012         if (parseContext->loopNestingLevel <= 0) {
2013             parseContext->error($1.line, "continue statement only allowed in loops", "", "");
2014             parseContext->recover();
2015         }
2016         $$ = parseContext->intermediate.addBranch(EOpContinue, $1.line);
2017     }
2018     | BREAK SEMICOLON {
2019         if (parseContext->loopNestingLevel <= 0) {
2020             parseContext->error($1.line, "break statement only allowed in loops", "", "");
2021             parseContext->recover();
2022         }
2023         $$ = parseContext->intermediate.addBranch(EOpBreak, $1.line);
2024     }
2025     | RETURN SEMICOLON {
2026         $$ = parseContext->intermediate.addBranch(EOpReturn, $1.line);
2027         if (parseContext->currentFunctionType->getBasicType() != EbtVoid) {
2028             parseContext->error($1.line, "non-void function must return a value", "return", "");
2029             parseContext->recover();
2030         }
2031     }
2032     | RETURN expression SEMICOLON {
2033         $$ = parseContext->intermediate.addBranch(EOpReturn, $2, $1.line);
2034         parseContext->functionReturnsValue = true;
2035         if (parseContext->currentFunctionType->getBasicType() == EbtVoid) {
2036             parseContext->error($1.line, "void function cannot return a value", "return", "");
2037             parseContext->recover();
2038         } else if (*(parseContext->currentFunctionType) != $2->getType()) {
2039             parseContext->error($1.line, "function return is not matching type:", "return", "");
2040             parseContext->recover();
2041         }
2042     }
2043     | DISCARD SEMICOLON {
2044         FRAG_ONLY("discard", $1.line);
2045         $$ = parseContext->intermediate.addBranch(EOpKill, $1.line);
2046     }
2047     ;
2048
2049 // Grammar Note:  No 'goto'.  Gotos are not supported.
2050
2051 translation_unit
2052     : external_declaration {
2053         $$ = $1;
2054         parseContext->treeRoot = $$;
2055     }
2056     | translation_unit external_declaration {
2057         $$ = parseContext->intermediate.growAggregate($1, $2, 0);
2058         parseContext->treeRoot = $$;
2059     }
2060     ;
2061
2062 external_declaration
2063     : function_definition {
2064         $$ = $1;
2065     }
2066     | declaration {
2067         $$ = $1;
2068     }
2069     ;
2070
2071 function_definition
2072     : function_prototype {
2073         TFunction& function = *($1.function);
2074         TFunction* prevDec = static_cast<TFunction*>(parseContext->symbolTable.find(function.getMangledName()));
2075         //
2076         // Note:  'prevDec' could be 'function' if this is the first time we've seen function
2077         // as it would have just been put in the symbol table.  Otherwise, we're looking up
2078         // an earlier occurance.
2079         //
2080         if (prevDec->isDefined()) {
2081             //
2082             // Then this function already has a body.
2083             //
2084             parseContext->error($1.line, "function already has a body", function.getName().c_str(), "");
2085             parseContext->recover();
2086         }
2087         prevDec->setDefined();
2088
2089         //
2090         // Raise error message if main function takes any parameters or return anything other than void
2091         //
2092         if (function.getName() == "main") {
2093             if (function.getParamCount() > 0) {
2094                 parseContext->error($1.line, "function cannot take any parameter(s)", function.getName().c_str(), "");
2095                 parseContext->recover();
2096             }
2097             if (function.getReturnType().getBasicType() != EbtVoid) {
2098                 parseContext->error($1.line, "", function.getReturnType().getBasicString(), "main function cannot return a value");
2099                 parseContext->recover();
2100             }
2101         }
2102
2103         //
2104         // New symbol table scope for body of function plus its arguments
2105         //
2106         parseContext->symbolTable.push();
2107
2108         //
2109         // Remember the return type for later checking for RETURN statements.
2110         //
2111         parseContext->currentFunctionType = &(prevDec->getReturnType());
2112         parseContext->functionReturnsValue = false;
2113
2114         //
2115         // Insert parameters into the symbol table.
2116         // If the parameter has no name, it's not an error, just don't insert it
2117         // (could be used for unused args).
2118         //
2119         // Also, accumulate the list of parameters into the HIL, so lower level code
2120         // knows where to find parameters.
2121         //
2122         TIntermAggregate* paramNodes = new TIntermAggregate;
2123         for (int i = 0; i < function.getParamCount(); i++) {
2124             TParameter& param = function[i];
2125             if (param.name != 0) {
2126                 TVariable *variable = new TVariable(param.name, *param.type);
2127                 //
2128                 // Insert the parameters with name in the symbol table.
2129                 //
2130                 if (! parseContext->symbolTable.insert(*variable)) {
2131                     parseContext->error($1.line, "redefinition", variable->getName().c_str(), "");
2132                     parseContext->recover();
2133                     delete variable;
2134                 }
2135                 //
2136                 // Transfer ownership of name pointer to symbol table.
2137                 //
2138                 param.name = 0;
2139
2140                 //
2141                 // Add the parameter to the HIL
2142                 //
2143                 paramNodes = parseContext->intermediate.growAggregate(
2144                                                paramNodes,
2145                                                parseContext->intermediate.addSymbol(variable->getUniqueId(),
2146                                                                        variable->getName(),
2147                                                                        variable->getType(), $1.line),
2148                                                $1.line);
2149             } else {
2150                 paramNodes = parseContext->intermediate.growAggregate(paramNodes, parseContext->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line);
2151             }
2152         }
2153         parseContext->intermediate.setAggregateOperator(paramNodes, EOpParameters, $1.line);
2154         $1.intermAggregate = paramNodes;
2155         parseContext->loopNestingLevel = 0;
2156     }
2157     compound_statement_no_new_scope {
2158         //?? Check that all paths return a value if return type != void ?
2159         //   May be best done as post process phase on intermediate code
2160         if (parseContext->currentFunctionType->getBasicType() != EbtVoid && ! parseContext->functionReturnsValue) {
2161             parseContext->error($1.line, "function does not return a value:", "", $1.function->getName().c_str());
2162             parseContext->recover();
2163         }
2164         parseContext->symbolTable.pop();
2165         $$ = parseContext->intermediate.growAggregate($1.intermAggregate, $3, 0);
2166         parseContext->intermediate.setAggregateOperator($$, EOpFunction, $1.line);
2167         $$->getAsAggregate()->setName($1.function->getMangledName().c_str());
2168         $$->getAsAggregate()->setType($1.function->getReturnType());
2169
2170         // store the pragma information for debug and optimize and other vendor specific
2171         // information. This information can be queried from the parse tree
2172         $$->getAsAggregate()->setOptimize(parseContext->contextPragma.optimize);
2173         $$->getAsAggregate()->setDebug(parseContext->contextPragma.debug);
2174         $$->getAsAggregate()->addToPragmaTable(parseContext->contextPragma.pragmaTable);
2175     }
2176     ;
2177
2178 %%