Fix #2095: correct the indentation.
[platform/upstream/glslang.git] / glslang / MachineIndependent / Scan.cpp
1 //
2 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
3 // Copyright (C) 2013 LunarG, Inc.
4 // Copyright (C) 2017 ARM Limited.
5 //
6 // All rights reserved.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions
10 // are met:
11 //
12 //    Redistributions of source code must retain the above copyright
13 //    notice, this list of conditions and the following disclaimer.
14 //
15 //    Redistributions in binary form must reproduce the above
16 //    copyright notice, this list of conditions and the following
17 //    disclaimer in the documentation and/or other materials provided
18 //    with the distribution.
19 //
20 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
21 //    contributors may be used to endorse or promote products derived
22 //    from this software without specific prior written permission.
23 //
24 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 // POSSIBILITY OF SUCH DAMAGE.
36 //
37
38 //
39 // GLSL scanning, leveraging the scanning done by the preprocessor.
40 //
41
42 #include <cstring>
43 #include <unordered_map>
44 #include <unordered_set>
45
46 #include "../Include/Types.h"
47 #include "SymbolTable.h"
48 #include "ParseHelper.h"
49 #include "attribute.h"
50 #include "glslang_tab.cpp.h"
51 #include "ScanContext.h"
52 #include "Scan.h"
53
54 // preprocessor includes
55 #include "preprocessor/PpContext.h"
56 #include "preprocessor/PpTokens.h"
57
58 // Required to avoid missing prototype warnings for some compilers
59 int yylex(YYSTYPE*, glslang::TParseContext&);
60
61 namespace glslang {
62
63 // read past any white space
64 void TInputScanner::consumeWhiteSpace(bool& foundNonSpaceTab)
65 {
66     int c = peek();  // don't accidentally consume anything other than whitespace
67     while (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
68         if (c == '\r' || c == '\n')
69             foundNonSpaceTab = true;
70         get();
71         c = peek();
72     }
73 }
74
75 // return true if a comment was actually consumed
76 bool TInputScanner::consumeComment()
77 {
78     if (peek() != '/')
79         return false;
80
81     get();  // consume the '/'
82     int c = peek();
83     if (c == '/') {
84
85         // a '//' style comment
86         get();  // consume the second '/'
87         c = get();
88         do {
89             while (c != EndOfInput && c != '\\' && c != '\r' && c != '\n')
90                 c = get();
91
92             if (c == EndOfInput || c == '\r' || c == '\n') {
93                 while (c == '\r' || c == '\n')
94                     c = get();
95
96                 // we reached the end of the comment
97                 break;
98             } else {
99                 // it's a '\', so we need to keep going, after skipping what's escaped
100
101                 // read the skipped character
102                 c = get();
103
104                 // if it's a two-character newline, skip both characters
105                 if (c == '\r' && peek() == '\n')
106                     get();
107                 c = get();
108             }
109         } while (true);
110
111         // put back the last non-comment character
112         if (c != EndOfInput)
113             unget();
114
115         return true;
116     } else if (c == '*') {
117
118         // a '/*' style comment
119         get();  // consume the '*'
120         c = get();
121         do {
122             while (c != EndOfInput && c != '*')
123                 c = get();
124             if (c == '*') {
125                 c = get();
126                 if (c == '/')
127                     break;  // end of comment
128                 // not end of comment
129             } else // end of input
130                 break;
131         } while (true);
132
133         return true;
134     } else {
135         // it's not a comment, put the '/' back
136         unget();
137
138         return false;
139     }
140 }
141
142 // skip whitespace, then skip a comment, rinse, repeat
143 void TInputScanner::consumeWhitespaceComment(bool& foundNonSpaceTab)
144 {
145     do {
146         consumeWhiteSpace(foundNonSpaceTab);
147
148         // if not starting a comment now, then done
149         int c = peek();
150         if (c != '/' || c == EndOfInput)
151             return;
152
153         // skip potential comment
154         foundNonSpaceTab = true;
155         if (! consumeComment())
156             return;
157
158     } while (true);
159 }
160
161 // Returns true if there was non-white space (e.g., a comment, newline) before the #version
162 // or no #version was found; otherwise, returns false.  There is no error case, it always
163 // succeeds, but will leave version == 0 if no #version was found.
164 //
165 // Sets notFirstToken based on whether tokens (beyond white space and comments)
166 // appeared before the #version.
167 //
168 // N.B. does not attempt to leave input in any particular known state.  The assumption
169 // is that scanning will start anew, following the rules for the chosen version/profile,
170 // and with a corresponding parsing context.
171 //
172 bool TInputScanner::scanVersion(int& version, EProfile& profile, bool& notFirstToken)
173 {
174     // This function doesn't have to get all the semantics correct,
175     // just find the #version if there is a correct one present.
176     // The preprocessor will have the responsibility of getting all the semantics right.
177
178     bool versionNotFirst = false;  // means not first WRT comments and white space, nothing more
179     notFirstToken = false;         // means not first WRT to real tokens
180     version = 0;                   // means not found
181     profile = ENoProfile;
182
183     bool foundNonSpaceTab = false;
184     bool lookingInMiddle = false;
185     int c;
186     do {
187         if (lookingInMiddle) {
188             notFirstToken = true;
189             // make forward progress by finishing off the current line plus extra new lines
190             if (peek() != '\n' && peek() != '\r') {
191                 do {
192                     c = get();
193                 } while (c != EndOfInput && c != '\n' && c != '\r');
194             }
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 #ifndef GLSLANG_WEB
326 std::unordered_set<const char*, str_hash, str_eq>* ReservedSet = nullptr;
327 #endif
328
329 };
330
331 namespace glslang {
332
333 void TScanContext::fillInKeywordMap()
334 {
335     if (KeywordMap != nullptr) {
336         // this is really an error, as this should called only once per process
337         // but, the only risk is if two threads called simultaneously
338         return;
339     }
340     KeywordMap = new std::unordered_map<const char*, int, str_hash, str_eq>;
341
342     (*KeywordMap)["const"] =                   CONST;
343     (*KeywordMap)["uniform"] =                 UNIFORM;
344     (*KeywordMap)["buffer"] =                  BUFFER;
345     (*KeywordMap)["in"] =                      IN;
346     (*KeywordMap)["out"] =                     OUT;
347     (*KeywordMap)["smooth"] =                  SMOOTH;
348     (*KeywordMap)["flat"] =                    FLAT;
349     (*KeywordMap)["centroid"] =                CENTROID;
350     (*KeywordMap)["invariant"] =               INVARIANT;
351     (*KeywordMap)["packed"] =                  PACKED;
352     (*KeywordMap)["resource"] =                RESOURCE;
353     (*KeywordMap)["inout"] =                   INOUT;
354     (*KeywordMap)["struct"] =                  STRUCT;
355     (*KeywordMap)["break"] =                   BREAK;
356     (*KeywordMap)["continue"] =                CONTINUE;
357     (*KeywordMap)["do"] =                      DO;
358     (*KeywordMap)["for"] =                     FOR;
359     (*KeywordMap)["while"] =                   WHILE;
360     (*KeywordMap)["switch"] =                  SWITCH;
361     (*KeywordMap)["case"] =                    CASE;
362     (*KeywordMap)["default"] =                 DEFAULT;
363     (*KeywordMap)["if"] =                      IF;
364     (*KeywordMap)["else"] =                    ELSE;
365     (*KeywordMap)["discard"] =                 DISCARD;
366     (*KeywordMap)["return"] =                  RETURN;
367     (*KeywordMap)["void"] =                    VOID;
368     (*KeywordMap)["bool"] =                    BOOL;
369     (*KeywordMap)["float"] =                   FLOAT;
370     (*KeywordMap)["int"] =                     INT;
371     (*KeywordMap)["bvec2"] =                   BVEC2;
372     (*KeywordMap)["bvec3"] =                   BVEC3;
373     (*KeywordMap)["bvec4"] =                   BVEC4;
374     (*KeywordMap)["vec2"] =                    VEC2;
375     (*KeywordMap)["vec3"] =                    VEC3;
376     (*KeywordMap)["vec4"] =                    VEC4;
377     (*KeywordMap)["ivec2"] =                   IVEC2;
378     (*KeywordMap)["ivec3"] =                   IVEC3;
379     (*KeywordMap)["ivec4"] =                   IVEC4;
380     (*KeywordMap)["mat2"] =                    MAT2;
381     (*KeywordMap)["mat3"] =                    MAT3;
382     (*KeywordMap)["mat4"] =                    MAT4;
383     (*KeywordMap)["true"] =                    BOOLCONSTANT;
384     (*KeywordMap)["false"] =                   BOOLCONSTANT;
385     (*KeywordMap)["layout"] =                  LAYOUT;
386     (*KeywordMap)["shared"] =                  SHARED;
387     (*KeywordMap)["highp"] =                   HIGH_PRECISION;
388     (*KeywordMap)["mediump"] =                 MEDIUM_PRECISION;
389     (*KeywordMap)["lowp"] =                    LOW_PRECISION;
390     (*KeywordMap)["superp"] =                  SUPERP;
391     (*KeywordMap)["precision"] =               PRECISION;
392     (*KeywordMap)["mat2x2"] =                  MAT2X2;
393     (*KeywordMap)["mat2x3"] =                  MAT2X3;
394     (*KeywordMap)["mat2x4"] =                  MAT2X4;
395     (*KeywordMap)["mat3x2"] =                  MAT3X2;
396     (*KeywordMap)["mat3x3"] =                  MAT3X3;
397     (*KeywordMap)["mat3x4"] =                  MAT3X4;
398     (*KeywordMap)["mat4x2"] =                  MAT4X2;
399     (*KeywordMap)["mat4x3"] =                  MAT4X3;
400     (*KeywordMap)["mat4x4"] =                  MAT4X4;
401     (*KeywordMap)["uint"] =                    UINT;
402     (*KeywordMap)["uvec2"] =                   UVEC2;
403     (*KeywordMap)["uvec3"] =                   UVEC3;
404     (*KeywordMap)["uvec4"] =                   UVEC4;
405
406 #ifndef GLSLANG_WEB
407     (*KeywordMap)["nonuniformEXT"] =           NONUNIFORM;
408     (*KeywordMap)["demote"] =                  DEMOTE;
409     (*KeywordMap)["attribute"] =               ATTRIBUTE;
410     (*KeywordMap)["varying"] =                 VARYING;
411     (*KeywordMap)["noperspective"] =           NOPERSPECTIVE;
412     (*KeywordMap)["coherent"] =                COHERENT;
413     (*KeywordMap)["devicecoherent"] =          DEVICECOHERENT;
414     (*KeywordMap)["queuefamilycoherent"] =     QUEUEFAMILYCOHERENT;
415     (*KeywordMap)["workgroupcoherent"] =       WORKGROUPCOHERENT;
416     (*KeywordMap)["subgroupcoherent"] =        SUBGROUPCOHERENT;
417     (*KeywordMap)["nonprivate"] =              NONPRIVATE;
418     (*KeywordMap)["restrict"] =                RESTRICT;
419     (*KeywordMap)["readonly"] =                READONLY;
420     (*KeywordMap)["writeonly"] =               WRITEONLY;
421     (*KeywordMap)["atomic_uint"] =             ATOMIC_UINT;
422     (*KeywordMap)["volatile"] =                VOLATILE;
423     (*KeywordMap)["patch"] =                   PATCH;
424     (*KeywordMap)["sample"] =                  SAMPLE;
425     (*KeywordMap)["subroutine"] =              SUBROUTINE;
426     (*KeywordMap)["dmat2"] =                   DMAT2;
427     (*KeywordMap)["dmat3"] =                   DMAT3;
428     (*KeywordMap)["dmat4"] =                   DMAT4;
429     (*KeywordMap)["dmat2x2"] =                 DMAT2X2;
430     (*KeywordMap)["dmat2x3"] =                 DMAT2X3;
431     (*KeywordMap)["dmat2x4"] =                 DMAT2X4;
432     (*KeywordMap)["dmat3x2"] =                 DMAT3X2;
433     (*KeywordMap)["dmat3x3"] =                 DMAT3X3;
434     (*KeywordMap)["dmat3x4"] =                 DMAT3X4;
435     (*KeywordMap)["dmat4x2"] =                 DMAT4X2;
436     (*KeywordMap)["dmat4x3"] =                 DMAT4X3;
437     (*KeywordMap)["dmat4x4"] =                 DMAT4X4;
438     (*KeywordMap)["image1D"] =                 IMAGE1D;
439     (*KeywordMap)["iimage1D"] =                IIMAGE1D;
440     (*KeywordMap)["uimage1D"] =                UIMAGE1D;
441     (*KeywordMap)["image2D"] =                 IMAGE2D;
442     (*KeywordMap)["iimage2D"] =                IIMAGE2D;
443     (*KeywordMap)["uimage2D"] =                UIMAGE2D;
444     (*KeywordMap)["image3D"] =                 IMAGE3D;
445     (*KeywordMap)["iimage3D"] =                IIMAGE3D;
446     (*KeywordMap)["uimage3D"] =                UIMAGE3D;
447     (*KeywordMap)["image2DRect"] =             IMAGE2DRECT;
448     (*KeywordMap)["iimage2DRect"] =            IIMAGE2DRECT;
449     (*KeywordMap)["uimage2DRect"] =            UIMAGE2DRECT;
450     (*KeywordMap)["imageCube"] =               IMAGECUBE;
451     (*KeywordMap)["iimageCube"] =              IIMAGECUBE;
452     (*KeywordMap)["uimageCube"] =              UIMAGECUBE;
453     (*KeywordMap)["imageBuffer"] =             IMAGEBUFFER;
454     (*KeywordMap)["iimageBuffer"] =            IIMAGEBUFFER;
455     (*KeywordMap)["uimageBuffer"] =            UIMAGEBUFFER;
456     (*KeywordMap)["image1DArray"] =            IMAGE1DARRAY;
457     (*KeywordMap)["iimage1DArray"] =           IIMAGE1DARRAY;
458     (*KeywordMap)["uimage1DArray"] =           UIMAGE1DARRAY;
459     (*KeywordMap)["image2DArray"] =            IMAGE2DARRAY;
460     (*KeywordMap)["iimage2DArray"] =           IIMAGE2DARRAY;
461     (*KeywordMap)["uimage2DArray"] =           UIMAGE2DARRAY;
462     (*KeywordMap)["imageCubeArray"] =          IMAGECUBEARRAY;
463     (*KeywordMap)["iimageCubeArray"] =         IIMAGECUBEARRAY;
464     (*KeywordMap)["uimageCubeArray"] =         UIMAGECUBEARRAY;
465     (*KeywordMap)["image2DMS"] =               IMAGE2DMS;
466     (*KeywordMap)["iimage2DMS"] =              IIMAGE2DMS;
467     (*KeywordMap)["uimage2DMS"] =              UIMAGE2DMS;
468     (*KeywordMap)["image2DMSArray"] =          IMAGE2DMSARRAY;
469     (*KeywordMap)["iimage2DMSArray"] =         IIMAGE2DMSARRAY;
470     (*KeywordMap)["uimage2DMSArray"] =         UIMAGE2DMSARRAY;
471     (*KeywordMap)["double"] =                  DOUBLE;
472     (*KeywordMap)["dvec2"] =                   DVEC2;
473     (*KeywordMap)["dvec3"] =                   DVEC3;
474     (*KeywordMap)["dvec4"] =                   DVEC4;
475     (*KeywordMap)["int64_t"] =                 INT64_T;
476     (*KeywordMap)["uint64_t"] =                UINT64_T;
477     (*KeywordMap)["i64vec2"] =                 I64VEC2;
478     (*KeywordMap)["i64vec3"] =                 I64VEC3;
479     (*KeywordMap)["i64vec4"] =                 I64VEC4;
480     (*KeywordMap)["u64vec2"] =                 U64VEC2;
481     (*KeywordMap)["u64vec3"] =                 U64VEC3;
482     (*KeywordMap)["u64vec4"] =                 U64VEC4;
483
484     // GL_EXT_shader_explicit_arithmetic_types
485     (*KeywordMap)["int8_t"] =                  INT8_T;
486     (*KeywordMap)["i8vec2"] =                  I8VEC2;
487     (*KeywordMap)["i8vec3"] =                  I8VEC3;
488     (*KeywordMap)["i8vec4"] =                  I8VEC4;
489     (*KeywordMap)["uint8_t"] =                 UINT8_T;
490     (*KeywordMap)["u8vec2"] =                  U8VEC2;
491     (*KeywordMap)["u8vec3"] =                  U8VEC3;
492     (*KeywordMap)["u8vec4"] =                  U8VEC4;
493
494     (*KeywordMap)["int16_t"] =                 INT16_T;
495     (*KeywordMap)["i16vec2"] =                 I16VEC2;
496     (*KeywordMap)["i16vec3"] =                 I16VEC3;
497     (*KeywordMap)["i16vec4"] =                 I16VEC4;
498     (*KeywordMap)["uint16_t"] =                UINT16_T;
499     (*KeywordMap)["u16vec2"] =                 U16VEC2;
500     (*KeywordMap)["u16vec3"] =                 U16VEC3;
501     (*KeywordMap)["u16vec4"] =                 U16VEC4;
502
503     (*KeywordMap)["int32_t"] =                 INT32_T;
504     (*KeywordMap)["i32vec2"] =                 I32VEC2;
505     (*KeywordMap)["i32vec3"] =                 I32VEC3;
506     (*KeywordMap)["i32vec4"] =                 I32VEC4;
507     (*KeywordMap)["uint32_t"] =                UINT32_T;
508     (*KeywordMap)["u32vec2"] =                 U32VEC2;
509     (*KeywordMap)["u32vec3"] =                 U32VEC3;
510     (*KeywordMap)["u32vec4"] =                 U32VEC4;
511
512     (*KeywordMap)["float16_t"] =               FLOAT16_T;
513     (*KeywordMap)["f16vec2"] =                 F16VEC2;
514     (*KeywordMap)["f16vec3"] =                 F16VEC3;
515     (*KeywordMap)["f16vec4"] =                 F16VEC4;
516     (*KeywordMap)["f16mat2"] =                 F16MAT2;
517     (*KeywordMap)["f16mat3"] =                 F16MAT3;
518     (*KeywordMap)["f16mat4"] =                 F16MAT4;
519     (*KeywordMap)["f16mat2x2"] =               F16MAT2X2;
520     (*KeywordMap)["f16mat2x3"] =               F16MAT2X3;
521     (*KeywordMap)["f16mat2x4"] =               F16MAT2X4;
522     (*KeywordMap)["f16mat3x2"] =               F16MAT3X2;
523     (*KeywordMap)["f16mat3x3"] =               F16MAT3X3;
524     (*KeywordMap)["f16mat3x4"] =               F16MAT3X4;
525     (*KeywordMap)["f16mat4x2"] =               F16MAT4X2;
526     (*KeywordMap)["f16mat4x3"] =               F16MAT4X3;
527     (*KeywordMap)["f16mat4x4"] =               F16MAT4X4;
528
529     (*KeywordMap)["float32_t"] =               FLOAT32_T;
530     (*KeywordMap)["f32vec2"] =                 F32VEC2;
531     (*KeywordMap)["f32vec3"] =                 F32VEC3;
532     (*KeywordMap)["f32vec4"] =                 F32VEC4;
533     (*KeywordMap)["f32mat2"] =                 F32MAT2;
534     (*KeywordMap)["f32mat3"] =                 F32MAT3;
535     (*KeywordMap)["f32mat4"] =                 F32MAT4;
536     (*KeywordMap)["f32mat2x2"] =               F32MAT2X2;
537     (*KeywordMap)["f32mat2x3"] =               F32MAT2X3;
538     (*KeywordMap)["f32mat2x4"] =               F32MAT2X4;
539     (*KeywordMap)["f32mat3x2"] =               F32MAT3X2;
540     (*KeywordMap)["f32mat3x3"] =               F32MAT3X3;
541     (*KeywordMap)["f32mat3x4"] =               F32MAT3X4;
542     (*KeywordMap)["f32mat4x2"] =               F32MAT4X2;
543     (*KeywordMap)["f32mat4x3"] =               F32MAT4X3;
544     (*KeywordMap)["f32mat4x4"] =               F32MAT4X4;
545     (*KeywordMap)["float64_t"] =               FLOAT64_T;
546     (*KeywordMap)["f64vec2"] =                 F64VEC2;
547     (*KeywordMap)["f64vec3"] =                 F64VEC3;
548     (*KeywordMap)["f64vec4"] =                 F64VEC4;
549     (*KeywordMap)["f64mat2"] =                 F64MAT2;
550     (*KeywordMap)["f64mat3"] =                 F64MAT3;
551     (*KeywordMap)["f64mat4"] =                 F64MAT4;
552     (*KeywordMap)["f64mat2x2"] =               F64MAT2X2;
553     (*KeywordMap)["f64mat2x3"] =               F64MAT2X3;
554     (*KeywordMap)["f64mat2x4"] =               F64MAT2X4;
555     (*KeywordMap)["f64mat3x2"] =               F64MAT3X2;
556     (*KeywordMap)["f64mat3x3"] =               F64MAT3X3;
557     (*KeywordMap)["f64mat3x4"] =               F64MAT3X4;
558     (*KeywordMap)["f64mat4x2"] =               F64MAT4X2;
559     (*KeywordMap)["f64mat4x3"] =               F64MAT4X3;
560     (*KeywordMap)["f64mat4x4"] =               F64MAT4X4;
561 #endif
562
563     (*KeywordMap)["sampler2D"] =               SAMPLER2D;
564     (*KeywordMap)["samplerCube"] =             SAMPLERCUBE;
565     (*KeywordMap)["samplerCubeShadow"] =       SAMPLERCUBESHADOW;
566     (*KeywordMap)["sampler2DArray"] =          SAMPLER2DARRAY;
567     (*KeywordMap)["sampler2DArrayShadow"] =    SAMPLER2DARRAYSHADOW;
568     (*KeywordMap)["isampler2D"] =              ISAMPLER2D;
569     (*KeywordMap)["isampler3D"] =              ISAMPLER3D;
570     (*KeywordMap)["isamplerCube"] =            ISAMPLERCUBE;
571     (*KeywordMap)["isampler2DArray"] =         ISAMPLER2DARRAY;
572     (*KeywordMap)["usampler2D"] =              USAMPLER2D;
573     (*KeywordMap)["usampler3D"] =              USAMPLER3D;
574     (*KeywordMap)["usamplerCube"] =            USAMPLERCUBE;
575     (*KeywordMap)["usampler2DArray"] =         USAMPLER2DARRAY;
576     (*KeywordMap)["sampler3D"] =               SAMPLER3D;
577     (*KeywordMap)["sampler2DShadow"] =         SAMPLER2DSHADOW;
578
579     (*KeywordMap)["texture2D"] =               TEXTURE2D;
580     (*KeywordMap)["textureCube"] =             TEXTURECUBE;
581     (*KeywordMap)["texture2DArray"] =          TEXTURE2DARRAY;
582     (*KeywordMap)["itexture2D"] =              ITEXTURE2D;
583     (*KeywordMap)["itexture3D"] =              ITEXTURE3D;
584     (*KeywordMap)["itextureCube"] =            ITEXTURECUBE;
585     (*KeywordMap)["itexture2DArray"] =         ITEXTURE2DARRAY;
586     (*KeywordMap)["utexture2D"] =              UTEXTURE2D;
587     (*KeywordMap)["utexture3D"] =              UTEXTURE3D;
588     (*KeywordMap)["utextureCube"] =            UTEXTURECUBE;
589     (*KeywordMap)["utexture2DArray"] =         UTEXTURE2DARRAY;
590     (*KeywordMap)["texture3D"] =               TEXTURE3D;
591
592     (*KeywordMap)["sampler"] =                 SAMPLER;
593     (*KeywordMap)["samplerShadow"] =           SAMPLERSHADOW;
594
595 #ifndef GLSLANG_WEB
596     (*KeywordMap)["textureCubeArray"] =        TEXTURECUBEARRAY;
597     (*KeywordMap)["itextureCubeArray"] =       ITEXTURECUBEARRAY;
598     (*KeywordMap)["utextureCubeArray"] =       UTEXTURECUBEARRAY;
599     (*KeywordMap)["samplerCubeArray"] =        SAMPLERCUBEARRAY;
600     (*KeywordMap)["samplerCubeArrayShadow"] =  SAMPLERCUBEARRAYSHADOW;
601     (*KeywordMap)["isamplerCubeArray"] =       ISAMPLERCUBEARRAY;
602     (*KeywordMap)["usamplerCubeArray"] =       USAMPLERCUBEARRAY;
603     (*KeywordMap)["sampler1DArrayShadow"] =    SAMPLER1DARRAYSHADOW;
604     (*KeywordMap)["isampler1DArray"] =         ISAMPLER1DARRAY;
605     (*KeywordMap)["usampler1D"] =              USAMPLER1D;
606     (*KeywordMap)["isampler1D"] =              ISAMPLER1D;
607     (*KeywordMap)["usampler1DArray"] =         USAMPLER1DARRAY;
608     (*KeywordMap)["samplerBuffer"] =           SAMPLERBUFFER;
609     (*KeywordMap)["isampler2DRect"] =          ISAMPLER2DRECT;
610     (*KeywordMap)["usampler2DRect"] =          USAMPLER2DRECT;
611     (*KeywordMap)["isamplerBuffer"] =          ISAMPLERBUFFER;
612     (*KeywordMap)["usamplerBuffer"] =          USAMPLERBUFFER;
613     (*KeywordMap)["sampler2DMS"] =             SAMPLER2DMS;
614     (*KeywordMap)["isampler2DMS"] =            ISAMPLER2DMS;
615     (*KeywordMap)["usampler2DMS"] =            USAMPLER2DMS;
616     (*KeywordMap)["sampler2DMSArray"] =        SAMPLER2DMSARRAY;
617     (*KeywordMap)["isampler2DMSArray"] =       ISAMPLER2DMSARRAY;
618     (*KeywordMap)["usampler2DMSArray"] =       USAMPLER2DMSARRAY;
619     (*KeywordMap)["sampler1D"] =               SAMPLER1D;
620     (*KeywordMap)["sampler1DShadow"] =         SAMPLER1DSHADOW;
621     (*KeywordMap)["sampler2DRect"] =           SAMPLER2DRECT;
622     (*KeywordMap)["sampler2DRectShadow"] =     SAMPLER2DRECTSHADOW;
623     (*KeywordMap)["sampler1DArray"] =          SAMPLER1DARRAY;
624
625     (*KeywordMap)["samplerExternalOES"] =      SAMPLEREXTERNALOES; // GL_OES_EGL_image_external
626
627     (*KeywordMap)["__samplerExternal2DY2YEXT"] = SAMPLEREXTERNAL2DY2YEXT; // GL_EXT_YUV_target
628
629     (*KeywordMap)["itexture1DArray"] =         ITEXTURE1DARRAY;
630     (*KeywordMap)["utexture1D"] =              UTEXTURE1D;
631     (*KeywordMap)["itexture1D"] =              ITEXTURE1D;
632     (*KeywordMap)["utexture1DArray"] =         UTEXTURE1DARRAY;
633     (*KeywordMap)["textureBuffer"] =           TEXTUREBUFFER;
634     (*KeywordMap)["itexture2DRect"] =          ITEXTURE2DRECT;
635     (*KeywordMap)["utexture2DRect"] =          UTEXTURE2DRECT;
636     (*KeywordMap)["itextureBuffer"] =          ITEXTUREBUFFER;
637     (*KeywordMap)["utextureBuffer"] =          UTEXTUREBUFFER;
638     (*KeywordMap)["texture2DMS"] =             TEXTURE2DMS;
639     (*KeywordMap)["itexture2DMS"] =            ITEXTURE2DMS;
640     (*KeywordMap)["utexture2DMS"] =            UTEXTURE2DMS;
641     (*KeywordMap)["texture2DMSArray"] =        TEXTURE2DMSARRAY;
642     (*KeywordMap)["itexture2DMSArray"] =       ITEXTURE2DMSARRAY;
643     (*KeywordMap)["utexture2DMSArray"] =       UTEXTURE2DMSARRAY;
644     (*KeywordMap)["texture1D"] =               TEXTURE1D;
645     (*KeywordMap)["texture2DRect"] =           TEXTURE2DRECT;
646     (*KeywordMap)["texture1DArray"] =          TEXTURE1DARRAY;
647
648     (*KeywordMap)["subpassInput"] =            SUBPASSINPUT;
649     (*KeywordMap)["subpassInputMS"] =          SUBPASSINPUTMS;
650     (*KeywordMap)["isubpassInput"] =           ISUBPASSINPUT;
651     (*KeywordMap)["isubpassInputMS"] =         ISUBPASSINPUTMS;
652     (*KeywordMap)["usubpassInput"] =           USUBPASSINPUT;
653     (*KeywordMap)["usubpassInputMS"] =         USUBPASSINPUTMS;
654
655     (*KeywordMap)["f16sampler1D"] =                 F16SAMPLER1D;
656     (*KeywordMap)["f16sampler2D"] =                 F16SAMPLER2D;
657     (*KeywordMap)["f16sampler3D"] =                 F16SAMPLER3D;
658     (*KeywordMap)["f16sampler2DRect"] =             F16SAMPLER2DRECT;
659     (*KeywordMap)["f16samplerCube"] =               F16SAMPLERCUBE;
660     (*KeywordMap)["f16sampler1DArray"] =            F16SAMPLER1DARRAY;
661     (*KeywordMap)["f16sampler2DArray"] =            F16SAMPLER2DARRAY;
662     (*KeywordMap)["f16samplerCubeArray"] =          F16SAMPLERCUBEARRAY;
663     (*KeywordMap)["f16samplerBuffer"] =             F16SAMPLERBUFFER;
664     (*KeywordMap)["f16sampler2DMS"] =               F16SAMPLER2DMS;
665     (*KeywordMap)["f16sampler2DMSArray"] =          F16SAMPLER2DMSARRAY;
666     (*KeywordMap)["f16sampler1DShadow"] =           F16SAMPLER1DSHADOW;
667     (*KeywordMap)["f16sampler2DShadow"] =           F16SAMPLER2DSHADOW;
668     (*KeywordMap)["f16sampler2DRectShadow"] =       F16SAMPLER2DRECTSHADOW;
669     (*KeywordMap)["f16samplerCubeShadow"] =         F16SAMPLERCUBESHADOW;
670     (*KeywordMap)["f16sampler1DArrayShadow"] =      F16SAMPLER1DARRAYSHADOW;
671     (*KeywordMap)["f16sampler2DArrayShadow"] =      F16SAMPLER2DARRAYSHADOW;
672     (*KeywordMap)["f16samplerCubeArrayShadow"] =    F16SAMPLERCUBEARRAYSHADOW;
673
674     (*KeywordMap)["f16image1D"] =                   F16IMAGE1D;
675     (*KeywordMap)["f16image2D"] =                   F16IMAGE2D;
676     (*KeywordMap)["f16image3D"] =                   F16IMAGE3D;
677     (*KeywordMap)["f16image2DRect"] =               F16IMAGE2DRECT;
678     (*KeywordMap)["f16imageCube"] =                 F16IMAGECUBE;
679     (*KeywordMap)["f16image1DArray"] =              F16IMAGE1DARRAY;
680     (*KeywordMap)["f16image2DArray"] =              F16IMAGE2DARRAY;
681     (*KeywordMap)["f16imageCubeArray"] =            F16IMAGECUBEARRAY;
682     (*KeywordMap)["f16imageBuffer"] =               F16IMAGEBUFFER;
683     (*KeywordMap)["f16image2DMS"] =                 F16IMAGE2DMS;
684     (*KeywordMap)["f16image2DMSArray"] =            F16IMAGE2DMSARRAY;
685
686     (*KeywordMap)["f16texture1D"] =                 F16TEXTURE1D;
687     (*KeywordMap)["f16texture2D"] =                 F16TEXTURE2D;
688     (*KeywordMap)["f16texture3D"] =                 F16TEXTURE3D;
689     (*KeywordMap)["f16texture2DRect"] =             F16TEXTURE2DRECT;
690     (*KeywordMap)["f16textureCube"] =               F16TEXTURECUBE;
691     (*KeywordMap)["f16texture1DArray"] =            F16TEXTURE1DARRAY;
692     (*KeywordMap)["f16texture2DArray"] =            F16TEXTURE2DARRAY;
693     (*KeywordMap)["f16textureCubeArray"] =          F16TEXTURECUBEARRAY;
694     (*KeywordMap)["f16textureBuffer"] =             F16TEXTUREBUFFER;
695     (*KeywordMap)["f16texture2DMS"] =               F16TEXTURE2DMS;
696     (*KeywordMap)["f16texture2DMSArray"] =          F16TEXTURE2DMSARRAY;
697
698     (*KeywordMap)["f16subpassInput"] =              F16SUBPASSINPUT;
699     (*KeywordMap)["f16subpassInputMS"] =            F16SUBPASSINPUTMS;
700     (*KeywordMap)["__explicitInterpAMD"] =     EXPLICITINTERPAMD;
701     (*KeywordMap)["pervertexNV"] =             PERVERTEXNV;
702     (*KeywordMap)["precise"] =                 PRECISE;
703
704     (*KeywordMap)["rayPayloadNV"] =            PAYLOADNV;
705     (*KeywordMap)["rayPayloadInNV"] =          PAYLOADINNV;
706     (*KeywordMap)["hitAttributeNV"] =          HITATTRNV;
707     (*KeywordMap)["callableDataNV"] =          CALLDATANV;
708     (*KeywordMap)["callableDataInNV"] =        CALLDATAINNV;
709     (*KeywordMap)["accelerationStructureNV"] = ACCSTRUCTNV;
710     (*KeywordMap)["perprimitiveNV"] =          PERPRIMITIVENV;
711     (*KeywordMap)["perviewNV"] =               PERVIEWNV;
712     (*KeywordMap)["taskNV"] =                  PERTASKNV;
713
714     (*KeywordMap)["fcoopmatNV"] =              FCOOPMATNV;
715     (*KeywordMap)["icoopmatNV"] =              ICOOPMATNV;
716     (*KeywordMap)["ucoopmatNV"] =              UCOOPMATNV;
717
718     ReservedSet = new std::unordered_set<const char*, str_hash, str_eq>;
719
720     ReservedSet->insert("common");
721     ReservedSet->insert("partition");
722     ReservedSet->insert("active");
723     ReservedSet->insert("asm");
724     ReservedSet->insert("class");
725     ReservedSet->insert("union");
726     ReservedSet->insert("enum");
727     ReservedSet->insert("typedef");
728     ReservedSet->insert("template");
729     ReservedSet->insert("this");
730     ReservedSet->insert("goto");
731     ReservedSet->insert("inline");
732     ReservedSet->insert("noinline");
733     ReservedSet->insert("public");
734     ReservedSet->insert("static");
735     ReservedSet->insert("extern");
736     ReservedSet->insert("external");
737     ReservedSet->insert("interface");
738     ReservedSet->insert("long");
739     ReservedSet->insert("short");
740     ReservedSet->insert("half");
741     ReservedSet->insert("fixed");
742     ReservedSet->insert("unsigned");
743     ReservedSet->insert("input");
744     ReservedSet->insert("output");
745     ReservedSet->insert("hvec2");
746     ReservedSet->insert("hvec3");
747     ReservedSet->insert("hvec4");
748     ReservedSet->insert("fvec2");
749     ReservedSet->insert("fvec3");
750     ReservedSet->insert("fvec4");
751     ReservedSet->insert("sampler3DRect");
752     ReservedSet->insert("filter");
753     ReservedSet->insert("sizeof");
754     ReservedSet->insert("cast");
755     ReservedSet->insert("namespace");
756     ReservedSet->insert("using");
757 #endif
758 }
759
760 void TScanContext::deleteKeywordMap()
761 {
762     delete KeywordMap;
763     KeywordMap = nullptr;
764 #ifndef GLSLANG_WEB
765     delete ReservedSet;
766     ReservedSet = nullptr;
767 #endif
768 }
769
770 // Called by yylex to get the next token.
771 // Returning 0 implies end of input.
772 int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
773 {
774     do {
775         parserToken = &token;
776         TPpToken ppToken;
777         int token = pp->tokenize(ppToken);
778         if (token == EndOfInput)
779             return 0;
780
781         tokenText = ppToken.name;
782         loc = ppToken.loc;
783         parserToken->sType.lex.loc = loc;
784         switch (token) {
785         case ';':  afterType = false; afterBuffer = false; return SEMICOLON;
786         case ',':  afterType = false;   return COMMA;
787         case ':':                       return COLON;
788         case '=':  afterType = false;   return EQUAL;
789         case '(':  afterType = false;   return LEFT_PAREN;
790         case ')':  afterType = false;   return RIGHT_PAREN;
791         case '.':  field = true;        return DOT;
792         case '!':                       return BANG;
793         case '-':                       return DASH;
794         case '~':                       return TILDE;
795         case '+':                       return PLUS;
796         case '*':                       return STAR;
797         case '/':                       return SLASH;
798         case '%':                       return PERCENT;
799         case '<':                       return LEFT_ANGLE;
800         case '>':                       return RIGHT_ANGLE;
801         case '|':                       return VERTICAL_BAR;
802         case '^':                       return CARET;
803         case '&':                       return AMPERSAND;
804         case '?':                       return QUESTION;
805         case '[':                       return LEFT_BRACKET;
806         case ']':                       return RIGHT_BRACKET;
807         case '{':  afterStruct = false; afterBuffer = false; return LEFT_BRACE;
808         case '}':                       return RIGHT_BRACE;
809         case '\\':
810             parseContext.error(loc, "illegal use of escape character", "\\", "");
811             break;
812
813         case PPAtomAddAssign:          return ADD_ASSIGN;
814         case PPAtomSubAssign:          return SUB_ASSIGN;
815         case PPAtomMulAssign:          return MUL_ASSIGN;
816         case PPAtomDivAssign:          return DIV_ASSIGN;
817         case PPAtomModAssign:          return MOD_ASSIGN;
818
819         case PpAtomRight:              return RIGHT_OP;
820         case PpAtomLeft:               return LEFT_OP;
821
822         case PpAtomRightAssign:        return RIGHT_ASSIGN;
823         case PpAtomLeftAssign:         return LEFT_ASSIGN;
824         case PpAtomAndAssign:          return AND_ASSIGN;
825         case PpAtomOrAssign:           return OR_ASSIGN;
826         case PpAtomXorAssign:          return XOR_ASSIGN;
827
828         case PpAtomAnd:                return AND_OP;
829         case PpAtomOr:                 return OR_OP;
830         case PpAtomXor:                return XOR_OP;
831
832         case PpAtomEQ:                 return EQ_OP;
833         case PpAtomGE:                 return GE_OP;
834         case PpAtomNE:                 return NE_OP;
835         case PpAtomLE:                 return LE_OP;
836
837         case PpAtomDecrement:          return DEC_OP;
838         case PpAtomIncrement:          return INC_OP;
839
840         case PpAtomColonColon:
841             parseContext.error(loc, "not supported", "::", "");
842             break;
843
844         case PpAtomConstInt:           parserToken->sType.lex.i    = ppToken.ival;       return INTCONSTANT;
845         case PpAtomConstUint:          parserToken->sType.lex.i    = ppToken.ival;       return UINTCONSTANT;
846         case PpAtomConstFloat:         parserToken->sType.lex.d    = ppToken.dval;       return FLOATCONSTANT;
847 #ifndef GLSLANG_WEB
848         case PpAtomConstInt16:         parserToken->sType.lex.i    = ppToken.ival;       return INT16CONSTANT;
849         case PpAtomConstUint16:        parserToken->sType.lex.i    = ppToken.ival;       return UINT16CONSTANT;
850         case PpAtomConstInt64:         parserToken->sType.lex.i64  = ppToken.i64val;     return INT64CONSTANT;
851         case PpAtomConstUint64:        parserToken->sType.lex.i64  = ppToken.i64val;     return UINT64CONSTANT;
852         case PpAtomConstDouble:        parserToken->sType.lex.d    = ppToken.dval;       return DOUBLECONSTANT;
853         case PpAtomConstFloat16:       parserToken->sType.lex.d    = ppToken.dval;       return FLOAT16CONSTANT;
854 #endif
855         case PpAtomIdentifier:
856         {
857             int token = tokenizeIdentifier();
858             field = false;
859             return token;
860         }
861
862         case EndOfInput:               return 0;
863
864         default:
865             char buf[2];
866             buf[0] = (char)token;
867             buf[1] = 0;
868             parseContext.error(loc, "unexpected token", buf, "");
869             break;
870         }
871     } while (true);
872 }
873
874 int TScanContext::tokenizeIdentifier()
875 {
876 #ifndef GLSLANG_WEB
877     if (ReservedSet->find(tokenText) != ReservedSet->end())
878         return reservedWord();
879 #endif
880
881     auto it = KeywordMap->find(tokenText);
882     if (it == KeywordMap->end()) {
883         // Should have an identifier of some sort
884         return identifierOrType();
885     }
886     keyword = it->second;
887
888     switch (keyword) {
889     case CONST:
890     case UNIFORM:
891     case IN:
892     case OUT:
893     case INOUT:
894     case BREAK:
895     case CONTINUE:
896     case DO:
897     case FOR:
898     case WHILE:
899     case IF:
900     case ELSE:
901     case DISCARD:
902     case RETURN:
903     case CASE:
904         return keyword;
905
906     case BUFFER:
907         afterBuffer = true;
908         if ((parseContext.isEsProfile() && parseContext.version < 310) ||
909             (!parseContext.isEsProfile() && parseContext.version < 430))
910             return identifierOrType();
911         return keyword;
912
913     case STRUCT:
914         afterStruct = true;
915         return keyword;
916
917     case SWITCH:
918     case DEFAULT:
919         if ((parseContext.isEsProfile() && parseContext.version < 300) ||
920             (!parseContext.isEsProfile() && parseContext.version < 130))
921             reservedWord();
922         return keyword;
923
924     case VOID:
925     case BOOL:
926     case FLOAT:
927     case INT:
928     case BVEC2:
929     case BVEC3:
930     case BVEC4:
931     case VEC2:
932     case VEC3:
933     case VEC4:
934     case IVEC2:
935     case IVEC3:
936     case IVEC4:
937     case MAT2:
938     case MAT3:
939     case MAT4:
940     case SAMPLER2D:
941     case SAMPLERCUBE:
942         afterType = true;
943         return keyword;
944
945     case BOOLCONSTANT:
946         if (strcmp("true", tokenText) == 0)
947             parserToken->sType.lex.b = true;
948         else
949             parserToken->sType.lex.b = false;
950         return keyword;
951
952     case SMOOTH:
953         if ((parseContext.isEsProfile() && parseContext.version < 300) ||
954             (!parseContext.isEsProfile() && parseContext.version < 130))
955             return identifierOrType();
956         return keyword;
957     case FLAT:
958         if (parseContext.isEsProfile() && parseContext.version < 300)
959             reservedWord();
960         else if (!parseContext.isEsProfile() && parseContext.version < 130)
961             return identifierOrType();
962         return keyword;
963     case CENTROID:
964         if (parseContext.version < 120)
965             return identifierOrType();
966         return keyword;
967     case INVARIANT:
968         if (!parseContext.isEsProfile() && parseContext.version < 120)
969             return identifierOrType();
970         return keyword;
971     case PACKED:
972         if ((parseContext.isEsProfile() && parseContext.version < 300) ||
973             (!parseContext.isEsProfile() && parseContext.version < 330))
974             return reservedWord();
975         return identifierOrType();
976
977     case RESOURCE:
978     {
979         bool reserved = (parseContext.isEsProfile() && parseContext.version >= 300) ||
980                         (!parseContext.isEsProfile() && parseContext.version >= 420);
981         return identifierOrReserved(reserved);
982     }
983     case SUPERP:
984     {
985         bool reserved = parseContext.isEsProfile() || parseContext.version >= 130;
986         return identifierOrReserved(reserved);
987     }
988
989 #ifndef GLSLANG_WEB
990     case NOPERSPECTIVE:
991         if (parseContext.extensionTurnedOn(E_GL_NV_shader_noperspective_interpolation))
992             return keyword;
993         return es30ReservedFromGLSL(130);
994
995     case NONUNIFORM:
996         if (parseContext.extensionTurnedOn(E_GL_EXT_nonuniform_qualifier))
997             return keyword;
998         else
999             return identifierOrType();
1000     case ATTRIBUTE:
1001     case VARYING:
1002         if (parseContext.isEsProfile() && parseContext.version >= 300)
1003             reservedWord();
1004         return keyword;
1005     case PAYLOADNV:
1006     case PAYLOADINNV:
1007     case HITATTRNV:
1008     case CALLDATANV:
1009     case CALLDATAINNV:
1010     case ACCSTRUCTNV:
1011         if (parseContext.symbolTable.atBuiltInLevel() ||
1012             parseContext.extensionTurnedOn(E_GL_NV_ray_tracing))
1013             return keyword;
1014         return identifierOrType();
1015     case ATOMIC_UINT:
1016         if ((parseContext.isEsProfile() && parseContext.version >= 310) ||
1017             parseContext.extensionTurnedOn(E_GL_ARB_shader_atomic_counters))
1018             return keyword;
1019         return es30ReservedFromGLSL(420);
1020
1021     case COHERENT:
1022     case DEVICECOHERENT:
1023     case QUEUEFAMILYCOHERENT:
1024     case WORKGROUPCOHERENT:
1025     case SUBGROUPCOHERENT:
1026     case NONPRIVATE:
1027     case RESTRICT:
1028     case READONLY:
1029     case WRITEONLY:
1030         if (parseContext.isEsProfile() && parseContext.version >= 310)
1031             return keyword;
1032         return es30ReservedFromGLSL(parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store) ? 130 : 420);
1033     case VOLATILE:
1034         if (parseContext.isEsProfile() && parseContext.version >= 310)
1035             return keyword;
1036         if (! parseContext.symbolTable.atBuiltInLevel() && (parseContext.isEsProfile() ||
1037             (parseContext.version < 420 && ! parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))))
1038             reservedWord();
1039         return keyword;
1040     case PATCH:
1041         if (parseContext.symbolTable.atBuiltInLevel() ||
1042             (parseContext.isEsProfile() &&
1043              (parseContext.version >= 320 ||
1044               parseContext.extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader))) ||
1045             (!parseContext.isEsProfile() && parseContext.extensionTurnedOn(E_GL_ARB_tessellation_shader)))
1046             return keyword;
1047
1048         return es30ReservedFromGLSL(400);
1049
1050     case SAMPLE:
1051         if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
1052             parseContext.extensionsTurnedOn(1, &E_GL_OES_shader_multisample_interpolation))
1053             return keyword;
1054         return es30ReservedFromGLSL(400);
1055
1056     case SUBROUTINE:
1057         return es30ReservedFromGLSL(400);
1058 #endif
1059     case SHARED:
1060         if ((parseContext.isEsProfile() && parseContext.version < 300) ||
1061             (!parseContext.isEsProfile() && parseContext.version < 140))
1062             return identifierOrType();
1063         return keyword;
1064     case LAYOUT:
1065     {
1066         const int numLayoutExts = 2;
1067         const char* layoutExts[numLayoutExts] = { E_GL_ARB_shading_language_420pack,
1068                                                   E_GL_ARB_explicit_attrib_location };
1069         if ((parseContext.isEsProfile() && parseContext.version < 300) ||
1070             (!parseContext.isEsProfile() && parseContext.version < 140 &&
1071             ! parseContext.extensionsTurnedOn(numLayoutExts, layoutExts)))
1072             return identifierOrType();
1073         return keyword;
1074     }
1075
1076     case HIGH_PRECISION:
1077     case MEDIUM_PRECISION:
1078     case LOW_PRECISION:
1079     case PRECISION:
1080         return precisionKeyword();
1081
1082     case MAT2X2:
1083     case MAT2X3:
1084     case MAT2X4:
1085     case MAT3X2:
1086     case MAT3X3:
1087     case MAT3X4:
1088     case MAT4X2:
1089     case MAT4X3:
1090     case MAT4X4:
1091         return matNxM();
1092
1093 #ifndef GLSLANG_WEB
1094     case DMAT2:
1095     case DMAT3:
1096     case DMAT4:
1097     case DMAT2X2:
1098     case DMAT2X3:
1099     case DMAT2X4:
1100     case DMAT3X2:
1101     case DMAT3X3:
1102     case DMAT3X4:
1103     case DMAT4X2:
1104     case DMAT4X3:
1105     case DMAT4X4:
1106         return dMat();
1107
1108     case IMAGE1D:
1109     case IIMAGE1D:
1110     case UIMAGE1D:
1111     case IMAGE1DARRAY:
1112     case IIMAGE1DARRAY:
1113     case UIMAGE1DARRAY:
1114     case IMAGE2DRECT:
1115     case IIMAGE2DRECT:
1116     case UIMAGE2DRECT:
1117         afterType = true;
1118         return firstGenerationImage(false);
1119
1120     case IMAGEBUFFER:
1121     case IIMAGEBUFFER:
1122     case UIMAGEBUFFER:
1123         afterType = true;
1124         if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
1125             parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
1126             return keyword;
1127         return firstGenerationImage(false);
1128
1129     case IMAGE2D:
1130     case IIMAGE2D:
1131     case UIMAGE2D:
1132     case IMAGE3D:
1133     case IIMAGE3D:
1134     case UIMAGE3D:
1135     case IMAGECUBE:
1136     case IIMAGECUBE:
1137     case UIMAGECUBE:
1138     case IMAGE2DARRAY:
1139     case IIMAGE2DARRAY:
1140     case UIMAGE2DARRAY:
1141         afterType = true;
1142         return firstGenerationImage(true);
1143
1144     case IMAGECUBEARRAY:
1145     case IIMAGECUBEARRAY:
1146     case UIMAGECUBEARRAY:
1147         afterType = true;
1148         if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
1149             parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
1150             return keyword;
1151         return secondGenerationImage();
1152
1153     case IMAGE2DMS:
1154     case IIMAGE2DMS:
1155     case UIMAGE2DMS:
1156     case IMAGE2DMSARRAY:
1157     case IIMAGE2DMSARRAY:
1158     case UIMAGE2DMSARRAY:
1159         afterType = true;
1160         return secondGenerationImage();
1161
1162     case DOUBLE:
1163     case DVEC2:
1164     case DVEC3:
1165     case DVEC4:
1166         afterType = true;
1167         if (parseContext.isEsProfile() || parseContext.version < 150 ||
1168             (!parseContext.symbolTable.atBuiltInLevel() &&
1169               parseContext.version < 400 &&
1170              !parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64)))
1171             reservedWord();
1172         return keyword;
1173
1174     case INT64_T:
1175     case UINT64_T:
1176     case I64VEC2:
1177     case I64VEC3:
1178     case I64VEC4:
1179     case U64VEC2:
1180     case U64VEC3:
1181     case U64VEC4:
1182         afterType = true;
1183         if (parseContext.symbolTable.atBuiltInLevel() ||
1184             parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64) ||
1185             parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
1186             parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int64))
1187             return keyword;
1188         return identifierOrType();
1189
1190     case INT8_T:
1191     case UINT8_T:
1192     case I8VEC2:
1193     case I8VEC3:
1194     case I8VEC4:
1195     case U8VEC2:
1196     case U8VEC3:
1197     case U8VEC4:
1198         afterType = true;
1199         if (parseContext.symbolTable.atBuiltInLevel() ||
1200             parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
1201             parseContext.extensionTurnedOn(E_GL_EXT_shader_8bit_storage) ||
1202             parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int8))
1203             return keyword;
1204         return identifierOrType();
1205
1206     case INT16_T:
1207     case UINT16_T:
1208     case I16VEC2:
1209     case I16VEC3:
1210     case I16VEC4:
1211     case U16VEC2:
1212     case U16VEC3:
1213     case U16VEC4:
1214         afterType = true;
1215         if (parseContext.symbolTable.atBuiltInLevel() ||
1216             parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_int16) ||
1217             parseContext.extensionTurnedOn(E_GL_EXT_shader_16bit_storage) ||
1218             parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
1219             parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int16))
1220             return keyword;
1221         return identifierOrType();
1222     case INT32_T:
1223     case UINT32_T:
1224     case I32VEC2:
1225     case I32VEC3:
1226     case I32VEC4:
1227     case U32VEC2:
1228     case U32VEC3:
1229     case U32VEC4:
1230         afterType = true;
1231         if (parseContext.symbolTable.atBuiltInLevel() ||
1232             parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
1233             parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int32))
1234             return keyword;
1235         return identifierOrType();
1236     case FLOAT32_T:
1237     case F32VEC2:
1238     case F32VEC3:
1239     case F32VEC4:
1240     case F32MAT2:
1241     case F32MAT3:
1242     case F32MAT4:
1243     case F32MAT2X2:
1244     case F32MAT2X3:
1245     case F32MAT2X4:
1246     case F32MAT3X2:
1247     case F32MAT3X3:
1248     case F32MAT3X4:
1249     case F32MAT4X2:
1250     case F32MAT4X3:
1251     case F32MAT4X4:
1252         afterType = true;
1253         if (parseContext.symbolTable.atBuiltInLevel() ||
1254             parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
1255             parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float32))
1256             return keyword;
1257         return identifierOrType();
1258
1259     case FLOAT64_T:
1260     case F64VEC2:
1261     case F64VEC3:
1262     case F64VEC4:
1263     case F64MAT2:
1264     case F64MAT3:
1265     case F64MAT4:
1266     case F64MAT2X2:
1267     case F64MAT2X3:
1268     case F64MAT2X4:
1269     case F64MAT3X2:
1270     case F64MAT3X3:
1271     case F64MAT3X4:
1272     case F64MAT4X2:
1273     case F64MAT4X3:
1274     case F64MAT4X4:
1275         afterType = true;
1276         if (parseContext.symbolTable.atBuiltInLevel() ||
1277             parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
1278             parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float64))
1279             return keyword;
1280         return identifierOrType();
1281
1282     case FLOAT16_T:
1283     case F16VEC2:
1284     case F16VEC3:
1285     case F16VEC4:
1286         afterType = true;
1287         if (parseContext.symbolTable.atBuiltInLevel() ||
1288             parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) ||
1289             parseContext.extensionTurnedOn(E_GL_EXT_shader_16bit_storage) ||
1290             parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
1291             parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16))
1292             return keyword;
1293
1294         return identifierOrType();
1295
1296     case F16MAT2:
1297     case F16MAT3:
1298     case F16MAT4:
1299     case F16MAT2X2:
1300     case F16MAT2X3:
1301     case F16MAT2X4:
1302     case F16MAT3X2:
1303     case F16MAT3X3:
1304     case F16MAT3X4:
1305     case F16MAT4X2:
1306     case F16MAT4X3:
1307     case F16MAT4X4:
1308         afterType = true;
1309         if (parseContext.symbolTable.atBuiltInLevel() ||
1310             parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) ||
1311             parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
1312             parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16))
1313             return keyword;
1314
1315         return identifierOrType();
1316
1317     case SAMPLERCUBEARRAY:
1318     case SAMPLERCUBEARRAYSHADOW:
1319     case ISAMPLERCUBEARRAY:
1320     case USAMPLERCUBEARRAY:
1321         afterType = true;
1322         if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
1323             parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
1324             return keyword;
1325         if (parseContext.isEsProfile() || (parseContext.version < 400 && ! parseContext.extensionTurnedOn(E_GL_ARB_texture_cube_map_array)))
1326             reservedWord();
1327         return keyword;
1328
1329     case TEXTURECUBEARRAY:
1330     case ITEXTURECUBEARRAY:
1331     case UTEXTURECUBEARRAY:
1332         if (parseContext.spvVersion.vulkan > 0)
1333             return keyword;
1334         else
1335             return identifierOrType();
1336 #endif
1337
1338     case UINT:
1339     case UVEC2:
1340     case UVEC3:
1341     case UVEC4:
1342     case SAMPLERCUBESHADOW:
1343     case SAMPLER2DARRAY:
1344     case SAMPLER2DARRAYSHADOW:
1345     case ISAMPLER2D:
1346     case ISAMPLER3D:
1347     case ISAMPLERCUBE:
1348     case ISAMPLER2DARRAY:
1349     case USAMPLER2D:
1350     case USAMPLER3D:
1351     case USAMPLERCUBE:
1352     case USAMPLER2DARRAY:
1353         afterType = true;
1354         return nonreservedKeyword(300, 130);
1355
1356     case SAMPLER3D:
1357         afterType = true;
1358         if (parseContext.isEsProfile() && parseContext.version < 300) {
1359             if (!parseContext.extensionTurnedOn(E_GL_OES_texture_3D))
1360                 reservedWord();
1361         }
1362         return keyword;
1363
1364     case SAMPLER2DSHADOW:
1365         afterType = true;
1366         if (parseContext.isEsProfile() && parseContext.version < 300) {
1367             if (!parseContext.extensionTurnedOn(E_GL_EXT_shadow_samplers))
1368                 reservedWord();
1369         }
1370         return keyword;
1371
1372     case TEXTURE2D:
1373     case TEXTURECUBE:
1374     case TEXTURE2DARRAY:
1375     case ITEXTURE2D:
1376     case ITEXTURE3D:
1377     case ITEXTURECUBE:
1378     case ITEXTURE2DARRAY:
1379     case UTEXTURE2D:
1380     case UTEXTURE3D:
1381     case UTEXTURECUBE:
1382     case UTEXTURE2DARRAY:
1383     case TEXTURE3D:
1384     case SAMPLER:
1385     case SAMPLERSHADOW:
1386         if (parseContext.spvVersion.vulkan > 0)
1387             return keyword;
1388         else
1389             return identifierOrType();
1390
1391 #ifndef GLSLANG_WEB
1392     case ISAMPLER1D:
1393     case ISAMPLER1DARRAY:
1394     case SAMPLER1DARRAYSHADOW:
1395     case USAMPLER1D:
1396     case USAMPLER1DARRAY:
1397         afterType = true;
1398         return es30ReservedFromGLSL(130);
1399     case ISAMPLER2DRECT:
1400     case USAMPLER2DRECT:
1401         afterType = true;
1402         return es30ReservedFromGLSL(140);
1403
1404     case SAMPLERBUFFER:
1405         afterType = true;
1406         if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
1407             parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
1408             return keyword;
1409         return es30ReservedFromGLSL(130);
1410
1411     case ISAMPLERBUFFER:
1412     case USAMPLERBUFFER:
1413         afterType = true;
1414         if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
1415             parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
1416             return keyword;
1417         return es30ReservedFromGLSL(140);
1418
1419     case SAMPLER2DMS:
1420     case ISAMPLER2DMS:
1421     case USAMPLER2DMS:
1422         afterType = true;
1423         if (parseContext.isEsProfile() && parseContext.version >= 310)
1424             return keyword;
1425         if (!parseContext.isEsProfile() && (parseContext.version > 140 ||
1426             (parseContext.version == 140 && parseContext.extensionsTurnedOn(1, &E_GL_ARB_texture_multisample))))
1427             return keyword;
1428         return es30ReservedFromGLSL(150);
1429
1430     case SAMPLER2DMSARRAY:
1431     case ISAMPLER2DMSARRAY:
1432     case USAMPLER2DMSARRAY:
1433         afterType = true;
1434         if ((parseContext.isEsProfile() && parseContext.version >= 320) ||
1435             parseContext.extensionsTurnedOn(1, &E_GL_OES_texture_storage_multisample_2d_array))
1436             return keyword;
1437         if (!parseContext.isEsProfile() && (parseContext.version > 140 ||
1438             (parseContext.version == 140 && parseContext.extensionsTurnedOn(1, &E_GL_ARB_texture_multisample))))
1439             return keyword;
1440         return es30ReservedFromGLSL(150);
1441
1442     case SAMPLER1D:
1443     case SAMPLER1DSHADOW:
1444         afterType = true;
1445         if (parseContext.isEsProfile())
1446             reservedWord();
1447         return keyword;
1448
1449     case SAMPLER2DRECT:
1450     case SAMPLER2DRECTSHADOW:
1451         afterType = true;
1452         if (parseContext.isEsProfile())
1453             reservedWord();
1454         else if (parseContext.version < 140 && ! parseContext.symbolTable.atBuiltInLevel() && ! parseContext.extensionTurnedOn(E_GL_ARB_texture_rectangle)) {
1455             if (parseContext.relaxedErrors())
1456                 parseContext.requireExtensions(loc, 1, &E_GL_ARB_texture_rectangle, "texture-rectangle sampler keyword");
1457             else
1458                 reservedWord();
1459         }
1460         return keyword;
1461
1462     case SAMPLER1DARRAY:
1463         afterType = true;
1464         if (parseContext.isEsProfile() && parseContext.version == 300)
1465             reservedWord();
1466         else if ((parseContext.isEsProfile() && parseContext.version < 300) ||
1467                  (!parseContext.isEsProfile() && parseContext.version < 130))
1468             return identifierOrType();
1469         return keyword;
1470
1471     case SAMPLEREXTERNALOES:
1472         afterType = true;
1473         if (parseContext.symbolTable.atBuiltInLevel() ||
1474             parseContext.extensionTurnedOn(E_GL_OES_EGL_image_external) ||
1475             parseContext.extensionTurnedOn(E_GL_OES_EGL_image_external_essl3))
1476             return keyword;
1477         return identifierOrType();
1478
1479     case SAMPLEREXTERNAL2DY2YEXT:
1480         afterType = true;
1481         if (parseContext.symbolTable.atBuiltInLevel() ||
1482             parseContext.extensionTurnedOn(E_GL_EXT_YUV_target))
1483             return keyword;
1484         return identifierOrType();
1485
1486     case ITEXTURE1DARRAY:
1487     case UTEXTURE1D:
1488     case ITEXTURE1D:
1489     case UTEXTURE1DARRAY:
1490     case TEXTUREBUFFER:
1491     case ITEXTURE2DRECT:
1492     case UTEXTURE2DRECT:
1493     case ITEXTUREBUFFER:
1494     case UTEXTUREBUFFER:
1495     case TEXTURE2DMS:
1496     case ITEXTURE2DMS:
1497     case UTEXTURE2DMS:
1498     case TEXTURE2DMSARRAY:
1499     case ITEXTURE2DMSARRAY:
1500     case UTEXTURE2DMSARRAY:
1501     case TEXTURE1D:
1502     case TEXTURE2DRECT:
1503     case TEXTURE1DARRAY:
1504         if (parseContext.spvVersion.vulkan > 0)
1505             return keyword;
1506         else
1507             return identifierOrType();
1508
1509     case SUBPASSINPUT:
1510     case SUBPASSINPUTMS:
1511     case ISUBPASSINPUT:
1512     case ISUBPASSINPUTMS:
1513     case USUBPASSINPUT:
1514     case USUBPASSINPUTMS:
1515         if (parseContext.spvVersion.vulkan > 0)
1516             return keyword;
1517         else
1518             return identifierOrType();
1519
1520     case F16SAMPLER1D:
1521     case F16SAMPLER2D:
1522     case F16SAMPLER3D:
1523     case F16SAMPLER2DRECT:
1524     case F16SAMPLERCUBE:
1525     case F16SAMPLER1DARRAY:
1526     case F16SAMPLER2DARRAY:
1527     case F16SAMPLERCUBEARRAY:
1528     case F16SAMPLERBUFFER:
1529     case F16SAMPLER2DMS:
1530     case F16SAMPLER2DMSARRAY:
1531     case F16SAMPLER1DSHADOW:
1532     case F16SAMPLER2DSHADOW:
1533     case F16SAMPLER1DARRAYSHADOW:
1534     case F16SAMPLER2DARRAYSHADOW:
1535     case F16SAMPLER2DRECTSHADOW:
1536     case F16SAMPLERCUBESHADOW:
1537     case F16SAMPLERCUBEARRAYSHADOW:
1538
1539     case F16IMAGE1D:
1540     case F16IMAGE2D:
1541     case F16IMAGE3D:
1542     case F16IMAGE2DRECT:
1543     case F16IMAGECUBE:
1544     case F16IMAGE1DARRAY:
1545     case F16IMAGE2DARRAY:
1546     case F16IMAGECUBEARRAY:
1547     case F16IMAGEBUFFER:
1548     case F16IMAGE2DMS:
1549     case F16IMAGE2DMSARRAY:
1550
1551     case F16TEXTURE1D:
1552     case F16TEXTURE2D:
1553     case F16TEXTURE3D:
1554     case F16TEXTURE2DRECT:
1555     case F16TEXTURECUBE:
1556     case F16TEXTURE1DARRAY:
1557     case F16TEXTURE2DARRAY:
1558     case F16TEXTURECUBEARRAY:
1559     case F16TEXTUREBUFFER:
1560     case F16TEXTURE2DMS:
1561     case F16TEXTURE2DMSARRAY:
1562
1563     case F16SUBPASSINPUT:
1564     case F16SUBPASSINPUTMS:
1565         afterType = true;
1566         if (parseContext.symbolTable.atBuiltInLevel() ||
1567             parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float_fetch))
1568             return keyword;
1569         return identifierOrType();
1570
1571     case EXPLICITINTERPAMD:
1572         if (parseContext.extensionTurnedOn(E_GL_AMD_shader_explicit_vertex_parameter))
1573             return keyword;
1574         return identifierOrType();
1575
1576     case PERVERTEXNV:
1577         if ((!parseContext.isEsProfile() && parseContext.version >= 450) ||
1578             parseContext.extensionTurnedOn(E_GL_NV_fragment_shader_barycentric))
1579             return keyword;
1580         return identifierOrType();
1581
1582     case PRECISE:
1583         if ((parseContext.isEsProfile() &&
1584              (parseContext.version >= 320 || parseContext.extensionsTurnedOn(Num_AEP_gpu_shader5, AEP_gpu_shader5))) ||
1585             (!parseContext.isEsProfile() && parseContext.version >= 400))
1586             return keyword;
1587         if (parseContext.isEsProfile() && parseContext.version == 310) {
1588             reservedWord();
1589             return keyword;
1590         }
1591         return identifierOrType();
1592
1593     case PERPRIMITIVENV:
1594     case PERVIEWNV:
1595     case PERTASKNV:
1596         if ((!parseContext.isEsProfile() && parseContext.version >= 450) ||
1597             (parseContext.isEsProfile() && parseContext.version >= 320) ||
1598             parseContext.extensionTurnedOn(E_GL_NV_mesh_shader))
1599             return keyword;
1600         return identifierOrType();
1601
1602     case FCOOPMATNV:
1603         afterType = true;
1604         if (parseContext.symbolTable.atBuiltInLevel() ||
1605             parseContext.extensionTurnedOn(E_GL_NV_cooperative_matrix))
1606             return keyword;
1607         return identifierOrType();
1608
1609     case UCOOPMATNV:
1610     case ICOOPMATNV:
1611         afterType = true;
1612         if (parseContext.symbolTable.atBuiltInLevel() ||
1613             parseContext.extensionTurnedOn(E_GL_NV_integer_cooperative_matrix))
1614             return keyword;
1615         return identifierOrType();
1616
1617     case DEMOTE:
1618         if (parseContext.extensionTurnedOn(E_GL_EXT_demote_to_helper_invocation))
1619             return keyword;
1620         else
1621             return identifierOrType();
1622 #endif
1623
1624     default:
1625         parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc);
1626         return 0;
1627     }
1628 }
1629
1630 int TScanContext::identifierOrType()
1631 {
1632     parserToken->sType.lex.string = NewPoolTString(tokenText);
1633     if (field)
1634         return IDENTIFIER;
1635
1636     parserToken->sType.lex.symbol = parseContext.symbolTable.find(*parserToken->sType.lex.string);
1637     if ((afterType == false && afterStruct == false) && parserToken->sType.lex.symbol != nullptr) {
1638         if (const TVariable* variable = parserToken->sType.lex.symbol->getAsVariable()) {
1639             if (variable->isUserType() &&
1640                 // treat redeclaration of forward-declared buffer/uniform reference as an identifier
1641                 !(variable->getType().isReference() && afterBuffer)) {
1642                 afterType = true;
1643
1644                 return TYPE_NAME;
1645             }
1646         }
1647     }
1648
1649     return IDENTIFIER;
1650 }
1651
1652 // Give an error for use of a reserved symbol.
1653 // However, allow built-in declarations to use reserved words, to allow
1654 // extension support before the extension is enabled.
1655 int TScanContext::reservedWord()
1656 {
1657     if (! parseContext.symbolTable.atBuiltInLevel())
1658         parseContext.error(loc, "Reserved word.", tokenText, "", "");
1659
1660     return 0;
1661 }
1662
1663 int TScanContext::identifierOrReserved(bool reserved)
1664 {
1665     if (reserved) {
1666         reservedWord();
1667
1668         return 0;
1669     }
1670
1671     if (parseContext.isForwardCompatible())
1672         parseContext.warn(loc, "using future reserved keyword", tokenText, "");
1673
1674     return identifierOrType();
1675 }
1676
1677 // For keywords that suddenly showed up on non-ES (not previously reserved)
1678 // but then got reserved by ES 3.0.
1679 int TScanContext::es30ReservedFromGLSL(int version)
1680 {
1681     if (parseContext.symbolTable.atBuiltInLevel())
1682         return keyword;
1683
1684     if ((parseContext.isEsProfile() && parseContext.version < 300) ||
1685         (!parseContext.isEsProfile() && parseContext.version < version)) {
1686             if (parseContext.isForwardCompatible())
1687                 parseContext.warn(loc, "future reserved word in ES 300 and keyword in GLSL", tokenText, "");
1688
1689             return identifierOrType();
1690     } else if (parseContext.isEsProfile() && parseContext.version >= 300)
1691         reservedWord();
1692
1693     return keyword;
1694 }
1695
1696 // For a keyword that was never reserved, until it suddenly
1697 // showed up, both in an es version and a non-ES version.
1698 int TScanContext::nonreservedKeyword(int esVersion, int nonEsVersion)
1699 {
1700     if ((parseContext.isEsProfile() && parseContext.version < esVersion) ||
1701         (!parseContext.isEsProfile() && parseContext.version < nonEsVersion)) {
1702         if (parseContext.isForwardCompatible())
1703             parseContext.warn(loc, "using future keyword", tokenText, "");
1704
1705         return identifierOrType();
1706     }
1707
1708     return keyword;
1709 }
1710
1711 int TScanContext::precisionKeyword()
1712 {
1713     if (parseContext.isEsProfile() || parseContext.version >= 130)
1714         return keyword;
1715
1716     if (parseContext.isForwardCompatible())
1717         parseContext.warn(loc, "using ES precision qualifier keyword", tokenText, "");
1718
1719     return identifierOrType();
1720 }
1721
1722 int TScanContext::matNxM()
1723 {
1724     afterType = true;
1725
1726     if (parseContext.version > 110)
1727         return keyword;
1728
1729     if (parseContext.isForwardCompatible())
1730         parseContext.warn(loc, "using future non-square matrix type keyword", tokenText, "");
1731
1732     return identifierOrType();
1733 }
1734
1735 int TScanContext::dMat()
1736 {
1737     afterType = true;
1738
1739     if (parseContext.isEsProfile() && parseContext.version >= 300) {
1740         reservedWord();
1741
1742         return keyword;
1743     }
1744
1745     if (!parseContext.isEsProfile() && (parseContext.version >= 400 ||
1746         parseContext.symbolTable.atBuiltInLevel() ||
1747         (parseContext.version >= 150 && parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64))))
1748         return keyword;
1749
1750     if (parseContext.isForwardCompatible())
1751         parseContext.warn(loc, "using future type keyword", tokenText, "");
1752
1753     return identifierOrType();
1754 }
1755
1756 int TScanContext::firstGenerationImage(bool inEs310)
1757 {
1758     if (parseContext.symbolTable.atBuiltInLevel() ||
1759         (!parseContext.isEsProfile() && (parseContext.version >= 420 ||
1760          parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))) ||
1761         (inEs310 && parseContext.isEsProfile() && parseContext.version >= 310))
1762         return keyword;
1763
1764     if ((parseContext.isEsProfile() && parseContext.version >= 300) ||
1765         (!parseContext.isEsProfile() && parseContext.version >= 130)) {
1766         reservedWord();
1767
1768         return keyword;
1769     }
1770
1771     if (parseContext.isForwardCompatible())
1772         parseContext.warn(loc, "using future type keyword", tokenText, "");
1773
1774     return identifierOrType();
1775 }
1776
1777 int TScanContext::secondGenerationImage()
1778 {
1779     if (parseContext.isEsProfile() && parseContext.version >= 310) {
1780         reservedWord();
1781         return keyword;
1782     }
1783
1784     if (parseContext.symbolTable.atBuiltInLevel() ||
1785         (!parseContext.isEsProfile() &&
1786          (parseContext.version >= 420 || parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))))
1787         return keyword;
1788
1789     if (parseContext.isForwardCompatible())
1790         parseContext.warn(loc, "using future type keyword", tokenText, "");
1791
1792     return identifierOrType();
1793 }
1794
1795 } // end namespace glslang