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