1 /*
2 //
3 // Copyright 2002 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 scripts/run_code_generation.py
13 WHICH GENERATES THE GLSL ES PARSER (glslang_tab_autogen.cpp AND glslang_tab_autogen.h).
14 */
15 
16 %{
17 // GENERATED FILE - DO NOT EDIT.
18 // Generated by generate_parser.py from glslang.y
19 //
20 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
21 // Use of this source code is governed by a BSD-style license that can be
22 // found in the LICENSE file.
23 //
24 // glslang.y:
25 //   Parser for the OpenGL shading language.
26 
27 // Ignore errors in auto-generated code.
28 #if defined(__GNUC__)
29 #pragma GCC diagnostic ignored "-Wunused-function"
30 #pragma GCC diagnostic ignored "-Wunused-variable"
31 #pragma GCC diagnostic ignored "-Wswitch-enum"
32 #elif defined(_MSC_VER)
33 #pragma warning(disable: 4065)
34 #pragma warning(disable: 4189)
35 #pragma warning(disable: 4244)
36 #pragma warning(disable: 4505)
37 #pragma warning(disable: 4701)
38 #pragma warning(disable: 4702)
39 #endif
40 #if defined(__clang__)
41 #pragma clang diagnostic ignored "-Wunreachable-code"
42 #endif
43 
44 #include "angle_gl.h"
45 #include "compiler/translator/Declarator.h"
46 #include "compiler/translator/SymbolTable.h"
47 #include "compiler/translator/ParseContext.h"
48 #include "GLSLANG/ShaderLang.h"
49 
50 #define YYENABLE_NLS 0
51 
52 using namespace sh;
53 
54 %}
55 %expect 1 /* One shift reduce conflict because of if | else */
56 %parse-param {TParseContext* context}
57 %param   {void *scanner}
58 %define api.pure full
59 %locations
60 
61 %code requires {
62 #define YYLTYPE TSourceLoc
63 #define YYLTYPE_IS_DECLARED 1
64 #define YYLTYPE_IS_TRIVIAL 1
65 }
66 
67 %union {
68     struct {
69         union {
70             const char *string;  // pool allocated.
71             float f;
72             int i;
73             unsigned int u;
74             bool b;
75         };
76         const TSymbol* symbol;
77     } lex;
78     struct {
79         TOperator op;
80         union {
81             TIntermNode *intermNode;
82             TIntermNodePair nodePair;
83             TIntermTyped *intermTypedNode;
84             TIntermAggregate *intermAggregate;
85             TIntermBlock *intermBlock;
86             TIntermDeclaration *intermDeclaration;
87             TIntermFunctionPrototype *intermFunctionPrototype;
88             TIntermSwitch *intermSwitch;
89             TIntermCase *intermCase;
90         };
91         union {
92             TVector<unsigned int> *arraySizes;
93             TTypeSpecifierNonArray typeSpecifierNonArray;
94             TPublicType type;
95             TPrecision precision;
96             TLayoutQualifier layoutQualifier;
97             TQualifier qualifier;
98             TFunction *function;
99             TFunctionLookup *functionLookup;
100             TParameter param;
101             TDeclarator *declarator;
102             TDeclaratorList *declaratorList;
103             TFieldList *fieldList;
104             TQualifierWrapperBase *qualifierWrapper;
105             TTypeQualifierBuilder *typeQualifierBuilder;
106         };
107     } interm;
108 }
109 
110 %{
111 extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner);
112 extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, const char* reason);
113 
114 #define YYLLOC_DEFAULT(Current, Rhs, N)                      \
115   do {                                                       \
116       if (N) {                                         \
117         (Current).first_file = YYRHSLOC(Rhs, 1).first_file;  \
118         (Current).first_line = YYRHSLOC(Rhs, 1).first_line;  \
119         (Current).last_file = YYRHSLOC(Rhs, N).last_file;    \
120         (Current).last_line = YYRHSLOC(Rhs, N).last_line;    \
121       }                                                      \
122       else {                                                 \
123         (Current).first_file = YYRHSLOC(Rhs, 0).last_file;   \
124         (Current).first_line = YYRHSLOC(Rhs, 0).last_line;   \
125         (Current).last_file = YYRHSLOC(Rhs, 0).last_file;    \
126         (Current).last_line = YYRHSLOC(Rhs, 0).last_line;    \
127       }                                                      \
128   } while (0)
129 
130 #define VERTEX_ONLY(S, L) do {  \
131     if (context->getShaderType() != GL_VERTEX_SHADER) {  \
132         context->error(L, " supported in vertex shaders only", S);  \
133     }  \
134 } while (0)
135 
136 #define COMPUTE_ONLY(S, L) do {  \
137     if (context->getShaderType() != GL_COMPUTE_SHADER) {  \
138         context->error(L, " supported in compute shaders only", S);  \
139     }  \
140 } while (0)
141 
142 #define ES2_ONLY(S, L) do {  \
143     if (context->getShaderVersion() != 100) {  \
144         context->error(L, " supported in GLSL ES 1.00 only", S);  \
145     }  \
146 } while (0)
147 
148 #define ES3_OR_NEWER(TOKEN, LINE, REASON) do {  \
149     if (context->getShaderVersion() < 300) {  \
150         context->error(LINE, REASON " supported in GLSL ES 3.00 and above only", TOKEN);  \
151     }  \
152 } while (0)
153 
154 #define ES3_1_ONLY(TOKEN, LINE, REASON) do {  \
155     if (context->getShaderVersion() != 310) {  \
156         context->error(LINE, REASON " supported in GLSL ES 3.10 only", TOKEN);  \
157     }  \
158 } while (0)
159 %}
160 
161 %token <lex> INVARIANT PRECISE HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION
162 %token <lex> ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE UINT_TYPE
163 %token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT
164 %token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4 UVEC2 UVEC3 UVEC4
165 %token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM BUFFER VARYING
166 %token <lex> MATRIX2x3 MATRIX3x2 MATRIX2x4 MATRIX4x2 MATRIX3x4 MATRIX4x3
167 %token <lex> CENTROID FLAT SMOOTH
168 %token <lex> READONLY WRITEONLY COHERENT RESTRICT VOLATILE SHARED
169 %token <lex> STRUCT VOID_TYPE WHILE
170 %token <lex> SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT SAMPLER2DARRAY
171 %token <lex> ISAMPLER2D ISAMPLER3D ISAMPLERCUBE ISAMPLER2DARRAY
172 %token <lex> USAMPLER2D USAMPLER3D USAMPLERCUBE USAMPLER2DARRAY
173 %token <lex> SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS
174 %token <lex> SAMPLER2DMSARRAY ISAMPLER2DMSARRAY USAMPLER2DMSARRAY
175 %token <lex> SAMPLER3D SAMPLER3DRECT SAMPLER2DSHADOW SAMPLERCUBESHADOW SAMPLER2DARRAYSHADOW SAMPLERVIDEOWEBGL
176 %token <lex> SAMPLEREXTERNAL2DY2YEXT
177 %token <lex> IMAGE2D IIMAGE2D UIMAGE2D IMAGE3D IIMAGE3D UIMAGE3D IMAGE2DARRAY IIMAGE2DARRAY UIMAGE2DARRAY
178 %token <lex> IMAGECUBE IIMAGECUBE UIMAGECUBE
179 %token <lex> ATOMICUINT
180 %token <lex> LAYOUT
181 %token <lex> YUVCSCSTANDARDEXT YUVCSCSTANDARDEXTCONSTANT
182 
183 %token <lex> IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT UINTCONSTANT BOOLCONSTANT
184 %token <lex> FIELD_SELECTION
185 %token <lex> LEFT_OP RIGHT_OP
186 %token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
187 %token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
188 %token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
189 %token <lex> SUB_ASSIGN
190 
191 %token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
192 %token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
193 %token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION
194 
195 %type <lex> identifier
196 %type <interm.op> assignment_operator unary_operator
197 %type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression
198 %type <interm.intermTypedNode> expression integer_expression assignment_expression
199 %type <interm.intermTypedNode> unary_expression multiplicative_expression additive_expression
200 %type <interm.intermTypedNode> relational_expression equality_expression
201 %type <interm.intermTypedNode> conditional_expression constant_expression
202 %type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression
203 %type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression
204 %type <interm.intermTypedNode> function_call initializer
205 
206 %type <interm.intermNode> condition conditionopt
207 %type <interm.intermBlock> translation_unit
208 %type <interm.intermNode> function_definition statement simple_statement
209 %type <interm.intermBlock> statement_list compound_statement_with_scope compound_statement_no_new_scope
210 %type <interm.intermNode> declaration_statement selection_statement expression_statement
211 %type <interm.intermNode> declaration external_declaration
212 %type <interm.intermNode> for_init_statement
213 %type <interm.nodePair> selection_rest_statement for_rest_statement
214 %type <interm.intermSwitch> switch_statement
215 %type <interm.intermCase> case_label
216 %type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope statement_with_scope
217 %type <interm> single_declaration init_declarator_list
218 
219 %type <interm.param> parameter_declaration parameter_declarator parameter_type_specifier
220 %type <interm.layoutQualifier> layout_qualifier_id_list layout_qualifier_id
221 
222 // Note: array_specifier guaranteed to be non-null.
223 %type <interm.arraySizes> array_specifier
224 
225 %type <interm.type> fully_specified_type type_specifier
226 
227 %type <interm.precision> precision_qualifier
228 %type <interm.layoutQualifier> layout_qualifier
229 %type <interm.qualifier> interpolation_qualifier
230 %type <interm.qualifierWrapper> storage_qualifier single_type_qualifier invariant_qualifier precise_qualifier
231 %type <interm.typeQualifierBuilder> type_qualifier
232 
233 %type <interm.typeSpecifierNonArray> type_specifier_nonarray struct_specifier
234 %type <interm.type> type_specifier_no_prec
235 %type <interm.declarator> struct_declarator
236 %type <interm.declaratorList> struct_declarator_list
237 %type <interm.fieldList> struct_declaration struct_declaration_list
238 %type <interm.function> function_header function_declarator
239 %type <interm.function> function_header_with_parameters
240 %type <interm.functionLookup> function_identifier function_call_header
241 %type <interm.functionLookup> function_call_header_with_parameters function_call_header_no_parameters
242 %type <interm.functionLookup> function_call_generic function_call_or_method
243 %type <interm> function_prototype
244 
245 %type <lex> enter_struct
246 
247 %start translation_unit
248 %%
249 
250 identifier
251     : IDENTIFIER
252     | TYPE_NAME
253 
254 variable_identifier
255     : IDENTIFIER {
256         // The symbol table search was done in the lexical phase
257         $$ = context->parseVariableIdentifier(@1, ImmutableString($1.string), $1.symbol);
258     }
259     ;
260 
261 primary_expression
262     : variable_identifier {
263         $$ = $1;
264     }
265     | INTCONSTANT {
266         TConstantUnion *unionArray = new TConstantUnion[1];
267         unionArray->setIConst($1.i);
268         $$ = context->addScalarLiteral(unionArray, @1);
269     }
270     | UINTCONSTANT {
271         TConstantUnion *unionArray = new TConstantUnion[1];
272         unionArray->setUConst($1.u);
273         $$ = context->addScalarLiteral(unionArray, @1);
274     }
275     | FLOATCONSTANT {
276         TConstantUnion *unionArray = new TConstantUnion[1];
277         unionArray->setFConst($1.f);
278         $$ = context->addScalarLiteral(unionArray, @1);
279     }
280     | BOOLCONSTANT {
281         TConstantUnion *unionArray = new TConstantUnion[1];
282         unionArray->setBConst($1.b);
283         $$ = context->addScalarLiteral(unionArray, @1);
284     }
285     | YUVCSCSTANDARDEXTCONSTANT {
286         if (!context->checkCanUseExtension(@1, TExtension::EXT_YUV_target))
287         {
288            context->error(@1, "unsupported value", ImmutableString($1.string));
289         }
290         TConstantUnion *unionArray = new TConstantUnion[1];
291         unionArray->setYuvCscStandardEXTConst(getYuvCscStandardEXT(ImmutableString($1.string)));
292         $$ = context->addScalarLiteral(unionArray, @1);
293     }
294     | LEFT_PAREN expression RIGHT_PAREN {
295         $$ = $2;
296     }
297     ;
298 
299 postfix_expression
300     : primary_expression {
301         $$ = $1;
302     }
303     | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET {
304         $$ = context->addIndexExpression($1, @2, $3);
305     }
306     | function_call {
307         $$ = $1;
308     }
309     | postfix_expression DOT FIELD_SELECTION {
310         $$ = context->addFieldSelectionExpression($1, @2, ImmutableString($3.string), @3);
311     }
312     | postfix_expression INC_OP {
313         $$ = context->addUnaryMathLValue(EOpPostIncrement, $1, @2);
314     }
315     | postfix_expression DEC_OP {
316         $$ = context->addUnaryMathLValue(EOpPostDecrement, $1, @2);
317     }
318     ;
319 
320 integer_expression
321     : expression {
322         context->checkIsScalarInteger($1, "[]");
323         $$ = $1;
324     }
325     ;
326 
327 function_call
328     : function_call_or_method {
329         $$ = context->addFunctionCallOrMethod($1, @1);
330     }
331     ;
332 
333 function_call_or_method
334     : function_call_generic {
335         $$ = $1;
336     }
337     | postfix_expression DOT function_call_generic {
338         ES3_OR_NEWER("", @3, "methods");
339         $$ = $3;
340         $$->setThisNode($1);
341     }
342     ;
343 
344 function_call_generic
345     : function_call_header_with_parameters RIGHT_PAREN {
346         $$ = $1;
347     }
348     | function_call_header_no_parameters RIGHT_PAREN {
349         $$ = $1;
350     }
351     ;
352 
353 function_call_header_no_parameters
354     : function_call_header VOID_TYPE {
355         $$ = $1;
356     }
357     | function_call_header {
358         $$ = $1;
359     }
360     ;
361 
362 function_call_header_with_parameters
363     : function_call_header assignment_expression {
364         $$ = $1;
365         $$->addArgument($2);
366     }
367     | function_call_header_with_parameters COMMA assignment_expression {
368         $$ = $1;
369         $$->addArgument($3);
370     }
371     ;
372 
373 function_call_header
374     : function_identifier LEFT_PAREN {
375         $$ = $1;
376     }
377     ;
378 
379 // Grammar Note:  Constructors look like functions, but are recognized as types.
380 
381 function_identifier
382     : type_specifier_no_prec {
383         $$ = context->addConstructorFunc($1);
384     }
385     | IDENTIFIER {
386         $$ = context->addNonConstructorFunc(ImmutableString($1.string), $1.symbol);
387     }
388     | FIELD_SELECTION {
389         $$ = context->addNonConstructorFunc(ImmutableString($1.string), $1.symbol);
390     }
391     ;
392 
393 unary_expression
394     : postfix_expression {
395         $$ = $1;
396     }
397     | INC_OP unary_expression {
398         $$ = context->addUnaryMathLValue(EOpPreIncrement, $2, @1);
399     }
400     | DEC_OP unary_expression {
401         $$ = context->addUnaryMathLValue(EOpPreDecrement, $2, @1);
402     }
403     | unary_operator unary_expression {
404         $$ = context->addUnaryMath($1, $2, @1);
405     }
406     ;
407 // Grammar Note:  No traditional style type casts.
408 
409 unary_operator
410     : PLUS  { $$ = EOpPositive; }
411     | DASH  { $$ = EOpNegative; }
412     | BANG  { $$ = EOpLogicalNot; }
413     | TILDE {
414         ES3_OR_NEWER("~", @$, "bit-wise operator");
415         $$ = EOpBitwiseNot;
416     }
417     ;
418 // Grammar Note:  No '*' or '&' unary ops.  Pointers are not supported.
419 
420 multiplicative_expression
421     : unary_expression { $$ = $1; }
422     | multiplicative_expression STAR unary_expression {
423         $$ = context->addBinaryMath(EOpMul, $1, $3, @2);
424     }
425     | multiplicative_expression SLASH unary_expression {
426         $$ = context->addBinaryMath(EOpDiv, $1, $3, @2);
427     }
428     | multiplicative_expression PERCENT unary_expression {
429         ES3_OR_NEWER("%", @2, "integer modulus operator");
430         $$ = context->addBinaryMath(EOpIMod, $1, $3, @2);
431     }
432     ;
433 
434 additive_expression
435     : multiplicative_expression { $$ = $1; }
436     | additive_expression PLUS multiplicative_expression {
437         $$ = context->addBinaryMath(EOpAdd, $1, $3, @2);
438     }
439     | additive_expression DASH multiplicative_expression {
440         $$ = context->addBinaryMath(EOpSub, $1, $3, @2);
441     }
442     ;
443 
444 shift_expression
445     : additive_expression { $$ = $1; }
446     | shift_expression LEFT_OP additive_expression {
447         ES3_OR_NEWER("<<", @2, "bit-wise operator");
448         $$ = context->addBinaryMath(EOpBitShiftLeft, $1, $3, @2);
449     }
450     | shift_expression RIGHT_OP additive_expression {
451         ES3_OR_NEWER(">>", @2, "bit-wise operator");
452         $$ = context->addBinaryMath(EOpBitShiftRight, $1, $3, @2);
453     }
454     ;
455 
456 relational_expression
457     : shift_expression { $$ = $1; }
458     | relational_expression LEFT_ANGLE shift_expression {
459         $$ = context->addBinaryMathBooleanResult(EOpLessThan, $1, $3, @2);
460     }
461     | relational_expression RIGHT_ANGLE shift_expression  {
462         $$ = context->addBinaryMathBooleanResult(EOpGreaterThan, $1, $3, @2);
463     }
464     | relational_expression LE_OP shift_expression  {
465         $$ = context->addBinaryMathBooleanResult(EOpLessThanEqual, $1, $3, @2);
466     }
467     | relational_expression GE_OP shift_expression  {
468         $$ = context->addBinaryMathBooleanResult(EOpGreaterThanEqual, $1, $3, @2);
469     }
470     ;
471 
472 equality_expression
473     : relational_expression { $$ = $1; }
474     | equality_expression EQ_OP relational_expression  {
475         $$ = context->addBinaryMathBooleanResult(EOpEqual, $1, $3, @2);
476     }
477     | equality_expression NE_OP relational_expression {
478         $$ = context->addBinaryMathBooleanResult(EOpNotEqual, $1, $3, @2);
479     }
480     ;
481 
482 and_expression
483     : equality_expression { $$ = $1; }
484     | and_expression AMPERSAND equality_expression {
485         ES3_OR_NEWER("&", @2, "bit-wise operator");
486         $$ = context->addBinaryMath(EOpBitwiseAnd, $1, $3, @2);
487     }
488     ;
489 
490 exclusive_or_expression
491     : and_expression { $$ = $1; }
492     | exclusive_or_expression CARET and_expression {
493         ES3_OR_NEWER("^", @2, "bit-wise operator");
494         $$ = context->addBinaryMath(EOpBitwiseXor, $1, $3, @2);
495     }
496     ;
497 
498 inclusive_or_expression
499     : exclusive_or_expression { $$ = $1; }
500     | inclusive_or_expression VERTICAL_BAR exclusive_or_expression {
501         ES3_OR_NEWER("|", @2, "bit-wise operator");
502         $$ = context->addBinaryMath(EOpBitwiseOr, $1, $3, @2);
503     }
504     ;
505 
506 logical_and_expression
507     : inclusive_or_expression { $$ = $1; }
508     | logical_and_expression AND_OP inclusive_or_expression {
509         $$ = context->addBinaryMathBooleanResult(EOpLogicalAnd, $1, $3, @2);
510     }
511     ;
512 
513 logical_xor_expression
514     : logical_and_expression { $$ = $1; }
515     | logical_xor_expression XOR_OP logical_and_expression  {
516         $$ = context->addBinaryMathBooleanResult(EOpLogicalXor, $1, $3, @2);
517     }
518     ;
519 
520 logical_or_expression
521     : logical_xor_expression { $$ = $1; }
522     | logical_or_expression OR_OP logical_xor_expression  {
523         $$ = context->addBinaryMathBooleanResult(EOpLogicalOr, $1, $3, @2);
524     }
525     ;
526 
527 conditional_expression
528     : logical_or_expression { $$ = $1; }
529     | logical_or_expression QUESTION expression COLON assignment_expression {
530         $$ = context->addTernarySelection($1, $3, $5, @2);
531     }
532     ;
533 
534 assignment_expression
535     : conditional_expression { $$ = $1; }
536     | unary_expression assignment_operator assignment_expression {
537         $$ = context->addAssign($2, $1, $3, @2);
538     }
539     ;
540 
541 assignment_operator
542     : EQUAL        { $$ = EOpAssign; }
543     | MUL_ASSIGN   { $$ = EOpMulAssign; }
544     | DIV_ASSIGN   { $$ = EOpDivAssign; }
545     | MOD_ASSIGN   {
546         ES3_OR_NEWER("%=", @$, "integer modulus operator");
547         $$ = EOpIModAssign;
548     }
549     | ADD_ASSIGN   { $$ = EOpAddAssign; }
550     | SUB_ASSIGN   { $$ = EOpSubAssign; }
551     | LEFT_ASSIGN {
552         ES3_OR_NEWER("<<=", @$, "bit-wise operator");
553         $$ = EOpBitShiftLeftAssign;
554     }
555     | RIGHT_ASSIGN {
556         ES3_OR_NEWER(">>=", @$, "bit-wise operator");
557         $$ = EOpBitShiftRightAssign;
558     }
559     | AND_ASSIGN {
560         ES3_OR_NEWER("&=", @$, "bit-wise operator");
561         $$ = EOpBitwiseAndAssign;
562     }
563     | XOR_ASSIGN {
564         ES3_OR_NEWER("^=", @$, "bit-wise operator");
565         $$ = EOpBitwiseXorAssign;
566     }
567     | OR_ASSIGN {
568         ES3_OR_NEWER("|=", @$, "bit-wise operator");
569         $$ = EOpBitwiseOrAssign;
570     }
571     ;
572 
573 expression
574     : assignment_expression {
575         $$ = $1;
576     }
577     | expression COMMA assignment_expression {
578         $$ = context->addComma($1, $3, @2);
579     }
580     ;
581 
582 constant_expression
583     : conditional_expression {
584         context->checkIsConst($1);
585         $$ = $1;
586     }
587     ;
588 
589 enter_struct
590     : IDENTIFIER LEFT_BRACE {
591         context->enterStructDeclaration(@1, ImmutableString($1.string));
592         $$ = $1;
593     }
594     ;
595 
596 declaration
597     : function_prototype SEMICOLON {
598         $$ = context->addFunctionPrototypeDeclaration(*($1.function), @1);
599     }
600     | init_declarator_list SEMICOLON {
601         $$ = $1.intermDeclaration;
602     }
603     | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
604         context->parseDefaultPrecisionQualifier($2, $3, @1);
605         $$ = nullptr;
606     }
607     | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE SEMICOLON {
608         ES3_OR_NEWER(ImmutableString($2.string), @1, "interface blocks");
609         $$ = context->addInterfaceBlock(*$1, @2, ImmutableString($2.string), $3, kEmptyImmutableString, @$, NULL, @$);
610     }
611     | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON {
612         ES3_OR_NEWER(ImmutableString($2.string), @1, "interface blocks");
613         $$ = context->addInterfaceBlock(*$1, @2, ImmutableString($2.string), $3, ImmutableString($5.string), @5, NULL, @$);
614     }
615     | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET SEMICOLON {
616         ES3_OR_NEWER(ImmutableString($2.string), @1, "interface blocks");
617         $$ = context->addInterfaceBlock(*$1, @2, ImmutableString($2.string), $3, ImmutableString($5.string), @5, $7, @6);
618     }
619     | type_qualifier SEMICOLON {
620         context->parseGlobalLayoutQualifier(*$1);
621         $$ = nullptr;
622     }
623     | type_qualifier IDENTIFIER SEMICOLON // e.g. to qualify an existing variable as invariant or precise
624     {
625         $$ = context->parseGlobalQualifierDeclaration(*$1, @2, ImmutableString($2.string), $2.symbol);
626     }
627     ;
628 
629 function_prototype
630     : function_declarator RIGHT_PAREN  {
631         $$.function = context->parseFunctionDeclarator(@2, $1);
632         context->exitFunctionDeclaration();
633     }
634     ;
635 
636 function_declarator
637     : function_header {
638         $$ = $1;
639     }
640     | function_header_with_parameters {
641         $$ = $1;
642     }
643     ;
644 
645 
646 function_header_with_parameters
647     : function_header parameter_declaration {
648         // Add the parameter
649         $$ = $1;
650         if ($2.type->getBasicType() != EbtVoid)
651         {
652             $1->addParameter($2.createVariable(&context->symbolTable));
653         }
654     }
655     | function_header_with_parameters COMMA parameter_declaration {
656         $$ = $1;
657         // Only first parameter of one-parameter functions can be void
658         // The check for named parameters not being void is done in parameter_declarator
659         if ($3.type->getBasicType() == EbtVoid)
660         {
661             // This parameter > first is void
662             context->error(@2, "cannot be a parameter type except for '(void)'", "void");
663         }
664         else
665         {
666             $1->addParameter($3.createVariable(&context->symbolTable));
667         }
668     }
669     ;
670 
671 function_header
672     : fully_specified_type IDENTIFIER LEFT_PAREN {
673         $$ = context->parseFunctionHeader($1, ImmutableString($2.string), @2);
674 
675         context->symbolTable.push();
676         context->enterFunctionDeclaration();
677     }
678     ;
679 
680 parameter_declarator
681     // Type + name
682     : type_specifier identifier {
683         $$ = context->parseParameterDeclarator($1, ImmutableString($2.string), @2);
684     }
685     | type_specifier identifier array_specifier {
686         $$ = context->parseParameterArrayDeclarator(ImmutableString($2.string), @2, *($3), @3, &$1);
687     }
688     ;
689 
690 parameter_declaration
691     : type_qualifier parameter_declarator {
692         $$ = $2;
693         context->checkIsParameterQualifierValid(@2, *$1, $2.type);
694     }
695     | parameter_declarator {
696         $$ = $1;
697         $$.type->setQualifier(EvqIn);
698     }
699     | type_qualifier parameter_type_specifier {
700         $$ = $2;
701         context->checkIsParameterQualifierValid(@2, *$1, $2.type);
702     }
703     | parameter_type_specifier {
704         $$ = $1;
705         $$.type->setQualifier(EvqIn);
706     }
707     ;
708 
709 parameter_type_specifier
710     : type_specifier {
711         TParameter param = { 0, new TType($1) };
712         $$ = param;
713     }
714     ;
715 
716 init_declarator_list
717     : single_declaration {
718         $$ = $1;
719     }
720     | init_declarator_list COMMA identifier {
721         $$ = $1;
722         context->parseDeclarator($$.type, @3, ImmutableString($3.string), $$.intermDeclaration);
723     }
724     | init_declarator_list COMMA identifier array_specifier {
725         $$ = $1;
726         context->parseArrayDeclarator($$.type, @3, ImmutableString($3.string), @4, *($4), $$.intermDeclaration);
727     }
728     | init_declarator_list COMMA identifier array_specifier EQUAL initializer {
729         ES3_OR_NEWER("=", @5, "first-class arrays (array initializer)");
730         $$ = $1;
731         context->parseArrayInitDeclarator($$.type, @3, ImmutableString($3.string), @4, *($4), @5, $6, $$.intermDeclaration);
732     }
733     | init_declarator_list COMMA identifier EQUAL initializer {
734         $$ = $1;
735         context->parseInitDeclarator($$.type, @3, ImmutableString($3.string), @4, $5, $$.intermDeclaration);
736     }
737     ;
738 
739 single_declaration
740     : fully_specified_type {
741         $$.type = $1;
742         $$.intermDeclaration = context->parseSingleDeclaration($$.type, @1, kEmptyImmutableString);
743     }
744     | fully_specified_type identifier {
745         $$.type = $1;
746         $$.intermDeclaration = context->parseSingleDeclaration($$.type, @2, ImmutableString($2.string));
747     }
748     | fully_specified_type identifier array_specifier {
749         $$.type = $1;
750         $$.intermDeclaration = context->parseSingleArrayDeclaration($$.type, @2, ImmutableString($2.string), @3, *($3));
751     }
752     | fully_specified_type identifier array_specifier EQUAL initializer {
753         ES3_OR_NEWER("[]", @3, "first-class arrays (array initializer)");
754         $$.type = $1;
755         $$.intermDeclaration = context->parseSingleArrayInitDeclaration($$.type, @2, ImmutableString($2.string), @3, *($3), @4, $5);
756     }
757     | fully_specified_type identifier EQUAL initializer {
758         $$.type = $1;
759         $$.intermDeclaration = context->parseSingleInitDeclaration($$.type, @2, ImmutableString($2.string), @3, $4);
760     }
761     ;
762 
763 fully_specified_type
764     : type_specifier {
765         context->addFullySpecifiedType(&$1);
766         $$ = $1;
767     }
768     | type_qualifier type_specifier {
769         $$ = context->addFullySpecifiedType(*$1, $2);
770     }
771     ;
772 
773 interpolation_qualifier
774     : SMOOTH {
775         $$ = EvqSmooth;
776     }
777     | FLAT {
778         $$ = EvqFlat;
779     }
780     ;
781 
782 type_qualifier
783     : single_type_qualifier {
784         $$ = context->createTypeQualifierBuilder(@1);
785         $$->appendQualifier($1);
786     }
787     | type_qualifier single_type_qualifier {
788         $$ = $1;
789         $$->appendQualifier($2);
790     }
791     ;
792 
793 invariant_qualifier
794     : INVARIANT {
795         // empty
796     }
797     ;
798 
799 precise_qualifier
800     : PRECISE {
801         // empty
802     }
803     ;
804 
805 single_type_qualifier
806     : storage_qualifier {
807         context->checkLocalVariableConstStorageQualifier(*$1);
808         $$ = $1;
809     }
810     | layout_qualifier {
811         context->checkIsAtGlobalLevel(@1, "layout");
812         $$ = new TLayoutQualifierWrapper($1, @1);
813     }
814     | precision_qualifier {
815         $$ = new TPrecisionQualifierWrapper($1, @1);
816     }
817     | interpolation_qualifier {
818         $$ = new TInterpolationQualifierWrapper($1, @1);
819     }
820     | invariant_qualifier {
821         context->checkIsAtGlobalLevel(@1, "invariant");
822         $$ = new TInvariantQualifierWrapper(@1);
823     }
824     | precise_qualifier {
825         $$ = new TPreciseQualifierWrapper(@1);
826     }
827     ;
828 
829 
830 storage_qualifier
831     :
832     ATTRIBUTE {
833         VERTEX_ONLY("attribute", @1);
834         ES2_ONLY("attribute", @1);
835         $$ = context->parseGlobalStorageQualifier(EvqAttribute, @1);
836     }
837     | VARYING {
838         ES2_ONLY("varying", @1);
839         $$ = context->parseVaryingQualifier(@1);
840     }
841     | CONST_QUAL {
842         $$ = new TStorageQualifierWrapper(EvqConst, @1);
843     }
844     | IN_QUAL {
845         $$ = context->parseInQualifier(@1);
846     }
847     | OUT_QUAL {
848         $$ = context->parseOutQualifier(@1);
849     }
850     | INOUT_QUAL {
851         $$ = context->parseInOutQualifier(@1);
852     }
853     | CENTROID {
854         ES3_OR_NEWER("centroid", @1, "storage qualifier");
855         $$ = new TStorageQualifierWrapper(EvqCentroid, @1);
856     }
857     | UNIFORM {
858         $$ = context->parseGlobalStorageQualifier(EvqUniform, @1);
859     }
860     | BUFFER {
861         ES3_1_ONLY("buffer", @1, "storage qualifier");
862         $$ = context->parseGlobalStorageQualifier(EvqBuffer, @1);
863     }
864     | READONLY {
865         $$ = new TMemoryQualifierWrapper(EvqReadOnly, @1);
866     }
867     | WRITEONLY {
868         $$ = new TMemoryQualifierWrapper(EvqWriteOnly, @1);
869     }
870     | COHERENT {
871         $$ = new TMemoryQualifierWrapper(EvqCoherent, @1);
872     }
873     | RESTRICT {
874         $$ = new TMemoryQualifierWrapper(EvqRestrict, @1);
875     }
876     | VOLATILE {
877         $$ = new TMemoryQualifierWrapper(EvqVolatile, @1);
878     }
879     | SHARED {
880         COMPUTE_ONLY("shared", @1);
881         $$ = context->parseGlobalStorageQualifier(EvqShared, @1);
882     }
883     ;
884 
885 type_specifier
886     : type_specifier_no_prec {
887         $$ = $1;
888         $$.precision = context->symbolTable.getDefaultPrecision($1.getBasicType());
889     }
890     ;
891 
892 precision_qualifier
893     : HIGH_PRECISION {
894         $$ = EbpHigh;
895     }
896     | MEDIUM_PRECISION {
897         $$ = EbpMedium;
898     }
899     | LOW_PRECISION  {
900         $$ = EbpLow;
901     }
902     ;
903 
904 layout_qualifier
905     : LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN {
906         ES3_OR_NEWER("layout", @1, "qualifier");
907         $$ = $3;
908     }
909     ;
910 
911 layout_qualifier_id_list
912     : layout_qualifier_id {
913         $$ = $1;
914     }
915     | layout_qualifier_id_list COMMA layout_qualifier_id {
916         $$ = context->joinLayoutQualifiers($1, $3, @3);
917     }
918     ;
919 
920 layout_qualifier_id
921     : IDENTIFIER {
922         $$ = context->parseLayoutQualifier(ImmutableString($1.string), @1);
923     }
924     | IDENTIFIER EQUAL INTCONSTANT {
925         $$ = context->parseLayoutQualifier(ImmutableString($1.string), @1, $3.i, @3);
926     }
927     | IDENTIFIER EQUAL UINTCONSTANT {
928         $$ = context->parseLayoutQualifier(ImmutableString($1.string), @1, $3.i, @3);
929     }
930     | SHARED {
931         $$ = context->parseLayoutQualifier(ImmutableString("shared"), @1);
932     }
933     ;
934 
935 type_specifier_no_prec
936     : type_specifier_nonarray {
937         $$.initialize($1, (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary));
938     }
939     | type_specifier_nonarray array_specifier {
940         $$.initialize($1, (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary));
941         $$.setArraySizes($2);
942     }
943     ;
944 
945 array_specifier
946     : LEFT_BRACKET RIGHT_BRACKET {
947         ES3_OR_NEWER("[]", @1, "implicitly sized array");
948         $$ = new TVector<unsigned int>();
949         $$->push_back(0u);
950     }
951     | LEFT_BRACKET constant_expression RIGHT_BRACKET {
952         $$ = new TVector<unsigned int>();
953         unsigned int size = context->checkIsValidArraySize(@1, $2);
954         // Make the type an array even if size check failed.
955         // This ensures useless error messages regarding a variable's non-arrayness won't follow.
956         $$->push_back(size);
957     }
958     | array_specifier LEFT_BRACKET RIGHT_BRACKET {
959         ES3_1_ONLY("[]", @2, "arrays of arrays");
960         $$ = $1;
961         $$->insert($$->begin(), 0u);
962     }
963     | array_specifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
964         ES3_1_ONLY("[]", @2, "arrays of arrays");
965         $$ = $1;
966         unsigned int size = context->checkIsValidArraySize(@2, $3);
967         // Make the type an array even if size check failed.
968         // This ensures useless error messages regarding a variable's non-arrayness won't follow.
969         $$->insert($$->begin(), size);
970     }
971     ;
972 
973 type_specifier_nonarray
974     : VOID_TYPE {
975         $$.initialize(EbtVoid, @1);
976     }
977     | FLOAT_TYPE {
978         $$.initialize(EbtFloat, @1);
979     }
980     | INT_TYPE {
981         $$.initialize(EbtInt, @1);
982     }
983     | UINT_TYPE {
984         $$.initialize(EbtUInt, @1);
985     }
986     | BOOL_TYPE {
987         $$.initialize(EbtBool, @1);
988     }
989     | VEC2 {
990         $$.initialize(EbtFloat, @1);
991         $$.setAggregate(2);
992     }
993     | VEC3 {
994         $$.initialize(EbtFloat, @1);
995         $$.setAggregate(3);
996     }
997     | VEC4 {
998         $$.initialize(EbtFloat, @1);
999         $$.setAggregate(4);
1000     }
1001     | BVEC2 {
1002         $$.initialize(EbtBool, @1);
1003         $$.setAggregate(2);
1004     }
1005     | BVEC3 {
1006         $$.initialize(EbtBool, @1);
1007         $$.setAggregate(3);
1008     }
1009     | BVEC4 {
1010         $$.initialize(EbtBool, @1);
1011         $$.setAggregate(4);
1012     }
1013     | IVEC2 {
1014         $$.initialize(EbtInt, @1);
1015         $$.setAggregate(2);
1016     }
1017     | IVEC3 {
1018         $$.initialize(EbtInt, @1);
1019         $$.setAggregate(3);
1020     }
1021     | IVEC4 {
1022         $$.initialize(EbtInt, @1);
1023         $$.setAggregate(4);
1024     }
1025     | UVEC2 {
1026         $$.initialize(EbtUInt, @1);
1027         $$.setAggregate(2);
1028     }
1029     | UVEC3 {
1030         $$.initialize(EbtUInt, @1);
1031         $$.setAggregate(3);
1032     }
1033     | UVEC4 {
1034         $$.initialize(EbtUInt, @1);
1035         $$.setAggregate(4);
1036     }
1037     | MATRIX2 {
1038         $$.initialize(EbtFloat, @1);
1039         $$.setMatrix(2, 2);
1040     }
1041     | MATRIX3 {
1042         $$.initialize(EbtFloat, @1);
1043         $$.setMatrix(3, 3);
1044     }
1045     | MATRIX4 {
1046         $$.initialize(EbtFloat, @1);
1047         $$.setMatrix(4, 4);
1048     }
1049     | MATRIX2x3 {
1050         $$.initialize(EbtFloat, @1);
1051         $$.setMatrix(2, 3);
1052     }
1053     | MATRIX3x2 {
1054         $$.initialize(EbtFloat, @1);
1055         $$.setMatrix(3, 2);
1056     }
1057     | MATRIX2x4 {
1058         $$.initialize(EbtFloat, @1);
1059         $$.setMatrix(2, 4);
1060     }
1061     | MATRIX4x2 {
1062         $$.initialize(EbtFloat, @1);
1063         $$.setMatrix(4, 2);
1064     }
1065     | MATRIX3x4 {
1066         $$.initialize(EbtFloat, @1);
1067         $$.setMatrix(3, 4);
1068     }
1069     | MATRIX4x3 {
1070         $$.initialize(EbtFloat, @1);
1071         $$.setMatrix(4, 3);
1072     }
1073     | YUVCSCSTANDARDEXT {
1074         if (!context->checkCanUseExtension(@1, TExtension::EXT_YUV_target))
1075         {
1076             context->error(@1, "unsupported type", "yuvCscStandardEXT");
1077         }
1078         $$.initialize(EbtYuvCscStandardEXT, @1);
1079     }
1080     | SAMPLER2D {
1081         $$.initialize(EbtSampler2D, @1);
1082     }
1083     | SAMPLER3D {
1084         $$.initialize(EbtSampler3D, @1);
1085     }
1086     | SAMPLERCUBE {
1087         $$.initialize(EbtSamplerCube, @1);
1088     }
1089     | SAMPLER2DARRAY {
1090         $$.initialize(EbtSampler2DArray, @1);
1091     }
1092     | SAMPLER2DMS {
1093         $$.initialize(EbtSampler2DMS, @1);
1094     }
1095     | SAMPLER2DMSARRAY {
1096         $$.initialize(EbtSampler2DMSArray, @1);
1097     }
1098     | ISAMPLER2D {
1099         $$.initialize(EbtISampler2D, @1);
1100     }
1101     | ISAMPLER3D {
1102         $$.initialize(EbtISampler3D, @1);
1103     }
1104     | ISAMPLERCUBE {
1105         $$.initialize(EbtISamplerCube, @1);
1106     }
1107     | ISAMPLER2DARRAY {
1108         $$.initialize(EbtISampler2DArray, @1);
1109     }
1110     | ISAMPLER2DMS {
1111         $$.initialize(EbtISampler2DMS, @1);
1112     }
1113     | ISAMPLER2DMSARRAY {
1114         $$.initialize(EbtISampler2DMSArray, @1);
1115     }
1116     | USAMPLER2D {
1117         $$.initialize(EbtUSampler2D, @1);
1118     }
1119     | USAMPLER3D {
1120         $$.initialize(EbtUSampler3D, @1);
1121     }
1122     | USAMPLERCUBE {
1123         $$.initialize(EbtUSamplerCube, @1);
1124     }
1125     | USAMPLER2DARRAY {
1126         $$.initialize(EbtUSampler2DArray, @1);
1127     }
1128     | USAMPLER2DMS {
1129         $$.initialize(EbtUSampler2DMS, @1);
1130     }
1131     | USAMPLER2DMSARRAY {
1132         $$.initialize(EbtUSampler2DMSArray, @1);
1133     }
1134     | SAMPLER2DSHADOW {
1135         $$.initialize(EbtSampler2DShadow, @1);
1136     }
1137     | SAMPLERCUBESHADOW {
1138         $$.initialize(EbtSamplerCubeShadow, @1);
1139     }
1140     | SAMPLER2DARRAYSHADOW {
1141         $$.initialize(EbtSampler2DArrayShadow, @1);
1142     }
1143     | SAMPLERVIDEOWEBGL {
1144         if (!context->checkCanUseExtension(@1, TExtension::WEBGL_video_texture))
1145         {
1146             context->error(@1, "unsupported type", "samplerVideoWEBGL");
1147         }
1148         $$.initialize(EbtSamplerVideoWEBGL, @1);
1149     }
1150     | SAMPLER_EXTERNAL_OES {
1151         constexpr std::array<TExtension, 3u> extensions{ { TExtension::NV_EGL_stream_consumer_external,
1152                                                            TExtension::OES_EGL_image_external_essl3,
1153                                                            TExtension::OES_EGL_image_external } };
1154         if (!context->checkCanUseOneOfExtensions(@1, extensions))
1155         {
1156             context->error(@1, "unsupported type", "samplerExternalOES");
1157         }
1158         $$.initialize(EbtSamplerExternalOES, @1);
1159     }
1160     | SAMPLEREXTERNAL2DY2YEXT {
1161         if (!context->checkCanUseExtension(@1, TExtension::EXT_YUV_target))
1162         {
1163             context->error(@1, "unsupported type", "__samplerExternal2DY2YEXT");
1164         }
1165         $$.initialize(EbtSamplerExternal2DY2YEXT, @1);
1166     }
1167     | SAMPLER2DRECT {
1168         if (!context->checkCanUseExtension(@1, TExtension::ARB_texture_rectangle))
1169         {
1170             context->error(@1, "unsupported type", "sampler2DRect");
1171         }
1172         $$.initialize(EbtSampler2DRect, @1);
1173     }
1174     | IMAGE2D {
1175         $$.initialize(EbtImage2D, @1);
1176     }
1177     | IIMAGE2D {
1178         $$.initialize(EbtIImage2D, @1);
1179     }
1180     | UIMAGE2D {
1181         $$.initialize(EbtUImage2D, @1);
1182     }
1183     | IMAGE3D {
1184         $$.initialize(EbtImage3D, @1);
1185     }
1186     | IIMAGE3D {
1187         $$.initialize(EbtIImage3D, @1);
1188     }
1189     | UIMAGE3D {
1190         $$.initialize(EbtUImage3D, @1);
1191     }
1192     | IMAGE2DARRAY {
1193         $$.initialize(EbtImage2DArray, @1);
1194     }
1195     | IIMAGE2DARRAY {
1196         $$.initialize(EbtIImage2DArray, @1);
1197     }
1198     | UIMAGE2DARRAY {
1199         $$.initialize(EbtUImage2DArray, @1);
1200     }
1201     | IMAGECUBE {
1202         $$.initialize(EbtImageCube, @1);
1203     }
1204     | IIMAGECUBE {
1205         $$.initialize(EbtIImageCube, @1);
1206     }
1207     | UIMAGECUBE {
1208         $$.initialize(EbtUImageCube, @1);
1209     }
1210     | ATOMICUINT {
1211         $$.initialize(EbtAtomicCounter, @1);
1212     }
1213     | struct_specifier {
1214         $$ = $1;
1215     }
1216     | TYPE_NAME {
1217         // This is for user defined type names. The lexical phase looked up the type.
1218         const TStructure *structure = static_cast<const TStructure*>($1.symbol);
1219         $$.initializeStruct(structure, false, @1);
1220     }
1221     ;
1222 
1223 struct_specifier
1224     : STRUCT identifier LEFT_BRACE { context->enterStructDeclaration(@2, ImmutableString($2.string)); } struct_declaration_list RIGHT_BRACE {
1225         $$ = context->addStructure(@1, @2, ImmutableString($2.string), $5);
1226     }
1227     | STRUCT LEFT_BRACE { context->enterStructDeclaration(@2, kEmptyImmutableString); } struct_declaration_list RIGHT_BRACE {
1228         $$ = context->addStructure(@1, @$, kEmptyImmutableString, $4);
1229     }
1230     ;
1231 
1232 struct_declaration_list
1233     : struct_declaration {
1234         $$ = context->addStructFieldList($1, @1);
1235     }
1236     | struct_declaration_list struct_declaration {
1237         $$ = context->combineStructFieldLists($1, $2, @2);
1238     }
1239     ;
1240 
1241 struct_declaration
1242     : type_specifier struct_declarator_list SEMICOLON {
1243         $$ = context->addStructDeclaratorList($1, $2);
1244     }
1245     | type_qualifier type_specifier struct_declarator_list SEMICOLON {
1246         // ES3 Only, but errors should be handled elsewhere
1247         $$ = context->addStructDeclaratorListWithQualifiers(*$1, &$2, $3);
1248     }
1249     ;
1250 
1251 struct_declarator_list
1252     : struct_declarator {
1253         $$ = new TDeclaratorList();
1254         $$->push_back($1);
1255     }
1256     | struct_declarator_list COMMA struct_declarator {
1257         $$->push_back($3);
1258     }
1259     ;
1260 
1261 struct_declarator
1262     : identifier {
1263         $$ = context->parseStructDeclarator(ImmutableString($1.string), @1);
1264     }
1265     | identifier array_specifier {
1266         $$ = context->parseStructArrayDeclarator(ImmutableString($1.string), @1, $2);
1267     }
1268     ;
1269 
1270 initializer
1271     : assignment_expression { $$ = $1; }
1272     ;
1273 
1274 declaration_statement
1275     : declaration { $$ = $1; }
1276     ;
1277 
1278 statement
1279     : compound_statement_with_scope { $$ = $1; }
1280     | simple_statement              { $$ = $1; }
1281     ;
1282 
1283 // Grammar Note:  Labeled statements for SWITCH only; 'goto' is not supported.
1284 
1285 simple_statement
1286     : declaration_statement { $$ = $1; }
1287     | expression_statement  { $$ = $1; }
1288     | selection_statement   { $$ = $1; }
1289     | switch_statement      { $$ = $1; }
1290     | case_label            { $$ = $1; }
1291     | iteration_statement   { $$ = $1; }
1292     | jump_statement        { $$ = $1; }
1293     ;
1294 
1295 compound_statement_with_scope
1296     : LEFT_BRACE RIGHT_BRACE {
1297         $$ = new TIntermBlock();
1298         $$->setLine(@$);
1299     }
1300     | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE {
1301         $3->setLine(@$);
1302         $$ = $3;
1303     }
1304     ;
1305 
1306 statement_no_new_scope
1307     : compound_statement_no_new_scope { $$ = $1; }
1308     | simple_statement                { $$ = $1; }
1309     ;
1310 
1311 statement_with_scope
1312     : { context->symbolTable.push(); } compound_statement_no_new_scope { context->symbolTable.pop(); $$ = $2; }
1313     | { context->symbolTable.push(); } simple_statement                { context->symbolTable.pop(); $$ = $2; }
1314     ;
1315 
1316 compound_statement_no_new_scope
1317     // Statement that doesn't create a new scope for iteration_statement, function definition (scope is created for parameters)
1318     : LEFT_BRACE RIGHT_BRACE {
1319         $$ = new TIntermBlock();
1320         $$->setLine(@$);
1321     }
1322     | LEFT_BRACE statement_list RIGHT_BRACE {
1323         $2->setLine(@$);
1324         $$ = $2;
1325     }
1326     ;
1327 
1328 statement_list
1329     : statement {
1330         $$ = new TIntermBlock();
1331         context->appendStatement($$, $1);
1332     }
1333     | statement_list statement {
1334         $$ = $1;
1335         context->appendStatement($$, $2);
1336     }
1337     ;
1338 
1339 expression_statement
1340     : SEMICOLON  { $$ = context->addEmptyStatement(@$); }
1341     | expression SEMICOLON  { $$ = $1; }
1342     ;
1343 
1344 selection_statement
1345     : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
1346         $$ = context->addIfElse($3, $5, @1);
1347     }
1348     ;
1349 
1350 selection_rest_statement
1351     : statement_with_scope ELSE statement_with_scope {
1352         $$.node1 = $1;
1353         $$.node2 = $3;
1354     }
1355     | statement_with_scope {
1356         $$.node1 = $1;
1357         $$.node2 = nullptr;
1358     }
1359     ;
1360 
1361 // Note that we've diverged from the spec grammar here a bit for the sake of simplicity.
1362 // We're reusing compound_statement_with_scope instead of having separate rules for switch.
1363 switch_statement
1364     : SWITCH LEFT_PAREN expression RIGHT_PAREN { context->incrSwitchNestingLevel(); } compound_statement_with_scope {
1365         $$ = context->addSwitch($3, $6, @1);
1366         context->decrSwitchNestingLevel();
1367     }
1368     ;
1369 
1370 case_label
1371     : CASE constant_expression COLON {
1372         $$ = context->addCase($2, @1);
1373     }
1374     | DEFAULT COLON {
1375         $$ = context->addDefault(@1);
1376     }
1377     ;
1378 
1379 condition
1380     : expression {
1381         $$ = $1;
1382         context->checkIsScalarBool($1->getLine(), $1);
1383     }
1384     | fully_specified_type identifier EQUAL initializer {
1385         $$ = context->addConditionInitializer($1, ImmutableString($2.string), $4, @2);
1386     }
1387     ;
1388 
1389 iteration_statement
1390     : WHILE LEFT_PAREN { context->symbolTable.push(); context->incrLoopNestingLevel(); } condition RIGHT_PAREN statement_no_new_scope {
1391         context->symbolTable.pop();
1392         $$ = context->addLoop(ELoopWhile, 0, $4, 0, $6, @1);
1393         context->decrLoopNestingLevel();
1394     }
1395     | DO { context->incrLoopNestingLevel(); } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
1396         $$ = context->addLoop(ELoopDoWhile, 0, $6, 0, $3, @4);
1397         context->decrLoopNestingLevel();
1398     }
1399     | FOR LEFT_PAREN { context->symbolTable.push(); context->incrLoopNestingLevel(); } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
1400         context->symbolTable.pop();
1401         $$ = context->addLoop(ELoopFor, $4, $5.node1, reinterpret_cast<TIntermTyped*>($5.node2), $7, @1);
1402         context->decrLoopNestingLevel();
1403     }
1404     ;
1405 
1406 for_init_statement
1407     : expression_statement {
1408         $$ = $1;
1409     }
1410     | declaration_statement {
1411         $$ = $1;
1412     }
1413     ;
1414 
1415 conditionopt
1416     : condition {
1417         $$ = $1;
1418     }
1419     | /* May be null */ {
1420         $$ = nullptr;
1421     }
1422     ;
1423 
1424 for_rest_statement
1425     : conditionopt SEMICOLON {
1426         $$.node1 = $1;
1427         $$.node2 = 0;
1428     }
1429     | conditionopt SEMICOLON expression  {
1430         $$.node1 = $1;
1431         $$.node2 = $3;
1432     }
1433     ;
1434 
1435 jump_statement
1436     : CONTINUE SEMICOLON {
1437         $$ = context->addBranch(EOpContinue, @1);
1438     }
1439     | BREAK SEMICOLON {
1440         $$ = context->addBranch(EOpBreak, @1);
1441     }
1442     | RETURN SEMICOLON {
1443         $$ = context->addBranch(EOpReturn, @1);
1444     }
1445     | RETURN expression SEMICOLON {
1446         $$ = context->addBranch(EOpReturn, $2, @1);
1447     }
1448     | DISCARD SEMICOLON {
1449         $$ = context->addBranch(EOpKill, @1);
1450     }
1451     ;
1452 
1453 // Grammar Note:  No 'goto'.  Gotos are not supported.
1454 
1455 translation_unit
1456     : external_declaration {
1457         $$ = new TIntermBlock();
1458         $$->setLine(@$);
1459         $$->appendStatement($1);
1460         context->setTreeRoot($$);
1461     }
1462     | translation_unit external_declaration {
1463         $$->appendStatement($2);
1464     }
1465     ;
1466 
1467 external_declaration
1468     : function_definition {
1469         $$ = $1;
1470     }
1471     | declaration {
1472         $$ = $1;
1473     }
1474     ;
1475 
1476 function_definition
1477     : function_prototype {
1478         context->parseFunctionDefinitionHeader(@1, $1.function, &($1.intermFunctionPrototype));
1479     }
1480     compound_statement_no_new_scope {
1481         $$ = context->addFunctionDefinition($1.intermFunctionPrototype, $3, @1);
1482     }
1483     ;
1484 
1485 %%
1486 
1487 int glslang_parse(TParseContext* context) {
1488     return yyparse(context, context->getScanner());
1489 }
1490