gfx/angle/src/compiler/glslang.y

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial