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