Home | History | Annotate | Download | only in MachineIndependent
      1 //
      2 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
      3 // Copyright (C) 2013 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 3Dlabs Inc. Ltd. 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 // GLSL scanning, leveraging the scanning done by the preprocessor.
     39 //
     40 
     41 #include <cstring>
     42 #include <unordered_map>
     43 #include <unordered_set>
     44 
     45 #include "../Include/Types.h"
     46 #include "SymbolTable.h"
     47 #include "ParseHelper.h"
     48 #include "glslang_tab.cpp.h"
     49 #include "ScanContext.h"
     50 #include "Scan.h"
     51 
     52 // preprocessor includes
     53 #include "preprocessor/PpContext.h"
     54 #include "preprocessor/PpTokens.h"
     55 
     56 // Required to avoid missing prototype warnings for some compilers
     57 int yylex(YYSTYPE*, glslang::TParseContext&);
     58 
     59 namespace glslang {
     60 
     61 // read past any white space
     62 void TInputScanner::consumeWhiteSpace(bool& foundNonSpaceTab)
     63 {
     64     int c = peek();  // don't accidentally consume anything other than whitespace
     65     while (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
     66         if (c == '\r' || c == '\n')
     67             foundNonSpaceTab = true;
     68         get();
     69         c = peek();
     70     }
     71 }
     72 
     73 // return true if a comment was actually consumed
     74 bool TInputScanner::consumeComment()
     75 {
     76     if (peek() != '/')
     77         return false;
     78 
     79     get();  // consume the '/'
     80     int c = peek();
     81     if (c == '/') {
     82 
     83         // a '//' style comment
     84         get();  // consume the second '/'
     85         c = get();
     86         do {
     87             while (c != EndOfInput && c != '\\' && c != '\r' && c != '\n')
     88                 c = get();
     89 
     90             if (c == EndOfInput || c == '\r' || c == '\n') {
     91                 while (c == '\r' || c == '\n')
     92                     c = get();
     93 
     94                 // we reached the end of the comment
     95                 break;
     96             } else {
     97                 // it's a '\', so we need to keep going, after skipping what's escaped
     98 
     99                 // read the skipped character
    100                 c = get();
    101 
    102                 // if it's a two-character newline, skip both characters
    103                 if (c == '\r' && peek() == '\n')
    104                     get();
    105                 c = get();
    106             }
    107         } while (true);
    108 
    109         // put back the last non-comment character
    110         if (c != EndOfInput)
    111             unget();
    112 
    113         return true;
    114     } else if (c == '*') {
    115 
    116         // a '/*' style comment
    117         get();  // consume the '*'
    118         c = get();
    119         do {
    120             while (c != EndOfInput && c != '*')
    121                 c = get();
    122             if (c == '*') {
    123                 c = get();
    124                 if (c == '/')
    125                     break;  // end of comment
    126                 // not end of comment
    127             } else // end of input
    128                 break;
    129         } while (true);
    130 
    131         return true;
    132     } else {
    133         // it's not a comment, put the '/' back
    134         unget();
    135 
    136         return false;
    137     }
    138 }
    139 
    140 // skip whitespace, then skip a comment, rinse, repeat
    141 void TInputScanner::consumeWhitespaceComment(bool& foundNonSpaceTab)
    142 {
    143     do {
    144         consumeWhiteSpace(foundNonSpaceTab);
    145 
    146         // if not starting a comment now, then done
    147         int c = peek();
    148         if (c != '/' || c == EndOfInput)
    149             return;
    150 
    151         // skip potential comment
    152         foundNonSpaceTab = true;
    153         if (! consumeComment())
    154             return;
    155 
    156     } while (true);
    157 }
    158 
    159 // Returns true if there was non-white space (e.g., a comment, newline) before the #version
    160 // or no #version was found; otherwise, returns false.  There is no error case, it always
    161 // succeeds, but will leave version == 0 if no #version was found.
    162 //
    163 // Sets notFirstToken based on whether tokens (beyond white space and comments)
    164 // appeared before the #version.
    165 //
    166 // N.B. does not attempt to leave input in any particular known state.  The assumption
    167 // is that scanning will start anew, following the rules for the chosen version/profile,
    168 // and with a corresponding parsing context.
    169 //
    170 bool TInputScanner::scanVersion(int& version, EProfile& profile, bool& notFirstToken)
    171 {
    172     // This function doesn't have to get all the semantics correct,
    173     // just find the #version if there is a correct one present.
    174     // The preprocessor will have the responsibility of getting all the semantics right.
    175 
    176     bool versionNotFirst = false;  // means not first WRT comments and white space, nothing more
    177     notFirstToken = false;         // means not first WRT to real tokens
    178     version = 0;                   // means not found
    179     profile = ENoProfile;
    180 
    181     bool foundNonSpaceTab = false;
    182     bool lookingInMiddle = false;
    183     int c;
    184     do {
    185         if (lookingInMiddle) {
    186             notFirstToken = true;
    187             // make forward progress by finishing off the current line plus extra new lines
    188             if (peek() == '\n' || peek() == '\r') {
    189                 while (peek() == '\n' || peek() == '\r')
    190                     get();
    191             } else
    192                 do {
    193                     c = get();
    194                 } while (c != EndOfInput && c != '\n' && c != '\r');
    195                 while (peek() == '\n' || peek() == '\r')
    196                     get();
    197                 if (peek() == EndOfInput)
    198                     return true;
    199         }
    200         lookingInMiddle = true;
    201 
    202         // Nominal start, skipping the desktop allowed comments and white space, but tracking if
    203         // something else was found for ES:
    204         consumeWhitespaceComment(foundNonSpaceTab);
    205         if (foundNonSpaceTab)
    206             versionNotFirst = true;
    207 
    208         // "#"
    209         if (get() != '#') {
    210             versionNotFirst = true;
    211             continue;
    212         }
    213 
    214         // whitespace
    215         do {
    216             c = get();
    217         } while (c == ' ' || c == '\t');
    218 
    219         // "version"
    220         if (    c != 'v' ||
    221             get() != 'e' ||
    222             get() != 'r' ||
    223             get() != 's' ||
    224             get() != 'i' ||
    225             get() != 'o' ||
    226             get() != 'n') {
    227             versionNotFirst = true;
    228             continue;
    229         }
    230 
    231         // whitespace
    232         do {
    233             c = get();
    234         } while (c == ' ' || c == '\t');
    235 
    236         // version number
    237         while (c >= '0' && c <= '9') {
    238             version = 10 * version + (c - '0');
    239             c = get();
    240         }
    241         if (version == 0) {
    242             versionNotFirst = true;
    243             continue;
    244         }
    245 
    246         // whitespace
    247         while (c == ' ' || c == '\t')
    248             c = get();
    249 
    250         // profile
    251         const int maxProfileLength = 13;  // not including any 0
    252         char profileString[maxProfileLength];
    253         int profileLength;
    254         for (profileLength = 0; profileLength < maxProfileLength; ++profileLength) {
    255             if (c == EndOfInput || c == ' ' || c == '\t' || c == '\n' || c == '\r')
    256                 break;
    257             profileString[profileLength] = (char)c;
    258             c = get();
    259         }
    260         if (c != EndOfInput && c != ' ' && c != '\t' && c != '\n' && c != '\r') {
    261             versionNotFirst = true;
    262             continue;
    263         }
    264 
    265         if (profileLength == 2 && strncmp(profileString, "es", profileLength) == 0)
    266             profile = EEsProfile;
    267         else if (profileLength == 4 && strncmp(profileString, "core", profileLength) == 0)
    268             profile = ECoreProfile;
    269         else if (profileLength == 13 && strncmp(profileString, "compatibility", profileLength) == 0)
    270             profile = ECompatibilityProfile;
    271 
    272         return versionNotFirst;
    273     } while (true);
    274 }
    275 
    276 // Fill this in when doing glslang-level scanning, to hand back to the parser.
    277 class TParserToken {
    278 public:
    279     explicit TParserToken(YYSTYPE& b) : sType(b) { }
    280 
    281     YYSTYPE& sType;
    282 protected:
    283     TParserToken(TParserToken&);
    284     TParserToken& operator=(TParserToken&);
    285 };
    286 
    287 } // end namespace glslang
    288 
    289 // This is the function the glslang parser (i.e., bison) calls to get its next token
    290 int yylex(YYSTYPE* glslangTokenDesc, glslang::TParseContext& parseContext)
    291 {
    292     glslang::TParserToken token(*glslangTokenDesc);
    293 
    294     return parseContext.getScanContext()->tokenize(parseContext.getPpContext(), token);
    295 }
    296 
    297 namespace {
    298 
    299 struct str_eq
    300 {
    301     bool operator()(const char* lhs, const char* rhs) const
    302     {
    303         return strcmp(lhs, rhs) == 0;
    304     }
    305 };
    306 
    307 struct str_hash
    308 {
    309     size_t operator()(const char* str) const
    310     {
    311         // djb2
    312         unsigned long hash = 5381;
    313         int c;
    314 
    315         while ((c = *str++) != 0)
    316             hash = ((hash << 5) + hash) + c;
    317 
    318         return hash;
    319     }
    320 };
    321 
    322 // A single global usable by all threads, by all versions, by all languages.
    323 // After a single process-level initialization, this is read only and thread safe
    324 std::unordered_map<const char*, int, str_hash, str_eq>* KeywordMap = nullptr;
    325 std::unordered_set<const char*, str_hash, str_eq>* ReservedSet = nullptr;
    326 
    327 };
    328 
    329 namespace glslang {
    330 
    331 void TScanContext::fillInKeywordMap()
    332 {
    333     if (KeywordMap != nullptr) {
    334         // this is really an error, as this should called only once per process
    335         // but, the only risk is if two threads called simultaneously
    336         return;
    337     }
    338     KeywordMap = new std::unordered_map<const char*, int, str_hash, str_eq>;
    339 
    340     (*KeywordMap)["const"] =                   CONST;
    341     (*KeywordMap)["uniform"] =                 UNIFORM;
    342     (*KeywordMap)["in"] =                      IN;
    343     (*KeywordMap)["out"] =                     OUT;
    344     (*KeywordMap)["inout"] =                   INOUT;
    345     (*KeywordMap)["struct"] =                  STRUCT;
    346     (*KeywordMap)["break"] =                   BREAK;
    347     (*KeywordMap)["continue"] =                CONTINUE;
    348     (*KeywordMap)["do"] =                      DO;
    349     (*KeywordMap)["for"] =                     FOR;
    350     (*KeywordMap)["while"] =                   WHILE;
    351     (*KeywordMap)["switch"] =                  SWITCH;
    352     (*KeywordMap)["case"] =                    CASE;
    353     (*KeywordMap)["default"] =                 DEFAULT;
    354     (*KeywordMap)["if"] =                      IF;
    355     (*KeywordMap)["else"] =                    ELSE;
    356     (*KeywordMap)["discard"] =                 DISCARD;
    357     (*KeywordMap)["return"] =                  RETURN;
    358     (*KeywordMap)["void"] =                    VOID;
    359     (*KeywordMap)["bool"] =                    BOOL;
    360     (*KeywordMap)["float"] =                   FLOAT;
    361     (*KeywordMap)["int"] =                     INT;
    362     (*KeywordMap)["bvec2"] =                   BVEC2;
    363     (*KeywordMap)["bvec3"] =                   BVEC3;
    364     (*KeywordMap)["bvec4"] =                   BVEC4;
    365     (*KeywordMap)["vec2"] =                    VEC2;
    366     (*KeywordMap)["vec3"] =                    VEC3;
    367     (*KeywordMap)["vec4"] =                    VEC4;
    368     (*KeywordMap)["ivec2"] =                   IVEC2;
    369     (*KeywordMap)["ivec3"] =                   IVEC3;
    370     (*KeywordMap)["ivec4"] =                   IVEC4;
    371     (*KeywordMap)["mat2"] =                    MAT2;
    372     (*KeywordMap)["mat3"] =                    MAT3;
    373     (*KeywordMap)["mat4"] =                    MAT4;
    374     (*KeywordMap)["true"] =                    BOOLCONSTANT;
    375     (*KeywordMap)["false"] =                   BOOLCONSTANT;
    376     (*KeywordMap)["attribute"] =               ATTRIBUTE;
    377     (*KeywordMap)["varying"] =                 VARYING;
    378     (*KeywordMap)["buffer"] =                  BUFFER;
    379     (*KeywordMap)["coherent"] =                COHERENT;
    380     (*KeywordMap)["restrict"] =                RESTRICT;
    381     (*KeywordMap)["readonly"] =                READONLY;
    382     (*KeywordMap)["writeonly"] =               WRITEONLY;
    383     (*KeywordMap)["atomic_uint"] =             ATOMIC_UINT;
    384     (*KeywordMap)["volatile"] =                VOLATILE;
    385     (*KeywordMap)["layout"] =                  LAYOUT;
    386     (*KeywordMap)["shared"] =                  SHARED;
    387     (*KeywordMap)["patch"] =                   PATCH;
    388     (*KeywordMap)["sample"] =                  SAMPLE;
    389     (*KeywordMap)["subroutine"] =              SUBROUTINE;
    390     (*KeywordMap)["highp"] =                   HIGH_PRECISION;
    391     (*KeywordMap)["mediump"] =                 MEDIUM_PRECISION;
    392     (*KeywordMap)["lowp"] =                    LOW_PRECISION;
    393     (*KeywordMap)["precision"] =               PRECISION;
    394     (*KeywordMap)["mat2x2"] =                  MAT2X2;
    395     (*KeywordMap)["mat2x3"] =                  MAT2X3;
    396     (*KeywordMap)["mat2x4"] =                  MAT2X4;
    397     (*KeywordMap)["mat3x2"] =                  MAT3X2;
    398     (*KeywordMap)["mat3x3"] =                  MAT3X3;
    399     (*KeywordMap)["mat3x4"] =                  MAT3X4;
    400     (*KeywordMap)["mat4x2"] =                  MAT4X2;
    401     (*KeywordMap)["mat4x3"] =                  MAT4X3;
    402     (*KeywordMap)["mat4x4"] =                  MAT4X4;
    403     (*KeywordMap)["dmat2"] =                   DMAT2;
    404     (*KeywordMap)["dmat3"] =                   DMAT3;
    405     (*KeywordMap)["dmat4"] =                   DMAT4;
    406     (*KeywordMap)["dmat2x2"] =                 DMAT2X2;
    407     (*KeywordMap)["dmat2x3"] =                 DMAT2X3;
    408     (*KeywordMap)["dmat2x4"] =                 DMAT2X4;
    409     (*KeywordMap)["dmat3x2"] =                 DMAT3X2;
    410     (*KeywordMap)["dmat3x3"] =                 DMAT3X3;
    411     (*KeywordMap)["dmat3x4"] =                 DMAT3X4;
    412     (*KeywordMap)["dmat4x2"] =                 DMAT4X2;
    413     (*KeywordMap)["dmat4x3"] =                 DMAT4X3;
    414     (*KeywordMap)["dmat4x4"] =                 DMAT4X4;
    415     (*KeywordMap)["image1D"] =                 IMAGE1D;
    416     (*KeywordMap)["iimage1D"] =                IIMAGE1D;
    417     (*KeywordMap)["uimage1D"] =                UIMAGE1D;
    418     (*KeywordMap)["image2D"] =                 IMAGE2D;
    419     (*KeywordMap)["iimage2D"] =                IIMAGE2D;
    420     (*KeywordMap)["uimage2D"] =                UIMAGE2D;
    421     (*KeywordMap)["image3D"] =                 IMAGE3D;
    422     (*KeywordMap)["iimage3D"] =                IIMAGE3D;
    423     (*KeywordMap)["uimage3D"] =                UIMAGE3D;
    424     (*KeywordMap)["image2DRect"] =             IMAGE2DRECT;
    425     (*KeywordMap)["iimage2DRect"] =            IIMAGE2DRECT;
    426     (*KeywordMap)["uimage2DRect"] =            UIMAGE2DRECT;
    427     (*KeywordMap)["imageCube"] =               IMAGECUBE;
    428     (*KeywordMap)["iimageCube"] =              IIMAGECUBE;
    429     (*KeywordMap)["uimageCube"] =              UIMAGECUBE;
    430     (*KeywordMap)["imageBuffer"] =             IMAGEBUFFER;
    431     (*KeywordMap)["iimageBuffer"] =            IIMAGEBUFFER;
    432     (*KeywordMap)["uimageBuffer"] =            UIMAGEBUFFER;
    433     (*KeywordMap)["image1DArray"] =            IMAGE1DARRAY;
    434     (*KeywordMap)["iimage1DArray"] =           IIMAGE1DARRAY;
    435     (*KeywordMap)["uimage1DArray"] =           UIMAGE1DARRAY;
    436     (*KeywordMap)["image2DArray"] =            IMAGE2DARRAY;
    437     (*KeywordMap)["iimage2DArray"] =           IIMAGE2DARRAY;
    438     (*KeywordMap)["uimage2DArray"] =           UIMAGE2DARRAY;
    439     (*KeywordMap)["imageCubeArray"] =          IMAGECUBEARRAY;
    440     (*KeywordMap)["iimageCubeArray"] =         IIMAGECUBEARRAY;
    441     (*KeywordMap)["uimageCubeArray"] =         UIMAGECUBEARRAY;
    442     (*KeywordMap)["image2DMS"] =               IMAGE2DMS;
    443     (*KeywordMap)["iimage2DMS"] =              IIMAGE2DMS;
    444     (*KeywordMap)["uimage2DMS"] =              UIMAGE2DMS;
    445     (*KeywordMap)["image2DMSArray"] =          IMAGE2DMSARRAY;
    446     (*KeywordMap)["iimage2DMSArray"] =         IIMAGE2DMSARRAY;
    447     (*KeywordMap)["uimage2DMSArray"] =         UIMAGE2DMSARRAY;
    448     (*KeywordMap)["double"] =                  DOUBLE;
    449     (*KeywordMap)["dvec2"] =                   DVEC2;
    450     (*KeywordMap)["dvec3"] =                   DVEC3;
    451     (*KeywordMap)["dvec4"] =                   DVEC4;
    452     (*KeywordMap)["uint"] =                    UINT;
    453     (*KeywordMap)["uvec2"] =                   UVEC2;
    454     (*KeywordMap)["uvec3"] =                   UVEC3;
    455     (*KeywordMap)["uvec4"] =                   UVEC4;
    456 
    457     (*KeywordMap)["int64_t"] =                 INT64_T;
    458     (*KeywordMap)["uint64_t"] =                UINT64_T;
    459     (*KeywordMap)["i64vec2"] =                 I64VEC2;
    460     (*KeywordMap)["i64vec3"] =                 I64VEC3;
    461     (*KeywordMap)["i64vec4"] =                 I64VEC4;
    462     (*KeywordMap)["u64vec2"] =                 U64VEC2;
    463     (*KeywordMap)["u64vec3"] =                 U64VEC3;
    464     (*KeywordMap)["u64vec4"] =                 U64VEC4;
    465 
    466 #ifdef AMD_EXTENSIONS
    467     (*KeywordMap)["int16_t"] =                 INT16_T;
    468     (*KeywordMap)["uint16_t"] =                UINT16_T;
    469     (*KeywordMap)["i16vec2"] =                 I16VEC2;
    470     (*KeywordMap)["i16vec3"] =                 I16VEC3;
    471     (*KeywordMap)["i16vec4"] =                 I16VEC4;
    472     (*KeywordMap)["u16vec2"] =                 U16VEC2;
    473     (*KeywordMap)["u16vec3"] =                 U16VEC3;
    474     (*KeywordMap)["u16vec4"] =                 U16VEC4;
    475 
    476     (*KeywordMap)["float16_t"] =               FLOAT16_T;
    477     (*KeywordMap)["f16vec2"] =                 F16VEC2;
    478     (*KeywordMap)["f16vec3"] =                 F16VEC3;
    479     (*KeywordMap)["f16vec4"] =                 F16VEC4;
    480     (*KeywordMap)["f16mat2"] =                 F16MAT2;
    481     (*KeywordMap)["f16mat3"] =                 F16MAT3;
    482     (*KeywordMap)["f16mat4"] =                 F16MAT4;
    483     (*KeywordMap)["f16mat2x2"] =               F16MAT2X2;
    484     (*KeywordMap)["f16mat2x3"] =               F16MAT2X3;
    485     (*KeywordMap)["f16mat2x4"] =               F16MAT2X4;
    486     (*KeywordMap)["f16mat3x2"] =               F16MAT3X2;
    487     (*KeywordMap)["f16mat3x3"] =               F16MAT3X3;
    488     (*KeywordMap)["f16mat3x4"] =               F16MAT3X4;
    489     (*KeywordMap)["f16mat4x2"] =               F16MAT4X2;
    490     (*KeywordMap)["f16mat4x3"] =               F16MAT4X3;
    491     (*KeywordMap)["f16mat4x4"] =               F16MAT4X4;
    492 #endif
    493 
    494     (*KeywordMap)["sampler2D"] =               SAMPLER2D;
    495     (*KeywordMap)["samplerCube"] =             SAMPLERCUBE;
    496     (*KeywordMap)["samplerCubeArray"] =        SAMPLERCUBEARRAY;
    497     (*KeywordMap)["samplerCubeArrayShadow"] =  SAMPLERCUBEARRAYSHADOW;
    498     (*KeywordMap)["isamplerCubeArray"] =       ISAMPLERCUBEARRAY;
    499     (*KeywordMap)["usamplerCubeArray"] =       USAMPLERCUBEARRAY;
    500     (*KeywordMap)["sampler1DArrayShadow"] =    SAMPLER1DARRAYSHADOW;
    501     (*KeywordMap)["isampler1DArray"] =         ISAMPLER1DARRAY;
    502     (*KeywordMap)["usampler1D"] =              USAMPLER1D;
    503     (*KeywordMap)["isampler1D"] =              ISAMPLER1D;
    504     (*KeywordMap)["usampler1DArray"] =         USAMPLER1DARRAY;
    505     (*KeywordMap)["samplerBuffer"] =           SAMPLERBUFFER;
    506     (*KeywordMap)["samplerCubeShadow"] =       SAMPLERCUBESHADOW;
    507     (*KeywordMap)["sampler2DArray"] =          SAMPLER2DARRAY;
    508     (*KeywordMap)["sampler2DArrayShadow"] =    SAMPLER2DARRAYSHADOW;
    509     (*KeywordMap)["isampler2D"] =              ISAMPLER2D;
    510     (*KeywordMap)["isampler3D"] =              ISAMPLER3D;
    511     (*KeywordMap)["isamplerCube"] =            ISAMPLERCUBE;
    512     (*KeywordMap)["isampler2DArray"] =         ISAMPLER2DARRAY;
    513     (*KeywordMap)["usampler2D"] =              USAMPLER2D;
    514     (*KeywordMap)["usampler3D"] =              USAMPLER3D;
    515     (*KeywordMap)["usamplerCube"] =            USAMPLERCUBE;
    516     (*KeywordMap)["usampler2DArray"] =         USAMPLER2DARRAY;
    517     (*KeywordMap)["isampler2DRect"] =          ISAMPLER2DRECT;
    518     (*KeywordMap)["usampler2DRect"] =          USAMPLER2DRECT;
    519     (*KeywordMap)["isamplerBuffer"] =          ISAMPLERBUFFER;
    520     (*KeywordMap)["usamplerBuffer"] =          USAMPLERBUFFER;
    521     (*KeywordMap)["sampler2DMS"] =             SAMPLER2DMS;
    522     (*KeywordMap)["isampler2DMS"] =            ISAMPLER2DMS;
    523     (*KeywordMap)["usampler2DMS"] =            USAMPLER2DMS;
    524     (*KeywordMap)["sampler2DMSArray"] =        SAMPLER2DMSARRAY;
    525     (*KeywordMap)["isampler2DMSArray"] =       ISAMPLER2DMSARRAY;
    526     (*KeywordMap)["usampler2DMSArray"] =       USAMPLER2DMSARRAY;
    527     (*KeywordMap)["sampler1D"] =               SAMPLER1D;
    528     (*KeywordMap)["sampler1DShadow"] =         SAMPLER1DSHADOW;
    529     (*KeywordMap)["sampler3D"] =               SAMPLER3D;
    530     (*KeywordMap)["sampler2DShadow"] =         SAMPLER2DSHADOW;
    531     (*KeywordMap)["sampler2DRect"] =           SAMPLER2DRECT;
    532     (*KeywordMap)["sampler2DRectShadow"] =     SAMPLER2DRECTSHADOW;
    533     (*KeywordMap)["sampler1DArray"] =          SAMPLER1DARRAY;
    534 
    535     (*KeywordMap)["samplerExternalOES"] =      SAMPLEREXTERNALOES; // GL_OES_EGL_image_external
    536 
    537     (*KeywordMap)["sampler"] =                 SAMPLER;
    538     (*KeywordMap)["samplerShadow"] =           SAMPLERSHADOW;
    539 
    540     (*KeywordMap)["texture2D"] =               TEXTURE2D;
    541     (*KeywordMap)["textureCube"] =             TEXTURECUBE;
    542     (*KeywordMap)["textureCubeArray"] =        TEXTURECUBEARRAY;
    543     (*KeywordMap)["itextureCubeArray"] =       ITEXTURECUBEARRAY;
    544     (*KeywordMap)["utextureCubeArray"] =       UTEXTURECUBEARRAY;
    545     (*KeywordMap)["itexture1DArray"] =         ITEXTURE1DARRAY;
    546     (*KeywordMap)["utexture1D"] =              UTEXTURE1D;
    547     (*KeywordMap)["itexture1D"] =              ITEXTURE1D;
    548     (*KeywordMap)["utexture1DArray"] =         UTEXTURE1DARRAY;
    549     (*KeywordMap)["textureBuffer"] =           TEXTUREBUFFER;
    550     (*KeywordMap)["texture2DArray"] =          TEXTURE2DARRAY;
    551     (*KeywordMap)["itexture2D"] =              ITEXTURE2D;
    552     (*KeywordMap)["itexture3D"] =              ITEXTURE3D;
    553     (*KeywordMap)["itextureCube"] =            ITEXTURECUBE;
    554     (*KeywordMap)["itexture2DArray"] =         ITEXTURE2DARRAY;
    555     (*KeywordMap)["utexture2D"] =              UTEXTURE2D;
    556     (*KeywordMap)["utexture3D"] =              UTEXTURE3D;
    557     (*KeywordMap)["utextureCube"] =            UTEXTURECUBE;
    558     (*KeywordMap)["utexture2DArray"] =         UTEXTURE2DARRAY;
    559     (*KeywordMap)["itexture2DRect"] =          ITEXTURE2DRECT;
    560     (*KeywordMap)["utexture2DRect"] =          UTEXTURE2DRECT;
    561     (*KeywordMap)["itextureBuffer"] =          ITEXTUREBUFFER;
    562     (*KeywordMap)["utextureBuffer"] =          UTEXTUREBUFFER;
    563     (*KeywordMap)["texture2DMS"] =             TEXTURE2DMS;
    564     (*KeywordMap)["itexture2DMS"] =            ITEXTURE2DMS;
    565     (*KeywordMap)["utexture2DMS"] =            UTEXTURE2DMS;
    566     (*KeywordMap)["texture2DMSArray"] =        TEXTURE2DMSARRAY;
    567     (*KeywordMap)["itexture2DMSArray"] =       ITEXTURE2DMSARRAY;
    568     (*KeywordMap)["utexture2DMSArray"] =       UTEXTURE2DMSARRAY;
    569     (*KeywordMap)["texture1D"] =               TEXTURE1D;
    570     (*KeywordMap)["texture3D"] =               TEXTURE3D;
    571     (*KeywordMap)["texture2DRect"] =           TEXTURE2DRECT;
    572     (*KeywordMap)["texture1DArray"] =          TEXTURE1DARRAY;
    573 
    574     (*KeywordMap)["subpassInput"] =            SUBPASSINPUT;
    575     (*KeywordMap)["subpassInputMS"] =          SUBPASSINPUTMS;
    576     (*KeywordMap)["isubpassInput"] =           ISUBPASSINPUT;
    577     (*KeywordMap)["isubpassInputMS"] =         ISUBPASSINPUTMS;
    578     (*KeywordMap)["usubpassInput"] =           USUBPASSINPUT;
    579     (*KeywordMap)["usubpassInputMS"] =         USUBPASSINPUTMS;
    580 
    581     (*KeywordMap)["noperspective"] =           NOPERSPECTIVE;
    582     (*KeywordMap)["smooth"] =                  SMOOTH;
    583     (*KeywordMap)["flat"] =                    FLAT;
    584 #ifdef AMD_EXTENSIONS
    585     (*KeywordMap)["__explicitInterpAMD"] =     __EXPLICITINTERPAMD;
    586 #endif
    587     (*KeywordMap)["centroid"] =                CENTROID;
    588     (*KeywordMap)["precise"] =                 PRECISE;
    589     (*KeywordMap)["invariant"] =               INVARIANT;
    590     (*KeywordMap)["packed"] =                  PACKED;
    591     (*KeywordMap)["resource"] =                RESOURCE;
    592     (*KeywordMap)["superp"] =                  SUPERP;
    593 
    594     ReservedSet = new std::unordered_set<const char*, str_hash, str_eq>;
    595 
    596     ReservedSet->insert("common");
    597     ReservedSet->insert("partition");
    598     ReservedSet->insert("active");
    599     ReservedSet->insert("asm");
    600     ReservedSet->insert("class");
    601     ReservedSet->insert("union");
    602     ReservedSet->insert("enum");
    603     ReservedSet->insert("typedef");
    604     ReservedSet->insert("template");
    605     ReservedSet->insert("this");
    606     ReservedSet->insert("goto");
    607     ReservedSet->insert("inline");
    608     ReservedSet->insert("noinline");
    609     ReservedSet->insert("public");
    610     ReservedSet->insert("static");
    611     ReservedSet->insert("extern");
    612     ReservedSet->insert("external");
    613     ReservedSet->insert("interface");
    614     ReservedSet->insert("long");
    615     ReservedSet->insert("short");
    616     ReservedSet->insert("half");
    617     ReservedSet->insert("fixed");
    618     ReservedSet->insert("unsigned");
    619     ReservedSet->insert("input");
    620     ReservedSet->insert("output");
    621     ReservedSet->insert("hvec2");
    622     ReservedSet->insert("hvec3");
    623     ReservedSet->insert("hvec4");
    624     ReservedSet->insert("fvec2");
    625     ReservedSet->insert("fvec3");
    626     ReservedSet->insert("fvec4");
    627     ReservedSet->insert("sampler3DRect");
    628     ReservedSet->insert("filter");
    629     ReservedSet->insert("sizeof");
    630     ReservedSet->insert("cast");
    631     ReservedSet->insert("namespace");
    632     ReservedSet->insert("using");
    633 }
    634 
    635 void TScanContext::deleteKeywordMap()
    636 {
    637     delete KeywordMap;
    638     KeywordMap = nullptr;
    639     delete ReservedSet;
    640     ReservedSet = nullptr;
    641 }
    642 
    643 // Called by yylex to get the next token.
    644 // Returning 0 implies end of input.
    645 int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
    646 {
    647     do {
    648         parserToken = &token;
    649         TPpToken ppToken;
    650         int token = pp->tokenize(ppToken);
    651         if (token == EndOfInput)
    652             return 0;
    653 
    654         tokenText = ppToken.name;
    655         loc = ppToken.loc;
    656         parserToken->sType.lex.loc = loc;
    657         switch (token) {
    658         case ';':  afterType = false;   return SEMICOLON;
    659         case ',':  afterType = false;   return COMMA;
    660         case ':':                       return COLON;
    661         case '=':  afterType = false;   return EQUAL;
    662         case '(':  afterType = false;   return LEFT_PAREN;
    663         case ')':  afterType = false;   return RIGHT_PAREN;
    664         case '.':  field = true;        return DOT;
    665         case '!':                       return BANG;
    666         case '-':                       return DASH;
    667         case '~':                       return TILDE;
    668         case '+':                       return PLUS;
    669         case '*':                       return STAR;
    670         case '/':                       return SLASH;
    671         case '%':                       return PERCENT;
    672         case '<':                       return LEFT_ANGLE;
    673         case '>':                       return RIGHT_ANGLE;
    674         case '|':                       return VERTICAL_BAR;
    675         case '^':                       return CARET;
    676         case '&':                       return AMPERSAND;
    677         case '?':                       return QUESTION;
    678         case '[':                       return LEFT_BRACKET;
    679         case ']':                       return RIGHT_BRACKET;
    680         case '{':                       return LEFT_BRACE;
    681         case '}':                       return RIGHT_BRACE;
    682         case '\\':
    683             parseContext.error(loc, "illegal use of escape character", "\\", "");
    684             break;
    685 
    686         case PPAtomAddAssign:          return ADD_ASSIGN;
    687         case PPAtomSubAssign:          return SUB_ASSIGN;
    688         case PPAtomMulAssign:          return MUL_ASSIGN;
    689         case PPAtomDivAssign:          return DIV_ASSIGN;
    690         case PPAtomModAssign:          return MOD_ASSIGN;
    691 
    692         case PpAtomRight:              return RIGHT_OP;
    693         case PpAtomLeft:               return LEFT_OP;
    694 
    695         case PpAtomRightAssign:        return RIGHT_ASSIGN;
    696         case PpAtomLeftAssign:         return LEFT_ASSIGN;
    697         case PpAtomAndAssign:          return AND_ASSIGN;
    698         case PpAtomOrAssign:           return OR_ASSIGN;
    699         case PpAtomXorAssign:          return XOR_ASSIGN;
    700 
    701         case PpAtomAnd:                return AND_OP;
    702         case PpAtomOr:                 return OR_OP;
    703         case PpAtomXor:                return XOR_OP;
    704 
    705         case PpAtomEQ:                 return EQ_OP;
    706         case PpAtomGE:                 return GE_OP;
    707         case PpAtomNE:                 return NE_OP;
    708         case PpAtomLE:                 return LE_OP;
    709 
    710         case PpAtomDecrement:          return DEC_OP;
    711         case PpAtomIncrement:          return INC_OP;
    712 
    713         case PpAtomColonColon:
    714             parseContext.error(loc, "not supported", "::", "");
    715             break;
    716 
    717         case PpAtomConstInt:           parserToken->sType.lex.i   = ppToken.ival;       return INTCONSTANT;
    718         case PpAtomConstUint:          parserToken->sType.lex.i   = ppToken.ival;       return UINTCONSTANT;
    719         case PpAtomConstInt64:         parserToken->sType.lex.i64 = ppToken.i64val;     return INT64CONSTANT;
    720         case PpAtomConstUint64:        parserToken->sType.lex.i64 = ppToken.i64val;     return UINT64CONSTANT;
    721 #ifdef AMD_EXTENSIONS
    722         case PpAtomConstInt16:         parserToken->sType.lex.i   = ppToken.ival;       return INT16CONSTANT;
    723         case PpAtomConstUint16:        parserToken->sType.lex.i   = ppToken.ival;       return UINT16CONSTANT;
    724 #endif
    725         case PpAtomConstFloat:         parserToken->sType.lex.d   = ppToken.dval;       return FLOATCONSTANT;
    726         case PpAtomConstDouble:        parserToken->sType.lex.d   = ppToken.dval;       return DOUBLECONSTANT;
    727 #ifdef AMD_EXTENSIONS
    728         case PpAtomConstFloat16:       parserToken->sType.lex.d   = ppToken.dval;       return FLOAT16CONSTANT;
    729 #endif
    730         case PpAtomIdentifier:
    731         {
    732             int token = tokenizeIdentifier();
    733             field = false;
    734             return token;
    735         }
    736 
    737         case EndOfInput:               return 0;
    738 
    739         default:
    740             char buf[2];
    741             buf[0] = (char)token;
    742             buf[1] = 0;
    743             parseContext.error(loc, "unexpected token", buf, "");
    744             break;
    745         }
    746     } while (true);
    747 }
    748 
    749 int TScanContext::tokenizeIdentifier()
    750 {
    751     if (ReservedSet->find(tokenText) != ReservedSet->end())
    752         return reservedWord();
    753 
    754     auto it = KeywordMap->find(tokenText);
    755     if (it == KeywordMap->end()) {
    756         // Should have an identifier of some sort
    757         return identifierOrType();
    758     }
    759     keyword = it->second;
    760 
    761     switch (keyword) {
    762     case CONST:
    763     case UNIFORM:
    764     case IN:
    765     case OUT:
    766     case INOUT:
    767     case STRUCT:
    768     case BREAK:
    769     case CONTINUE:
    770     case DO:
    771     case FOR:
    772     case WHILE:
    773     case IF:
    774     case ELSE:
    775     case DISCARD:
    776     case RETURN:
    777     case CASE:
    778         return keyword;
    779 
    780     case SWITCH:
    781     case DEFAULT:
    782         if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
    783             (parseContext.profile != EEsProfile && parseContext.version < 130))
    784             reservedWord();
    785         return keyword;
    786 
    787     case VOID:
    788     case BOOL:
    789     case FLOAT:
    790     case INT:
    791     case BVEC2:
    792     case BVEC3:
    793     case BVEC4:
    794     case VEC2:
    795     case VEC3:
    796     case VEC4:
    797     case IVEC2:
    798     case IVEC3:
    799     case IVEC4:
    800     case MAT2:
    801     case MAT3:
    802     case MAT4:
    803     case SAMPLER2D:
    804     case SAMPLERCUBE:
    805         afterType = true;
    806         return keyword;
    807 
    808     case BOOLCONSTANT:
    809         if (strcmp("true", tokenText) == 0)
    810             parserToken->sType.lex.b = true;
    811         else
    812             parserToken->sType.lex.b = false;
    813         return keyword;
    814 
    815     case ATTRIBUTE:
    816     case VARYING:
    817         if (parseContext.profile == EEsProfile && parseContext.version >= 300)
    818             reservedWord();
    819         return keyword;
    820 
    821     case BUFFER:
    822         if ((parseContext.profile == EEsProfile && parseContext.version < 310) ||
    823             (parseContext.profile != EEsProfile && parseContext.version < 430))
    824             return identifierOrType();
    825         return keyword;
    826 
    827     case ATOMIC_UINT:
    828         if ((parseContext.profile == EEsProfile && parseContext.version >= 310) ||
    829             parseContext.extensionTurnedOn(E_GL_ARB_shader_atomic_counters))
    830             return keyword;
    831         return es30ReservedFromGLSL(420);
    832 
    833     case COHERENT:
    834     case RESTRICT:
    835     case READONLY:
    836     case WRITEONLY:
    837         if (parseContext.profile == EEsProfile && parseContext.version >= 310)
    838             return keyword;
    839         return es30ReservedFromGLSL(parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store) ? 130 : 420);
    840 
    841     case VOLATILE:
    842         if (parseContext.profile == EEsProfile && parseContext.version >= 310)
    843             return keyword;
    844         if (! parseContext.symbolTable.atBuiltInLevel() && (parseContext.profile == EEsProfile || (parseContext.version < 420 && ! parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))))
    845             reservedWord();
    846         return keyword;
    847 
    848     case LAYOUT:
    849     {
    850         const int numLayoutExts = 2;
    851         const char* layoutExts[numLayoutExts] = { E_GL_ARB_shading_language_420pack,
    852                                                   E_GL_ARB_explicit_attrib_location };
    853         if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
    854             (parseContext.profile != EEsProfile && parseContext.version < 140 &&
    855             ! parseContext.extensionsTurnedOn(numLayoutExts, layoutExts)))
    856             return identifierOrType();
    857         return keyword;
    858     }
    859     case SHARED:
    860         if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
    861             (parseContext.profile != EEsProfile && parseContext.version < 140))
    862             return identifierOrType();
    863         return keyword;
    864 
    865     case PATCH:
    866         if (parseContext.symbolTable.atBuiltInLevel() ||
    867             (parseContext.profile == EEsProfile &&
    868              (parseContext.version >= 320 ||
    869               parseContext.extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader))) ||
    870             (parseContext.profile != EEsProfile && parseContext.extensionTurnedOn(E_GL_ARB_tessellation_shader)))
    871             return keyword;
    872 
    873         return es30ReservedFromGLSL(400);
    874 
    875     case SAMPLE:
    876         if ((parseContext.profile == EEsProfile && parseContext.version >= 320) ||
    877             parseContext.extensionsTurnedOn(1, &E_GL_OES_shader_multisample_interpolation))
    878             return keyword;
    879         return es30ReservedFromGLSL(400);
    880 
    881     case SUBROUTINE:
    882         return es30ReservedFromGLSL(400);
    883 
    884     case HIGH_PRECISION:
    885     case MEDIUM_PRECISION:
    886     case LOW_PRECISION:
    887     case PRECISION:
    888         return precisionKeyword();
    889 
    890     case MAT2X2:
    891     case MAT2X3:
    892     case MAT2X4:
    893     case MAT3X2:
    894     case MAT3X3:
    895     case MAT3X4:
    896     case MAT4X2:
    897     case MAT4X3:
    898     case MAT4X4:
    899         return matNxM();
    900 
    901     case DMAT2:
    902     case DMAT3:
    903     case DMAT4:
    904     case DMAT2X2:
    905     case DMAT2X3:
    906     case DMAT2X4:
    907     case DMAT3X2:
    908     case DMAT3X3:
    909     case DMAT3X4:
    910     case DMAT4X2:
    911     case DMAT4X3:
    912     case DMAT4X4:
    913         return dMat();
    914 
    915     case IMAGE1D:
    916     case IIMAGE1D:
    917     case UIMAGE1D:
    918     case IMAGE1DARRAY:
    919     case IIMAGE1DARRAY:
    920     case UIMAGE1DARRAY:
    921     case IMAGE2DRECT:
    922     case IIMAGE2DRECT:
    923     case UIMAGE2DRECT:
    924         afterType = true;
    925         return firstGenerationImage(false);
    926 
    927     case IMAGEBUFFER:
    928     case IIMAGEBUFFER:
    929     case UIMAGEBUFFER:
    930         afterType = true;
    931         if ((parseContext.profile == EEsProfile && parseContext.version >= 320) ||
    932             parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
    933             return keyword;
    934         return firstGenerationImage(false);
    935 
    936     case IMAGE2D:
    937     case IIMAGE2D:
    938     case UIMAGE2D:
    939     case IMAGE3D:
    940     case IIMAGE3D:
    941     case UIMAGE3D:
    942     case IMAGECUBE:
    943     case IIMAGECUBE:
    944     case UIMAGECUBE:
    945     case IMAGE2DARRAY:
    946     case IIMAGE2DARRAY:
    947     case UIMAGE2DARRAY:
    948         afterType = true;
    949         return firstGenerationImage(true);
    950 
    951     case IMAGECUBEARRAY:
    952     case IIMAGECUBEARRAY:
    953     case UIMAGECUBEARRAY:
    954         afterType = true;
    955         if ((parseContext.profile == EEsProfile && parseContext.version >= 320) ||
    956             parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
    957             return keyword;
    958         return secondGenerationImage();
    959 
    960     case IMAGE2DMS:
    961     case IIMAGE2DMS:
    962     case UIMAGE2DMS:
    963     case IMAGE2DMSARRAY:
    964     case IIMAGE2DMSARRAY:
    965     case UIMAGE2DMSARRAY:
    966         afterType = true;
    967         return secondGenerationImage();
    968 
    969     case DOUBLE:
    970     case DVEC2:
    971     case DVEC3:
    972     case DVEC4:
    973         afterType = true;
    974         if (parseContext.profile == EEsProfile || parseContext.version < 400)
    975             reservedWord();
    976         return keyword;
    977 
    978     case INT64_T:
    979     case UINT64_T:
    980     case I64VEC2:
    981     case I64VEC3:
    982     case I64VEC4:
    983     case U64VEC2:
    984     case U64VEC3:
    985     case U64VEC4:
    986         afterType = true;
    987         if (parseContext.symbolTable.atBuiltInLevel() ||
    988             (parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64) &&
    989              parseContext.profile != EEsProfile && parseContext.version >= 450))
    990             return keyword;
    991         return identifierOrType();
    992 
    993 #ifdef AMD_EXTENSIONS
    994     case INT16_T:
    995     case UINT16_T:
    996     case I16VEC2:
    997     case I16VEC3:
    998     case I16VEC4:
    999     case U16VEC2:
   1000     case U16VEC3:
   1001     case U16VEC4:
   1002         afterType = true;
   1003         if (parseContext.symbolTable.atBuiltInLevel() ||
   1004             (parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_int16) &&
   1005              parseContext.profile != EEsProfile && parseContext.version >= 450))
   1006             return keyword;
   1007         return identifierOrType();
   1008 
   1009     case FLOAT16_T:
   1010     case F16VEC2:
   1011     case F16VEC3:
   1012     case F16VEC4:
   1013     case F16MAT2:
   1014     case F16MAT3:
   1015     case F16MAT4:
   1016     case F16MAT2X2:
   1017     case F16MAT2X3:
   1018     case F16MAT2X4:
   1019     case F16MAT3X2:
   1020     case F16MAT3X3:
   1021     case F16MAT3X4:
   1022     case F16MAT4X2:
   1023     case F16MAT4X3:
   1024     case F16MAT4X4:
   1025         afterType = true;
   1026         if (parseContext.symbolTable.atBuiltInLevel() ||
   1027             (parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) &&
   1028              parseContext.profile != EEsProfile && parseContext.version >= 450))
   1029             return keyword;
   1030         return identifierOrType();
   1031 #endif
   1032 
   1033     case SAMPLERCUBEARRAY:
   1034     case SAMPLERCUBEARRAYSHADOW:
   1035     case ISAMPLERCUBEARRAY:
   1036     case USAMPLERCUBEARRAY:
   1037         afterType = true;
   1038         if ((parseContext.profile == EEsProfile && parseContext.version >= 320) ||
   1039             parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
   1040             return keyword;
   1041         if (parseContext.profile == EEsProfile || (parseContext.version < 400 && ! parseContext.extensionTurnedOn(E_GL_ARB_texture_cube_map_array)))
   1042             reservedWord();
   1043         return keyword;
   1044 
   1045     case ISAMPLER1D:
   1046     case ISAMPLER1DARRAY:
   1047     case SAMPLER1DARRAYSHADOW:
   1048     case USAMPLER1D:
   1049     case USAMPLER1DARRAY:
   1050         afterType = true;
   1051         return es30ReservedFromGLSL(130);
   1052 
   1053     case UINT:
   1054     case UVEC2:
   1055     case UVEC3:
   1056     case UVEC4:
   1057     case SAMPLERCUBESHADOW:
   1058     case SAMPLER2DARRAY:
   1059     case SAMPLER2DARRAYSHADOW:
   1060     case ISAMPLER2D:
   1061     case ISAMPLER3D:
   1062     case ISAMPLERCUBE:
   1063     case ISAMPLER2DARRAY:
   1064     case USAMPLER2D:
   1065     case USAMPLER3D:
   1066     case USAMPLERCUBE:
   1067     case USAMPLER2DARRAY:
   1068         afterType = true;
   1069         return nonreservedKeyword(300, 130);
   1070 
   1071     case ISAMPLER2DRECT:
   1072     case USAMPLER2DRECT:
   1073         afterType = true;
   1074         return es30ReservedFromGLSL(140);
   1075 
   1076     case SAMPLERBUFFER:
   1077         afterType = true;
   1078         if ((parseContext.profile == EEsProfile && parseContext.version >= 320) ||
   1079             parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
   1080             return keyword;
   1081         return es30ReservedFromGLSL(130);
   1082 
   1083     case ISAMPLERBUFFER:
   1084     case USAMPLERBUFFER:
   1085         afterType = true;
   1086         if ((parseContext.profile == EEsProfile && parseContext.version >= 320) ||
   1087             parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
   1088             return keyword;
   1089         return es30ReservedFromGLSL(140);
   1090 
   1091     case SAMPLER2DMS:
   1092     case ISAMPLER2DMS:
   1093     case USAMPLER2DMS:
   1094         afterType = true;
   1095         if (parseContext.profile == EEsProfile && parseContext.version >= 310)
   1096             return keyword;
   1097         return es30ReservedFromGLSL(150);
   1098 
   1099     case SAMPLER2DMSARRAY:
   1100     case ISAMPLER2DMSARRAY:
   1101     case USAMPLER2DMSARRAY:
   1102         afterType = true;
   1103         if ((parseContext.profile == EEsProfile && parseContext.version >= 320) ||
   1104             parseContext.extensionsTurnedOn(1, &E_GL_OES_texture_storage_multisample_2d_array))
   1105             return keyword;
   1106         return es30ReservedFromGLSL(150);
   1107 
   1108     case SAMPLER1D:
   1109     case SAMPLER1DSHADOW:
   1110         afterType = true;
   1111         if (parseContext.profile == EEsProfile)
   1112             reservedWord();
   1113         return keyword;
   1114 
   1115     case SAMPLER3D:
   1116         afterType = true;
   1117         if (parseContext.profile == EEsProfile && parseContext.version < 300) {
   1118             if (! parseContext.extensionTurnedOn(E_GL_OES_texture_3D))
   1119                 reservedWord();
   1120         }
   1121         return keyword;
   1122 
   1123     case SAMPLER2DSHADOW:
   1124         afterType = true;
   1125         if (parseContext.profile == EEsProfile && parseContext.version < 300) {
   1126             if (!parseContext.extensionTurnedOn(E_GL_EXT_shadow_samplers))
   1127                 reservedWord();
   1128         }
   1129         return keyword;
   1130 
   1131     case SAMPLER2DRECT:
   1132     case SAMPLER2DRECTSHADOW:
   1133         afterType = true;
   1134         if (parseContext.profile == EEsProfile)
   1135             reservedWord();
   1136         else if (parseContext.version < 140 && ! parseContext.symbolTable.atBuiltInLevel() && ! parseContext.extensionTurnedOn(E_GL_ARB_texture_rectangle)) {
   1137             if (parseContext.relaxedErrors())
   1138                 parseContext.requireExtensions(loc, 1, &E_GL_ARB_texture_rectangle, "texture-rectangle sampler keyword");
   1139             else
   1140                 reservedWord();
   1141         }
   1142         return keyword;
   1143 
   1144     case SAMPLER1DARRAY:
   1145         afterType = true;
   1146         if (parseContext.profile == EEsProfile && parseContext.version == 300)
   1147             reservedWord();
   1148         else if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
   1149                  (parseContext.profile != EEsProfile && parseContext.version < 130))
   1150             return identifierOrType();
   1151         return keyword;
   1152 
   1153     case SAMPLEREXTERNALOES:
   1154         afterType = true;
   1155         if (parseContext.symbolTable.atBuiltInLevel() || parseContext.extensionTurnedOn(E_GL_OES_EGL_image_external))
   1156             return keyword;
   1157         return identifierOrType();
   1158 
   1159     case TEXTURE2D:
   1160     case TEXTURECUBE:
   1161     case TEXTURECUBEARRAY:
   1162     case ITEXTURECUBEARRAY:
   1163     case UTEXTURECUBEARRAY:
   1164     case ITEXTURE1DARRAY:
   1165     case UTEXTURE1D:
   1166     case ITEXTURE1D:
   1167     case UTEXTURE1DARRAY:
   1168     case TEXTUREBUFFER:
   1169     case TEXTURE2DARRAY:
   1170     case ITEXTURE2D:
   1171     case ITEXTURE3D:
   1172     case ITEXTURECUBE:
   1173     case ITEXTURE2DARRAY:
   1174     case UTEXTURE2D:
   1175     case UTEXTURE3D:
   1176     case UTEXTURECUBE:
   1177     case UTEXTURE2DARRAY:
   1178     case ITEXTURE2DRECT:
   1179     case UTEXTURE2DRECT:
   1180     case ITEXTUREBUFFER:
   1181     case UTEXTUREBUFFER:
   1182     case TEXTURE2DMS:
   1183     case ITEXTURE2DMS:
   1184     case UTEXTURE2DMS:
   1185     case TEXTURE2DMSARRAY:
   1186     case ITEXTURE2DMSARRAY:
   1187     case UTEXTURE2DMSARRAY:
   1188     case TEXTURE1D:
   1189     case TEXTURE3D:
   1190     case TEXTURE2DRECT:
   1191     case TEXTURE1DARRAY:
   1192     case SAMPLER:
   1193     case SAMPLERSHADOW:
   1194         if (parseContext.spvVersion.vulkan >= 100)
   1195             return keyword;
   1196         else
   1197             return identifierOrType();
   1198 
   1199     case SUBPASSINPUT:
   1200     case SUBPASSINPUTMS:
   1201     case ISUBPASSINPUT:
   1202     case ISUBPASSINPUTMS:
   1203     case USUBPASSINPUT:
   1204     case USUBPASSINPUTMS:
   1205         if (parseContext.spvVersion.vulkan >= 100)
   1206             return keyword;
   1207         else
   1208             return identifierOrType();
   1209 
   1210     case NOPERSPECTIVE:
   1211         return es30ReservedFromGLSL(130);
   1212 
   1213     case SMOOTH:
   1214         if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
   1215             (parseContext.profile != EEsProfile && parseContext.version < 130))
   1216             return identifierOrType();
   1217         return keyword;
   1218 
   1219 #ifdef AMD_EXTENSIONS
   1220     case __EXPLICITINTERPAMD:
   1221         if (parseContext.profile != EEsProfile && parseContext.version >= 450 &&
   1222             parseContext.extensionTurnedOn(E_GL_AMD_shader_explicit_vertex_parameter))
   1223             return keyword;
   1224         return identifierOrType();
   1225 #endif
   1226 
   1227     case FLAT:
   1228         if (parseContext.profile == EEsProfile && parseContext.version < 300)
   1229             reservedWord();
   1230         else if (parseContext.profile != EEsProfile && parseContext.version < 130)
   1231             return identifierOrType();
   1232         return keyword;
   1233 
   1234     case CENTROID:
   1235         if (parseContext.version < 120)
   1236             return identifierOrType();
   1237         return keyword;
   1238 
   1239     case PRECISE:
   1240         if ((parseContext.profile == EEsProfile &&
   1241              (parseContext.version >= 320 || parseContext.extensionsTurnedOn(Num_AEP_gpu_shader5, AEP_gpu_shader5))) ||
   1242             (parseContext.profile != EEsProfile && parseContext.version >= 400))
   1243             return keyword;
   1244         if (parseContext.profile == EEsProfile && parseContext.version == 310) {
   1245             reservedWord();
   1246             return keyword;
   1247         }
   1248         return identifierOrType();
   1249 
   1250     case INVARIANT:
   1251         if (parseContext.profile != EEsProfile && parseContext.version < 120)
   1252             return identifierOrType();
   1253         return keyword;
   1254 
   1255     case PACKED:
   1256         if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
   1257             (parseContext.profile != EEsProfile && parseContext.version < 330))
   1258             return reservedWord();
   1259         return identifierOrType();
   1260 
   1261     case RESOURCE:
   1262     {
   1263         bool reserved = (parseContext.profile == EEsProfile && parseContext.version >= 300) ||
   1264                         (parseContext.profile != EEsProfile && parseContext.version >= 420);
   1265         return identifierOrReserved(reserved);
   1266     }
   1267     case SUPERP:
   1268     {
   1269         bool reserved = parseContext.profile == EEsProfile || parseContext.version >= 130;
   1270         return identifierOrReserved(reserved);
   1271     }
   1272 
   1273     default:
   1274         parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc);
   1275         return 0;
   1276     }
   1277 }
   1278 
   1279 int TScanContext::identifierOrType()
   1280 {
   1281     parserToken->sType.lex.string = NewPoolTString(tokenText);
   1282     if (field)
   1283         return IDENTIFIER;
   1284 
   1285     parserToken->sType.lex.symbol = parseContext.symbolTable.find(*parserToken->sType.lex.string);
   1286     if (afterType == false && parserToken->sType.lex.symbol) {
   1287         if (const TVariable* variable = parserToken->sType.lex.symbol->getAsVariable()) {
   1288             if (variable->isUserType()) {
   1289                 afterType = true;
   1290 
   1291                 return TYPE_NAME;
   1292             }
   1293         }
   1294     }
   1295 
   1296     return IDENTIFIER;
   1297 }
   1298 
   1299 // Give an error for use of a reserved symbol.
   1300 // However, allow built-in declarations to use reserved words, to allow
   1301 // extension support before the extension is enabled.
   1302 int TScanContext::reservedWord()
   1303 {
   1304     if (! parseContext.symbolTable.atBuiltInLevel())
   1305         parseContext.error(loc, "Reserved word.", tokenText, "", "");
   1306 
   1307     return 0;
   1308 }
   1309 
   1310 int TScanContext::identifierOrReserved(bool reserved)
   1311 {
   1312     if (reserved) {
   1313         reservedWord();
   1314 
   1315         return 0;
   1316     }
   1317 
   1318     if (parseContext.forwardCompatible)
   1319         parseContext.warn(loc, "using future reserved keyword", tokenText, "");
   1320 
   1321     return identifierOrType();
   1322 }
   1323 
   1324 // For keywords that suddenly showed up on non-ES (not previously reserved)
   1325 // but then got reserved by ES 3.0.
   1326 int TScanContext::es30ReservedFromGLSL(int version)
   1327 {
   1328     if (parseContext.symbolTable.atBuiltInLevel())
   1329         return keyword;
   1330 
   1331     if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
   1332         (parseContext.profile != EEsProfile && parseContext.version < version)) {
   1333             if (parseContext.forwardCompatible)
   1334                 parseContext.warn(loc, "future reserved word in ES 300 and keyword in GLSL", tokenText, "");
   1335 
   1336             return identifierOrType();
   1337     } else if (parseContext.profile == EEsProfile && parseContext.version >= 300)
   1338         reservedWord();
   1339 
   1340     return keyword;
   1341 }
   1342 
   1343 // For a keyword that was never reserved, until it suddenly
   1344 // showed up, both in an es version and a non-ES version.
   1345 int TScanContext::nonreservedKeyword(int esVersion, int nonEsVersion)
   1346 {
   1347     if ((parseContext.profile == EEsProfile && parseContext.version < esVersion) ||
   1348         (parseContext.profile != EEsProfile && parseContext.version < nonEsVersion)) {
   1349         if (parseContext.forwardCompatible)
   1350             parseContext.warn(loc, "using future keyword", tokenText, "");
   1351 
   1352         return identifierOrType();
   1353     }
   1354 
   1355     return keyword;
   1356 }
   1357 
   1358 int TScanContext::precisionKeyword()
   1359 {
   1360     if (parseContext.profile == EEsProfile || parseContext.version >= 130)
   1361         return keyword;
   1362 
   1363     if (parseContext.forwardCompatible)
   1364         parseContext.warn(loc, "using ES precision qualifier keyword", tokenText, "");
   1365 
   1366     return identifierOrType();
   1367 }
   1368 
   1369 int TScanContext::matNxM()
   1370 {
   1371     afterType = true;
   1372 
   1373     if (parseContext.version > 110)
   1374         return keyword;
   1375 
   1376     if (parseContext.forwardCompatible)
   1377         parseContext.warn(loc, "using future non-square matrix type keyword", tokenText, "");
   1378 
   1379     return identifierOrType();
   1380 }
   1381 
   1382 int TScanContext::dMat()
   1383 {
   1384     afterType = true;
   1385 
   1386     if (parseContext.profile == EEsProfile && parseContext.version >= 300) {
   1387         reservedWord();
   1388 
   1389         return keyword;
   1390     }
   1391 
   1392     if (parseContext.profile != EEsProfile && parseContext.version >= 400)
   1393         return keyword;
   1394 
   1395     if (parseContext.forwardCompatible)
   1396         parseContext.warn(loc, "using future type keyword", tokenText, "");
   1397 
   1398     return identifierOrType();
   1399 }
   1400 
   1401 int TScanContext::firstGenerationImage(bool inEs310)
   1402 {
   1403     if (parseContext.symbolTable.atBuiltInLevel() ||
   1404         (parseContext.profile != EEsProfile && (parseContext.version >= 420 || parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))) ||
   1405         (inEs310 && parseContext.profile == EEsProfile && parseContext.version >= 310))
   1406         return keyword;
   1407 
   1408     if ((parseContext.profile == EEsProfile && parseContext.version >= 300) ||
   1409         (parseContext.profile != EEsProfile && parseContext.version >= 130)) {
   1410         reservedWord();
   1411 
   1412         return keyword;
   1413     }
   1414 
   1415     if (parseContext.forwardCompatible)
   1416         parseContext.warn(loc, "using future type keyword", tokenText, "");
   1417 
   1418     return identifierOrType();
   1419 }
   1420 
   1421 int TScanContext::secondGenerationImage()
   1422 {
   1423     if (parseContext.profile == EEsProfile && parseContext.version >= 310) {
   1424         reservedWord();
   1425         return keyword;
   1426     }
   1427 
   1428     if (parseContext.symbolTable.atBuiltInLevel() ||
   1429         (parseContext.profile != EEsProfile &&
   1430          (parseContext.version >= 420 || parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))))
   1431         return keyword;
   1432 
   1433     if (parseContext.forwardCompatible)
   1434         parseContext.warn(loc, "using future type keyword", tokenText, "");
   1435 
   1436     return identifierOrType();
   1437 }
   1438 
   1439 } // end namespace glslang
   1440