1 //
2 // Copyright (C) 2016-2018 Google, Inc.
3 // Copyright (C) 2016 LunarG, Inc.
4 //
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
11 //    Redistributions of source code must retain the above copyright
12 //    notice, this list of conditions and the following disclaimer.
13 //
14 //    Redistributions in binary form must reproduce the above
15 //    copyright notice, this list of conditions and the following
16 //    disclaimer in the documentation and/or other materials provided
17 //    with the distribution.
18 //
19 //    Neither the name of Google, Inc., nor the names of its
20 //    contributors may be used to endorse or promote products derived
21 //    from this software without specific prior written permission.
22 //
23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 // POSSIBILITY OF SUCH DAMAGE.
35 //
36 
37 //
38 // This is a set of mutually recursive methods implementing the HLSL grammar.
39 // Generally, each returns
40 //  - through an argument: a type specifically appropriate to which rule it
41 //    recognized
42 //  - through the return value: true/false to indicate whether or not it
43 //    recognized its rule
44 //
45 // As much as possible, only grammar recognition should happen in this file,
46 // with all other work being farmed out to hlslParseHelper.cpp, which in turn
47 // will build the AST.
48 //
49 // The next token, yet to be "accepted" is always sitting in 'token'.
50 // When a method says it accepts a rule, that means all tokens involved
51 // in the rule will have been consumed, and none left in 'token'.
52 //
53 
54 #include "hlslTokens.h"
55 #include "hlslGrammar.h"
56 #include "hlslAttributes.h"
57 
58 namespace glslang {
59 
60 // Root entry point to this recursive decent parser.
61 // Return true if compilation unit was successfully accepted.
parse()62 bool HlslGrammar::parse()
63 {
64     advanceToken();
65     return acceptCompilationUnit();
66 }
67 
expected(const char * syntax)68 void HlslGrammar::expected(const char* syntax)
69 {
70     parseContext.error(token.loc, "Expected", syntax, "");
71 }
72 
unimplemented(const char * error)73 void HlslGrammar::unimplemented(const char* error)
74 {
75     parseContext.error(token.loc, "Unimplemented", error, "");
76 }
77 
78 // IDENTIFIER
79 // THIS
80 // type that can be used as IDENTIFIER
81 //
82 // Only process the next token if it is an identifier.
83 // Return true if it was an identifier.
acceptIdentifier(HlslToken & idToken)84 bool HlslGrammar::acceptIdentifier(HlslToken& idToken)
85 {
86     // IDENTIFIER
87     if (peekTokenClass(EHTokIdentifier)) {
88         idToken = token;
89         advanceToken();
90         return true;
91     }
92 
93     // THIS
94     // -> maps to the IDENTIFIER spelled with the internal special name for 'this'
95     if (peekTokenClass(EHTokThis)) {
96         idToken = token;
97         advanceToken();
98         idToken.tokenClass = EHTokIdentifier;
99         idToken.string = NewPoolTString(intermediate.implicitThisName);
100         return true;
101     }
102 
103     // type that can be used as IDENTIFIER
104 
105     // Even though "sample", "bool", "float", etc keywords (for types, interpolation modifiers),
106     // they ARE still accepted as identifiers.  This is not a dense space: e.g, "void" is not a
107     // valid identifier, nor is "linear".  This code special cases the known instances of this, so
108     // e.g, "int sample;" or "float float;" is accepted.  Other cases can be added here if needed.
109 
110     const char* idString = getTypeString(peek());
111     if (idString == nullptr)
112         return false;
113 
114     token.string     = NewPoolTString(idString);
115     token.tokenClass = EHTokIdentifier;
116     idToken = token;
117     typeIdentifiers = true;
118 
119     advanceToken();
120 
121     return true;
122 }
123 
124 // compilationUnit
125 //      : declaration_list EOF
126 //
acceptCompilationUnit()127 bool HlslGrammar::acceptCompilationUnit()
128 {
129     if (! acceptDeclarationList(unitNode))
130         return false;
131 
132     if (! peekTokenClass(EHTokNone))
133         return false;
134 
135     // set root of AST
136     if (unitNode && !unitNode->getAsAggregate())
137         unitNode = intermediate.growAggregate(nullptr, unitNode);
138     intermediate.setTreeRoot(unitNode);
139 
140     return true;
141 }
142 
143 // Recognize the following, but with the extra condition that it can be
144 // successfully terminated by EOF or '}'.
145 //
146 // declaration_list
147 //      : list of declaration_or_semicolon followed by EOF or RIGHT_BRACE
148 //
149 // declaration_or_semicolon
150 //      : declaration
151 //      : SEMICOLON
152 //
acceptDeclarationList(TIntermNode * & nodeList)153 bool HlslGrammar::acceptDeclarationList(TIntermNode*& nodeList)
154 {
155     do {
156         // HLSL allows extra semicolons between global declarations
157         do { } while (acceptTokenClass(EHTokSemicolon));
158 
159         // EOF or RIGHT_BRACE
160         if (peekTokenClass(EHTokNone) || peekTokenClass(EHTokRightBrace))
161             return true;
162 
163         // declaration
164         if (! acceptDeclaration(nodeList))
165             return false;
166     } while (true);
167 
168     return true;
169 }
170 
171 // sampler_state
172 //      : LEFT_BRACE [sampler_state_assignment ... ] RIGHT_BRACE
173 //
174 // sampler_state_assignment
175 //     : sampler_state_identifier EQUAL value SEMICOLON
176 //
177 // sampler_state_identifier
178 //     : ADDRESSU
179 //     | ADDRESSV
180 //     | ADDRESSW
181 //     | BORDERCOLOR
182 //     | FILTER
183 //     | MAXANISOTROPY
184 //     | MAXLOD
185 //     | MINLOD
186 //     | MIPLODBIAS
187 //
acceptSamplerState()188 bool HlslGrammar::acceptSamplerState()
189 {
190     // TODO: this should be genericized to accept a list of valid tokens and
191     // return token/value pairs.  Presently it is specific to texture values.
192 
193     if (! acceptTokenClass(EHTokLeftBrace))
194         return true;
195 
196     parseContext.warn(token.loc, "unimplemented", "immediate sampler state", "");
197 
198     do {
199         // read state name
200         HlslToken state;
201         if (! acceptIdentifier(state))
202             break;  // end of list
203 
204         // FXC accepts any case
205         TString stateName = *state.string;
206         std::transform(stateName.begin(), stateName.end(), stateName.begin(), ::tolower);
207 
208         if (! acceptTokenClass(EHTokAssign)) {
209             expected("assign");
210             return false;
211         }
212 
213         if (stateName == "minlod" || stateName == "maxlod") {
214             if (! peekTokenClass(EHTokIntConstant)) {
215                 expected("integer");
216                 return false;
217             }
218 
219             TIntermTyped* lod = nullptr;
220             if (! acceptLiteral(lod))  // should never fail, since we just looked for an integer
221                 return false;
222         } else if (stateName == "maxanisotropy") {
223             if (! peekTokenClass(EHTokIntConstant)) {
224                 expected("integer");
225                 return false;
226             }
227 
228             TIntermTyped* maxAnisotropy = nullptr;
229             if (! acceptLiteral(maxAnisotropy))  // should never fail, since we just looked for an integer
230                 return false;
231         } else if (stateName == "filter") {
232             HlslToken filterMode;
233             if (! acceptIdentifier(filterMode)) {
234                 expected("filter mode");
235                 return false;
236             }
237         } else if (stateName == "addressu" || stateName == "addressv" || stateName == "addressw") {
238             HlslToken addrMode;
239             if (! acceptIdentifier(addrMode)) {
240                 expected("texture address mode");
241                 return false;
242             }
243         } else if (stateName == "miplodbias") {
244             TIntermTyped* lodBias = nullptr;
245             if (! acceptLiteral(lodBias)) {
246                 expected("lod bias");
247                 return false;
248             }
249         } else if (stateName == "bordercolor") {
250             return false;
251         } else {
252             expected("texture state");
253             return false;
254         }
255 
256         // SEMICOLON
257         if (! acceptTokenClass(EHTokSemicolon)) {
258             expected("semicolon");
259             return false;
260         }
261     } while (true);
262 
263     if (! acceptTokenClass(EHTokRightBrace))
264         return false;
265 
266     return true;
267 }
268 
269 // sampler_declaration_dx9
270 //    : SAMPLER identifier EQUAL sampler_type sampler_state
271 //
acceptSamplerDeclarationDX9(TType &)272 bool HlslGrammar::acceptSamplerDeclarationDX9(TType& /*type*/)
273 {
274     if (! acceptTokenClass(EHTokSampler))
275         return false;
276 
277     // TODO: remove this when DX9 style declarations are implemented.
278     unimplemented("Direct3D 9 sampler declaration");
279 
280     // read sampler name
281     HlslToken name;
282     if (! acceptIdentifier(name)) {
283         expected("sampler name");
284         return false;
285     }
286 
287     if (! acceptTokenClass(EHTokAssign)) {
288         expected("=");
289         return false;
290     }
291 
292     return false;
293 }
294 
295 // declaration
296 //      : attributes attributed_declaration
297 //      | NAMESPACE IDENTIFIER LEFT_BRACE declaration_list RIGHT_BRACE
298 //
299 // attributed_declaration
300 //      : sampler_declaration_dx9 post_decls SEMICOLON
301 //      | fully_specified_type                           // for cbuffer/tbuffer
302 //      | fully_specified_type declarator_list SEMICOLON // for non cbuffer/tbuffer
303 //      | fully_specified_type identifier function_parameters post_decls compound_statement  // function definition
304 //      | fully_specified_type identifier sampler_state post_decls compound_statement        // sampler definition
305 //      | typedef declaration
306 //
307 // declarator_list
308 //      : declarator COMMA declarator COMMA declarator...  // zero or more declarators
309 //
310 // declarator
311 //      : identifier array_specifier post_decls
312 //      | identifier array_specifier post_decls EQUAL assignment_expression
313 //      | identifier function_parameters post_decls                                          // function prototype
314 //
315 // Parsing has to go pretty far in to know whether it's a variable, prototype, or
316 // function definition, so the implementation below doesn't perfectly divide up the grammar
317 // as above.  (The 'identifier' in the first item in init_declarator list is the
318 // same as 'identifier' for function declarations.)
319 //
320 // This can generate more than one subtree, one per initializer or a function body.
321 // All initializer subtrees are put in their own aggregate node, making one top-level
322 // node for all the initializers. Each function created is a top-level node to grow
323 // into the passed-in nodeList.
324 //
325 // If 'nodeList' is passed in as non-null, it must be an aggregate to extend for
326 // each top-level node the declaration creates. Otherwise, if only one top-level
327 // node in generated here, that is want is returned in nodeList.
328 //
acceptDeclaration(TIntermNode * & nodeList)329 bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
330 {
331     // NAMESPACE IDENTIFIER LEFT_BRACE declaration_list RIGHT_BRACE
332     if (acceptTokenClass(EHTokNamespace)) {
333         HlslToken namespaceToken;
334         if (!acceptIdentifier(namespaceToken)) {
335             expected("namespace name");
336             return false;
337         }
338         parseContext.pushNamespace(*namespaceToken.string);
339         if (!acceptTokenClass(EHTokLeftBrace)) {
340             expected("{");
341             return false;
342         }
343         if (!acceptDeclarationList(nodeList)) {
344             expected("declaration list");
345             return false;
346         }
347         if (!acceptTokenClass(EHTokRightBrace)) {
348             expected("}");
349             return false;
350         }
351         parseContext.popNamespace();
352         return true;
353     }
354 
355     bool declarator_list = false; // true when processing comma separation
356 
357     // attributes
358     TFunctionDeclarator declarator;
359     acceptAttributes(declarator.attributes);
360 
361     // typedef
362     bool typedefDecl = acceptTokenClass(EHTokTypedef);
363 
364     TType declaredType;
365 
366     // DX9 sampler declaration use a different syntax
367     // DX9 shaders need to run through HLSL compiler (fxc) via a back compat mode, it isn't going to
368     // be possible to simultaneously compile D3D10+ style shaders and DX9 shaders. If we want to compile DX9
369     // HLSL shaders, this will have to be a master level switch
370     // As such, the sampler keyword in D3D10+ turns into an automatic sampler type, and is commonly used
371     // For that reason, this line is commented out
372     // if (acceptSamplerDeclarationDX9(declaredType))
373     //     return true;
374 
375     bool forbidDeclarators = (peekTokenClass(EHTokCBuffer) || peekTokenClass(EHTokTBuffer));
376     // fully_specified_type
377     if (! acceptFullySpecifiedType(declaredType, nodeList, declarator.attributes, forbidDeclarators))
378         return false;
379 
380     // cbuffer and tbuffer end with the closing '}'.
381     // No semicolon is included.
382     if (forbidDeclarators)
383         return true;
384 
385     // Check if there are invalid in/out qualifiers
386     switch (declaredType.getQualifier().storage) {
387     case EvqIn:
388     case EvqOut:
389     case EvqInOut:
390         parseContext.error(token.loc, "in/out qualifiers are only valid on parameters", token.string->c_str(), "");
391     default:
392         break;
393     }
394 
395     // declarator_list
396     //    : declarator
397     //         : identifier
398     HlslToken idToken;
399     TIntermAggregate* initializers = nullptr;
400     while (acceptIdentifier(idToken)) {
401         TString *fullName = idToken.string;
402         if (parseContext.symbolTable.atGlobalLevel())
403             parseContext.getFullNamespaceName(fullName);
404         if (peekTokenClass(EHTokLeftParen)) {
405             // looks like function parameters
406 
407             // merge in the attributes into the return type
408             parseContext.transferTypeAttributes(token.loc, declarator.attributes, declaredType, true);
409 
410             // Potentially rename shader entry point function.  No-op most of the time.
411             parseContext.renameShaderFunction(fullName);
412 
413             // function_parameters
414             declarator.function = new TFunction(fullName, declaredType);
415             if (!acceptFunctionParameters(*declarator.function)) {
416                 expected("function parameter list");
417                 return false;
418             }
419 
420             // post_decls
421             acceptPostDecls(declarator.function->getWritableType().getQualifier());
422 
423             // compound_statement (function body definition) or just a prototype?
424             declarator.loc = token.loc;
425             if (peekTokenClass(EHTokLeftBrace)) {
426                 if (declarator_list)
427                     parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
428                 if (typedefDecl)
429                     parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
430                 return acceptFunctionDefinition(declarator, nodeList, nullptr);
431             } else {
432                 if (typedefDecl)
433                     parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
434                 parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, true);
435             }
436         } else {
437             // A variable declaration.
438 
439             // merge in the attributes, the first time around, into the shared type
440             if (! declarator_list)
441                 parseContext.transferTypeAttributes(token.loc, declarator.attributes, declaredType);
442 
443             // Fix the storage qualifier if it's a global.
444             if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
445                 declaredType.getQualifier().storage = EvqUniform;
446 
447             // recognize array_specifier
448             TArraySizes* arraySizes = nullptr;
449             acceptArraySpecifier(arraySizes);
450 
451             // We can handle multiple variables per type declaration, so
452             // the number of types can expand when arrayness is different.
453             TType variableType;
454             variableType.shallowCopy(declaredType);
455 
456             // In the most general case, arrayness is potentially coming both from the
457             // declared type and from the variable: "int[] a[];" or just one or the other.
458             // Merge it all to the variableType, so all arrayness is part of the variableType.
459             variableType.transferArraySizes(arraySizes);
460             variableType.copyArrayInnerSizes(declaredType.getArraySizes());
461 
462             // samplers accept immediate sampler state
463             if (variableType.getBasicType() == EbtSampler) {
464                 if (! acceptSamplerState())
465                     return false;
466             }
467 
468             // post_decls
469             acceptPostDecls(variableType.getQualifier());
470 
471             // EQUAL assignment_expression
472             TIntermTyped* expressionNode = nullptr;
473             if (acceptTokenClass(EHTokAssign)) {
474                 if (typedefDecl)
475                     parseContext.error(idToken.loc, "can't have an initializer", "typedef", "");
476                 if (! acceptAssignmentExpression(expressionNode)) {
477                     expected("initializer");
478                     return false;
479                 }
480             }
481 
482             // TODO: things scoped within an annotation need their own name space;
483             // TODO: non-constant strings are not yet handled.
484             if (!(variableType.getBasicType() == EbtString && !variableType.getQualifier().isConstant()) &&
485                 parseContext.getAnnotationNestingLevel() == 0) {
486                 if (typedefDecl)
487                     parseContext.declareTypedef(idToken.loc, *fullName, variableType);
488                 else if (variableType.getBasicType() == EbtBlock) {
489                     if (expressionNode)
490                         parseContext.error(idToken.loc, "buffer aliasing not yet supported", "block initializer", "");
491                     parseContext.declareBlock(idToken.loc, variableType, fullName);
492                     parseContext.declareStructBufferCounter(idToken.loc, variableType, *fullName);
493                 } else {
494                     if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) {
495                         // this isn't really an individual variable, but a member of the $Global buffer
496                         parseContext.growGlobalUniformBlock(idToken.loc, variableType, *fullName);
497                     } else {
498                         // Declare the variable and add any initializer code to the AST.
499                         // The top-level node is always made into an aggregate, as that's
500                         // historically how the AST has been.
501                         initializers = intermediate.growAggregate(initializers,
502                             parseContext.declareVariable(idToken.loc, *fullName, variableType, expressionNode),
503                             idToken.loc);
504                     }
505                 }
506             }
507         }
508 
509         // COMMA
510         if (acceptTokenClass(EHTokComma))
511             declarator_list = true;
512     }
513 
514     // The top-level initializer node is a sequence.
515     if (initializers != nullptr)
516         initializers->setOperator(EOpSequence);
517 
518     // if we have a locally scoped static, it needs a globally scoped initializer
519     if (declaredType.getQualifier().storage == EvqGlobal && !parseContext.symbolTable.atGlobalLevel()) {
520         unitNode = intermediate.growAggregate(unitNode, initializers, idToken.loc);
521     } else {
522         // Add the initializers' aggregate to the nodeList we were handed.
523         if (nodeList)
524             nodeList = intermediate.growAggregate(nodeList, initializers);
525         else
526             nodeList = initializers;
527     }
528 
529     // SEMICOLON
530     if (! acceptTokenClass(EHTokSemicolon)) {
531         // This may have been a false detection of what appeared to be a declaration, but
532         // was actually an assignment such as "float = 4", where "float" is an identifier.
533         // We put the token back to let further parsing happen for cases where that may
534         // happen.  This errors on the side of caution, and mostly triggers the error.
535         if (peek() == EHTokAssign || peek() == EHTokLeftBracket || peek() == EHTokDot || peek() == EHTokComma)
536             recedeToken();
537         else
538             expected(";");
539         return false;
540     }
541 
542     return true;
543 }
544 
545 // control_declaration
546 //      : fully_specified_type identifier EQUAL expression
547 //
acceptControlDeclaration(TIntermNode * & node)548 bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
549 {
550     node = nullptr;
551     TAttributes attributes;
552 
553     // fully_specified_type
554     TType type;
555     if (! acceptFullySpecifiedType(type, attributes))
556         return false;
557 
558     if (attributes.size() > 0)
559         parseContext.warn(token.loc, "attributes don't apply to control declaration", "", "");
560 
561     // filter out type casts
562     if (peekTokenClass(EHTokLeftParen)) {
563         recedeToken();
564         return false;
565     }
566 
567     // identifier
568     HlslToken idToken;
569     if (! acceptIdentifier(idToken)) {
570         expected("identifier");
571         return false;
572     }
573 
574     // EQUAL
575     TIntermTyped* expressionNode = nullptr;
576     if (! acceptTokenClass(EHTokAssign)) {
577         expected("=");
578         return false;
579     }
580 
581     // expression
582     if (! acceptExpression(expressionNode)) {
583         expected("initializer");
584         return false;
585     }
586 
587     node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode);
588 
589     return true;
590 }
591 
592 // fully_specified_type
593 //      : type_specifier
594 //      | type_qualifier type_specifier
595 //
acceptFullySpecifiedType(TType & type,const TAttributes & attributes)596 bool HlslGrammar::acceptFullySpecifiedType(TType& type, const TAttributes& attributes)
597 {
598     TIntermNode* nodeList = nullptr;
599     return acceptFullySpecifiedType(type, nodeList, attributes);
600 }
acceptFullySpecifiedType(TType & type,TIntermNode * & nodeList,const TAttributes & attributes,bool forbidDeclarators)601 bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList, const TAttributes& attributes, bool forbidDeclarators)
602 {
603     // type_qualifier
604     TQualifier qualifier;
605     qualifier.clear();
606     if (! acceptQualifier(qualifier))
607         return false;
608     TSourceLoc loc = token.loc;
609 
610     // type_specifier
611     if (! acceptType(type, nodeList)) {
612         // If this is not a type, we may have inadvertently gone down a wrong path
613         // by parsing "sample", which can be treated like either an identifier or a
614         // qualifier.  Back it out, if we did.
615         if (qualifier.sample)
616             recedeToken();
617 
618         return false;
619     }
620 
621     if (type.getBasicType() == EbtBlock) {
622         // the type was a block, which set some parts of the qualifier
623         parseContext.mergeQualifiers(type.getQualifier(), qualifier);
624 
625         // merge in the attributes
626         parseContext.transferTypeAttributes(token.loc, attributes, type);
627 
628         // further, it can create an anonymous instance of the block
629         // (cbuffer and tbuffer don't consume the next identifier, and
630         // should set forbidDeclarators)
631         if (forbidDeclarators || peek() != EHTokIdentifier)
632             parseContext.declareBlock(loc, type);
633     } else {
634         // Some qualifiers are set when parsing the type.  Merge those with
635         // whatever comes from acceptQualifier.
636         assert(qualifier.layoutFormat == ElfNone);
637 
638         qualifier.layoutFormat = type.getQualifier().layoutFormat;
639         qualifier.precision    = type.getQualifier().precision;
640 
641         if (type.getQualifier().storage == EvqOut ||
642             type.getQualifier().storage == EvqBuffer) {
643             qualifier.storage      = type.getQualifier().storage;
644             qualifier.readonly     = type.getQualifier().readonly;
645         }
646 
647         if (type.isBuiltIn())
648             qualifier.builtIn = type.getQualifier().builtIn;
649 
650         type.getQualifier() = qualifier;
651     }
652 
653     return true;
654 }
655 
656 // type_qualifier
657 //      : qualifier qualifier ...
658 //
659 // Zero or more of these, so this can't return false.
660 //
acceptQualifier(TQualifier & qualifier)661 bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
662 {
663     do {
664         switch (peek()) {
665         case EHTokStatic:
666             qualifier.storage = EvqGlobal;
667             break;
668         case EHTokExtern:
669             // TODO: no meaning in glslang?
670             break;
671         case EHTokShared:
672             // TODO: hint
673             break;
674         case EHTokGroupShared:
675             qualifier.storage = EvqShared;
676             break;
677         case EHTokUniform:
678             qualifier.storage = EvqUniform;
679             break;
680         case EHTokConst:
681             qualifier.storage = EvqConst;
682             break;
683         case EHTokVolatile:
684             qualifier.volatil = true;
685             break;
686         case EHTokLinear:
687             qualifier.smooth = true;
688             break;
689         case EHTokCentroid:
690             qualifier.centroid = true;
691             break;
692         case EHTokNointerpolation:
693             qualifier.flat = true;
694             break;
695         case EHTokNoperspective:
696             qualifier.nopersp = true;
697             break;
698         case EHTokSample:
699             qualifier.sample = true;
700             break;
701         case EHTokRowMajor:
702             qualifier.layoutMatrix = ElmColumnMajor;
703             break;
704         case EHTokColumnMajor:
705             qualifier.layoutMatrix = ElmRowMajor;
706             break;
707         case EHTokPrecise:
708             qualifier.noContraction = true;
709             break;
710         case EHTokIn:
711             if (qualifier.storage != EvqUniform) {
712                 qualifier.storage = (qualifier.storage == EvqOut) ? EvqInOut : EvqIn;
713             }
714             break;
715         case EHTokOut:
716             qualifier.storage = (qualifier.storage == EvqIn) ? EvqInOut : EvqOut;
717             break;
718         case EHTokInOut:
719             qualifier.storage = EvqInOut;
720             break;
721         case EHTokLayout:
722             if (! acceptLayoutQualifierList(qualifier))
723                 return false;
724             continue;
725         case EHTokGloballyCoherent:
726             qualifier.coherent = true;
727             break;
728         case EHTokInline:
729             // TODO: map this to SPIR-V function control
730             break;
731 
732         // GS geometries: these are specified on stage input variables, and are an error (not verified here)
733         // for output variables.
734         case EHTokPoint:
735             qualifier.storage = EvqIn;
736             if (!parseContext.handleInputGeometry(token.loc, ElgPoints))
737                 return false;
738             break;
739         case EHTokLine:
740             qualifier.storage = EvqIn;
741             if (!parseContext.handleInputGeometry(token.loc, ElgLines))
742                 return false;
743             break;
744         case EHTokTriangle:
745             qualifier.storage = EvqIn;
746             if (!parseContext.handleInputGeometry(token.loc, ElgTriangles))
747                 return false;
748             break;
749         case EHTokLineAdj:
750             qualifier.storage = EvqIn;
751             if (!parseContext.handleInputGeometry(token.loc, ElgLinesAdjacency))
752                 return false;
753             break;
754         case EHTokTriangleAdj:
755             qualifier.storage = EvqIn;
756             if (!parseContext.handleInputGeometry(token.loc, ElgTrianglesAdjacency))
757                 return false;
758             break;
759 
760         default:
761             return true;
762         }
763         advanceToken();
764     } while (true);
765 }
766 
767 // layout_qualifier_list
768 //      : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN
769 //
770 // layout_qualifier
771 //      : identifier
772 //      | identifier EQUAL expression
773 //
774 // Zero or more of these, so this can't return false.
775 //
acceptLayoutQualifierList(TQualifier & qualifier)776 bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier)
777 {
778     if (! acceptTokenClass(EHTokLayout))
779         return false;
780 
781     // LEFT_PAREN
782     if (! acceptTokenClass(EHTokLeftParen))
783         return false;
784 
785     do {
786         // identifier
787         HlslToken idToken;
788         if (! acceptIdentifier(idToken))
789             break;
790 
791         // EQUAL expression
792         if (acceptTokenClass(EHTokAssign)) {
793             TIntermTyped* expr;
794             if (! acceptConditionalExpression(expr)) {
795                 expected("expression");
796                 return false;
797             }
798             parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr);
799         } else
800             parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string);
801 
802         // COMMA
803         if (! acceptTokenClass(EHTokComma))
804             break;
805     } while (true);
806 
807     // RIGHT_PAREN
808     if (! acceptTokenClass(EHTokRightParen)) {
809         expected(")");
810         return false;
811     }
812 
813     return true;
814 }
815 
816 // template_type
817 //      : FLOAT
818 //      | DOUBLE
819 //      | INT
820 //      | DWORD
821 //      | UINT
822 //      | BOOL
823 //
acceptTemplateVecMatBasicType(TBasicType & basicType)824 bool HlslGrammar::acceptTemplateVecMatBasicType(TBasicType& basicType)
825 {
826     switch (peek()) {
827     case EHTokFloat:
828         basicType = EbtFloat;
829         break;
830     case EHTokDouble:
831         basicType = EbtDouble;
832         break;
833     case EHTokInt:
834     case EHTokDword:
835         basicType = EbtInt;
836         break;
837     case EHTokUint:
838         basicType = EbtUint;
839         break;
840     case EHTokBool:
841         basicType = EbtBool;
842         break;
843     default:
844         return false;
845     }
846 
847     advanceToken();
848 
849     return true;
850 }
851 
852 // vector_template_type
853 //      : VECTOR
854 //      | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE
855 //
acceptVectorTemplateType(TType & type)856 bool HlslGrammar::acceptVectorTemplateType(TType& type)
857 {
858     if (! acceptTokenClass(EHTokVector))
859         return false;
860 
861     if (! acceptTokenClass(EHTokLeftAngle)) {
862         // in HLSL, 'vector' alone means float4.
863         new(&type) TType(EbtFloat, EvqTemporary, 4);
864         return true;
865     }
866 
867     TBasicType basicType;
868     if (! acceptTemplateVecMatBasicType(basicType)) {
869         expected("scalar type");
870         return false;
871     }
872 
873     // COMMA
874     if (! acceptTokenClass(EHTokComma)) {
875         expected(",");
876         return false;
877     }
878 
879     // integer
880     if (! peekTokenClass(EHTokIntConstant)) {
881         expected("literal integer");
882         return false;
883     }
884 
885     TIntermTyped* vecSize;
886     if (! acceptLiteral(vecSize))
887         return false;
888 
889     const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst();
890 
891     new(&type) TType(basicType, EvqTemporary, vecSizeI);
892 
893     if (vecSizeI == 1)
894         type.makeVector();
895 
896     if (!acceptTokenClass(EHTokRightAngle)) {
897         expected("right angle bracket");
898         return false;
899     }
900 
901     return true;
902 }
903 
904 // matrix_template_type
905 //      : MATRIX
906 //      | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE
907 //
acceptMatrixTemplateType(TType & type)908 bool HlslGrammar::acceptMatrixTemplateType(TType& type)
909 {
910     if (! acceptTokenClass(EHTokMatrix))
911         return false;
912 
913     if (! acceptTokenClass(EHTokLeftAngle)) {
914         // in HLSL, 'matrix' alone means float4x4.
915         new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
916         return true;
917     }
918 
919     TBasicType basicType;
920     if (! acceptTemplateVecMatBasicType(basicType)) {
921         expected("scalar type");
922         return false;
923     }
924 
925     // COMMA
926     if (! acceptTokenClass(EHTokComma)) {
927         expected(",");
928         return false;
929     }
930 
931     // integer rows
932     if (! peekTokenClass(EHTokIntConstant)) {
933         expected("literal integer");
934         return false;
935     }
936 
937     TIntermTyped* rows;
938     if (! acceptLiteral(rows))
939         return false;
940 
941     // COMMA
942     if (! acceptTokenClass(EHTokComma)) {
943         expected(",");
944         return false;
945     }
946 
947     // integer cols
948     if (! peekTokenClass(EHTokIntConstant)) {
949         expected("literal integer");
950         return false;
951     }
952 
953     TIntermTyped* cols;
954     if (! acceptLiteral(cols))
955         return false;
956 
957     new(&type) TType(basicType, EvqTemporary, 0,
958                      rows->getAsConstantUnion()->getConstArray()[0].getIConst(),
959                      cols->getAsConstantUnion()->getConstArray()[0].getIConst());
960 
961     if (!acceptTokenClass(EHTokRightAngle)) {
962         expected("right angle bracket");
963         return false;
964     }
965 
966     return true;
967 }
968 
969 // layout_geometry
970 //      : LINESTREAM
971 //      | POINTSTREAM
972 //      | TRIANGLESTREAM
973 //
acceptOutputPrimitiveGeometry(TLayoutGeometry & geometry)974 bool HlslGrammar::acceptOutputPrimitiveGeometry(TLayoutGeometry& geometry)
975 {
976     // read geometry type
977     const EHlslTokenClass geometryType = peek();
978 
979     switch (geometryType) {
980     case EHTokPointStream:    geometry = ElgPoints;        break;
981     case EHTokLineStream:     geometry = ElgLineStrip;     break;
982     case EHTokTriangleStream: geometry = ElgTriangleStrip; break;
983     default:
984         return false;  // not a layout geometry
985     }
986 
987     advanceToken();  // consume the layout keyword
988     return true;
989 }
990 
991 // tessellation_decl_type
992 //      : INPUTPATCH
993 //      | OUTPUTPATCH
994 //
acceptTessellationDeclType(TBuiltInVariable & patchType)995 bool HlslGrammar::acceptTessellationDeclType(TBuiltInVariable& patchType)
996 {
997     // read geometry type
998     const EHlslTokenClass tessType = peek();
999 
1000     switch (tessType) {
1001     case EHTokInputPatch:    patchType = EbvInputPatch;  break;
1002     case EHTokOutputPatch:   patchType = EbvOutputPatch; break;
1003     default:
1004         return false;  // not a tessellation decl
1005     }
1006 
1007     advanceToken();  // consume the keyword
1008     return true;
1009 }
1010 
1011 // tessellation_patch_template_type
1012 //      : tessellation_decl_type LEFT_ANGLE type comma integer_literal RIGHT_ANGLE
1013 //
acceptTessellationPatchTemplateType(TType & type)1014 bool HlslGrammar::acceptTessellationPatchTemplateType(TType& type)
1015 {
1016     TBuiltInVariable patchType;
1017 
1018     if (! acceptTessellationDeclType(patchType))
1019         return false;
1020 
1021     if (! acceptTokenClass(EHTokLeftAngle))
1022         return false;
1023 
1024     if (! acceptType(type)) {
1025         expected("tessellation patch type");
1026         return false;
1027     }
1028 
1029     if (! acceptTokenClass(EHTokComma))
1030         return false;
1031 
1032     // integer size
1033     if (! peekTokenClass(EHTokIntConstant)) {
1034         expected("literal integer");
1035         return false;
1036     }
1037 
1038     TIntermTyped* size;
1039     if (! acceptLiteral(size))
1040         return false;
1041 
1042     TArraySizes* arraySizes = new TArraySizes;
1043     arraySizes->addInnerSize(size->getAsConstantUnion()->getConstArray()[0].getIConst());
1044     type.transferArraySizes(arraySizes);
1045     type.getQualifier().builtIn = patchType;
1046 
1047     if (! acceptTokenClass(EHTokRightAngle)) {
1048         expected("right angle bracket");
1049         return false;
1050     }
1051 
1052     return true;
1053 }
1054 
1055 // stream_out_template_type
1056 //      : output_primitive_geometry_type LEFT_ANGLE type RIGHT_ANGLE
1057 //
acceptStreamOutTemplateType(TType & type,TLayoutGeometry & geometry)1058 bool HlslGrammar::acceptStreamOutTemplateType(TType& type, TLayoutGeometry& geometry)
1059 {
1060     geometry = ElgNone;
1061 
1062     if (! acceptOutputPrimitiveGeometry(geometry))
1063         return false;
1064 
1065     if (! acceptTokenClass(EHTokLeftAngle))
1066         return false;
1067 
1068     if (! acceptType(type)) {
1069         expected("stream output type");
1070         return false;
1071     }
1072 
1073     type.getQualifier().storage = EvqOut;
1074     type.getQualifier().builtIn = EbvGsOutputStream;
1075 
1076     if (! acceptTokenClass(EHTokRightAngle)) {
1077         expected("right angle bracket");
1078         return false;
1079     }
1080 
1081     return true;
1082 }
1083 
1084 // annotations
1085 //      : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
1086 //
acceptAnnotations(TQualifier &)1087 bool HlslGrammar::acceptAnnotations(TQualifier&)
1088 {
1089     if (! acceptTokenClass(EHTokLeftAngle))
1090         return false;
1091 
1092     // note that we are nesting a name space
1093     parseContext.nestAnnotations();
1094 
1095     // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE
1096     do {
1097         // eat any extra SEMI_COLON; don't know if the grammar calls for this or not
1098         while (acceptTokenClass(EHTokSemicolon))
1099             ;
1100 
1101         if (acceptTokenClass(EHTokRightAngle))
1102             break;
1103 
1104         // declaration
1105         TIntermNode* node = nullptr;
1106         if (! acceptDeclaration(node)) {
1107             expected("declaration in annotation");
1108             return false;
1109         }
1110     } while (true);
1111 
1112     parseContext.unnestAnnotations();
1113     return true;
1114 }
1115 
1116 // subpass input type
1117 //      : SUBPASSINPUT
1118 //      | SUBPASSINPUT VECTOR LEFT_ANGLE template_type RIGHT_ANGLE
1119 //      | SUBPASSINPUTMS
1120 //      | SUBPASSINPUTMS VECTOR LEFT_ANGLE template_type RIGHT_ANGLE
acceptSubpassInputType(TType & type)1121 bool HlslGrammar::acceptSubpassInputType(TType& type)
1122 {
1123     // read subpass type
1124     const EHlslTokenClass subpassInputType = peek();
1125 
1126     bool multisample;
1127 
1128     switch (subpassInputType) {
1129     case EHTokSubpassInput:   multisample = false; break;
1130     case EHTokSubpassInputMS: multisample = true;  break;
1131     default:
1132         return false;  // not a subpass input declaration
1133     }
1134 
1135     advanceToken();  // consume the sampler type keyword
1136 
1137     TType subpassType(EbtFloat, EvqUniform, 4); // default type is float4
1138 
1139     if (acceptTokenClass(EHTokLeftAngle)) {
1140         if (! acceptType(subpassType)) {
1141             expected("scalar or vector type");
1142             return false;
1143         }
1144 
1145         const TBasicType basicRetType = subpassType.getBasicType() ;
1146 
1147         switch (basicRetType) {
1148         case EbtFloat:
1149         case EbtUint:
1150         case EbtInt:
1151         case EbtStruct:
1152             break;
1153         default:
1154             unimplemented("basic type in subpass input");
1155             return false;
1156         }
1157 
1158         if (! acceptTokenClass(EHTokRightAngle)) {
1159             expected("right angle bracket");
1160             return false;
1161         }
1162     }
1163 
1164     const TBasicType subpassBasicType = subpassType.isStruct() ? (*subpassType.getStruct())[0].type->getBasicType()
1165         : subpassType.getBasicType();
1166 
1167     TSampler sampler;
1168     sampler.setSubpass(subpassBasicType, multisample);
1169 
1170     // Remember the declared return type.  Function returns false on error.
1171     if (!parseContext.setTextureReturnType(sampler, subpassType, token.loc))
1172         return false;
1173 
1174     type.shallowCopy(TType(sampler, EvqUniform));
1175 
1176     return true;
1177 }
1178 
1179 // sampler_type for DX9 compatibility
1180 //      : SAMPLER
1181 //      | SAMPLER1D
1182 //      | SAMPLER2D
1183 //      | SAMPLER3D
1184 //      | SAMPLERCUBE
acceptSamplerTypeDX9(TType & type)1185 bool HlslGrammar::acceptSamplerTypeDX9(TType &type)
1186 {
1187     // read sampler type
1188     const EHlslTokenClass samplerType = peek();
1189 
1190     TSamplerDim dim = EsdNone;
1191     TType txType(EbtFloat, EvqUniform, 4); // default type is float4
1192 
1193     bool isShadow = false;
1194 
1195     switch (samplerType)
1196     {
1197     case EHTokSampler:		dim = Esd2D;	break;
1198     case EHTokSampler1d:	dim = Esd1D;	break;
1199     case EHTokSampler2d:	dim = Esd2D;	break;
1200     case EHTokSampler3d:	dim = Esd3D;	break;
1201     case EHTokSamplerCube:	dim = EsdCube;	break;
1202     default:
1203         return false; // not a dx9 sampler declaration
1204     }
1205 
1206     advanceToken(); // consume the sampler type keyword
1207 
1208     TArraySizes *arraySizes = nullptr; // TODO: array
1209 
1210     TSampler sampler;
1211     sampler.set(txType.getBasicType(), dim, false, isShadow, false);
1212 
1213     if (!parseContext.setTextureReturnType(sampler, txType, token.loc))
1214         return false;
1215 
1216     type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
1217     type.getQualifier().layoutFormat = ElfNone;
1218 
1219     return true;
1220 }
1221 
1222 // sampler_type
1223 //      : SAMPLER
1224 //      | SAMPLER1D
1225 //      | SAMPLER2D
1226 //      | SAMPLER3D
1227 //      | SAMPLERCUBE
1228 //      | SAMPLERSTATE
1229 //      | SAMPLERCOMPARISONSTATE
acceptSamplerType(TType & type)1230 bool HlslGrammar::acceptSamplerType(TType& type)
1231 {
1232     // read sampler type
1233     const EHlslTokenClass samplerType = peek();
1234 
1235     // TODO: for DX9
1236     // TSamplerDim dim = EsdNone;
1237 
1238     bool isShadow = false;
1239 
1240     switch (samplerType) {
1241     case EHTokSampler:      break;
1242     case EHTokSampler1d:    /*dim = Esd1D*/; break;
1243     case EHTokSampler2d:    /*dim = Esd2D*/; break;
1244     case EHTokSampler3d:    /*dim = Esd3D*/; break;
1245     case EHTokSamplerCube:  /*dim = EsdCube*/; break;
1246     case EHTokSamplerState: break;
1247     case EHTokSamplerComparisonState: isShadow = true; break;
1248     default:
1249         return false;  // not a sampler declaration
1250     }
1251 
1252     advanceToken();  // consume the sampler type keyword
1253 
1254     TArraySizes* arraySizes = nullptr; // TODO: array
1255 
1256     TSampler sampler;
1257     sampler.setPureSampler(isShadow);
1258 
1259     type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
1260 
1261     return true;
1262 }
1263 
1264 // texture_type
1265 //      | BUFFER
1266 //      | TEXTURE1D
1267 //      | TEXTURE1DARRAY
1268 //      | TEXTURE2D
1269 //      | TEXTURE2DARRAY
1270 //      | TEXTURE3D
1271 //      | TEXTURECUBE
1272 //      | TEXTURECUBEARRAY
1273 //      | TEXTURE2DMS
1274 //      | TEXTURE2DMSARRAY
1275 //      | RWBUFFER
1276 //      | RWTEXTURE1D
1277 //      | RWTEXTURE1DARRAY
1278 //      | RWTEXTURE2D
1279 //      | RWTEXTURE2DARRAY
1280 //      | RWTEXTURE3D
1281 
acceptTextureType(TType & type)1282 bool HlslGrammar::acceptTextureType(TType& type)
1283 {
1284     const EHlslTokenClass textureType = peek();
1285 
1286     TSamplerDim dim = EsdNone;
1287     bool array = false;
1288     bool ms    = false;
1289     bool image = false;
1290     bool combined = true;
1291 
1292     switch (textureType) {
1293     case EHTokBuffer:            dim = EsdBuffer; combined = false;    break;
1294     case EHTokTexture1d:         dim = Esd1D;                          break;
1295     case EHTokTexture1darray:    dim = Esd1D; array = true;            break;
1296     case EHTokTexture2d:         dim = Esd2D;                          break;
1297     case EHTokTexture2darray:    dim = Esd2D; array = true;            break;
1298     case EHTokTexture3d:         dim = Esd3D;                          break;
1299     case EHTokTextureCube:       dim = EsdCube;                        break;
1300     case EHTokTextureCubearray:  dim = EsdCube; array = true;          break;
1301     case EHTokTexture2DMS:       dim = Esd2D; ms = true;               break;
1302     case EHTokTexture2DMSarray:  dim = Esd2D; array = true; ms = true; break;
1303     case EHTokRWBuffer:          dim = EsdBuffer; image=true;          break;
1304     case EHTokRWTexture1d:       dim = Esd1D; array=false; image=true; break;
1305     case EHTokRWTexture1darray:  dim = Esd1D; array=true;  image=true; break;
1306     case EHTokRWTexture2d:       dim = Esd2D; array=false; image=true; break;
1307     case EHTokRWTexture2darray:  dim = Esd2D; array=true;  image=true; break;
1308     case EHTokRWTexture3d:       dim = Esd3D; array=false; image=true; break;
1309     default:
1310         return false;  // not a texture declaration
1311     }
1312 
1313     advanceToken();  // consume the texture object keyword
1314 
1315     TType txType(EbtFloat, EvqUniform, 4); // default type is float4
1316 
1317     TIntermTyped* msCount = nullptr;
1318 
1319     // texture type: required for multisample types and RWBuffer/RWTextures!
1320     if (acceptTokenClass(EHTokLeftAngle)) {
1321         if (! acceptType(txType)) {
1322             expected("scalar or vector type");
1323             return false;
1324         }
1325 
1326         const TBasicType basicRetType = txType.getBasicType() ;
1327 
1328         switch (basicRetType) {
1329         case EbtFloat:
1330         case EbtUint:
1331         case EbtInt:
1332         case EbtStruct:
1333             break;
1334         default:
1335             unimplemented("basic type in texture");
1336             return false;
1337         }
1338 
1339         // Buffers can handle small mats if they fit in 4 components
1340         if (dim == EsdBuffer && txType.isMatrix()) {
1341             if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) {
1342                 expected("components < 4 in matrix buffer type");
1343                 return false;
1344             }
1345 
1346             // TODO: except we don't handle it yet...
1347             unimplemented("matrix type in buffer");
1348             return false;
1349         }
1350 
1351         if (!txType.isScalar() && !txType.isVector() && !txType.isStruct()) {
1352             expected("scalar, vector, or struct type");
1353             return false;
1354         }
1355 
1356         if (ms && acceptTokenClass(EHTokComma)) {
1357             // read sample count for multisample types, if given
1358             if (! peekTokenClass(EHTokIntConstant)) {
1359                 expected("multisample count");
1360                 return false;
1361             }
1362 
1363             if (! acceptLiteral(msCount))  // should never fail, since we just found an integer
1364                 return false;
1365         }
1366 
1367         if (! acceptTokenClass(EHTokRightAngle)) {
1368             expected("right angle bracket");
1369             return false;
1370         }
1371     } else if (ms) {
1372         expected("texture type for multisample");
1373         return false;
1374     } else if (image) {
1375         expected("type for RWTexture/RWBuffer");
1376         return false;
1377     }
1378 
1379     TArraySizes* arraySizes = nullptr;
1380     const bool shadow = false; // declared on the sampler
1381 
1382     TSampler sampler;
1383     TLayoutFormat format = ElfNone;
1384 
1385     // Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat.  We handle only a limit set.
1386     if (image || dim == EsdBuffer)
1387         format = parseContext.getLayoutFromTxType(token.loc, txType);
1388 
1389     const TBasicType txBasicType = txType.isStruct() ? (*txType.getStruct())[0].type->getBasicType()
1390         : txType.getBasicType();
1391 
1392     // Non-image Buffers are combined
1393     if (dim == EsdBuffer && !image) {
1394         sampler.set(txType.getBasicType(), dim, array);
1395     } else {
1396         // DX10 textures are separated.  TODO: DX9.
1397         if (image) {
1398             sampler.setImage(txBasicType, dim, array, shadow, ms);
1399         } else {
1400             sampler.setTexture(txBasicType, dim, array, shadow, ms);
1401         }
1402     }
1403 
1404     // Remember the declared return type.  Function returns false on error.
1405     if (!parseContext.setTextureReturnType(sampler, txType, token.loc))
1406         return false;
1407 
1408     // Force uncombined, if necessary
1409     if (!combined)
1410         sampler.combined = false;
1411 
1412     type.shallowCopy(TType(sampler, EvqUniform, arraySizes));
1413     type.getQualifier().layoutFormat = format;
1414 
1415     return true;
1416 }
1417 
1418 // If token is for a type, update 'type' with the type information,
1419 // and return true and advance.
1420 // Otherwise, return false, and don't advance
acceptType(TType & type)1421 bool HlslGrammar::acceptType(TType& type)
1422 {
1423     TIntermNode* nodeList = nullptr;
1424     return acceptType(type, nodeList);
1425 }
acceptType(TType & type,TIntermNode * & nodeList)1426 bool HlslGrammar::acceptType(TType& type, TIntermNode*& nodeList)
1427 {
1428     // Basic types for min* types, use native halfs if the option allows them.
1429     bool enable16BitTypes = parseContext.hlslEnable16BitTypes();
1430 
1431     const TBasicType min16float_bt = enable16BitTypes ? EbtFloat16 : EbtFloat;
1432     const TBasicType min10float_bt = enable16BitTypes ? EbtFloat16 : EbtFloat;
1433     const TBasicType half_bt       = enable16BitTypes ? EbtFloat16 : EbtFloat;
1434     const TBasicType min16int_bt   = enable16BitTypes ? EbtInt16   : EbtInt;
1435     const TBasicType min12int_bt   = enable16BitTypes ? EbtInt16   : EbtInt;
1436     const TBasicType min16uint_bt  = enable16BitTypes ? EbtUint16  : EbtUint;
1437 
1438     // Some types might have turned into identifiers. Take the hit for checking
1439     // when this has happened.
1440     if (typeIdentifiers) {
1441         const char* identifierString = getTypeString(peek());
1442         if (identifierString != nullptr) {
1443             TString name = identifierString;
1444             // if it's an identifier, it's not a type
1445             if (parseContext.symbolTable.find(name) != nullptr)
1446                 return false;
1447         }
1448     }
1449 
1450     bool isUnorm = false;
1451     bool isSnorm = false;
1452 
1453     // Accept snorm and unorm.  Presently, this is ignored, save for an error check below.
1454     switch (peek()) {
1455     case EHTokUnorm:
1456         isUnorm = true;
1457         advanceToken();  // eat the token
1458         break;
1459     case EHTokSNorm:
1460         isSnorm = true;
1461         advanceToken();  // eat the token
1462         break;
1463     default:
1464         break;
1465     }
1466 
1467     switch (peek()) {
1468     case EHTokVector:
1469         return acceptVectorTemplateType(type);
1470         break;
1471 
1472     case EHTokMatrix:
1473         return acceptMatrixTemplateType(type);
1474         break;
1475 
1476     case EHTokPointStream:            // fall through
1477     case EHTokLineStream:             // ...
1478     case EHTokTriangleStream:         // ...
1479         {
1480             TLayoutGeometry geometry;
1481             if (! acceptStreamOutTemplateType(type, geometry))
1482                 return false;
1483 
1484             if (! parseContext.handleOutputGeometry(token.loc, geometry))
1485                 return false;
1486 
1487             return true;
1488         }
1489 
1490     case EHTokInputPatch:             // fall through
1491     case EHTokOutputPatch:            // ...
1492         {
1493             if (! acceptTessellationPatchTemplateType(type))
1494                 return false;
1495 
1496             return true;
1497         }
1498 
1499     case EHTokSampler:                // fall through
1500     case EHTokSampler1d:              // ...
1501     case EHTokSampler2d:              // ...
1502     case EHTokSampler3d:              // ...
1503     case EHTokSamplerCube:            // ...
1504         if (parseContext.hlslDX9Compatible())
1505             return acceptSamplerTypeDX9(type);
1506         else
1507             return acceptSamplerType(type);
1508         break;
1509 
1510     case EHTokSamplerState:           // fall through
1511     case EHTokSamplerComparisonState: // ...
1512         return acceptSamplerType(type);
1513         break;
1514 
1515     case EHTokSubpassInput:           // fall through
1516     case EHTokSubpassInputMS:         // ...
1517         return acceptSubpassInputType(type);
1518         break;
1519 
1520     case EHTokBuffer:                 // fall through
1521     case EHTokTexture1d:              // ...
1522     case EHTokTexture1darray:         // ...
1523     case EHTokTexture2d:              // ...
1524     case EHTokTexture2darray:         // ...
1525     case EHTokTexture3d:              // ...
1526     case EHTokTextureCube:            // ...
1527     case EHTokTextureCubearray:       // ...
1528     case EHTokTexture2DMS:            // ...
1529     case EHTokTexture2DMSarray:       // ...
1530     case EHTokRWTexture1d:            // ...
1531     case EHTokRWTexture1darray:       // ...
1532     case EHTokRWTexture2d:            // ...
1533     case EHTokRWTexture2darray:       // ...
1534     case EHTokRWTexture3d:            // ...
1535     case EHTokRWBuffer:               // ...
1536         return acceptTextureType(type);
1537         break;
1538 
1539     case EHTokAppendStructuredBuffer:
1540     case EHTokByteAddressBuffer:
1541     case EHTokConsumeStructuredBuffer:
1542     case EHTokRWByteAddressBuffer:
1543     case EHTokRWStructuredBuffer:
1544     case EHTokStructuredBuffer:
1545         return acceptStructBufferType(type);
1546         break;
1547 
1548     case EHTokTextureBuffer:
1549         return acceptTextureBufferType(type);
1550         break;
1551 
1552     case EHTokConstantBuffer:
1553         return acceptConstantBufferType(type);
1554 
1555     case EHTokClass:
1556     case EHTokStruct:
1557     case EHTokCBuffer:
1558     case EHTokTBuffer:
1559         return acceptStruct(type, nodeList);
1560 
1561     case EHTokIdentifier:
1562         // An identifier could be for a user-defined type.
1563         // Note we cache the symbol table lookup, to save for a later rule
1564         // when this is not a type.
1565         if (parseContext.lookupUserType(*token.string, type) != nullptr) {
1566             advanceToken();
1567             return true;
1568         } else
1569             return false;
1570 
1571     case EHTokVoid:
1572         new(&type) TType(EbtVoid);
1573         break;
1574 
1575     case EHTokString:
1576         new(&type) TType(EbtString);
1577         break;
1578 
1579     case EHTokFloat:
1580         new(&type) TType(EbtFloat);
1581         break;
1582     case EHTokFloat1:
1583         new(&type) TType(EbtFloat);
1584         type.makeVector();
1585         break;
1586     case EHTokFloat2:
1587         new(&type) TType(EbtFloat, EvqTemporary, 2);
1588         break;
1589     case EHTokFloat3:
1590         new(&type) TType(EbtFloat, EvqTemporary, 3);
1591         break;
1592     case EHTokFloat4:
1593         new(&type) TType(EbtFloat, EvqTemporary, 4);
1594         break;
1595 
1596     case EHTokDouble:
1597         new(&type) TType(EbtDouble);
1598         break;
1599     case EHTokDouble1:
1600         new(&type) TType(EbtDouble);
1601         type.makeVector();
1602         break;
1603     case EHTokDouble2:
1604         new(&type) TType(EbtDouble, EvqTemporary, 2);
1605         break;
1606     case EHTokDouble3:
1607         new(&type) TType(EbtDouble, EvqTemporary, 3);
1608         break;
1609     case EHTokDouble4:
1610         new(&type) TType(EbtDouble, EvqTemporary, 4);
1611         break;
1612 
1613     case EHTokInt:
1614     case EHTokDword:
1615         new(&type) TType(EbtInt);
1616         break;
1617     case EHTokInt1:
1618         new(&type) TType(EbtInt);
1619         type.makeVector();
1620         break;
1621     case EHTokInt2:
1622         new(&type) TType(EbtInt, EvqTemporary, 2);
1623         break;
1624     case EHTokInt3:
1625         new(&type) TType(EbtInt, EvqTemporary, 3);
1626         break;
1627     case EHTokInt4:
1628         new(&type) TType(EbtInt, EvqTemporary, 4);
1629         break;
1630 
1631     case EHTokUint:
1632         new(&type) TType(EbtUint);
1633         break;
1634     case EHTokUint1:
1635         new(&type) TType(EbtUint);
1636         type.makeVector();
1637         break;
1638     case EHTokUint2:
1639         new(&type) TType(EbtUint, EvqTemporary, 2);
1640         break;
1641     case EHTokUint3:
1642         new(&type) TType(EbtUint, EvqTemporary, 3);
1643         break;
1644     case EHTokUint4:
1645         new(&type) TType(EbtUint, EvqTemporary, 4);
1646         break;
1647 
1648     case EHTokUint64:
1649         new(&type) TType(EbtUint64);
1650         break;
1651 
1652     case EHTokBool:
1653         new(&type) TType(EbtBool);
1654         break;
1655     case EHTokBool1:
1656         new(&type) TType(EbtBool);
1657         type.makeVector();
1658         break;
1659     case EHTokBool2:
1660         new(&type) TType(EbtBool, EvqTemporary, 2);
1661         break;
1662     case EHTokBool3:
1663         new(&type) TType(EbtBool, EvqTemporary, 3);
1664         break;
1665     case EHTokBool4:
1666         new(&type) TType(EbtBool, EvqTemporary, 4);
1667         break;
1668 
1669     case EHTokHalf:
1670         new(&type) TType(half_bt, EvqTemporary);
1671         break;
1672     case EHTokHalf1:
1673         new(&type) TType(half_bt, EvqTemporary);
1674         type.makeVector();
1675         break;
1676     case EHTokHalf2:
1677         new(&type) TType(half_bt, EvqTemporary, 2);
1678         break;
1679     case EHTokHalf3:
1680         new(&type) TType(half_bt, EvqTemporary, 3);
1681         break;
1682     case EHTokHalf4:
1683         new(&type) TType(half_bt, EvqTemporary, 4);
1684         break;
1685 
1686     case EHTokMin16float:
1687         new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1688         break;
1689     case EHTokMin16float1:
1690         new(&type) TType(min16float_bt, EvqTemporary, EpqMedium);
1691         type.makeVector();
1692         break;
1693     case EHTokMin16float2:
1694         new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 2);
1695         break;
1696     case EHTokMin16float3:
1697         new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 3);
1698         break;
1699     case EHTokMin16float4:
1700         new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 4);
1701         break;
1702 
1703     case EHTokMin10float:
1704         new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1705         break;
1706     case EHTokMin10float1:
1707         new(&type) TType(min10float_bt, EvqTemporary, EpqMedium);
1708         type.makeVector();
1709         break;
1710     case EHTokMin10float2:
1711         new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 2);
1712         break;
1713     case EHTokMin10float3:
1714         new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 3);
1715         break;
1716     case EHTokMin10float4:
1717         new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 4);
1718         break;
1719 
1720     case EHTokMin16int:
1721         new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1722         break;
1723     case EHTokMin16int1:
1724         new(&type) TType(min16int_bt, EvqTemporary, EpqMedium);
1725         type.makeVector();
1726         break;
1727     case EHTokMin16int2:
1728         new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 2);
1729         break;
1730     case EHTokMin16int3:
1731         new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 3);
1732         break;
1733     case EHTokMin16int4:
1734         new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 4);
1735         break;
1736 
1737     case EHTokMin12int:
1738         new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1739         break;
1740     case EHTokMin12int1:
1741         new(&type) TType(min12int_bt, EvqTemporary, EpqMedium);
1742         type.makeVector();
1743         break;
1744     case EHTokMin12int2:
1745         new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 2);
1746         break;
1747     case EHTokMin12int3:
1748         new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 3);
1749         break;
1750     case EHTokMin12int4:
1751         new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 4);
1752         break;
1753 
1754     case EHTokMin16uint:
1755         new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1756         break;
1757     case EHTokMin16uint1:
1758         new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium);
1759         type.makeVector();
1760         break;
1761     case EHTokMin16uint2:
1762         new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 2);
1763         break;
1764     case EHTokMin16uint3:
1765         new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 3);
1766         break;
1767     case EHTokMin16uint4:
1768         new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 4);
1769         break;
1770 
1771     case EHTokInt1x1:
1772         new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1);
1773         break;
1774     case EHTokInt1x2:
1775         new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2);
1776         break;
1777     case EHTokInt1x3:
1778         new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3);
1779         break;
1780     case EHTokInt1x4:
1781         new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4);
1782         break;
1783     case EHTokInt2x1:
1784         new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1);
1785         break;
1786     case EHTokInt2x2:
1787         new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2);
1788         break;
1789     case EHTokInt2x3:
1790         new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3);
1791         break;
1792     case EHTokInt2x4:
1793         new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4);
1794         break;
1795     case EHTokInt3x1:
1796         new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1);
1797         break;
1798     case EHTokInt3x2:
1799         new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2);
1800         break;
1801     case EHTokInt3x3:
1802         new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3);
1803         break;
1804     case EHTokInt3x4:
1805         new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4);
1806         break;
1807     case EHTokInt4x1:
1808         new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1);
1809         break;
1810     case EHTokInt4x2:
1811         new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2);
1812         break;
1813     case EHTokInt4x3:
1814         new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3);
1815         break;
1816     case EHTokInt4x4:
1817         new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4);
1818         break;
1819 
1820     case EHTokUint1x1:
1821         new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1);
1822         break;
1823     case EHTokUint1x2:
1824         new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2);
1825         break;
1826     case EHTokUint1x3:
1827         new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3);
1828         break;
1829     case EHTokUint1x4:
1830         new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4);
1831         break;
1832     case EHTokUint2x1:
1833         new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1);
1834         break;
1835     case EHTokUint2x2:
1836         new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2);
1837         break;
1838     case EHTokUint2x3:
1839         new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3);
1840         break;
1841     case EHTokUint2x4:
1842         new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4);
1843         break;
1844     case EHTokUint3x1:
1845         new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1);
1846         break;
1847     case EHTokUint3x2:
1848         new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2);
1849         break;
1850     case EHTokUint3x3:
1851         new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3);
1852         break;
1853     case EHTokUint3x4:
1854         new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4);
1855         break;
1856     case EHTokUint4x1:
1857         new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1);
1858         break;
1859     case EHTokUint4x2:
1860         new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2);
1861         break;
1862     case EHTokUint4x3:
1863         new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3);
1864         break;
1865     case EHTokUint4x4:
1866         new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4);
1867         break;
1868 
1869     case EHTokBool1x1:
1870         new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1);
1871         break;
1872     case EHTokBool1x2:
1873         new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2);
1874         break;
1875     case EHTokBool1x3:
1876         new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3);
1877         break;
1878     case EHTokBool1x4:
1879         new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4);
1880         break;
1881     case EHTokBool2x1:
1882         new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1);
1883         break;
1884     case EHTokBool2x2:
1885         new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2);
1886         break;
1887     case EHTokBool2x3:
1888         new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3);
1889         break;
1890     case EHTokBool2x4:
1891         new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4);
1892         break;
1893     case EHTokBool3x1:
1894         new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1);
1895         break;
1896     case EHTokBool3x2:
1897         new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2);
1898         break;
1899     case EHTokBool3x3:
1900         new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3);
1901         break;
1902     case EHTokBool3x4:
1903         new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4);
1904         break;
1905     case EHTokBool4x1:
1906         new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1);
1907         break;
1908     case EHTokBool4x2:
1909         new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2);
1910         break;
1911     case EHTokBool4x3:
1912         new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3);
1913         break;
1914     case EHTokBool4x4:
1915         new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4);
1916         break;
1917 
1918     case EHTokFloat1x1:
1919         new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1);
1920         break;
1921     case EHTokFloat1x2:
1922         new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2);
1923         break;
1924     case EHTokFloat1x3:
1925         new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3);
1926         break;
1927     case EHTokFloat1x4:
1928         new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4);
1929         break;
1930     case EHTokFloat2x1:
1931         new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1);
1932         break;
1933     case EHTokFloat2x2:
1934         new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2);
1935         break;
1936     case EHTokFloat2x3:
1937         new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3);
1938         break;
1939     case EHTokFloat2x4:
1940         new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4);
1941         break;
1942     case EHTokFloat3x1:
1943         new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1);
1944         break;
1945     case EHTokFloat3x2:
1946         new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2);
1947         break;
1948     case EHTokFloat3x3:
1949         new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3);
1950         break;
1951     case EHTokFloat3x4:
1952         new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4);
1953         break;
1954     case EHTokFloat4x1:
1955         new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1);
1956         break;
1957     case EHTokFloat4x2:
1958         new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2);
1959         break;
1960     case EHTokFloat4x3:
1961         new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3);
1962         break;
1963     case EHTokFloat4x4:
1964         new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4);
1965         break;
1966 
1967     case EHTokHalf1x1:
1968         new(&type) TType(half_bt, EvqTemporary, 0, 1, 1);
1969         break;
1970     case EHTokHalf1x2:
1971         new(&type) TType(half_bt, EvqTemporary, 0, 1, 2);
1972         break;
1973     case EHTokHalf1x3:
1974         new(&type) TType(half_bt, EvqTemporary, 0, 1, 3);
1975         break;
1976     case EHTokHalf1x4:
1977         new(&type) TType(half_bt, EvqTemporary, 0, 1, 4);
1978         break;
1979     case EHTokHalf2x1:
1980         new(&type) TType(half_bt, EvqTemporary, 0, 2, 1);
1981         break;
1982     case EHTokHalf2x2:
1983         new(&type) TType(half_bt, EvqTemporary, 0, 2, 2);
1984         break;
1985     case EHTokHalf2x3:
1986         new(&type) TType(half_bt, EvqTemporary, 0, 2, 3);
1987         break;
1988     case EHTokHalf2x4:
1989         new(&type) TType(half_bt, EvqTemporary, 0, 2, 4);
1990         break;
1991     case EHTokHalf3x1:
1992         new(&type) TType(half_bt, EvqTemporary, 0, 3, 1);
1993         break;
1994     case EHTokHalf3x2:
1995         new(&type) TType(half_bt, EvqTemporary, 0, 3, 2);
1996         break;
1997     case EHTokHalf3x3:
1998         new(&type) TType(half_bt, EvqTemporary, 0, 3, 3);
1999         break;
2000     case EHTokHalf3x4:
2001         new(&type) TType(half_bt, EvqTemporary, 0, 3, 4);
2002         break;
2003     case EHTokHalf4x1:
2004         new(&type) TType(half_bt, EvqTemporary, 0, 4, 1);
2005         break;
2006     case EHTokHalf4x2:
2007         new(&type) TType(half_bt, EvqTemporary, 0, 4, 2);
2008         break;
2009     case EHTokHalf4x3:
2010         new(&type) TType(half_bt, EvqTemporary, 0, 4, 3);
2011         break;
2012     case EHTokHalf4x4:
2013         new(&type) TType(half_bt, EvqTemporary, 0, 4, 4);
2014         break;
2015 
2016     case EHTokDouble1x1:
2017         new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1);
2018         break;
2019     case EHTokDouble1x2:
2020         new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2);
2021         break;
2022     case EHTokDouble1x3:
2023         new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3);
2024         break;
2025     case EHTokDouble1x4:
2026         new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4);
2027         break;
2028     case EHTokDouble2x1:
2029         new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1);
2030         break;
2031     case EHTokDouble2x2:
2032         new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2);
2033         break;
2034     case EHTokDouble2x3:
2035         new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3);
2036         break;
2037     case EHTokDouble2x4:
2038         new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4);
2039         break;
2040     case EHTokDouble3x1:
2041         new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1);
2042         break;
2043     case EHTokDouble3x2:
2044         new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2);
2045         break;
2046     case EHTokDouble3x3:
2047         new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3);
2048         break;
2049     case EHTokDouble3x4:
2050         new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4);
2051         break;
2052     case EHTokDouble4x1:
2053         new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1);
2054         break;
2055     case EHTokDouble4x2:
2056         new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2);
2057         break;
2058     case EHTokDouble4x3:
2059         new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3);
2060         break;
2061     case EHTokDouble4x4:
2062         new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4);
2063         break;
2064 
2065     default:
2066         return false;
2067     }
2068 
2069     advanceToken();
2070 
2071     if ((isUnorm || isSnorm) && !type.isFloatingDomain()) {
2072         parseContext.error(token.loc, "unorm and snorm only valid in floating point domain", "", "");
2073         return false;
2074     }
2075 
2076     return true;
2077 }
2078 
2079 // struct
2080 //      : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
2081 //      | struct_type            post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
2082 //      | struct_type IDENTIFIER // use of previously declared struct type
2083 //
2084 // struct_type
2085 //      : STRUCT
2086 //      | CLASS
2087 //      | CBUFFER
2088 //      | TBUFFER
2089 //
acceptStruct(TType & type,TIntermNode * & nodeList)2090 bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList)
2091 {
2092     // This storage qualifier will tell us whether it's an AST
2093     // block type or just a generic structure type.
2094     TStorageQualifier storageQualifier = EvqTemporary;
2095     bool readonly = false;
2096 
2097     if (acceptTokenClass(EHTokCBuffer)) {
2098         // CBUFFER
2099         storageQualifier = EvqUniform;
2100     } else if (acceptTokenClass(EHTokTBuffer)) {
2101         // TBUFFER
2102         storageQualifier = EvqBuffer;
2103         readonly = true;
2104     } else if (! acceptTokenClass(EHTokClass) && ! acceptTokenClass(EHTokStruct)) {
2105         // Neither CLASS nor STRUCT
2106         return false;
2107     }
2108 
2109     // Now known to be one of CBUFFER, TBUFFER, CLASS, or STRUCT
2110 
2111 
2112     // IDENTIFIER.  It might also be a keyword which can double as an identifier.
2113     // For example:  'cbuffer ConstantBuffer' or 'struct ConstantBuffer' is legal.
2114     // 'cbuffer int' is also legal, and 'struct int' appears rejected only because
2115     // it attempts to redefine the 'int' type.
2116     const char* idString = getTypeString(peek());
2117     TString structName = "";
2118     if (peekTokenClass(EHTokIdentifier) || idString != nullptr) {
2119         if (idString != nullptr)
2120             structName = *idString;
2121         else
2122             structName = *token.string;
2123         advanceToken();
2124     }
2125 
2126     // post_decls
2127     TQualifier postDeclQualifier;
2128     postDeclQualifier.clear();
2129     bool postDeclsFound = acceptPostDecls(postDeclQualifier);
2130 
2131     // LEFT_BRACE, or
2132     // struct_type IDENTIFIER
2133     if (! acceptTokenClass(EHTokLeftBrace)) {
2134         if (structName.size() > 0 && !postDeclsFound && parseContext.lookupUserType(structName, type) != nullptr) {
2135             // struct_type IDENTIFIER
2136             return true;
2137         } else {
2138             expected("{");
2139             return false;
2140         }
2141     }
2142 
2143 
2144     // struct_declaration_list
2145     TTypeList* typeList;
2146     // Save each member function so they can be processed after we have a fully formed 'this'.
2147     TVector<TFunctionDeclarator> functionDeclarators;
2148 
2149     parseContext.pushNamespace(structName);
2150     bool acceptedList = acceptStructDeclarationList(typeList, nodeList, functionDeclarators);
2151     parseContext.popNamespace();
2152 
2153     if (! acceptedList) {
2154         expected("struct member declarations");
2155         return false;
2156     }
2157 
2158     // RIGHT_BRACE
2159     if (! acceptTokenClass(EHTokRightBrace)) {
2160         expected("}");
2161         return false;
2162     }
2163 
2164     // create the user-defined type
2165     if (storageQualifier == EvqTemporary)
2166         new(&type) TType(typeList, structName);
2167     else {
2168         postDeclQualifier.storage = storageQualifier;
2169         postDeclQualifier.readonly = readonly;
2170         new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock
2171     }
2172 
2173     parseContext.declareStruct(token.loc, structName, type);
2174 
2175     // For member functions: now that we know the type of 'this', go back and
2176     // - add their implicit argument with 'this' (not to the mangling, just the argument list)
2177     // - parse the functions, their tokens were saved for deferred parsing (now)
2178     for (int b = 0; b < (int)functionDeclarators.size(); ++b) {
2179         // update signature
2180         if (functionDeclarators[b].function->hasImplicitThis())
2181             functionDeclarators[b].function->addThisParameter(type, intermediate.implicitThisName);
2182     }
2183 
2184     // All member functions get parsed inside the class/struct namespace and with the
2185     // class/struct members in a symbol-table level.
2186     parseContext.pushNamespace(structName);
2187     parseContext.pushThisScope(type, functionDeclarators);
2188     bool deferredSuccess = true;
2189     for (int b = 0; b < (int)functionDeclarators.size() && deferredSuccess; ++b) {
2190         // parse body
2191         pushTokenStream(functionDeclarators[b].body);
2192         if (! acceptFunctionBody(functionDeclarators[b], nodeList))
2193             deferredSuccess = false;
2194         popTokenStream();
2195     }
2196     parseContext.popThisScope();
2197     parseContext.popNamespace();
2198 
2199     return deferredSuccess;
2200 }
2201 
2202 // constantbuffer
2203 //    : CONSTANTBUFFER LEFT_ANGLE type RIGHT_ANGLE
acceptConstantBufferType(TType & type)2204 bool HlslGrammar::acceptConstantBufferType(TType& type)
2205 {
2206     if (! acceptTokenClass(EHTokConstantBuffer))
2207         return false;
2208 
2209     if (! acceptTokenClass(EHTokLeftAngle)) {
2210         expected("left angle bracket");
2211         return false;
2212     }
2213 
2214     TType templateType;
2215     if (! acceptType(templateType)) {
2216         expected("type");
2217         return false;
2218     }
2219 
2220     if (! acceptTokenClass(EHTokRightAngle)) {
2221         expected("right angle bracket");
2222         return false;
2223     }
2224 
2225     TQualifier postDeclQualifier;
2226     postDeclQualifier.clear();
2227     postDeclQualifier.storage = EvqUniform;
2228 
2229     if (templateType.isStruct()) {
2230         // Make a block from the type parsed as the template argument
2231         TTypeList* typeList = templateType.getWritableStruct();
2232         new(&type) TType(typeList, "", postDeclQualifier); // sets EbtBlock
2233 
2234         type.getQualifier().storage = EvqUniform;
2235 
2236         return true;
2237     } else {
2238         parseContext.error(token.loc, "non-structure type in ConstantBuffer", "", "");
2239         return false;
2240     }
2241 }
2242 
2243 // texture_buffer
2244 //    : TEXTUREBUFFER LEFT_ANGLE type RIGHT_ANGLE
acceptTextureBufferType(TType & type)2245 bool HlslGrammar::acceptTextureBufferType(TType& type)
2246 {
2247     if (! acceptTokenClass(EHTokTextureBuffer))
2248         return false;
2249 
2250     if (! acceptTokenClass(EHTokLeftAngle)) {
2251         expected("left angle bracket");
2252         return false;
2253     }
2254 
2255     TType templateType;
2256     if (! acceptType(templateType)) {
2257         expected("type");
2258         return false;
2259     }
2260 
2261     if (! acceptTokenClass(EHTokRightAngle)) {
2262         expected("right angle bracket");
2263         return false;
2264     }
2265 
2266     templateType.getQualifier().storage = EvqBuffer;
2267     templateType.getQualifier().readonly = true;
2268 
2269     TType blockType(templateType.getWritableStruct(), "", templateType.getQualifier());
2270 
2271     blockType.getQualifier().storage = EvqBuffer;
2272     blockType.getQualifier().readonly = true;
2273 
2274     type.shallowCopy(blockType);
2275 
2276     return true;
2277 }
2278 
2279 
2280 // struct_buffer
2281 //    : APPENDSTRUCTUREDBUFFER
2282 //    | BYTEADDRESSBUFFER
2283 //    | CONSUMESTRUCTUREDBUFFER
2284 //    | RWBYTEADDRESSBUFFER
2285 //    | RWSTRUCTUREDBUFFER
2286 //    | STRUCTUREDBUFFER
acceptStructBufferType(TType & type)2287 bool HlslGrammar::acceptStructBufferType(TType& type)
2288 {
2289     const EHlslTokenClass structBuffType = peek();
2290 
2291     // TODO: globallycoherent
2292     bool hasTemplateType = true;
2293     bool readonly = false;
2294 
2295     TStorageQualifier storage = EvqBuffer;
2296     TBuiltInVariable  builtinType = EbvNone;
2297 
2298     switch (structBuffType) {
2299     case EHTokAppendStructuredBuffer:
2300         builtinType = EbvAppendConsume;
2301         break;
2302     case EHTokByteAddressBuffer:
2303         hasTemplateType = false;
2304         readonly = true;
2305         builtinType = EbvByteAddressBuffer;
2306         break;
2307     case EHTokConsumeStructuredBuffer:
2308         builtinType = EbvAppendConsume;
2309         break;
2310     case EHTokRWByteAddressBuffer:
2311         hasTemplateType = false;
2312         builtinType = EbvRWByteAddressBuffer;
2313         break;
2314     case EHTokRWStructuredBuffer:
2315         builtinType = EbvRWStructuredBuffer;
2316         break;
2317     case EHTokStructuredBuffer:
2318         builtinType = EbvStructuredBuffer;
2319         readonly = true;
2320         break;
2321     default:
2322         return false;  // not a structure buffer type
2323     }
2324 
2325     advanceToken();  // consume the structure keyword
2326 
2327     // type on which this StructedBuffer is templatized.  E.g, StructedBuffer<MyStruct> ==> MyStruct
2328     TType* templateType = new TType;
2329 
2330     if (hasTemplateType) {
2331         if (! acceptTokenClass(EHTokLeftAngle)) {
2332             expected("left angle bracket");
2333             return false;
2334         }
2335 
2336         if (! acceptType(*templateType)) {
2337             expected("type");
2338             return false;
2339         }
2340         if (! acceptTokenClass(EHTokRightAngle)) {
2341             expected("right angle bracket");
2342             return false;
2343         }
2344     } else {
2345         // byte address buffers have no explicit type.
2346         TType uintType(EbtUint, storage);
2347         templateType->shallowCopy(uintType);
2348     }
2349 
2350     // Create an unsized array out of that type.
2351     // TODO: does this work if it's already an array type?
2352     TArraySizes* unsizedArray = new TArraySizes;
2353     unsizedArray->addInnerSize(UnsizedArraySize);
2354     templateType->transferArraySizes(unsizedArray);
2355     templateType->getQualifier().storage = storage;
2356 
2357     // field name is canonical for all structbuffers
2358     templateType->setFieldName("@data");
2359 
2360     TTypeList* blockStruct = new TTypeList;
2361     TTypeLoc  member = { templateType, token.loc };
2362     blockStruct->push_back(member);
2363 
2364     // This is the type of the buffer block (SSBO)
2365     TType blockType(blockStruct, "", templateType->getQualifier());
2366 
2367     blockType.getQualifier().storage = storage;
2368     blockType.getQualifier().readonly = readonly;
2369     blockType.getQualifier().builtIn = builtinType;
2370 
2371     // We may have created an equivalent type before, in which case we should use its
2372     // deep structure.
2373     parseContext.shareStructBufferType(blockType);
2374 
2375     type.shallowCopy(blockType);
2376 
2377     return true;
2378 }
2379 
2380 // struct_declaration_list
2381 //      : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ...
2382 //
2383 // struct_declaration
2384 //      : attributes fully_specified_type struct_declarator COMMA struct_declarator ...
2385 //      | attributes fully_specified_type IDENTIFIER function_parameters post_decls compound_statement // member-function definition
2386 //
2387 // struct_declarator
2388 //      : IDENTIFIER post_decls
2389 //      | IDENTIFIER array_specifier post_decls
2390 //      | IDENTIFIER function_parameters post_decls                                         // member-function prototype
2391 //
acceptStructDeclarationList(TTypeList * & typeList,TIntermNode * & nodeList,TVector<TFunctionDeclarator> & declarators)2392 bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*& nodeList,
2393                                               TVector<TFunctionDeclarator>& declarators)
2394 {
2395     typeList = new TTypeList();
2396     HlslToken idToken;
2397 
2398     do {
2399         // success on seeing the RIGHT_BRACE coming up
2400         if (peekTokenClass(EHTokRightBrace))
2401             break;
2402 
2403         // struct_declaration
2404 
2405         // attributes
2406         TAttributes attributes;
2407         acceptAttributes(attributes);
2408 
2409         bool declarator_list = false;
2410 
2411         // fully_specified_type
2412         TType memberType;
2413         if (! acceptFullySpecifiedType(memberType, nodeList, attributes)) {
2414             expected("member type");
2415             return false;
2416         }
2417 
2418         // merge in the attributes
2419         parseContext.transferTypeAttributes(token.loc, attributes, memberType);
2420 
2421         // struct_declarator COMMA struct_declarator ...
2422         bool functionDefinitionAccepted = false;
2423         do {
2424             if (! acceptIdentifier(idToken)) {
2425                 expected("member name");
2426                 return false;
2427             }
2428 
2429             if (peekTokenClass(EHTokLeftParen)) {
2430                 // function_parameters
2431                 if (!declarator_list) {
2432                     declarators.resize(declarators.size() + 1);
2433                     // request a token stream for deferred processing
2434                     functionDefinitionAccepted = acceptMemberFunctionDefinition(nodeList, memberType, *idToken.string,
2435                                                                                 declarators.back());
2436                     if (functionDefinitionAccepted)
2437                         break;
2438                 }
2439                 expected("member-function definition");
2440                 return false;
2441             } else {
2442                 // add it to the list of members
2443                 TTypeLoc member = { new TType(EbtVoid), token.loc };
2444                 member.type->shallowCopy(memberType);
2445                 member.type->setFieldName(*idToken.string);
2446                 typeList->push_back(member);
2447 
2448                 // array_specifier
2449                 TArraySizes* arraySizes = nullptr;
2450                 acceptArraySpecifier(arraySizes);
2451                 if (arraySizes)
2452                     typeList->back().type->transferArraySizes(arraySizes);
2453 
2454                 acceptPostDecls(member.type->getQualifier());
2455 
2456                 // EQUAL assignment_expression
2457                 if (acceptTokenClass(EHTokAssign)) {
2458                     parseContext.warn(idToken.loc, "struct-member initializers ignored", "typedef", "");
2459                     TIntermTyped* expressionNode = nullptr;
2460                     if (! acceptAssignmentExpression(expressionNode)) {
2461                         expected("initializer");
2462                         return false;
2463                     }
2464                 }
2465             }
2466             // success on seeing the SEMICOLON coming up
2467             if (peekTokenClass(EHTokSemicolon))
2468                 break;
2469 
2470             // COMMA
2471             if (acceptTokenClass(EHTokComma))
2472                 declarator_list = true;
2473             else {
2474                 expected(",");
2475                 return false;
2476             }
2477 
2478         } while (true);
2479 
2480         // SEMI_COLON
2481         if (! functionDefinitionAccepted && ! acceptTokenClass(EHTokSemicolon)) {
2482             expected(";");
2483             return false;
2484         }
2485 
2486     } while (true);
2487 
2488     return true;
2489 }
2490 
2491 // member_function_definition
2492 //    | function_parameters post_decls compound_statement
2493 //
2494 // Expects type to have EvqGlobal for a static member and
2495 // EvqTemporary for non-static member.
acceptMemberFunctionDefinition(TIntermNode * & nodeList,const TType & type,TString & memberName,TFunctionDeclarator & declarator)2496 bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TType& type, TString& memberName,
2497                                                  TFunctionDeclarator& declarator)
2498 {
2499     bool accepted = false;
2500 
2501     TString* functionName = &memberName;
2502     parseContext.getFullNamespaceName(functionName);
2503     declarator.function = new TFunction(functionName, type);
2504     if (type.getQualifier().storage == EvqTemporary)
2505         declarator.function->setImplicitThis();
2506     else
2507         declarator.function->setIllegalImplicitThis();
2508 
2509     // function_parameters
2510     if (acceptFunctionParameters(*declarator.function)) {
2511         // post_decls
2512         acceptPostDecls(declarator.function->getWritableType().getQualifier());
2513 
2514         // compound_statement (function body definition)
2515         if (peekTokenClass(EHTokLeftBrace)) {
2516             declarator.loc = token.loc;
2517             declarator.body = new TVector<HlslToken>;
2518             accepted = acceptFunctionDefinition(declarator, nodeList, declarator.body);
2519         }
2520     } else
2521         expected("function parameter list");
2522 
2523     return accepted;
2524 }
2525 
2526 // function_parameters
2527 //      : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN
2528 //      | LEFT_PAREN VOID RIGHT_PAREN
2529 //
acceptFunctionParameters(TFunction & function)2530 bool HlslGrammar::acceptFunctionParameters(TFunction& function)
2531 {
2532     parseContext.beginParameterParsing(function);
2533 
2534     // LEFT_PAREN
2535     if (! acceptTokenClass(EHTokLeftParen))
2536         return false;
2537 
2538     // VOID RIGHT_PAREN
2539     if (! acceptTokenClass(EHTokVoid)) {
2540         do {
2541             // parameter_declaration
2542             if (! acceptParameterDeclaration(function))
2543                 break;
2544 
2545             // COMMA
2546             if (! acceptTokenClass(EHTokComma))
2547                 break;
2548         } while (true);
2549     }
2550 
2551     // RIGHT_PAREN
2552     if (! acceptTokenClass(EHTokRightParen)) {
2553         expected(")");
2554         return false;
2555     }
2556 
2557     return true;
2558 }
2559 
2560 // default_parameter_declaration
2561 //      : EQUAL conditional_expression
2562 //      : EQUAL initializer
acceptDefaultParameterDeclaration(const TType & type,TIntermTyped * & node)2563 bool HlslGrammar::acceptDefaultParameterDeclaration(const TType& type, TIntermTyped*& node)
2564 {
2565     node = nullptr;
2566 
2567     // Valid not to have a default_parameter_declaration
2568     if (!acceptTokenClass(EHTokAssign))
2569         return true;
2570 
2571     if (!acceptConditionalExpression(node)) {
2572         if (!acceptInitializer(node))
2573             return false;
2574 
2575         // For initializer lists, we have to const-fold into a constructor for the type, so build
2576         // that.
2577         TFunction* constructor = parseContext.makeConstructorCall(token.loc, type);
2578         if (constructor == nullptr)  // cannot construct
2579             return false;
2580 
2581         TIntermTyped* arguments = nullptr;
2582         for (int i = 0; i < int(node->getAsAggregate()->getSequence().size()); i++)
2583             parseContext.handleFunctionArgument(constructor, arguments, node->getAsAggregate()->getSequence()[i]->getAsTyped());
2584 
2585         node = parseContext.handleFunctionCall(token.loc, constructor, node);
2586     }
2587 
2588     if (node == nullptr)
2589         return false;
2590 
2591     // If this is simply a constant, we can use it directly.
2592     if (node->getAsConstantUnion())
2593         return true;
2594 
2595     // Otherwise, it has to be const-foldable.
2596     TIntermTyped* origNode = node;
2597 
2598     node = intermediate.fold(node->getAsAggregate());
2599 
2600     if (node != nullptr && origNode != node)
2601         return true;
2602 
2603     parseContext.error(token.loc, "invalid default parameter value", "", "");
2604 
2605     return false;
2606 }
2607 
2608 // parameter_declaration
2609 //      : attributes attributed_declaration
2610 //
2611 // attributed_declaration
2612 //      : fully_specified_type post_decls [ = default_parameter_declaration ]
2613 //      | fully_specified_type identifier array_specifier post_decls [ = default_parameter_declaration ]
2614 //
acceptParameterDeclaration(TFunction & function)2615 bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
2616 {
2617     // attributes
2618     TAttributes attributes;
2619     acceptAttributes(attributes);
2620 
2621     // fully_specified_type
2622     TType* type = new TType;
2623     if (! acceptFullySpecifiedType(*type, attributes))
2624         return false;
2625 
2626     // merge in the attributes
2627     parseContext.transferTypeAttributes(token.loc, attributes, *type);
2628 
2629     // identifier
2630     HlslToken idToken;
2631     acceptIdentifier(idToken);
2632 
2633     // array_specifier
2634     TArraySizes* arraySizes = nullptr;
2635     acceptArraySpecifier(arraySizes);
2636     if (arraySizes) {
2637         if (arraySizes->hasUnsized()) {
2638             parseContext.error(token.loc, "function parameter requires array size", "[]", "");
2639             return false;
2640         }
2641 
2642         type->transferArraySizes(arraySizes);
2643     }
2644 
2645     // post_decls
2646     acceptPostDecls(type->getQualifier());
2647 
2648     TIntermTyped* defaultValue;
2649     if (!acceptDefaultParameterDeclaration(*type, defaultValue))
2650         return false;
2651 
2652     parseContext.paramFix(*type);
2653 
2654     // If any prior parameters have default values, all the parameters after that must as well.
2655     if (defaultValue == nullptr && function.getDefaultParamCount() > 0) {
2656         parseContext.error(idToken.loc, "invalid parameter after default value parameters", idToken.string->c_str(), "");
2657         return false;
2658     }
2659 
2660     TParameter param = { idToken.string, type, defaultValue };
2661     function.addParameter(param);
2662 
2663     return true;
2664 }
2665 
2666 // Do the work to create the function definition in addition to
2667 // parsing the body (compound_statement).
2668 //
2669 // If 'deferredTokens' are passed in, just get the token stream,
2670 // don't process.
2671 //
acceptFunctionDefinition(TFunctionDeclarator & declarator,TIntermNode * & nodeList,TVector<HlslToken> * deferredTokens)2672 bool HlslGrammar::acceptFunctionDefinition(TFunctionDeclarator& declarator, TIntermNode*& nodeList,
2673                                            TVector<HlslToken>* deferredTokens)
2674 {
2675     parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, false /* not prototype */);
2676 
2677     if (deferredTokens)
2678         return captureBlockTokens(*deferredTokens);
2679     else
2680         return acceptFunctionBody(declarator, nodeList);
2681 }
2682 
acceptFunctionBody(TFunctionDeclarator & declarator,TIntermNode * & nodeList)2683 bool HlslGrammar::acceptFunctionBody(TFunctionDeclarator& declarator, TIntermNode*& nodeList)
2684 {
2685     // we might get back an entry-point
2686     TIntermNode* entryPointNode = nullptr;
2687 
2688     // This does a pushScope()
2689     TIntermNode* functionNode = parseContext.handleFunctionDefinition(declarator.loc, *declarator.function,
2690                                                                       declarator.attributes, entryPointNode);
2691 
2692     // compound_statement
2693     TIntermNode* functionBody = nullptr;
2694     if (! acceptCompoundStatement(functionBody))
2695         return false;
2696 
2697     // this does a popScope()
2698     parseContext.handleFunctionBody(declarator.loc, *declarator.function, functionBody, functionNode);
2699 
2700     // Hook up the 1 or 2 function definitions.
2701     nodeList = intermediate.growAggregate(nodeList, functionNode);
2702     nodeList = intermediate.growAggregate(nodeList, entryPointNode);
2703 
2704     return true;
2705 }
2706 
2707 // Accept an expression with parenthesis around it, where
2708 // the parenthesis ARE NOT expression parenthesis, but the
2709 // syntactically required ones like in "if ( expression )".
2710 //
2711 // Also accepts a declaration expression; "if (int a = expression)".
2712 //
2713 // Note this one is not set up to be speculative; as it gives
2714 // errors if not found.
2715 //
acceptParenExpression(TIntermTyped * & expression)2716 bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression)
2717 {
2718     expression = nullptr;
2719 
2720     // LEFT_PAREN
2721     if (! acceptTokenClass(EHTokLeftParen))
2722         expected("(");
2723 
2724     bool decl = false;
2725     TIntermNode* declNode = nullptr;
2726     decl = acceptControlDeclaration(declNode);
2727     if (decl) {
2728         if (declNode == nullptr || declNode->getAsTyped() == nullptr) {
2729             expected("initialized declaration");
2730             return false;
2731         } else
2732             expression = declNode->getAsTyped();
2733     } else {
2734         // no declaration
2735         if (! acceptExpression(expression)) {
2736             expected("expression");
2737             return false;
2738         }
2739     }
2740 
2741     // RIGHT_PAREN
2742     if (! acceptTokenClass(EHTokRightParen))
2743         expected(")");
2744 
2745     return true;
2746 }
2747 
2748 // The top-level full expression recognizer.
2749 //
2750 // expression
2751 //      : assignment_expression COMMA assignment_expression COMMA assignment_expression ...
2752 //
acceptExpression(TIntermTyped * & node)2753 bool HlslGrammar::acceptExpression(TIntermTyped*& node)
2754 {
2755     node = nullptr;
2756 
2757     // assignment_expression
2758     if (! acceptAssignmentExpression(node))
2759         return false;
2760 
2761     if (! peekTokenClass(EHTokComma))
2762         return true;
2763 
2764     do {
2765         // ... COMMA
2766         TSourceLoc loc = token.loc;
2767         advanceToken();
2768 
2769         // ... assignment_expression
2770         TIntermTyped* rightNode = nullptr;
2771         if (! acceptAssignmentExpression(rightNode)) {
2772             expected("assignment expression");
2773             return false;
2774         }
2775 
2776         node = intermediate.addComma(node, rightNode, loc);
2777 
2778         if (! peekTokenClass(EHTokComma))
2779             return true;
2780     } while (true);
2781 }
2782 
2783 // initializer
2784 //      : LEFT_BRACE RIGHT_BRACE
2785 //      | LEFT_BRACE initializer_list RIGHT_BRACE
2786 //
2787 // initializer_list
2788 //      : assignment_expression COMMA assignment_expression COMMA ...
2789 //
acceptInitializer(TIntermTyped * & node)2790 bool HlslGrammar::acceptInitializer(TIntermTyped*& node)
2791 {
2792     // LEFT_BRACE
2793     if (! acceptTokenClass(EHTokLeftBrace))
2794         return false;
2795 
2796     // RIGHT_BRACE
2797     TSourceLoc loc = token.loc;
2798     if (acceptTokenClass(EHTokRightBrace)) {
2799         // a zero-length initializer list
2800         node = intermediate.makeAggregate(loc);
2801         return true;
2802     }
2803 
2804     // initializer_list
2805     node = nullptr;
2806     do {
2807         // assignment_expression
2808         TIntermTyped* expr;
2809         if (! acceptAssignmentExpression(expr)) {
2810             expected("assignment expression in initializer list");
2811             return false;
2812         }
2813 
2814         const bool firstNode = (node == nullptr);
2815 
2816         node = intermediate.growAggregate(node, expr, loc);
2817 
2818         // If every sub-node in the list has qualifier EvqConst, the returned node becomes
2819         // EvqConst.  Otherwise, it becomes EvqTemporary. That doesn't happen with e.g.
2820         // EvqIn or EvqPosition, since the collection isn't EvqPosition if all the members are.
2821         if (firstNode && expr->getQualifier().storage == EvqConst)
2822             node->getQualifier().storage = EvqConst;
2823         else if (expr->getQualifier().storage != EvqConst)
2824             node->getQualifier().storage = EvqTemporary;
2825 
2826         // COMMA
2827         if (acceptTokenClass(EHTokComma)) {
2828             if (acceptTokenClass(EHTokRightBrace))  // allow trailing comma
2829                 return true;
2830             continue;
2831         }
2832 
2833         // RIGHT_BRACE
2834         if (acceptTokenClass(EHTokRightBrace))
2835             return true;
2836 
2837         expected(", or }");
2838         return false;
2839     } while (true);
2840 }
2841 
2842 // Accept an assignment expression, where assignment operations
2843 // associate right-to-left.  That is, it is implicit, for example
2844 //
2845 //    a op (b op (c op d))
2846 //
2847 // assigment_expression
2848 //      : initializer
2849 //      | conditional_expression
2850 //      | conditional_expression assign_op conditional_expression assign_op conditional_expression ...
2851 //
acceptAssignmentExpression(TIntermTyped * & node)2852 bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
2853 {
2854     // initializer
2855     if (peekTokenClass(EHTokLeftBrace)) {
2856         if (acceptInitializer(node))
2857             return true;
2858 
2859         expected("initializer");
2860         return false;
2861     }
2862 
2863     // conditional_expression
2864     if (! acceptConditionalExpression(node))
2865         return false;
2866 
2867     // assignment operation?
2868     TOperator assignOp = HlslOpMap::assignment(peek());
2869     if (assignOp == EOpNull)
2870         return true;
2871 
2872     // assign_op
2873     TSourceLoc loc = token.loc;
2874     advanceToken();
2875 
2876     // conditional_expression assign_op conditional_expression ...
2877     // Done by recursing this function, which automatically
2878     // gets the right-to-left associativity.
2879     TIntermTyped* rightNode = nullptr;
2880     if (! acceptAssignmentExpression(rightNode)) {
2881         expected("assignment expression");
2882         return false;
2883     }
2884 
2885     node = parseContext.handleAssign(loc, assignOp, node, rightNode);
2886     node = parseContext.handleLvalue(loc, "assign", node);
2887 
2888     if (node == nullptr) {
2889         parseContext.error(loc, "could not create assignment", "", "");
2890         return false;
2891     }
2892 
2893     if (! peekTokenClass(EHTokComma))
2894         return true;
2895 
2896     return true;
2897 }
2898 
2899 // Accept a conditional expression, which associates right-to-left,
2900 // accomplished by the "true" expression calling down to lower
2901 // precedence levels than this level.
2902 //
2903 // conditional_expression
2904 //      : binary_expression
2905 //      | binary_expression QUESTION expression COLON assignment_expression
2906 //
acceptConditionalExpression(TIntermTyped * & node)2907 bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
2908 {
2909     // binary_expression
2910     if (! acceptBinaryExpression(node, PlLogicalOr))
2911         return false;
2912 
2913     if (! acceptTokenClass(EHTokQuestion))
2914         return true;
2915 
2916     node = parseContext.convertConditionalExpression(token.loc, node, false);
2917     if (node == nullptr)
2918         return false;
2919 
2920     ++parseContext.controlFlowNestingLevel;  // this only needs to work right if no errors
2921 
2922     TIntermTyped* trueNode = nullptr;
2923     if (! acceptExpression(trueNode)) {
2924         expected("expression after ?");
2925         return false;
2926     }
2927     TSourceLoc loc = token.loc;
2928 
2929     if (! acceptTokenClass(EHTokColon)) {
2930         expected(":");
2931         return false;
2932     }
2933 
2934     TIntermTyped* falseNode = nullptr;
2935     if (! acceptAssignmentExpression(falseNode)) {
2936         expected("expression after :");
2937         return false;
2938     }
2939 
2940     --parseContext.controlFlowNestingLevel;
2941 
2942     node = intermediate.addSelection(node, trueNode, falseNode, loc);
2943 
2944     return true;
2945 }
2946 
2947 // Accept a binary expression, for binary operations that
2948 // associate left-to-right.  This is, it is implicit, for example
2949 //
2950 //    ((a op b) op c) op d
2951 //
2952 // binary_expression
2953 //      : expression op expression op expression ...
2954 //
2955 // where 'expression' is the next higher level in precedence.
2956 //
acceptBinaryExpression(TIntermTyped * & node,PrecedenceLevel precedenceLevel)2957 bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel)
2958 {
2959     if (precedenceLevel > PlMul)
2960         return acceptUnaryExpression(node);
2961 
2962     // assignment_expression
2963     if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1)))
2964         return false;
2965 
2966     do {
2967         TOperator op = HlslOpMap::binary(peek());
2968         PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op);
2969         if (tokenLevel < precedenceLevel)
2970             return true;
2971 
2972         // ... op
2973         TSourceLoc loc = token.loc;
2974         advanceToken();
2975 
2976         // ... expression
2977         TIntermTyped* rightNode = nullptr;
2978         if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) {
2979             expected("expression");
2980             return false;
2981         }
2982 
2983         node = intermediate.addBinaryMath(op, node, rightNode, loc);
2984         if (node == nullptr) {
2985             parseContext.error(loc, "Could not perform requested binary operation", "", "");
2986             return false;
2987         }
2988     } while (true);
2989 }
2990 
2991 // unary_expression
2992 //      : (type) unary_expression
2993 //      | + unary_expression
2994 //      | - unary_expression
2995 //      | ! unary_expression
2996 //      | ~ unary_expression
2997 //      | ++ unary_expression
2998 //      | -- unary_expression
2999 //      | postfix_expression
3000 //
acceptUnaryExpression(TIntermTyped * & node)3001 bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
3002 {
3003     // (type) unary_expression
3004     // Have to look two steps ahead, because this could be, e.g., a
3005     // postfix_expression instead, since that also starts with at "(".
3006     if (acceptTokenClass(EHTokLeftParen)) {
3007         TType castType;
3008         if (acceptType(castType)) {
3009             // recognize any array_specifier as part of the type
3010             TArraySizes* arraySizes = nullptr;
3011             acceptArraySpecifier(arraySizes);
3012             if (arraySizes != nullptr)
3013                 castType.transferArraySizes(arraySizes);
3014             TSourceLoc loc = token.loc;
3015             if (acceptTokenClass(EHTokRightParen)) {
3016                 // We've matched "(type)" now, get the expression to cast
3017                 if (! acceptUnaryExpression(node))
3018                     return false;
3019 
3020                 // Hook it up like a constructor
3021                 TFunction* constructorFunction = parseContext.makeConstructorCall(loc, castType);
3022                 if (constructorFunction == nullptr) {
3023                     expected("type that can be constructed");
3024                     return false;
3025                 }
3026                 TIntermTyped* arguments = nullptr;
3027                 parseContext.handleFunctionArgument(constructorFunction, arguments, node);
3028                 node = parseContext.handleFunctionCall(loc, constructorFunction, arguments);
3029 
3030                 return node != nullptr;
3031             } else {
3032                 // This could be a parenthesized constructor, ala (int(3)), and we just accepted
3033                 // the '(int' part.  We must back up twice.
3034                 recedeToken();
3035                 recedeToken();
3036 
3037                 // Note, there are no array constructors like
3038                 //   (float[2](...))
3039                 if (arraySizes != nullptr)
3040                     parseContext.error(loc, "parenthesized array constructor not allowed", "([]())", "", "");
3041             }
3042         } else {
3043             // This isn't a type cast, but it still started "(", so if it is a
3044             // unary expression, it can only be a postfix_expression, so try that.
3045             // Back it up first.
3046             recedeToken();
3047             return acceptPostfixExpression(node);
3048         }
3049     }
3050 
3051     // peek for "op unary_expression"
3052     TOperator unaryOp = HlslOpMap::preUnary(peek());
3053 
3054     // postfix_expression (if no unary operator)
3055     if (unaryOp == EOpNull)
3056         return acceptPostfixExpression(node);
3057 
3058     // op unary_expression
3059     TSourceLoc loc = token.loc;
3060     advanceToken();
3061     if (! acceptUnaryExpression(node))
3062         return false;
3063 
3064     // + is a no-op
3065     if (unaryOp == EOpAdd)
3066         return true;
3067 
3068     node = intermediate.addUnaryMath(unaryOp, node, loc);
3069 
3070     // These unary ops require lvalues
3071     if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement)
3072         node = parseContext.handleLvalue(loc, "unary operator", node);
3073 
3074     return node != nullptr;
3075 }
3076 
3077 // postfix_expression
3078 //      : LEFT_PAREN expression RIGHT_PAREN
3079 //      | literal
3080 //      | constructor
3081 //      | IDENTIFIER [ COLONCOLON IDENTIFIER [ COLONCOLON IDENTIFIER ... ] ]
3082 //      | function_call
3083 //      | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET
3084 //      | postfix_expression DOT IDENTIFIER
3085 //      | postfix_expression DOT IDENTIFIER arguments
3086 //      | postfix_expression arguments
3087 //      | postfix_expression INC_OP
3088 //      | postfix_expression DEC_OP
3089 //
acceptPostfixExpression(TIntermTyped * & node)3090 bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
3091 {
3092     // Not implemented as self-recursive:
3093     // The logical "right recursion" is done with a loop at the end
3094 
3095     // idToken will pick up either a variable or a function name in a function call
3096     HlslToken idToken;
3097 
3098     // Find something before the postfix operations, as they can't operate
3099     // on nothing.  So, no "return true", they fall through, only "return false".
3100     if (acceptTokenClass(EHTokLeftParen)) {
3101         // LEFT_PAREN expression RIGHT_PAREN
3102         if (! acceptExpression(node)) {
3103             expected("expression");
3104             return false;
3105         }
3106         if (! acceptTokenClass(EHTokRightParen)) {
3107             expected(")");
3108             return false;
3109         }
3110     } else if (acceptLiteral(node)) {
3111         // literal (nothing else to do yet)
3112     } else if (acceptConstructor(node)) {
3113         // constructor (nothing else to do yet)
3114     } else if (acceptIdentifier(idToken)) {
3115         // user-type, namespace name, variable, or function name
3116         TString* fullName = idToken.string;
3117         while (acceptTokenClass(EHTokColonColon)) {
3118             // user-type or namespace name
3119             fullName = NewPoolTString(fullName->c_str());
3120             fullName->append(parseContext.scopeMangler);
3121             if (acceptIdentifier(idToken))
3122                 fullName->append(*idToken.string);
3123             else {
3124                 expected("identifier after ::");
3125                 return false;
3126             }
3127         }
3128         if (! peekTokenClass(EHTokLeftParen)) {
3129             node = parseContext.handleVariable(idToken.loc, fullName);
3130             if (node == nullptr)
3131                 return false;
3132         } else if (acceptFunctionCall(idToken.loc, *fullName, node, nullptr)) {
3133             // function_call (nothing else to do yet)
3134         } else {
3135             expected("function call arguments");
3136             return false;
3137         }
3138     } else {
3139         // nothing found, can't post operate
3140         return false;
3141     }
3142 
3143     // Something was found, chain as many postfix operations as exist.
3144     do {
3145         TSourceLoc loc = token.loc;
3146         TOperator postOp = HlslOpMap::postUnary(peek());
3147 
3148         // Consume only a valid post-unary operator, otherwise we are done.
3149         switch (postOp) {
3150         case EOpIndexDirectStruct:
3151         case EOpIndexIndirect:
3152         case EOpPostIncrement:
3153         case EOpPostDecrement:
3154         case EOpScoping:
3155             advanceToken();
3156             break;
3157         default:
3158             return true;
3159         }
3160 
3161         // We have a valid post-unary operator, process it.
3162         switch (postOp) {
3163         case EOpScoping:
3164         case EOpIndexDirectStruct:
3165         {
3166             // DOT IDENTIFIER
3167             // includes swizzles, member variables, and member functions
3168             HlslToken field;
3169             if (! acceptIdentifier(field)) {
3170                 expected("swizzle or member");
3171                 return false;
3172             }
3173 
3174             if (peekTokenClass(EHTokLeftParen)) {
3175                 // member function
3176                 TIntermTyped* thisNode = node;
3177 
3178                 // arguments
3179                 if (! acceptFunctionCall(field.loc, *field.string, node, thisNode)) {
3180                     expected("function parameters");
3181                     return false;
3182                 }
3183             } else
3184                 node = parseContext.handleDotDereference(field.loc, node, *field.string);
3185 
3186             break;
3187         }
3188         case EOpIndexIndirect:
3189         {
3190             // LEFT_BRACKET integer_expression RIGHT_BRACKET
3191             TIntermTyped* indexNode = nullptr;
3192             if (! acceptExpression(indexNode) ||
3193                 ! peekTokenClass(EHTokRightBracket)) {
3194                 expected("expression followed by ']'");
3195                 return false;
3196             }
3197             advanceToken();
3198             node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode);
3199             if (node == nullptr)
3200                 return false;
3201             break;
3202         }
3203         case EOpPostIncrement:
3204             // INC_OP
3205             // fall through
3206         case EOpPostDecrement:
3207             // DEC_OP
3208             node = intermediate.addUnaryMath(postOp, node, loc);
3209             node = parseContext.handleLvalue(loc, "unary operator", node);
3210             break;
3211         default:
3212             assert(0);
3213             break;
3214         }
3215     } while (true);
3216 }
3217 
3218 // constructor
3219 //      : type argument_list
3220 //
acceptConstructor(TIntermTyped * & node)3221 bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
3222 {
3223     // type
3224     TType type;
3225     if (acceptType(type)) {
3226         TFunction* constructorFunction = parseContext.makeConstructorCall(token.loc, type);
3227         if (constructorFunction == nullptr)
3228             return false;
3229 
3230         // arguments
3231         TIntermTyped* arguments = nullptr;
3232         if (! acceptArguments(constructorFunction, arguments)) {
3233             // It's possible this is a type keyword used as an identifier.  Put the token back
3234             // for later use.
3235             recedeToken();
3236             return false;
3237         }
3238 
3239         if (arguments == nullptr) {
3240             expected("one or more arguments");
3241             return false;
3242         }
3243 
3244         // hook it up
3245         node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
3246 
3247         return node != nullptr;
3248     }
3249 
3250     return false;
3251 }
3252 
3253 // The function_call identifier was already recognized, and passed in as idToken.
3254 //
3255 // function_call
3256 //      : [idToken] arguments
3257 //
acceptFunctionCall(const TSourceLoc & loc,TString & name,TIntermTyped * & node,TIntermTyped * baseObject)3258 bool HlslGrammar::acceptFunctionCall(const TSourceLoc& loc, TString& name, TIntermTyped*& node, TIntermTyped* baseObject)
3259 {
3260     // name
3261     TString* functionName = nullptr;
3262     if (baseObject == nullptr) {
3263         functionName = &name;
3264     } else if (parseContext.isBuiltInMethod(loc, baseObject, name)) {
3265         // Built-in methods are not in the symbol table as methods, but as global functions
3266         // taking an explicit 'this' as the first argument.
3267         functionName = NewPoolTString(BUILTIN_PREFIX);
3268         functionName->append(name);
3269     } else {
3270         if (! baseObject->getType().isStruct()) {
3271             expected("structure");
3272             return false;
3273         }
3274         functionName = NewPoolTString("");
3275         functionName->append(baseObject->getType().getTypeName());
3276         parseContext.addScopeMangler(*functionName);
3277         functionName->append(name);
3278     }
3279 
3280     // function
3281     TFunction* function = new TFunction(functionName, TType(EbtVoid));
3282 
3283     // arguments
3284     TIntermTyped* arguments = nullptr;
3285     if (baseObject != nullptr) {
3286         // Non-static member functions have an implicit first argument of the base object.
3287         parseContext.handleFunctionArgument(function, arguments, baseObject);
3288     }
3289     if (! acceptArguments(function, arguments))
3290         return false;
3291 
3292     // call
3293     node = parseContext.handleFunctionCall(loc, function, arguments);
3294 
3295     return node != nullptr;
3296 }
3297 
3298 // arguments
3299 //      : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN
3300 //
3301 // The arguments are pushed onto the 'function' argument list and
3302 // onto the 'arguments' aggregate.
3303 //
acceptArguments(TFunction * function,TIntermTyped * & arguments)3304 bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments)
3305 {
3306     // LEFT_PAREN
3307     if (! acceptTokenClass(EHTokLeftParen))
3308         return false;
3309 
3310     // RIGHT_PAREN
3311     if (acceptTokenClass(EHTokRightParen))
3312         return true;
3313 
3314     // must now be at least one expression...
3315     do {
3316         // expression
3317         TIntermTyped* arg;
3318         if (! acceptAssignmentExpression(arg))
3319             return false;
3320 
3321         // hook it up
3322         parseContext.handleFunctionArgument(function, arguments, arg);
3323 
3324         // COMMA
3325         if (! acceptTokenClass(EHTokComma))
3326             break;
3327     } while (true);
3328 
3329     // RIGHT_PAREN
3330     if (! acceptTokenClass(EHTokRightParen)) {
3331         expected(")");
3332         return false;
3333     }
3334 
3335     return true;
3336 }
3337 
acceptLiteral(TIntermTyped * & node)3338 bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
3339 {
3340     switch (token.tokenClass) {
3341     case EHTokIntConstant:
3342         node = intermediate.addConstantUnion(token.i, token.loc, true);
3343         break;
3344     case EHTokUintConstant:
3345         node = intermediate.addConstantUnion(token.u, token.loc, true);
3346         break;
3347     case EHTokFloat16Constant:
3348         node = intermediate.addConstantUnion(token.d, EbtFloat16, token.loc, true);
3349         break;
3350     case EHTokFloatConstant:
3351         node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true);
3352         break;
3353     case EHTokDoubleConstant:
3354         node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true);
3355         break;
3356     case EHTokBoolConstant:
3357         node = intermediate.addConstantUnion(token.b, token.loc, true);
3358         break;
3359     case EHTokStringConstant:
3360         node = intermediate.addConstantUnion(token.string, token.loc, true);
3361         break;
3362 
3363     default:
3364         return false;
3365     }
3366 
3367     advanceToken();
3368 
3369     return true;
3370 }
3371 
3372 // simple_statement
3373 //      : SEMICOLON
3374 //      | declaration_statement
3375 //      | expression SEMICOLON
3376 //
acceptSimpleStatement(TIntermNode * & statement)3377 bool HlslGrammar::acceptSimpleStatement(TIntermNode*& statement)
3378 {
3379     // SEMICOLON
3380     if (acceptTokenClass(EHTokSemicolon))
3381         return true;
3382 
3383     // declaration
3384     if (acceptDeclaration(statement))
3385         return true;
3386 
3387     // expression
3388     TIntermTyped* node;
3389     if (acceptExpression(node))
3390         statement = node;
3391     else
3392         return false;
3393 
3394     // SEMICOLON (following an expression)
3395     if (acceptTokenClass(EHTokSemicolon))
3396         return true;
3397     else {
3398         expected(";");
3399         return false;
3400     }
3401 }
3402 
3403 // compound_statement
3404 //      : LEFT_CURLY statement statement ... RIGHT_CURLY
3405 //
acceptCompoundStatement(TIntermNode * & retStatement)3406 bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement)
3407 {
3408     TIntermAggregate* compoundStatement = nullptr;
3409 
3410     // LEFT_CURLY
3411     if (! acceptTokenClass(EHTokLeftBrace))
3412         return false;
3413 
3414     // statement statement ...
3415     TIntermNode* statement = nullptr;
3416     while (acceptStatement(statement)) {
3417         TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr;
3418         if (branch != nullptr && (branch->getFlowOp() == EOpCase ||
3419                                   branch->getFlowOp() == EOpDefault)) {
3420             // hook up individual subsequences within a switch statement
3421             parseContext.wrapupSwitchSubsequence(compoundStatement, statement);
3422             compoundStatement = nullptr;
3423         } else {
3424             // hook it up to the growing compound statement
3425             compoundStatement = intermediate.growAggregate(compoundStatement, statement);
3426         }
3427     }
3428     if (compoundStatement)
3429         compoundStatement->setOperator(EOpSequence);
3430 
3431     retStatement = compoundStatement;
3432 
3433     // RIGHT_CURLY
3434     return acceptTokenClass(EHTokRightBrace);
3435 }
3436 
acceptScopedStatement(TIntermNode * & statement)3437 bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement)
3438 {
3439     parseContext.pushScope();
3440     bool result = acceptStatement(statement);
3441     parseContext.popScope();
3442 
3443     return result;
3444 }
3445 
acceptScopedCompoundStatement(TIntermNode * & statement)3446 bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
3447 {
3448     parseContext.pushScope();
3449     bool result = acceptCompoundStatement(statement);
3450     parseContext.popScope();
3451 
3452     return result;
3453 }
3454 
3455 // statement
3456 //      : attributes attributed_statement
3457 //
3458 // attributed_statement
3459 //      : compound_statement
3460 //      | simple_statement
3461 //      | selection_statement
3462 //      | switch_statement
3463 //      | case_label
3464 //      | default_label
3465 //      | iteration_statement
3466 //      | jump_statement
3467 //
acceptStatement(TIntermNode * & statement)3468 bool HlslGrammar::acceptStatement(TIntermNode*& statement)
3469 {
3470     statement = nullptr;
3471 
3472     // attributes
3473     TAttributes attributes;
3474     acceptAttributes(attributes);
3475 
3476     // attributed_statement
3477     switch (peek()) {
3478     case EHTokLeftBrace:
3479         return acceptScopedCompoundStatement(statement);
3480 
3481     case EHTokIf:
3482         return acceptSelectionStatement(statement, attributes);
3483 
3484     case EHTokSwitch:
3485         return acceptSwitchStatement(statement, attributes);
3486 
3487     case EHTokFor:
3488     case EHTokDo:
3489     case EHTokWhile:
3490         return acceptIterationStatement(statement, attributes);
3491 
3492     case EHTokContinue:
3493     case EHTokBreak:
3494     case EHTokDiscard:
3495     case EHTokReturn:
3496         return acceptJumpStatement(statement);
3497 
3498     case EHTokCase:
3499         return acceptCaseLabel(statement);
3500     case EHTokDefault:
3501         return acceptDefaultLabel(statement);
3502 
3503     case EHTokRightBrace:
3504         // Performance: not strictly necessary, but stops a bunch of hunting early,
3505         // and is how sequences of statements end.
3506         return false;
3507 
3508     default:
3509         return acceptSimpleStatement(statement);
3510     }
3511 
3512     return true;
3513 }
3514 
3515 // attributes
3516 //      : [zero or more:] bracketed-attribute
3517 //
3518 // bracketed-attribute:
3519 //      : LEFT_BRACKET scoped-attribute RIGHT_BRACKET
3520 //      : LEFT_BRACKET LEFT_BRACKET scoped-attribute RIGHT_BRACKET RIGHT_BRACKET
3521 //
3522 // scoped-attribute:
3523 //      : attribute
3524 //      | namespace COLON COLON attribute
3525 //
3526 // attribute:
3527 //      : UNROLL
3528 //      | UNROLL LEFT_PAREN literal RIGHT_PAREN
3529 //      | FASTOPT
3530 //      | ALLOW_UAV_CONDITION
3531 //      | BRANCH
3532 //      | FLATTEN
3533 //      | FORCECASE
3534 //      | CALL
3535 //      | DOMAIN
3536 //      | EARLYDEPTHSTENCIL
3537 //      | INSTANCE
3538 //      | MAXTESSFACTOR
3539 //      | OUTPUTCONTROLPOINTS
3540 //      | OUTPUTTOPOLOGY
3541 //      | PARTITIONING
3542 //      | PATCHCONSTANTFUNC
3543 //      | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN
3544 //
acceptAttributes(TAttributes & attributes)3545 void HlslGrammar::acceptAttributes(TAttributes& attributes)
3546 {
3547     // For now, accept the [ XXX(X) ] syntax, but drop all but
3548     // numthreads, which is used to set the CS local size.
3549     // TODO: subset to correct set?  Pass on?
3550     do {
3551         HlslToken attributeToken;
3552 
3553         // LEFT_BRACKET?
3554         if (! acceptTokenClass(EHTokLeftBracket))
3555             return;
3556         // another LEFT_BRACKET?
3557         bool doubleBrackets = false;
3558         if (acceptTokenClass(EHTokLeftBracket))
3559             doubleBrackets = true;
3560 
3561         // attribute? (could be namespace; will adjust later)
3562         if (!acceptIdentifier(attributeToken)) {
3563             if (!peekTokenClass(EHTokRightBracket)) {
3564                 expected("namespace or attribute identifier");
3565                 advanceToken();
3566             }
3567         }
3568 
3569         TString nameSpace;
3570         if (acceptTokenClass(EHTokColonColon)) {
3571             // namespace COLON COLON
3572             nameSpace = *attributeToken.string;
3573             // attribute
3574             if (!acceptIdentifier(attributeToken)) {
3575                 expected("attribute identifier");
3576                 return;
3577             }
3578         }
3579 
3580         TIntermAggregate* expressions = nullptr;
3581 
3582         // (x, ...)
3583         if (acceptTokenClass(EHTokLeftParen)) {
3584             expressions = new TIntermAggregate;
3585 
3586             TIntermTyped* node;
3587             bool expectingExpression = false;
3588 
3589             while (acceptAssignmentExpression(node)) {
3590                 expectingExpression = false;
3591                 expressions->getSequence().push_back(node);
3592                 if (acceptTokenClass(EHTokComma))
3593                     expectingExpression = true;
3594             }
3595 
3596             // 'expressions' is an aggregate with the expressions in it
3597             if (! acceptTokenClass(EHTokRightParen))
3598                 expected(")");
3599 
3600             // Error for partial or missing expression
3601             if (expectingExpression || expressions->getSequence().empty())
3602                 expected("expression");
3603         }
3604 
3605         // RIGHT_BRACKET
3606         if (!acceptTokenClass(EHTokRightBracket)) {
3607             expected("]");
3608             return;
3609         }
3610         // another RIGHT_BRACKET?
3611         if (doubleBrackets && !acceptTokenClass(EHTokRightBracket)) {
3612             expected("]]");
3613             return;
3614         }
3615 
3616         // Add any values we found into the attribute map.
3617         if (attributeToken.string != nullptr) {
3618             TAttributeType attributeType = parseContext.attributeFromName(nameSpace, *attributeToken.string);
3619             if (attributeType == EatNone)
3620                 parseContext.warn(attributeToken.loc, "unrecognized attribute", attributeToken.string->c_str(), "");
3621             else {
3622                 TAttributeArgs attributeArgs = { attributeType, expressions };
3623                 attributes.push_back(attributeArgs);
3624             }
3625         }
3626     } while (true);
3627 }
3628 
3629 // selection_statement
3630 //      : IF LEFT_PAREN expression RIGHT_PAREN statement
3631 //      : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
3632 //
acceptSelectionStatement(TIntermNode * & statement,const TAttributes & attributes)3633 bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttributes& attributes)
3634 {
3635     TSourceLoc loc = token.loc;
3636 
3637     // IF
3638     if (! acceptTokenClass(EHTokIf))
3639         return false;
3640 
3641     // so that something declared in the condition is scoped to the lifetimes
3642     // of the then-else statements
3643     parseContext.pushScope();
3644 
3645     // LEFT_PAREN expression RIGHT_PAREN
3646     TIntermTyped* condition;
3647     if (! acceptParenExpression(condition))
3648         return false;
3649     condition = parseContext.convertConditionalExpression(loc, condition);
3650     if (condition == nullptr)
3651         return false;
3652 
3653     // create the child statements
3654     TIntermNodePair thenElse = { nullptr, nullptr };
3655 
3656     ++parseContext.controlFlowNestingLevel;  // this only needs to work right if no errors
3657 
3658     // then statement
3659     if (! acceptScopedStatement(thenElse.node1)) {
3660         expected("then statement");
3661         return false;
3662     }
3663 
3664     // ELSE
3665     if (acceptTokenClass(EHTokElse)) {
3666         // else statement
3667         if (! acceptScopedStatement(thenElse.node2)) {
3668             expected("else statement");
3669             return false;
3670         }
3671     }
3672 
3673     // Put the pieces together
3674     statement = intermediate.addSelection(condition, thenElse, loc);
3675     parseContext.handleSelectionAttributes(loc, statement->getAsSelectionNode(), attributes);
3676 
3677     parseContext.popScope();
3678     --parseContext.controlFlowNestingLevel;
3679 
3680     return true;
3681 }
3682 
3683 // switch_statement
3684 //      : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
3685 //
acceptSwitchStatement(TIntermNode * & statement,const TAttributes & attributes)3686 bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttributes& attributes)
3687 {
3688     // SWITCH
3689     TSourceLoc loc = token.loc;
3690 
3691     if (! acceptTokenClass(EHTokSwitch))
3692         return false;
3693 
3694     // LEFT_PAREN expression RIGHT_PAREN
3695     parseContext.pushScope();
3696     TIntermTyped* switchExpression;
3697     if (! acceptParenExpression(switchExpression)) {
3698         parseContext.popScope();
3699         return false;
3700     }
3701 
3702     // compound_statement
3703     parseContext.pushSwitchSequence(new TIntermSequence);
3704 
3705     ++parseContext.controlFlowNestingLevel;
3706     bool statementOkay = acceptCompoundStatement(statement);
3707     --parseContext.controlFlowNestingLevel;
3708 
3709     if (statementOkay)
3710         statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr,
3711                                            attributes);
3712 
3713     parseContext.popSwitchSequence();
3714     parseContext.popScope();
3715 
3716     return statementOkay;
3717 }
3718 
3719 // iteration_statement
3720 //      : WHILE LEFT_PAREN condition RIGHT_PAREN statement
3721 //      | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
3722 //      | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
3723 //
3724 // Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
acceptIterationStatement(TIntermNode * & statement,const TAttributes & attributes)3725 bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttributes& attributes)
3726 {
3727     TSourceLoc loc = token.loc;
3728     TIntermTyped* condition = nullptr;
3729 
3730     EHlslTokenClass loop = peek();
3731     assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
3732 
3733     //  WHILE or DO or FOR
3734     advanceToken();
3735 
3736     TIntermLoop* loopNode = nullptr;
3737     switch (loop) {
3738     case EHTokWhile:
3739         // so that something declared in the condition is scoped to the lifetime
3740         // of the while sub-statement
3741         parseContext.pushScope();  // this only needs to work right if no errors
3742         parseContext.nestLooping();
3743         ++parseContext.controlFlowNestingLevel;
3744 
3745         // LEFT_PAREN condition RIGHT_PAREN
3746         if (! acceptParenExpression(condition))
3747             return false;
3748         condition = parseContext.convertConditionalExpression(loc, condition);
3749         if (condition == nullptr)
3750             return false;
3751 
3752         // statement
3753         if (! acceptScopedStatement(statement)) {
3754             expected("while sub-statement");
3755             return false;
3756         }
3757 
3758         parseContext.unnestLooping();
3759         parseContext.popScope();
3760         --parseContext.controlFlowNestingLevel;
3761 
3762         loopNode = intermediate.addLoop(statement, condition, nullptr, true, loc);
3763         statement = loopNode;
3764         break;
3765 
3766     case EHTokDo:
3767         parseContext.nestLooping();  // this only needs to work right if no errors
3768         ++parseContext.controlFlowNestingLevel;
3769 
3770         // statement
3771         if (! acceptScopedStatement(statement)) {
3772             expected("do sub-statement");
3773             return false;
3774         }
3775 
3776         // WHILE
3777         if (! acceptTokenClass(EHTokWhile)) {
3778             expected("while");
3779             return false;
3780         }
3781 
3782         // LEFT_PAREN condition RIGHT_PAREN
3783         if (! acceptParenExpression(condition))
3784             return false;
3785         condition = parseContext.convertConditionalExpression(loc, condition);
3786         if (condition == nullptr)
3787             return false;
3788 
3789         if (! acceptTokenClass(EHTokSemicolon))
3790             expected(";");
3791 
3792         parseContext.unnestLooping();
3793         --parseContext.controlFlowNestingLevel;
3794 
3795         loopNode = intermediate.addLoop(statement, condition, 0, false, loc);
3796         statement = loopNode;
3797         break;
3798 
3799     case EHTokFor:
3800     {
3801         // LEFT_PAREN
3802         if (! acceptTokenClass(EHTokLeftParen))
3803             expected("(");
3804 
3805         // so that something declared in the condition is scoped to the lifetime
3806         // of the for sub-statement
3807         parseContext.pushScope();
3808 
3809         // initializer
3810         TIntermNode* initNode = nullptr;
3811         if (! acceptSimpleStatement(initNode))
3812             expected("for-loop initializer statement");
3813 
3814         parseContext.nestLooping();  // this only needs to work right if no errors
3815         ++parseContext.controlFlowNestingLevel;
3816 
3817         // condition SEMI_COLON
3818         acceptExpression(condition);
3819         if (! acceptTokenClass(EHTokSemicolon))
3820             expected(";");
3821         if (condition != nullptr) {
3822             condition = parseContext.convertConditionalExpression(loc, condition);
3823             if (condition == nullptr)
3824                 return false;
3825         }
3826 
3827         // iterator SEMI_COLON
3828         TIntermTyped* iterator = nullptr;
3829         acceptExpression(iterator);
3830         if (! acceptTokenClass(EHTokRightParen))
3831             expected(")");
3832 
3833         // statement
3834         if (! acceptScopedStatement(statement)) {
3835             expected("for sub-statement");
3836             return false;
3837         }
3838 
3839         statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc, loopNode);
3840 
3841         parseContext.popScope();
3842         parseContext.unnestLooping();
3843         --parseContext.controlFlowNestingLevel;
3844 
3845         break;
3846     }
3847 
3848     default:
3849         return false;
3850     }
3851 
3852     parseContext.handleLoopAttributes(loc, loopNode, attributes);
3853     return true;
3854 }
3855 
3856 // jump_statement
3857 //      : CONTINUE SEMICOLON
3858 //      | BREAK SEMICOLON
3859 //      | DISCARD SEMICOLON
3860 //      | RETURN SEMICOLON
3861 //      | RETURN expression SEMICOLON
3862 //
acceptJumpStatement(TIntermNode * & statement)3863 bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement)
3864 {
3865     EHlslTokenClass jump = peek();
3866     switch (jump) {
3867     case EHTokContinue:
3868     case EHTokBreak:
3869     case EHTokDiscard:
3870     case EHTokReturn:
3871         advanceToken();
3872         break;
3873     default:
3874         // not something we handle in this function
3875         return false;
3876     }
3877 
3878     switch (jump) {
3879     case EHTokContinue:
3880         statement = intermediate.addBranch(EOpContinue, token.loc);
3881         if (parseContext.loopNestingLevel == 0) {
3882             expected("loop");
3883             return false;
3884         }
3885         break;
3886     case EHTokBreak:
3887         statement = intermediate.addBranch(EOpBreak, token.loc);
3888         if (parseContext.loopNestingLevel == 0 && parseContext.switchSequenceStack.size() == 0) {
3889             expected("loop or switch");
3890             return false;
3891         }
3892         break;
3893     case EHTokDiscard:
3894         statement = intermediate.addBranch(EOpKill, token.loc);
3895         break;
3896 
3897     case EHTokReturn:
3898     {
3899         // expression
3900         TIntermTyped* node;
3901         if (acceptExpression(node)) {
3902             // hook it up
3903             statement = parseContext.handleReturnValue(token.loc, node);
3904         } else
3905             statement = intermediate.addBranch(EOpReturn, token.loc);
3906         break;
3907     }
3908 
3909     default:
3910         assert(0);
3911         return false;
3912     }
3913 
3914     // SEMICOLON
3915     if (! acceptTokenClass(EHTokSemicolon))
3916         expected(";");
3917 
3918     return true;
3919 }
3920 
3921 // case_label
3922 //      : CASE expression COLON
3923 //
acceptCaseLabel(TIntermNode * & statement)3924 bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement)
3925 {
3926     TSourceLoc loc = token.loc;
3927     if (! acceptTokenClass(EHTokCase))
3928         return false;
3929 
3930     TIntermTyped* expression;
3931     if (! acceptExpression(expression)) {
3932         expected("case expression");
3933         return false;
3934     }
3935 
3936     if (! acceptTokenClass(EHTokColon)) {
3937         expected(":");
3938         return false;
3939     }
3940 
3941     statement = parseContext.intermediate.addBranch(EOpCase, expression, loc);
3942 
3943     return true;
3944 }
3945 
3946 // default_label
3947 //      : DEFAULT COLON
3948 //
acceptDefaultLabel(TIntermNode * & statement)3949 bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement)
3950 {
3951     TSourceLoc loc = token.loc;
3952     if (! acceptTokenClass(EHTokDefault))
3953         return false;
3954 
3955     if (! acceptTokenClass(EHTokColon)) {
3956         expected(":");
3957         return false;
3958     }
3959 
3960     statement = parseContext.intermediate.addBranch(EOpDefault, loc);
3961 
3962     return true;
3963 }
3964 
3965 // array_specifier
3966 //      : LEFT_BRACKET integer_expression RGHT_BRACKET ... // optional
3967 //      : LEFT_BRACKET RGHT_BRACKET // optional
3968 //
acceptArraySpecifier(TArraySizes * & arraySizes)3969 void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
3970 {
3971     arraySizes = nullptr;
3972 
3973     // Early-out if there aren't any array dimensions
3974     if (!peekTokenClass(EHTokLeftBracket))
3975         return;
3976 
3977     // If we get here, we have at least one array dimension.  This will track the sizes we find.
3978     arraySizes = new TArraySizes;
3979 
3980     // Collect each array dimension.
3981     while (acceptTokenClass(EHTokLeftBracket)) {
3982         TSourceLoc loc = token.loc;
3983         TIntermTyped* sizeExpr = nullptr;
3984 
3985         // Array sizing expression is optional.  If omitted, array will be later sized by initializer list.
3986         const bool hasArraySize = acceptAssignmentExpression(sizeExpr);
3987 
3988         if (! acceptTokenClass(EHTokRightBracket)) {
3989             expected("]");
3990             return;
3991         }
3992 
3993         if (hasArraySize) {
3994             TArraySize arraySize;
3995             parseContext.arraySizeCheck(loc, sizeExpr, arraySize);
3996             arraySizes->addInnerSize(arraySize);
3997         } else {
3998             arraySizes->addInnerSize(0);  // sized by initializers.
3999         }
4000     }
4001 }
4002 
4003 // post_decls
4004 //      : COLON semantic // optional
4005 //        COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional
4006 //        COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional
4007 //        COLON LAYOUT layout_qualifier_list
4008 //        annotations // optional
4009 //
4010 // Return true if any tokens were accepted. That is,
4011 // false can be returned on successfully recognizing nothing,
4012 // not necessarily meaning bad syntax.
4013 //
acceptPostDecls(TQualifier & qualifier)4014 bool HlslGrammar::acceptPostDecls(TQualifier& qualifier)
4015 {
4016     bool found = false;
4017 
4018     do {
4019         // COLON
4020         if (acceptTokenClass(EHTokColon)) {
4021             found = true;
4022             HlslToken idToken;
4023             if (peekTokenClass(EHTokLayout))
4024                 acceptLayoutQualifierList(qualifier);
4025             else if (acceptTokenClass(EHTokPackOffset)) {
4026                 // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
4027                 if (! acceptTokenClass(EHTokLeftParen)) {
4028                     expected("(");
4029                     return false;
4030                 }
4031                 HlslToken locationToken;
4032                 if (! acceptIdentifier(locationToken)) {
4033                     expected("c[subcomponent][.component]");
4034                     return false;
4035                 }
4036                 HlslToken componentToken;
4037                 if (acceptTokenClass(EHTokDot)) {
4038                     if (! acceptIdentifier(componentToken)) {
4039                         expected("component");
4040                         return false;
4041                     }
4042                 }
4043                 if (! acceptTokenClass(EHTokRightParen)) {
4044                     expected(")");
4045                     break;
4046                 }
4047                 parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
4048             } else if (! acceptIdentifier(idToken)) {
4049                 expected("layout, semantic, packoffset, or register");
4050                 return false;
4051             } else if (*idToken.string == "register") {
4052                 // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
4053                 // LEFT_PAREN
4054                 if (! acceptTokenClass(EHTokLeftParen)) {
4055                     expected("(");
4056                     return false;
4057                 }
4058                 HlslToken registerDesc;  // for Type#
4059                 HlslToken profile;
4060                 if (! acceptIdentifier(registerDesc)) {
4061                     expected("register number description");
4062                     return false;
4063                 }
4064                 if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
4065                                                        acceptTokenClass(EHTokComma)) {
4066                     // Then we didn't really see the registerDesc yet, it was
4067                     // actually the profile.  Adjust...
4068                     profile = registerDesc;
4069                     if (! acceptIdentifier(registerDesc)) {
4070                         expected("register number description");
4071                         return false;
4072                     }
4073                 }
4074                 int subComponent = 0;
4075                 if (acceptTokenClass(EHTokLeftBracket)) {
4076                     // LEFT_BRACKET subcomponent RIGHT_BRACKET
4077                     if (! peekTokenClass(EHTokIntConstant)) {
4078                         expected("literal integer");
4079                         return false;
4080                     }
4081                     subComponent = token.i;
4082                     advanceToken();
4083                     if (! acceptTokenClass(EHTokRightBracket)) {
4084                         expected("]");
4085                         break;
4086                     }
4087                 }
4088                 // (COMMA SPACEN)opt
4089                 HlslToken spaceDesc;
4090                 if (acceptTokenClass(EHTokComma)) {
4091                     if (! acceptIdentifier(spaceDesc)) {
4092                         expected ("space identifier");
4093                         return false;
4094                     }
4095                 }
4096                 // RIGHT_PAREN
4097                 if (! acceptTokenClass(EHTokRightParen)) {
4098                     expected(")");
4099                     break;
4100                 }
4101                 parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
4102             } else {
4103                 // semantic, in idToken.string
4104                 TString semanticUpperCase = *idToken.string;
4105                 std::transform(semanticUpperCase.begin(), semanticUpperCase.end(), semanticUpperCase.begin(), ::toupper);
4106                 parseContext.handleSemantic(idToken.loc, qualifier, mapSemantic(semanticUpperCase.c_str()), semanticUpperCase);
4107             }
4108         } else if (peekTokenClass(EHTokLeftAngle)) {
4109             found = true;
4110             acceptAnnotations(qualifier);
4111         } else
4112             break;
4113 
4114     } while (true);
4115 
4116     return found;
4117 }
4118 
4119 //
4120 // Get the stream of tokens from the scanner, but skip all syntactic/semantic
4121 // processing.
4122 //
captureBlockTokens(TVector<HlslToken> & tokens)4123 bool HlslGrammar::captureBlockTokens(TVector<HlslToken>& tokens)
4124 {
4125     if (! peekTokenClass(EHTokLeftBrace))
4126         return false;
4127 
4128     int braceCount = 0;
4129 
4130     do {
4131         switch (peek()) {
4132         case EHTokLeftBrace:
4133             ++braceCount;
4134             break;
4135         case EHTokRightBrace:
4136             --braceCount;
4137             break;
4138         case EHTokNone:
4139             // End of input before balance { } is bad...
4140             return false;
4141         default:
4142             break;
4143         }
4144 
4145         tokens.push_back(token);
4146         advanceToken();
4147     } while (braceCount > 0);
4148 
4149     return true;
4150 }
4151 
4152 // Return a string for just the types that can also be declared as an identifier.
getTypeString(EHlslTokenClass tokenClass) const4153 const char* HlslGrammar::getTypeString(EHlslTokenClass tokenClass) const
4154 {
4155     switch (tokenClass) {
4156     case EHTokSample:     return "sample";
4157     case EHTokHalf:       return "half";
4158     case EHTokHalf1x1:    return "half1x1";
4159     case EHTokHalf1x2:    return "half1x2";
4160     case EHTokHalf1x3:    return "half1x3";
4161     case EHTokHalf1x4:    return "half1x4";
4162     case EHTokHalf2x1:    return "half2x1";
4163     case EHTokHalf2x2:    return "half2x2";
4164     case EHTokHalf2x3:    return "half2x3";
4165     case EHTokHalf2x4:    return "half2x4";
4166     case EHTokHalf3x1:    return "half3x1";
4167     case EHTokHalf3x2:    return "half3x2";
4168     case EHTokHalf3x3:    return "half3x3";
4169     case EHTokHalf3x4:    return "half3x4";
4170     case EHTokHalf4x1:    return "half4x1";
4171     case EHTokHalf4x2:    return "half4x2";
4172     case EHTokHalf4x3:    return "half4x3";
4173     case EHTokHalf4x4:    return "half4x4";
4174     case EHTokBool:       return "bool";
4175     case EHTokFloat:      return "float";
4176     case EHTokDouble:     return "double";
4177     case EHTokInt:        return "int";
4178     case EHTokUint:       return "uint";
4179     case EHTokMin16float: return "min16float";
4180     case EHTokMin10float: return "min10float";
4181     case EHTokMin16int:   return "min16int";
4182     case EHTokMin12int:   return "min12int";
4183     case EHTokConstantBuffer: return "ConstantBuffer";
4184     case EHTokLayout:     return "layout";
4185     default:
4186         return nullptr;
4187     }
4188 }
4189 
4190 } // end namespace glslang
4191