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.
8 * This is bison grammar and production code for parsing the OpenGL 2.0 shading
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.
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.
28 #include "compiler/SymbolTable.h"
29 #include "compiler/ParseHelper.h"
30 #include "GLSLANG/ShaderLang.h"
32 #define YYPARSE_PARAM parseContextLocal
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.
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*);
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(); \
51 #define VERTEX_ONLY(S, L) { \
52 if (parseContext->language != EShLangVertex) { \
53 parseContext->error(L, " supported in vertex shaders only ", S, "", ""); \
54 parseContext->recover(); \
58 #define FRAG_ONLY(S, L) { \
59 if (parseContext->language != EShLangFragment) { \
60 parseContext->error(L, " supported in fragment shaders only ", S, "", ""); \
61 parseContext->recover(); \
65 #define PACK_ONLY(S, L) { \
66 if (parseContext->language != EShLangPack) { \
67 parseContext->error(L, " supported in pack shaders only ", S, "", ""); \
68 parseContext->recover(); \
72 #define UNPACK_ONLY(S, L) { \
73 if (parseContext->language != EShLangUnpack) { \
74 parseContext->error(L, " supported in unpack shaders only ", S, "", ""); \
75 parseContext->recover(); \
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(); \
102 TIntermNode* intermNode;
103 TIntermNodePair nodePair;
104 TIntermTyped* intermTypedNode;
105 TIntermAggregate* intermAggregate;
109 TPrecision precision;
110 TQualifier qualifier;
120 extern int yylex(YYSTYPE*, void*);
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
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
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
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
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
165 %type <interm> parameter_declaration parameter_declarator parameter_type_specifier
166 %type <interm.qualifier> parameter_qualifier
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
179 %start translation_unit
184 // The symbol table search was done in the lexical phase
185 const TSymbol* symbol = $1.symbol;
186 const TVariable* variable;
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;
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();
200 variable = static_cast<const TVariable*>(symbol);
203 // don't delete $1.string, it's used by error recovery, and the pool
204 // pop will reclaim the memory
206 if (variable->getType().getQualifier() == EvqConst ) {
207 ConstantUnion* constArray = variable->getConstPointer();
208 TType t(variable->getType());
209 $$ = parseContext->intermediate.addConstantUnion(constArray, t, $1.line);
211 $$ = parseContext->intermediate.addSymbol(variable->getUniqueId(),
213 variable->getType(), $1.line);
218 : variable_identifier {
223 // INT_TYPE is only 16-bit plus sign bit for vertex/fragment shaders,
224 // check for overflow for constants
226 if (abs($1.i) >= (1 << 16)) {
227 parseContext->error($1.line, " integer constant overflow", "", "");
228 parseContext->recover();
230 ConstantUnion *unionArray = new ConstantUnion[1];
231 unionArray->setIConst($1.i);
232 $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $1.line);
235 ConstantUnion *unionArray = new ConstantUnion[1];
236 unionArray->setFConst($1.f);
237 $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line);
240 ConstantUnion *unionArray = new ConstantUnion[1];
241 unionArray->setBConst($1.b);
242 $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $1.line);
244 | LEFT_PAREN expression RIGHT_PAREN {
250 : primary_expression {
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(), "");
258 parseContext->error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression", "");
259 parseContext->recover();
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;
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);
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();
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();
284 if (parseContext->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line))
285 parseContext->recover();
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();
292 $$ = parseContext->intermediate.addIndex(EOpIndexDirect, $1, $3, $2.line);
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();
300 $$ = parseContext->intermediate.addIndex(EOpIndexIndirect, $1, $3, $2.line);
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()));
311 $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize(), $1->isMatrix()));
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));
324 $$->setType($1->getType());
329 | postfix_expression DOT FIELD_SELECTION {
331 parseContext->error($3.line, "cannot apply dot operator to an array", ".", "");
332 parseContext->recover();
335 if ($1->isVector()) {
336 TVectorFields fields;
337 if (! parseContext->parseVectorFields(*$3.string, $1->getNominalSize(), fields, $3.line)) {
339 fields.offsets[0] = 0;
340 parseContext->recover();
343 if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields
344 $$ = parseContext->addConstVectorNode(fields, $1, $3.line);
346 parseContext->recover();
350 $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, (int) (*$3.string).size()));
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()));
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()));
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;
372 parseContext->recover();
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()));
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()));
390 } else if ($1->getBasicType() == EbtStruct) {
391 bool fieldFound = false;
392 const TTypeList* fields = $1->getType().getStruct();
394 parseContext->error($2.line, "structure has no fields", "Internal Error", "");
395 parseContext->recover();
399 for (i = 0; i < fields->size(); ++i) {
400 if ((*fields)[i].type->getFieldName() == *$3.string) {
406 if ($1->getType().getQualifier() == EvqConst) {
407 $$ = parseContext->addConstStruct(*$3.string, $1, $2.line);
409 parseContext->recover();
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);
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);
426 parseContext->error($2.line, " no such field in structure", $3.string->c_str(), "");
427 parseContext->recover();
432 parseContext->error($2.line, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str(), "");
433 parseContext->recover();
436 // don't delete $3.string, it's from the pool
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);
443 parseContext->unaryOpError($2.line, "++", $1->getCompleteString());
444 parseContext->recover();
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);
453 parseContext->unaryOpError($2.line, "--", $1->getCompleteString());
454 parseContext->recover();
462 if (parseContext->integerErrorCheck($1, "[]"))
463 parseContext->recover();
469 : function_call_or_method {
470 TFunction* fnCall = $1.function;
471 TOperator op = fnCall->getBuiltInOp();
476 // Then this should be a constructor.
477 // Don't go through the symbol table for constructors.
478 // Their parameters will be verified algorithmically.
480 TType type(EbtVoid, EbpUndefined); // use this to get the type back
481 if (parseContext->constructorErrorCheck($1.line, $1.intermNode, *fnCall, op, &type)) {
485 // It's a constructor, of type 'type'.
487 $$ = parseContext->addConstructor($1.intermNode, &type, op, fnCall, $1.line);
491 parseContext->recover();
492 $$ = parseContext->intermediate.setAggregateOperator(0, op, $1.line);
497 // Not a constructor. Find it in the symbol table.
499 const TFunction* fnCandidate;
501 fnCandidate = parseContext->findFunction($1.line, fnCall, &builtIn);
504 // A declared function. But, it might still map to a built-in
507 op = fnCandidate->getBuiltInOp();
508 if (builtIn && op != EOpNull) {
510 // A function call mapped to a built-in operation.
512 if (fnCandidate->getParamCount() == 1) {
514 // Treat it like a built-in unary operator.
516 $$ = parseContext->intermediate.addUnaryMath(op, $1.intermNode, 0, parseContext->symbolTable);
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());
524 $$ = parseContext->intermediate.setAggregateOperator($1.intermAggregate, op, $1.line);
527 // This is a real function call
529 $$ = parseContext->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, $1.line);
530 $$->setType(fnCandidate->getReturnType());
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
536 $$->getAsAggregate()->setUserDefined();
537 $$->getAsAggregate()->setName(fnCandidate->getMangledName());
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();
549 qualifierList.push_back(qual);
552 $$->setType(fnCandidate->getReturnType());
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();
566 function_call_or_method
567 : function_call_generic {
570 | postfix_expression DOT function_call_generic {
571 parseContext->error($3.line, "methods are not supported", "", "");
572 parseContext->recover();
577 function_call_generic
578 : function_call_header_with_parameters RIGHT_PAREN {
582 | function_call_header_no_parameters RIGHT_PAREN {
588 function_call_header_no_parameters
589 : function_call_header VOID_TYPE {
593 | function_call_header {
599 function_call_header_with_parameters
600 : function_call_header assignment_expression {
601 TParameter param = { 0, new TType($2->getType()) };
602 $1->addParameter(param);
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);
615 : function_identifier LEFT_PAREN {
620 // Grammar Note: Constructors look like functions, but are recognized as types.
628 if (parseContext->extensionErrorCheck($1.line, "GL_3DL_array_objects")) {
629 parseContext->recover();
635 TString tempString = "";
637 TFunction *function = new TFunction(&tempString, type, EOpConstructStruct);
640 TOperator op = EOpNull;
645 case 2: op = EOpConstructMat2; break;
646 case 3: op = EOpConstructMat3; break;
647 case 4: op = EOpConstructMat4; break;
651 case 1: op = EOpConstructFloat; break;
652 case 2: op = EOpConstructVec2; break;
653 case 3: op = EOpConstructVec3; break;
654 case 4: op = EOpConstructVec4; break;
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;
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;
676 parseContext->error($1.line, "cannot construct this type", getBasicString($1.type), "");
677 parseContext->recover();
679 op = EOpConstructFloat;
681 TString tempString = "";
683 TFunction *function = new TFunction(&tempString, type, op);
688 if (parseContext->reservedErrorCheck($1.line, *$1.string))
689 parseContext->recover();
690 TType type(EbtVoid, EbpUndefined);
691 TFunction *function = new TFunction($1.string, type);
695 if (parseContext->reservedErrorCheck($1.line, *$1.string))
696 parseContext->recover();
697 TType type(EbtVoid, EbpUndefined);
698 TFunction *function = new TFunction($1.string, type);
704 : postfix_expression {
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);
712 parseContext->unaryOpError($1.line, "++", $2->getCompleteString());
713 parseContext->recover();
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);
722 parseContext->unaryOpError($1.line, "--", $2->getCompleteString());
723 parseContext->recover();
727 | unary_operator unary_expression {
728 if ($1.op != EOpNull) {
729 $$ = parseContext->intermediate.addUnaryMath($1.op, $2, $1.line, parseContext->symbolTable);
731 const char* errorOp = "";
733 case EOpNegative: errorOp = "-"; break;
734 case EOpLogicalNot: errorOp = "!"; break;
737 parseContext->unaryOpError($1.line, errorOp, $2->getCompleteString());
738 parseContext->recover();
745 // Grammar Note: No traditional style type casts.
748 : PLUS { $$.line = $1.line; $$.op = EOpNull; }
749 | DASH { $$.line = $1.line; $$.op = EOpNegative; }
750 | BANG { $$.line = $1.line; $$.op = EOpLogicalNot; }
752 // Grammar Note: No '*' or '&' unary ops. Pointers are not supported.
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);
760 parseContext->binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString());
761 parseContext->recover();
765 | multiplicative_expression SLASH unary_expression {
766 FRAG_VERT_ONLY("/", $2.line);
767 $$ = parseContext->intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line, parseContext->symbolTable);
769 parseContext->binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString());
770 parseContext->recover();
777 : multiplicative_expression { $$ = $1; }
778 | additive_expression PLUS multiplicative_expression {
779 $$ = parseContext->intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line, parseContext->symbolTable);
781 parseContext->binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString());
782 parseContext->recover();
786 | additive_expression DASH multiplicative_expression {
787 $$ = parseContext->intermediate.addBinaryMath(EOpSub, $1, $3, $2.line, parseContext->symbolTable);
789 parseContext->binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString());
790 parseContext->recover();
797 : additive_expression { $$ = $1; }
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);
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);
812 | relational_expression RIGHT_ANGLE shift_expression {
813 $$ = parseContext->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line, parseContext->symbolTable);
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);
822 | relational_expression LE_OP shift_expression {
823 $$ = parseContext->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line, parseContext->symbolTable);
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);
832 | relational_expression GE_OP shift_expression {
833 $$ = parseContext->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line, parseContext->symbolTable);
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);
845 : relational_expression { $$ = $1; }
846 | equality_expression EQ_OP relational_expression {
847 $$ = parseContext->intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line, parseContext->symbolTable);
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();
857 | equality_expression NE_OP relational_expression {
858 $$ = parseContext->intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line, parseContext->symbolTable);
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();
871 : equality_expression { $$ = $1; }
874 exclusive_or_expression
875 : and_expression { $$ = $1; }
878 inclusive_or_expression
879 : exclusive_or_expression { $$ = $1; }
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);
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);
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);
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);
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);
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);
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();
930 $$ = parseContext->intermediate.addSelection($1, $3, $5, $2.line);
931 if ($3->getType() != $5->getType())
935 parseContext->binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString());
936 parseContext->recover();
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);
949 parseContext->assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString());
950 parseContext->recover();
952 } else if (($1->isArray() || $3->isArray()) && parseContext->extensionErrorCheck($2.line, "GL_3DL_array_objects"))
953 parseContext->recover();
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; }
966 : assignment_expression {
969 | expression COMMA assignment_expression {
970 $$ = parseContext->intermediate.addComma($1, $3, $2.line);
972 parseContext->binaryOpError($2.line, ",", $1->getCompleteString(), $3->getCompleteString());
973 parseContext->recover();
980 : conditional_expression {
981 if (parseContext->constErrorCheck($1))
982 parseContext->recover();
988 : function_prototype SEMICOLON {
989 TFunction &function = *($1.function);
991 TIntermAggregate *prototype = new TIntermAggregate;
992 prototype->setType(function.getReturnType());
993 prototype->setName(function.getName());
995 for (int i = 0; i < function.getParamCount(); i++)
997 TParameter ¶m = function[i];
1000 TVariable *variable = new TVariable(param.name, *param.type);
1002 prototype = parseContext->intermediate.growAggregate(prototype, parseContext->intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), $1.line), $1.line);
1006 prototype = parseContext->intermediate.growAggregate(prototype, parseContext->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line);
1010 prototype->setOp(EOpPrototype);
1013 | init_declarator_list SEMICOLON {
1014 if ($1.intermAggregate)
1015 $1.intermAggregate->setOp(EOpDeclaration);
1016 $$ = $1.intermAggregate;
1018 | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
1019 parseContext->symbolTable.setDefaultPrecision( $3.type, $2 );
1025 : function_declarator RIGHT_PAREN {
1027 // Multiple declarations of the same function are allowed.
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).
1032 // Redeclarations are allowed. But, return types and parameter qualifiers must match.
1034 TFunction* prevDec = static_cast<TFunction*>(parseContext->symbolTable.find($1->getMangledName()));
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();
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();
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.
1056 parseContext->symbolTable.insert(*$$.function);
1064 | function_header_with_parameters {
1070 function_header_with_parameters
1071 : function_header parameter_declaration {
1072 // Add the parameter
1074 if ($2.param.type->getBasicType() != EbtVoid)
1075 $1->addParameter($2.param);
1077 delete $2.param.type;
1079 | function_header_with_parameters COMMA parameter_declaration {
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
1084 if ($3.param.type->getBasicType() == EbtVoid) {
1086 // This parameter > first is void
1088 parseContext->error($2.line, "cannot be an argument type except for '(void)'", "void", "");
1089 parseContext->recover();
1090 delete $3.param.type;
1092 // Add the parameter
1094 $1->addParameter($3.param);
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();
1105 // make sure a sampler is not involved as well...
1106 if (parseContext->structQualifierErrorCheck($2.line, $1))
1107 parseContext->recover();
1109 // Add the function as a prototype after parsing it (we do not support recursion)
1110 TFunction *function;
1112 function = new TFunction($2.string, type);
1117 parameter_declarator
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();
1124 if (parseContext->reservedErrorCheck($2.line, *$2.string))
1125 parseContext->recover();
1126 TParameter param = {$2.string, new TType($1)};
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();
1135 if (parseContext->reservedErrorCheck($2.line, *$2.string))
1136 parseContext->recover();
1139 if (parseContext->arraySizeErrorCheck($3.line, $4, size))
1140 parseContext->recover();
1141 $1.setArray(true, size);
1143 TType* type = new TType($1);
1144 TParameter param = { $2.string, type };
1150 parameter_declaration
1152 // The only parameter qualifier a parameter can have are
1153 // IN_QUAL, OUT_QUAL, INOUT_QUAL, or CONST.
1159 : type_qualifier parameter_qualifier parameter_declarator {
1161 if (parseContext->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type))
1162 parseContext->recover();
1164 | parameter_qualifier parameter_declarator {
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();
1174 | type_qualifier parameter_qualifier parameter_type_specifier {
1176 if (parseContext->paramErrorCheck($3.line, $1.qualifier, $2, $$.param.type))
1177 parseContext->recover();
1179 | parameter_qualifier parameter_type_specifier {
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();
1203 parameter_type_specifier
1205 TParameter param = { 0, new TType($1) };
1210 init_declarator_list
1211 : single_declaration {
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();
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);
1224 if (parseContext->structQualifierErrorCheck($3.line, $$.type))
1225 parseContext->recover();
1227 if (parseContext->nonInitConstErrorCheck($3.line, *$3.string, $$.type))
1228 parseContext->recover();
1230 if (parseContext->nonInitErrorCheck($3.line, *$3.string, $$.type))
1231 parseContext->recover();
1233 | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET {
1234 if (parseContext->structQualifierErrorCheck($3.line, $1.type))
1235 parseContext->recover();
1237 if (parseContext->nonInitConstErrorCheck($3.line, *$3.string, $1.type))
1238 parseContext->recover();
1242 if (parseContext->arrayTypeErrorCheck($4.line, $1.type) || parseContext->arrayQualifierErrorCheck($4.line, $1.type))
1243 parseContext->recover();
1245 $1.type.setArray(true);
1246 TVariable* variable;
1247 if (parseContext->arrayErrorCheck($4.line, *$3.string, $1.type, variable))
1248 parseContext->recover();
1251 | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
1252 if (parseContext->structQualifierErrorCheck($3.line, $1.type))
1253 parseContext->recover();
1255 if (parseContext->nonInitConstErrorCheck($3.line, *$3.string, $1.type))
1256 parseContext->recover();
1260 if (parseContext->arrayTypeErrorCheck($4.line, $1.type) || parseContext->arrayQualifierErrorCheck($4.line, $1.type))
1261 parseContext->recover();
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);
1275 | init_declarator_list COMMA IDENTIFIER LEFT_BRACKET RIGHT_BRACKET EQUAL initializer {
1276 if (parseContext->structQualifierErrorCheck($3.line, $1.type))
1277 parseContext->recover();
1281 TVariable* variable = 0;
1282 if (parseContext->arrayTypeErrorCheck($4.line, $1.type) || parseContext->arrayQualifierErrorCheck($4.line, $1.type))
1283 parseContext->recover();
1285 $1.type.setArray(true, $7->getType().getArraySize());
1286 if (parseContext->arrayErrorCheck($4.line, *$3.string, $1.type, variable))
1287 parseContext->recover();
1290 if (parseContext->extensionErrorCheck($$.line, "GL_3DL_array_objects"))
1291 parseContext->recover();
1293 TIntermNode* intermNode;
1294 if (!parseContext->executeInitializer($3.line, *$3.string, $1.type, $7, intermNode, variable)) {
1296 // build the intermediate representation
1299 $$.intermAggregate = parseContext->intermediate.growAggregate($1.intermNode, intermNode, $6.line);
1301 $$.intermAggregate = $1.intermAggregate;
1303 parseContext->recover();
1304 $$.intermAggregate = 0;
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();
1314 TVariable* variable = 0;
1315 if (parseContext->arrayTypeErrorCheck($4.line, $1.type) || parseContext->arrayQualifierErrorCheck($4.line, $1.type))
1316 parseContext->recover();
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();
1326 if (parseContext->extensionErrorCheck($$.line, "GL_3DL_array_objects"))
1327 parseContext->recover();
1329 TIntermNode* intermNode;
1330 if (!parseContext->executeInitializer($3.line, *$3.string, $1.type, $8, intermNode, variable)) {
1332 // build the intermediate representation
1335 $$.intermAggregate = parseContext->intermediate.growAggregate($1.intermNode, intermNode, $7.line);
1337 $$.intermAggregate = $1.intermAggregate;
1339 parseContext->recover();
1340 $$.intermAggregate = 0;
1344 | init_declarator_list COMMA IDENTIFIER EQUAL initializer {
1345 if (parseContext->structQualifierErrorCheck($3.line, $1.type))
1346 parseContext->recover();
1350 TIntermNode* intermNode;
1351 if (!parseContext->executeInitializer($3.line, *$3.string, $1.type, $5, intermNode)) {
1353 // build the intermediate representation
1356 $$.intermAggregate = parseContext->intermediate.growAggregate($1.intermNode, intermNode, $4.line);
1358 $$.intermAggregate = $1.intermAggregate;
1360 parseContext->recover();
1361 $$.intermAggregate = 0;
1367 : fully_specified_type {
1369 $$.intermAggregate = parseContext->intermediate.makeAggregate(parseContext->intermediate.addSymbol(0, "", TType($1), $1.line), $1.line);
1371 | fully_specified_type IDENTIFIER {
1372 $$.intermAggregate = parseContext->intermediate.makeAggregate(parseContext->intermediate.addSymbol(0, *$2.string, TType($1), $2.line), $2.line);
1374 if (parseContext->structQualifierErrorCheck($2.line, $$.type))
1375 parseContext->recover();
1377 if (parseContext->nonInitConstErrorCheck($2.line, *$2.string, $$.type))
1378 parseContext->recover();
1382 if (parseContext->nonInitErrorCheck($2.line, *$2.string, $$.type))
1383 parseContext->recover();
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);
1388 if (parseContext->structQualifierErrorCheck($2.line, $1))
1389 parseContext->recover();
1391 if (parseContext->nonInitConstErrorCheck($2.line, *$2.string, $1))
1392 parseContext->recover();
1396 if (parseContext->arrayTypeErrorCheck($3.line, $1) || parseContext->arrayQualifierErrorCheck($3.line, $1))
1397 parseContext->recover();
1400 TVariable* variable;
1401 if (parseContext->arrayErrorCheck($3.line, *$2.string, $1, variable))
1402 parseContext->recover();
1405 | fully_specified_type IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
1406 TType type = TType($1);
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);
1413 if (parseContext->structQualifierErrorCheck($2.line, $1))
1414 parseContext->recover();
1416 if (parseContext->nonInitConstErrorCheck($2.line, *$2.string, $1))
1417 parseContext->recover();
1421 if (parseContext->arrayTypeErrorCheck($3.line, $1) || parseContext->arrayQualifierErrorCheck($3.line, $1))
1422 parseContext->recover();
1425 if (parseContext->arraySizeErrorCheck($3.line, $4, size))
1426 parseContext->recover();
1428 $1.setArray(true, size);
1429 TVariable* variable;
1430 if (parseContext->arrayErrorCheck($3.line, *$2.string, $1, variable))
1431 parseContext->recover();
1434 | fully_specified_type IDENTIFIER EQUAL initializer {
1435 if (parseContext->structQualifierErrorCheck($2.line, $1))
1436 parseContext->recover();
1440 TIntermNode* intermNode;
1441 if (!parseContext->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) {
1443 // Build intermediate representation
1446 $$.intermAggregate = parseContext->intermediate.makeAggregate(intermNode, $3.line);
1448 $$.intermAggregate = 0;
1450 parseContext->recover();
1451 $$.intermAggregate = 0;
1454 | INVARIANT IDENTIFIER {
1455 VERTEX_ONLY("invariant declaration", $1.line);
1456 $$.qualifier = EvqInvariantVaryingOut;
1457 $$.intermAggregate = 0;
1461 // Place holder for the pack/unpack languages.
1463 // | buffer_specifier {
1464 // $$.intermAggregate = 0;
1468 // Grammar Note: No 'enum', or 'typedef'.
1471 // Place holder for the pack/unpack languages.
1473 //%type <interm> buffer_declaration
1474 //%type <interm.type> buffer_specifier input_or_output buffer_declaration_list
1476 // : input_or_output LEFT_BRACE buffer_declaration_list RIGHT_BRACE {
1482 // if (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "input"))
1483 // parseContext->recover();
1484 // UNPACK_ONLY("input", $1.line);
1485 // $$.qualifier = EvqInput;
1488 // if (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "output"))
1489 // parseContext->recover();
1490 // PACK_ONLY("output", $1.line);
1491 // $$.qualifier = EvqOutput;
1496 // Place holder for the pack/unpack languages.
1498 //buffer_declaration_list
1499 // : buffer_declaration {
1501 // | buffer_declaration_list buffer_declaration {
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
1514 // Place holder for the pack/unpack languages.
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
1529 fully_specified_type
1534 if (parseContext->extensionErrorCheck($1.line, "GL_3DL_array_objects")) {
1535 parseContext->recover();
1540 | type_qualifier type_specifier {
1541 if ($2.array && parseContext->extensionErrorCheck($2.line, "GL_3DL_array_objects")) {
1542 parseContext->recover();
1545 if ($2.array && parseContext->arrayQualifierErrorCheck($2.line, $1)) {
1546 parseContext->recover();
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();
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();
1561 $$.qualifier = $1.qualifier;
1567 $$.setBasic(EbtVoid, EvqConst, $1.line);
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);
1576 if (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "varying"))
1577 parseContext->recover();
1578 if (parseContext->language == EShLangVertex)
1579 $$.setBasic(EbtVoid, EvqVaryingOut, $1.line);
1581 $$.setBasic(EbtVoid, EvqVaryingIn, $1.line);
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);
1589 $$.setBasic(EbtVoid, EvqInvariantVaryingIn, $1.line);
1592 if (parseContext->globalErrorCheck($1.line, parseContext->symbolTable.atGlobalLevel(), "uniform"))
1593 parseContext->recover();
1594 $$.setBasic(EbtVoid, EvqUniform, $1.line);
1599 : type_specifier_no_prec {
1602 | precision_qualifier type_specifier_no_prec {
1612 | MEDIUM_PRECISION {
1620 type_specifier_no_prec
1621 : type_specifier_nonarray {
1624 | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET {
1627 if (parseContext->arrayTypeErrorCheck($2.line, $1))
1628 parseContext->recover();
1631 if (parseContext->arraySizeErrorCheck($2.line, $3, size))
1632 parseContext->recover();
1633 $$.setArray(true, size);
1638 type_specifier_nonarray
1640 TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1641 $$.setBasic(EbtVoid, qual, $1.line);
1644 TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1645 $$.setBasic(EbtFloat, qual, $1.line);
1648 TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1649 $$.setBasic(EbtInt, qual, $1.line);
1652 TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1653 $$.setBasic(EbtBool, qual, $1.line);
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);
1661 TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1662 $$.setBasic(EbtFloat, qual, $1.line);
1666 TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1667 $$.setBasic(EbtFloat, qual, $1.line);
1671 TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1672 $$.setBasic(EbtFloat, qual, $1.line);
1676 TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1677 $$.setBasic(EbtBool, qual, $1.line);
1681 TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1682 $$.setBasic(EbtBool, qual, $1.line);
1686 TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1687 $$.setBasic(EbtBool, qual, $1.line);
1691 TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1692 $$.setBasic(EbtInt, qual, $1.line);
1696 TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1697 $$.setBasic(EbtInt, qual, $1.line);
1701 TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1702 $$.setBasic(EbtInt, qual, $1.line);
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);
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);
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);
1724 FRAG_VERT_ONLY("sampler2D", $1.line);
1725 TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1726 $$.setBasic(EbtSampler2D, qual, $1.line);
1729 FRAG_VERT_ONLY("samplerCube", $1.line);
1730 TQualifier qual = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1731 $$.setBasic(EbtSamplerCube, qual, $1.line);
1733 | struct_specifier {
1734 FRAG_VERT_ONLY("struct", $1.line);
1736 $$.qualifier = parseContext->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
1740 // This is for user defined type names. The lexical phase looked up the
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;
1751 : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE {
1752 if (parseContext->reservedErrorCheck($2.line, *$2.string))
1753 parseContext->recover();
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();
1761 $$.setBasic(EbtStruct, EvqTemporary, $1.line);
1762 $$.userDef = structure;
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;
1771 struct_declaration_list
1772 : struct_declaration {
1775 | struct_declaration_list struct_declaration {
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();
1784 $$->push_back((*$2)[i]);
1790 : type_specifier struct_declarator_list SEMICOLON {
1793 if (parseContext->voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) {
1794 parseContext->recover();
1796 for (unsigned int i = 0; i < $$->size(); ++i) {
1798 // Careful not to replace already known aspects of type, like array-ness
1800 TType* type = (*$$)[i].type;
1801 type->setBasicType($1.type);
1802 type->setNominalSize($1.size);
1803 type->setMatrix($1.matrix);
1805 // don't allow arrays of arrays
1806 if (type->isArray()) {
1807 if (parseContext->arrayTypeErrorCheck($1.line, $1))
1808 parseContext->recover();
1811 type->setArraySize($1.arraySize);
1813 type->setStruct($1.userDef->getStruct());
1814 type->setTypeName($1.userDef->getTypeName());
1820 struct_declarator_list
1821 : struct_declarator {
1822 $$ = NewPoolTTypeList();
1825 | struct_declarator_list COMMA struct_declarator {
1832 if (parseContext->reservedErrorCheck($1.line, *$1.string))
1833 parseContext->recover();
1835 $$.type = new TType(EbtVoid, EbpUndefined);
1837 $$.type->setFieldName(*$1.string);
1839 | IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
1840 if (parseContext->reservedErrorCheck($1.line, *$1.string))
1841 parseContext->recover();
1843 $$.type = new TType(EbtVoid, EbpUndefined);
1845 $$.type->setFieldName(*$1.string);
1848 if (parseContext->arraySizeErrorCheck($2.line, $3, size))
1849 parseContext->recover();
1850 $$.type->setArraySize(size);
1855 : assignment_expression { $$ = $1; }
1858 declaration_statement
1859 : declaration { $$ = $1; }
1863 : compound_statement { $$ = $1; }
1864 | simple_statement { $$ = $1; }
1867 // Grammar Note: No labeled statements; 'goto' is not supported.
1870 : declaration_statement { $$ = $1; }
1871 | expression_statement { $$ = $1; }
1872 | selection_statement { $$ = $1; }
1873 | iteration_statement { $$ = $1; }
1874 | jump_statement { $$ = $1; }
1878 : LEFT_BRACE RIGHT_BRACE { $$ = 0; }
1879 | LEFT_BRACE { parseContext->symbolTable.push(); } statement_list { parseContext->symbolTable.pop(); } RIGHT_BRACE {
1881 $3->setOp(EOpSequence);
1886 statement_no_new_scope
1887 : compound_statement_no_new_scope { $$ = $1; }
1888 | simple_statement { $$ = $1; }
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 {
1896 | LEFT_BRACE statement_list RIGHT_BRACE {
1898 $2->setOp(EOpSequence);
1905 $$ = parseContext->intermediate.makeAggregate($1, 0);
1907 | statement_list statement {
1908 $$ = parseContext->intermediate.growAggregate($1, $2, 0);
1912 expression_statement
1913 : SEMICOLON { $$ = 0; }
1914 | expression SEMICOLON { $$ = static_cast<TIntermNode*>($1); }
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);
1925 selection_rest_statement
1926 : statement ELSE statement {
1936 // Grammar Note: No 'switch'. Switch statements not supported.
1939 // In 1996 c++ draft, conditions can include single declarations
1942 if (parseContext->boolErrorCheck($1->getLine(), $1))
1943 parseContext->recover();
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();
1952 if (!parseContext->executeInitializer($2.line, *$2.string, $1, $4, intermNode))
1955 parseContext->recover();
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;
1967 | DO { ++parseContext->loopNestingLevel; } statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
1968 if (parseContext->boolErrorCheck($8.line, $6))
1969 parseContext->recover();
1971 $$ = parseContext->intermediate.addLoop(0, $3, $6, 0, false, $4.line);
1972 --parseContext->loopNestingLevel;
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;
1982 : expression_statement {
1985 | declaration_statement {
1994 | /* May be null */ {
2000 : conditionopt SEMICOLON {
2004 | conditionopt SEMICOLON expression {
2011 : CONTINUE SEMICOLON {
2012 if (parseContext->loopNestingLevel <= 0) {
2013 parseContext->error($1.line, "continue statement only allowed in loops", "", "");
2014 parseContext->recover();
2016 $$ = parseContext->intermediate.addBranch(EOpContinue, $1.line);
2019 if (parseContext->loopNestingLevel <= 0) {
2020 parseContext->error($1.line, "break statement only allowed in loops", "", "");
2021 parseContext->recover();
2023 $$ = parseContext->intermediate.addBranch(EOpBreak, $1.line);
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();
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();
2043 | DISCARD SEMICOLON {
2044 FRAG_ONLY("discard", $1.line);
2045 $$ = parseContext->intermediate.addBranch(EOpKill, $1.line);
2049 // Grammar Note: No 'goto'. Gotos are not supported.
2052 : external_declaration {
2054 parseContext->treeRoot = $$;
2056 | translation_unit external_declaration {
2057 $$ = parseContext->intermediate.growAggregate($1, $2, 0);
2058 parseContext->treeRoot = $$;
2062 external_declaration
2063 : function_definition {
2072 : function_prototype {
2073 TFunction& function = *($1.function);
2074 TFunction* prevDec = static_cast<TFunction*>(parseContext->symbolTable.find(function.getMangledName()));
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.
2080 if (prevDec->isDefined()) {
2082 // Then this function already has a body.
2084 parseContext->error($1.line, "function already has a body", function.getName().c_str(), "");
2085 parseContext->recover();
2087 prevDec->setDefined();
2090 // Raise error message if main function takes any parameters or return anything other than void
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();
2097 if (function.getReturnType().getBasicType() != EbtVoid) {
2098 parseContext->error($1.line, "", function.getReturnType().getBasicString(), "main function cannot return a value");
2099 parseContext->recover();
2104 // New symbol table scope for body of function plus its arguments
2106 parseContext->symbolTable.push();
2109 // Remember the return type for later checking for RETURN statements.
2111 parseContext->currentFunctionType = &(prevDec->getReturnType());
2112 parseContext->functionReturnsValue = false;
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).
2119 // Also, accumulate the list of parameters into the HIL, so lower level code
2120 // knows where to find parameters.
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);
2128 // Insert the parameters with name in the symbol table.
2130 if (! parseContext->symbolTable.insert(*variable)) {
2131 parseContext->error($1.line, "redefinition", variable->getName().c_str(), "");
2132 parseContext->recover();
2136 // Transfer ownership of name pointer to symbol table.
2141 // Add the parameter to the HIL
2143 paramNodes = parseContext->intermediate.growAggregate(
2145 parseContext->intermediate.addSymbol(variable->getUniqueId(),
2146 variable->getName(),
2147 variable->getType(), $1.line),
2150 paramNodes = parseContext->intermediate.growAggregate(paramNodes, parseContext->intermediate.addSymbol(0, "", *param.type, $1.line), $1.line);
2153 parseContext->intermediate.setAggregateOperator(paramNodes, EOpParameters, $1.line);
2154 $1.intermAggregate = paramNodes;
2155 parseContext->loopNestingLevel = 0;
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();
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());
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);