8b3a30636f90d67cc8c05b3659bb6b766041d2bb
[platform/upstream/glslang.git] / glslang / MachineIndependent / Scan.cpp
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)["float16_t"] =               FLOAT16_T;
468     (*KeywordMap)["f16vec2"] =                 F16VEC2;
469     (*KeywordMap)["f16vec3"] =                 F16VEC3;
470     (*KeywordMap)["f16vec4"] =                 F16VEC4;
471     (*KeywordMap)["f16mat2"] =                 F16MAT2;
472     (*KeywordMap)["f16mat3"] =                 F16MAT3;
473     (*KeywordMap)["f16mat4"] =                 F16MAT4;
474     (*KeywordMap)["f16mat2x2"] =               F16MAT2X2;
475     (*KeywordMap)["f16mat2x3"] =               F16MAT2X3;
476     (*KeywordMap)["f16mat2x4"] =               F16MAT2X4;
477     (*KeywordMap)["f16mat3x2"] =               F16MAT3X2;
478     (*KeywordMap)["f16mat3x3"] =               F16MAT3X3;
479     (*KeywordMap)["f16mat3x4"] =               F16MAT3X4;
480     (*KeywordMap)["f16mat4x2"] =               F16MAT4X2;
481     (*KeywordMap)["f16mat4x3"] =               F16MAT4X3;
482     (*KeywordMap)["f16mat4x4"] =               F16MAT4X4;
483 #endif
484
485     (*KeywordMap)["sampler2D"] =               SAMPLER2D;
486     (*KeywordMap)["samplerCube"] =             SAMPLERCUBE;
487     (*KeywordMap)["samplerCubeArray"] =        SAMPLERCUBEARRAY;
488     (*KeywordMap)["samplerCubeArrayShadow"] =  SAMPLERCUBEARRAYSHADOW;
489     (*KeywordMap)["isamplerCubeArray"] =       ISAMPLERCUBEARRAY;
490     (*KeywordMap)["usamplerCubeArray"] =       USAMPLERCUBEARRAY;
491     (*KeywordMap)["sampler1DArrayShadow"] =    SAMPLER1DARRAYSHADOW;
492     (*KeywordMap)["isampler1DArray"] =         ISAMPLER1DARRAY;
493     (*KeywordMap)["usampler1D"] =              USAMPLER1D;
494     (*KeywordMap)["isampler1D"] =              ISAMPLER1D;
495     (*KeywordMap)["usampler1DArray"] =         USAMPLER1DARRAY;
496     (*KeywordMap)["samplerBuffer"] =           SAMPLERBUFFER;
497     (*KeywordMap)["samplerCubeShadow"] =       SAMPLERCUBESHADOW;
498     (*KeywordMap)["sampler2DArray"] =          SAMPLER2DARRAY;
499     (*KeywordMap)["sampler2DArrayShadow"] =    SAMPLER2DARRAYSHADOW;
500     (*KeywordMap)["isampler2D"] =              ISAMPLER2D;
501     (*KeywordMap)["isampler3D"] =              ISAMPLER3D;
502     (*KeywordMap)["isamplerCube"] =            ISAMPLERCUBE;
503     (*KeywordMap)["isampler2DArray"] =         ISAMPLER2DARRAY;
504     (*KeywordMap)["usampler2D"] =              USAMPLER2D;
505     (*KeywordMap)["usampler3D"] =              USAMPLER3D;
506     (*KeywordMap)["usamplerCube"] =            USAMPLERCUBE;
507     (*KeywordMap)["usampler2DArray"] =         USAMPLER2DARRAY;
508     (*KeywordMap)["isampler2DRect"] =          ISAMPLER2DRECT;
509     (*KeywordMap)["usampler2DRect"] =          USAMPLER2DRECT;
510     (*KeywordMap)["isamplerBuffer"] =          ISAMPLERBUFFER;
511     (*KeywordMap)["usamplerBuffer"] =          USAMPLERBUFFER;
512     (*KeywordMap)["sampler2DMS"] =             SAMPLER2DMS;
513     (*KeywordMap)["isampler2DMS"] =            ISAMPLER2DMS;
514     (*KeywordMap)["usampler2DMS"] =            USAMPLER2DMS;
515     (*KeywordMap)["sampler2DMSArray"] =        SAMPLER2DMSARRAY;
516     (*KeywordMap)["isampler2DMSArray"] =       ISAMPLER2DMSARRAY;
517     (*KeywordMap)["usampler2DMSArray"] =       USAMPLER2DMSARRAY;
518     (*KeywordMap)["sampler1D"] =               SAMPLER1D;
519     (*KeywordMap)["sampler1DShadow"] =         SAMPLER1DSHADOW;
520     (*KeywordMap)["sampler3D"] =               SAMPLER3D;
521     (*KeywordMap)["sampler2DShadow"] =         SAMPLER2DSHADOW;
522     (*KeywordMap)["sampler2DRect"] =           SAMPLER2DRECT;
523     (*KeywordMap)["sampler2DRectShadow"] =     SAMPLER2DRECTSHADOW;
524     (*KeywordMap)["sampler1DArray"] =          SAMPLER1DARRAY;
525
526     (*KeywordMap)["samplerExternalOES"] =      SAMPLEREXTERNALOES; // GL_OES_EGL_image_external
527
528     (*KeywordMap)["sampler"] =                 SAMPLER;
529     (*KeywordMap)["samplerShadow"] =           SAMPLERSHADOW;
530
531     (*KeywordMap)["texture2D"] =               TEXTURE2D;
532     (*KeywordMap)["textureCube"] =             TEXTURECUBE;
533     (*KeywordMap)["textureCubeArray"] =        TEXTURECUBEARRAY;
534     (*KeywordMap)["itextureCubeArray"] =       ITEXTURECUBEARRAY;
535     (*KeywordMap)["utextureCubeArray"] =       UTEXTURECUBEARRAY;
536     (*KeywordMap)["itexture1DArray"] =         ITEXTURE1DARRAY;
537     (*KeywordMap)["utexture1D"] =              UTEXTURE1D;
538     (*KeywordMap)["itexture1D"] =              ITEXTURE1D;
539     (*KeywordMap)["utexture1DArray"] =         UTEXTURE1DARRAY;
540     (*KeywordMap)["textureBuffer"] =           TEXTUREBUFFER;
541     (*KeywordMap)["texture2DArray"] =          TEXTURE2DARRAY;
542     (*KeywordMap)["itexture2D"] =              ITEXTURE2D;
543     (*KeywordMap)["itexture3D"] =              ITEXTURE3D;
544     (*KeywordMap)["itextureCube"] =            ITEXTURECUBE;
545     (*KeywordMap)["itexture2DArray"] =         ITEXTURE2DARRAY;
546     (*KeywordMap)["utexture2D"] =              UTEXTURE2D;
547     (*KeywordMap)["utexture3D"] =              UTEXTURE3D;
548     (*KeywordMap)["utextureCube"] =            UTEXTURECUBE;
549     (*KeywordMap)["utexture2DArray"] =         UTEXTURE2DARRAY;
550     (*KeywordMap)["itexture2DRect"] =          ITEXTURE2DRECT;
551     (*KeywordMap)["utexture2DRect"] =          UTEXTURE2DRECT;
552     (*KeywordMap)["itextureBuffer"] =          ITEXTUREBUFFER;
553     (*KeywordMap)["utextureBuffer"] =          UTEXTUREBUFFER;
554     (*KeywordMap)["texture2DMS"] =             TEXTURE2DMS;
555     (*KeywordMap)["itexture2DMS"] =            ITEXTURE2DMS;
556     (*KeywordMap)["utexture2DMS"] =            UTEXTURE2DMS;
557     (*KeywordMap)["texture2DMSArray"] =        TEXTURE2DMSARRAY;
558     (*KeywordMap)["itexture2DMSArray"] =       ITEXTURE2DMSARRAY;
559     (*KeywordMap)["utexture2DMSArray"] =       UTEXTURE2DMSARRAY;
560     (*KeywordMap)["texture1D"] =               TEXTURE1D;
561     (*KeywordMap)["texture3D"] =               TEXTURE3D;
562     (*KeywordMap)["texture2DRect"] =           TEXTURE2DRECT;
563     (*KeywordMap)["texture1DArray"] =          TEXTURE1DARRAY;
564
565     (*KeywordMap)["subpassInput"] =            SUBPASSINPUT;
566     (*KeywordMap)["subpassInputMS"] =          SUBPASSINPUTMS;
567     (*KeywordMap)["isubpassInput"] =           ISUBPASSINPUT;
568     (*KeywordMap)["isubpassInputMS"] =         ISUBPASSINPUTMS;
569     (*KeywordMap)["usubpassInput"] =           USUBPASSINPUT;
570     (*KeywordMap)["usubpassInputMS"] =         USUBPASSINPUTMS;
571
572     (*KeywordMap)["noperspective"] =           NOPERSPECTIVE;
573     (*KeywordMap)["smooth"] =                  SMOOTH;
574     (*KeywordMap)["flat"] =                    FLAT;
575 #ifdef AMD_EXTENSIONS
576     (*KeywordMap)["__explicitInterpAMD"] =     __EXPLICITINTERPAMD;
577 #endif
578     (*KeywordMap)["centroid"] =                CENTROID;
579     (*KeywordMap)["precise"] =                 PRECISE;
580     (*KeywordMap)["invariant"] =               INVARIANT;
581     (*KeywordMap)["packed"] =                  PACKED;
582     (*KeywordMap)["resource"] =                RESOURCE;
583     (*KeywordMap)["superp"] =                  SUPERP;
584
585     ReservedSet = new std::unordered_set<const char*, str_hash, str_eq>;
586
587     ReservedSet->insert("common");
588     ReservedSet->insert("partition");
589     ReservedSet->insert("active");
590     ReservedSet->insert("asm");
591     ReservedSet->insert("class");
592     ReservedSet->insert("union");
593     ReservedSet->insert("enum");
594     ReservedSet->insert("typedef");
595     ReservedSet->insert("template");
596     ReservedSet->insert("this");
597     ReservedSet->insert("goto");
598     ReservedSet->insert("inline");
599     ReservedSet->insert("noinline");
600     ReservedSet->insert("public");
601     ReservedSet->insert("static");
602     ReservedSet->insert("extern");
603     ReservedSet->insert("external");
604     ReservedSet->insert("interface");
605     ReservedSet->insert("long");
606     ReservedSet->insert("short");
607     ReservedSet->insert("half");
608     ReservedSet->insert("fixed");
609     ReservedSet->insert("unsigned");
610     ReservedSet->insert("input");
611     ReservedSet->insert("output");
612     ReservedSet->insert("hvec2");
613     ReservedSet->insert("hvec3");
614     ReservedSet->insert("hvec4");
615     ReservedSet->insert("fvec2");
616     ReservedSet->insert("fvec3");
617     ReservedSet->insert("fvec4");
618     ReservedSet->insert("sampler3DRect");
619     ReservedSet->insert("filter");
620     ReservedSet->insert("sizeof");
621     ReservedSet->insert("cast");
622     ReservedSet->insert("namespace");
623     ReservedSet->insert("using");
624 }
625
626 void TScanContext::deleteKeywordMap()
627 {
628     delete KeywordMap;
629     KeywordMap = nullptr;
630     delete ReservedSet;
631     ReservedSet = nullptr;
632 }
633
634 // Called by yylex to get the next token.
635 // Returning 0 implies end of input.
636 int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
637 {
638     do {
639         parserToken = &token;
640         TPpToken ppToken;
641         int token = pp->tokenize(ppToken);
642         if (token == EndOfInput)
643             return 0;
644
645         tokenText = ppToken.name;
646         loc = ppToken.loc;
647         parserToken->sType.lex.loc = loc;
648         switch (token) {
649         case ';':  afterType = false;   return SEMICOLON;
650         case ',':  afterType = false;   return COMMA;
651         case ':':                       return COLON;
652         case '=':  afterType = false;   return EQUAL;
653         case '(':  afterType = false;   return LEFT_PAREN;
654         case ')':  afterType = false;   return RIGHT_PAREN;
655         case '.':  field = true;        return DOT;
656         case '!':                       return BANG;
657         case '-':                       return DASH;
658         case '~':                       return TILDE;
659         case '+':                       return PLUS;
660         case '*':                       return STAR;
661         case '/':                       return SLASH;
662         case '%':                       return PERCENT;
663         case '<':                       return LEFT_ANGLE;
664         case '>':                       return RIGHT_ANGLE;
665         case '|':                       return VERTICAL_BAR;
666         case '^':                       return CARET;
667         case '&':                       return AMPERSAND;
668         case '?':                       return QUESTION;
669         case '[':                       return LEFT_BRACKET;
670         case ']':                       return RIGHT_BRACKET;
671         case '{':                       return LEFT_BRACE;
672         case '}':                       return RIGHT_BRACE;
673         case '\\':
674             parseContext.error(loc, "illegal use of escape character", "\\", "");
675             break;
676
677         case PPAtomAddAssign:          return ADD_ASSIGN;
678         case PPAtomSubAssign:          return SUB_ASSIGN;
679         case PPAtomMulAssign:          return MUL_ASSIGN;
680         case PPAtomDivAssign:          return DIV_ASSIGN;
681         case PPAtomModAssign:          return MOD_ASSIGN;
682
683         case PpAtomRight:              return RIGHT_OP;
684         case PpAtomLeft:               return LEFT_OP;
685
686         case PpAtomRightAssign:        return RIGHT_ASSIGN;
687         case PpAtomLeftAssign:         return LEFT_ASSIGN;
688         case PpAtomAndAssign:          return AND_ASSIGN;
689         case PpAtomOrAssign:           return OR_ASSIGN;
690         case PpAtomXorAssign:          return XOR_ASSIGN;
691
692         case PpAtomAnd:                return AND_OP;
693         case PpAtomOr:                 return OR_OP;
694         case PpAtomXor:                return XOR_OP;
695
696         case PpAtomEQ:                 return EQ_OP;
697         case PpAtomGE:                 return GE_OP;
698         case PpAtomNE:                 return NE_OP;
699         case PpAtomLE:                 return LE_OP;
700
701         case PpAtomDecrement:          return DEC_OP;
702         case PpAtomIncrement:          return INC_OP;
703
704         case PpAtomColonColon:
705             parseContext.error(loc, "not supported", "::", "");
706             break;
707
708         case PpAtomConstInt:           parserToken->sType.lex.i   = ppToken.ival;       return INTCONSTANT;
709         case PpAtomConstUint:          parserToken->sType.lex.i   = ppToken.ival;       return UINTCONSTANT;
710         case PpAtomConstInt64:         parserToken->sType.lex.i64 = ppToken.i64val;     return INT64CONSTANT;
711         case PpAtomConstUint64:        parserToken->sType.lex.i64 = ppToken.i64val;     return UINT64CONSTANT;
712         case PpAtomConstFloat:         parserToken->sType.lex.d   = ppToken.dval;       return FLOATCONSTANT;
713         case PpAtomConstDouble:        parserToken->sType.lex.d   = ppToken.dval;       return DOUBLECONSTANT;
714 #ifdef AMD_EXTENSIONS
715         case PpAtomConstFloat16:       parserToken->sType.lex.d   = ppToken.dval;       return FLOAT16CONSTANT;
716 #endif
717         case PpAtomIdentifier:
718         {
719             int token = tokenizeIdentifier();
720             field = false;
721             return token;
722         }
723
724         case EndOfInput:               return 0;
725
726         default:
727             char buf[2];
728             buf[0] = (char)token;
729             buf[1] = 0;
730             parseContext.error(loc, "unexpected token", buf, "");
731             break;
732         }
733     } while (true);
734 }
735
736 int TScanContext::tokenizeIdentifier()
737 {
738     if (ReservedSet->find(tokenText) != ReservedSet->end())
739         return reservedWord();
740
741     auto it = KeywordMap->find(tokenText);
742     if (it == KeywordMap->end()) {
743         // Should have an identifier of some sort
744         return identifierOrType();
745     }
746     keyword = it->second;
747
748     switch (keyword) {
749     case CONST:
750     case UNIFORM:
751     case IN:
752     case OUT:
753     case INOUT:
754     case STRUCT:
755     case BREAK:
756     case CONTINUE:
757     case DO:
758     case FOR:
759     case WHILE:
760     case IF:
761     case ELSE:
762     case DISCARD:
763     case RETURN:
764     case CASE:
765         return keyword;
766
767     case SWITCH:
768     case DEFAULT:
769         if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
770             (parseContext.profile != EEsProfile && parseContext.version < 130))
771             reservedWord();
772         return keyword;
773
774     case VOID:
775     case BOOL:
776     case FLOAT:
777     case INT:
778     case BVEC2:
779     case BVEC3:
780     case BVEC4:
781     case VEC2:
782     case VEC3:
783     case VEC4:
784     case IVEC2:
785     case IVEC3:
786     case IVEC4:
787     case MAT2:
788     case MAT3:
789     case MAT4:
790     case SAMPLER2D:
791     case SAMPLERCUBE:
792         afterType = true;
793         return keyword;
794
795     case BOOLCONSTANT:
796         if (strcmp("true", tokenText) == 0)
797             parserToken->sType.lex.b = true;
798         else
799             parserToken->sType.lex.b = false;
800         return keyword;
801
802     case ATTRIBUTE:
803     case VARYING:
804         if (parseContext.profile == EEsProfile && parseContext.version >= 300)
805             reservedWord();
806         return keyword;
807
808     case BUFFER:
809         if ((parseContext.profile == EEsProfile && parseContext.version < 310) ||
810             (parseContext.profile != EEsProfile && parseContext.version < 430))
811             return identifierOrType();
812         return keyword;
813
814     case ATOMIC_UINT:
815         if ((parseContext.profile == EEsProfile && parseContext.version >= 310) ||
816             parseContext.extensionTurnedOn(E_GL_ARB_shader_atomic_counters))
817             return keyword;
818         return es30ReservedFromGLSL(420);
819
820     case COHERENT:
821     case RESTRICT:
822     case READONLY:
823     case WRITEONLY:
824         if (parseContext.profile == EEsProfile && parseContext.version >= 310)
825             return keyword;
826         return es30ReservedFromGLSL(parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store) ? 130 : 420);
827
828     case VOLATILE:
829         if (parseContext.profile == EEsProfile && parseContext.version >= 310)
830             return keyword;
831         if (! parseContext.symbolTable.atBuiltInLevel() && (parseContext.profile == EEsProfile || (parseContext.version < 420 && ! parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))))
832             reservedWord();
833         return keyword;
834
835     case LAYOUT:
836     {
837         const int numLayoutExts = 2;
838         const char* layoutExts[numLayoutExts] = { E_GL_ARB_shading_language_420pack,
839                                                   E_GL_ARB_explicit_attrib_location };
840         if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
841             (parseContext.profile != EEsProfile && parseContext.version < 140 &&
842             ! parseContext.extensionsTurnedOn(numLayoutExts, layoutExts)))
843             return identifierOrType();
844         return keyword;
845     }
846     case SHARED:
847         if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
848             (parseContext.profile != EEsProfile && parseContext.version < 140))
849             return identifierOrType();
850         return keyword;
851
852     case PATCH:
853         if (parseContext.symbolTable.atBuiltInLevel() ||
854             (parseContext.profile == EEsProfile && parseContext.extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader)) ||
855             (parseContext.profile != EEsProfile && parseContext.extensionTurnedOn(E_GL_ARB_tessellation_shader)))
856             return keyword;
857
858         return es30ReservedFromGLSL(400);
859
860     case SAMPLE:
861         if (parseContext.extensionsTurnedOn(1, &E_GL_OES_shader_multisample_interpolation))
862             return keyword;
863         return es30ReservedFromGLSL(400);
864
865     case SUBROUTINE:
866         return es30ReservedFromGLSL(400);
867
868     case HIGH_PRECISION:
869     case MEDIUM_PRECISION:
870     case LOW_PRECISION:
871     case PRECISION:
872         return precisionKeyword();
873
874     case MAT2X2:
875     case MAT2X3:
876     case MAT2X4:
877     case MAT3X2:
878     case MAT3X3:
879     case MAT3X4:
880     case MAT4X2:
881     case MAT4X3:
882     case MAT4X4:
883         return matNxM();
884
885     case DMAT2:
886     case DMAT3:
887     case DMAT4:
888     case DMAT2X2:
889     case DMAT2X3:
890     case DMAT2X4:
891     case DMAT3X2:
892     case DMAT3X3:
893     case DMAT3X4:
894     case DMAT4X2:
895     case DMAT4X3:
896     case DMAT4X4:
897         return dMat();
898
899     case IMAGE1D:
900     case IIMAGE1D:
901     case UIMAGE1D:
902     case IMAGE1DARRAY:
903     case IIMAGE1DARRAY:
904     case UIMAGE1DARRAY:
905     case IMAGE2DRECT:
906     case IIMAGE2DRECT:
907     case UIMAGE2DRECT:
908         afterType = true;
909         return firstGenerationImage(false);
910
911     case IMAGEBUFFER:
912     case IIMAGEBUFFER:
913     case UIMAGEBUFFER:
914         afterType = true;
915         if (parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
916             return keyword;
917         return firstGenerationImage(false);
918
919     case IMAGE2D:
920     case IIMAGE2D:
921     case UIMAGE2D:
922     case IMAGE3D:
923     case IIMAGE3D:
924     case UIMAGE3D:
925     case IMAGECUBE:
926     case IIMAGECUBE:
927     case UIMAGECUBE:
928     case IMAGE2DARRAY:
929     case IIMAGE2DARRAY:
930     case UIMAGE2DARRAY:
931         afterType = true;
932         return firstGenerationImage(true);
933
934     case IMAGECUBEARRAY:
935     case IIMAGECUBEARRAY:
936     case UIMAGECUBEARRAY:
937         afterType = true;
938         if (parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
939             return keyword;
940         return secondGenerationImage();
941
942     case IMAGE2DMS:
943     case IIMAGE2DMS:
944     case UIMAGE2DMS:
945     case IMAGE2DMSARRAY:
946     case IIMAGE2DMSARRAY:
947     case UIMAGE2DMSARRAY:
948         afterType = true;
949         return secondGenerationImage();
950
951     case DOUBLE:
952     case DVEC2:
953     case DVEC3:
954     case DVEC4:
955         afterType = true;
956         if (parseContext.profile == EEsProfile || parseContext.version < 400)
957             reservedWord();
958         return keyword;
959
960     case INT64_T:
961     case UINT64_T:
962     case I64VEC2:
963     case I64VEC3:
964     case I64VEC4:
965     case U64VEC2:
966     case U64VEC3:
967     case U64VEC4:
968         afterType = true;
969         if (parseContext.symbolTable.atBuiltInLevel() ||
970             (parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64) &&
971              parseContext.profile != EEsProfile && parseContext.version >= 450))
972             return keyword;
973         return identifierOrType();
974
975 #ifdef AMD_EXTENSIONS
976     case FLOAT16_T:
977     case F16VEC2:
978     case F16VEC3:
979     case F16VEC4:
980     case F16MAT2:
981     case F16MAT3:
982     case F16MAT4:
983     case F16MAT2X2:
984     case F16MAT2X3:
985     case F16MAT2X4:
986     case F16MAT3X2:
987     case F16MAT3X3:
988     case F16MAT3X4:
989     case F16MAT4X2:
990     case F16MAT4X3:
991     case F16MAT4X4:
992         afterType = true;
993         if (parseContext.symbolTable.atBuiltInLevel() ||
994             (parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) &&
995              parseContext.profile != EEsProfile && parseContext.version >= 450))
996             return keyword;
997         return identifierOrType();
998 #endif
999
1000     case SAMPLERCUBEARRAY:
1001     case SAMPLERCUBEARRAYSHADOW:
1002     case ISAMPLERCUBEARRAY:
1003     case USAMPLERCUBEARRAY:
1004         afterType = true;
1005         if (parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
1006             return keyword;
1007         if (parseContext.profile == EEsProfile || (parseContext.version < 400 && ! parseContext.extensionTurnedOn(E_GL_ARB_texture_cube_map_array)))
1008             reservedWord();
1009         return keyword;
1010
1011     case ISAMPLER1D:
1012     case ISAMPLER1DARRAY:
1013     case SAMPLER1DARRAYSHADOW:
1014     case USAMPLER1D:
1015     case USAMPLER1DARRAY:
1016         afterType = true;
1017         return es30ReservedFromGLSL(130);
1018
1019     case UINT:
1020     case UVEC2:
1021     case UVEC3:
1022     case UVEC4:
1023     case SAMPLERCUBESHADOW:
1024     case SAMPLER2DARRAY:
1025     case SAMPLER2DARRAYSHADOW:
1026     case ISAMPLER2D:
1027     case ISAMPLER3D:
1028     case ISAMPLERCUBE:
1029     case ISAMPLER2DARRAY:
1030     case USAMPLER2D:
1031     case USAMPLER3D:
1032     case USAMPLERCUBE:
1033     case USAMPLER2DARRAY:
1034         afterType = true;
1035         return nonreservedKeyword(300, 130);
1036
1037     case ISAMPLER2DRECT:
1038     case USAMPLER2DRECT:
1039         afterType = true;
1040         return es30ReservedFromGLSL(140);
1041
1042     case SAMPLERBUFFER:
1043         afterType = true;
1044         if (parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
1045             return keyword;
1046         return es30ReservedFromGLSL(130);
1047
1048     case ISAMPLERBUFFER:
1049     case USAMPLERBUFFER:
1050         afterType = true;
1051         if (parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
1052             return keyword;
1053         return es30ReservedFromGLSL(140);
1054
1055     case SAMPLER2DMS:
1056     case ISAMPLER2DMS:
1057     case USAMPLER2DMS:
1058         afterType = true;
1059         if (parseContext.profile == EEsProfile && parseContext.version >= 310)
1060             return keyword;
1061         return es30ReservedFromGLSL(150);
1062
1063     case SAMPLER2DMSARRAY:
1064     case ISAMPLER2DMSARRAY:
1065     case USAMPLER2DMSARRAY:
1066         afterType = true;
1067         if (parseContext.extensionsTurnedOn(1, &E_GL_OES_texture_storage_multisample_2d_array))
1068             return keyword;
1069         return es30ReservedFromGLSL(150);
1070
1071     case SAMPLER1D:
1072     case SAMPLER1DSHADOW:
1073         afterType = true;
1074         if (parseContext.profile == EEsProfile)
1075             reservedWord();
1076         return keyword;
1077
1078     case SAMPLER3D:
1079         afterType = true;
1080         if (parseContext.profile == EEsProfile && parseContext.version < 300) {
1081             if (! parseContext.extensionTurnedOn(E_GL_OES_texture_3D))
1082                 reservedWord();
1083         }
1084         return keyword;
1085
1086     case SAMPLER2DSHADOW:
1087         afterType = true;
1088         if (parseContext.profile == EEsProfile && parseContext.version < 300)
1089             reservedWord();
1090         return keyword;
1091
1092     case SAMPLER2DRECT:
1093     case SAMPLER2DRECTSHADOW:
1094         afterType = true;
1095         if (parseContext.profile == EEsProfile)
1096             reservedWord();
1097         else if (parseContext.version < 140 && ! parseContext.symbolTable.atBuiltInLevel() && ! parseContext.extensionTurnedOn(E_GL_ARB_texture_rectangle)) {
1098             if (parseContext.relaxedErrors())
1099                 parseContext.requireExtensions(loc, 1, &E_GL_ARB_texture_rectangle, "texture-rectangle sampler keyword");
1100             else
1101                 reservedWord();
1102         }
1103         return keyword;
1104
1105     case SAMPLER1DARRAY:
1106         afterType = true;
1107         if (parseContext.profile == EEsProfile && parseContext.version == 300)
1108             reservedWord();
1109         else if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
1110                  (parseContext.profile != EEsProfile && parseContext.version < 130))
1111             return identifierOrType();
1112         return keyword;
1113
1114     case SAMPLEREXTERNALOES:
1115         afterType = true;
1116         if (parseContext.symbolTable.atBuiltInLevel() || parseContext.extensionTurnedOn(E_GL_OES_EGL_image_external))
1117             return keyword;
1118         return identifierOrType();
1119
1120     case TEXTURE2D:
1121     case TEXTURECUBE:
1122     case TEXTURECUBEARRAY:
1123     case ITEXTURECUBEARRAY:
1124     case UTEXTURECUBEARRAY:
1125     case ITEXTURE1DARRAY:
1126     case UTEXTURE1D:
1127     case ITEXTURE1D:
1128     case UTEXTURE1DARRAY:
1129     case TEXTUREBUFFER:
1130     case TEXTURE2DARRAY:
1131     case ITEXTURE2D:
1132     case ITEXTURE3D:
1133     case ITEXTURECUBE:
1134     case ITEXTURE2DARRAY:
1135     case UTEXTURE2D:
1136     case UTEXTURE3D:
1137     case UTEXTURECUBE:
1138     case UTEXTURE2DARRAY:
1139     case ITEXTURE2DRECT:
1140     case UTEXTURE2DRECT:
1141     case ITEXTUREBUFFER:
1142     case UTEXTUREBUFFER:
1143     case TEXTURE2DMS:
1144     case ITEXTURE2DMS:
1145     case UTEXTURE2DMS:
1146     case TEXTURE2DMSARRAY:
1147     case ITEXTURE2DMSARRAY:
1148     case UTEXTURE2DMSARRAY:
1149     case TEXTURE1D:
1150     case TEXTURE3D:
1151     case TEXTURE2DRECT:
1152     case TEXTURE1DARRAY:
1153     case SAMPLER:
1154     case SAMPLERSHADOW:
1155         if (parseContext.spvVersion.vulkan >= 100)
1156             return keyword;
1157         else
1158             return identifierOrType();
1159
1160     case SUBPASSINPUT:
1161     case SUBPASSINPUTMS:
1162     case ISUBPASSINPUT:
1163     case ISUBPASSINPUTMS:
1164     case USUBPASSINPUT:
1165     case USUBPASSINPUTMS:
1166         if (parseContext.spvVersion.vulkan >= 100)
1167             return keyword;
1168         else
1169             return identifierOrType();
1170
1171     case NOPERSPECTIVE:
1172         return es30ReservedFromGLSL(130);
1173
1174     case SMOOTH:
1175         if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
1176             (parseContext.profile != EEsProfile && parseContext.version < 130))
1177             return identifierOrType();
1178         return keyword;
1179
1180 #ifdef AMD_EXTENSIONS
1181     case __EXPLICITINTERPAMD:
1182         if (parseContext.profile != EEsProfile && parseContext.version >= 450 &&
1183             parseContext.extensionTurnedOn(E_GL_AMD_shader_explicit_vertex_parameter))
1184             return keyword;
1185         return identifierOrType();
1186 #endif
1187
1188     case FLAT:
1189         if (parseContext.profile == EEsProfile && parseContext.version < 300)
1190             reservedWord();
1191         else if (parseContext.profile != EEsProfile && parseContext.version < 130)
1192             return identifierOrType();
1193         return keyword;
1194
1195     case CENTROID:
1196         if (parseContext.version < 120)
1197             return identifierOrType();
1198         return keyword;
1199
1200     case PRECISE:
1201         if ((parseContext.profile == EEsProfile && parseContext.extensionsTurnedOn(Num_AEP_gpu_shader5, AEP_gpu_shader5)) ||
1202             (parseContext.profile != EEsProfile && parseContext.version >= 400))
1203             return keyword;
1204         if (parseContext.profile == EEsProfile && parseContext.version == 310) {
1205             reservedWord();
1206             return keyword;
1207         }
1208         return identifierOrType();
1209
1210     case INVARIANT:
1211         if (parseContext.profile != EEsProfile && parseContext.version < 120)
1212             return identifierOrType();
1213         return keyword;
1214
1215     case PACKED:
1216         if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
1217             (parseContext.profile != EEsProfile && parseContext.version < 330))
1218             return reservedWord();
1219         return identifierOrType();
1220
1221     case RESOURCE:
1222     {
1223         bool reserved = (parseContext.profile == EEsProfile && parseContext.version >= 300) ||
1224                         (parseContext.profile != EEsProfile && parseContext.version >= 420);
1225         return identifierOrReserved(reserved);
1226     }
1227     case SUPERP:
1228     {
1229         bool reserved = parseContext.profile == EEsProfile || parseContext.version >= 130;
1230         return identifierOrReserved(reserved);
1231     }
1232
1233     default:
1234         parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc);
1235         return 0;
1236     }
1237 }
1238
1239 int TScanContext::identifierOrType()
1240 {
1241     parserToken->sType.lex.string = NewPoolTString(tokenText);
1242     if (field)
1243         return IDENTIFIER;
1244
1245     parserToken->sType.lex.symbol = parseContext.symbolTable.find(*parserToken->sType.lex.string);
1246     if (afterType == false && parserToken->sType.lex.symbol) {
1247         if (const TVariable* variable = parserToken->sType.lex.symbol->getAsVariable()) {
1248             if (variable->isUserType()) {
1249                 afterType = true;
1250
1251                 return TYPE_NAME;
1252             }
1253         }
1254     }
1255
1256     return IDENTIFIER;
1257 }
1258
1259 // Give an error for use of a reserved symbol.
1260 // However, allow built-in declarations to use reserved words, to allow
1261 // extension support before the extension is enabled.
1262 int TScanContext::reservedWord()
1263 {
1264     if (! parseContext.symbolTable.atBuiltInLevel())
1265         parseContext.error(loc, "Reserved word.", tokenText, "", "");
1266
1267     return 0;
1268 }
1269
1270 int TScanContext::identifierOrReserved(bool reserved)
1271 {
1272     if (reserved) {
1273         reservedWord();
1274
1275         return 0;
1276     }
1277
1278     if (parseContext.forwardCompatible)
1279         parseContext.warn(loc, "using future reserved keyword", tokenText, "");
1280
1281     return identifierOrType();
1282 }
1283
1284 // For keywords that suddenly showed up on non-ES (not previously reserved)
1285 // but then got reserved by ES 3.0.
1286 int TScanContext::es30ReservedFromGLSL(int version)
1287 {
1288     if (parseContext.symbolTable.atBuiltInLevel())
1289         return keyword;
1290
1291     if ((parseContext.profile == EEsProfile && parseContext.version < 300) ||
1292         (parseContext.profile != EEsProfile && parseContext.version < version)) {
1293             if (parseContext.forwardCompatible)
1294                 parseContext.warn(loc, "future reserved word in ES 300 and keyword in GLSL", tokenText, "");
1295
1296             return identifierOrType();
1297     } else if (parseContext.profile == EEsProfile && parseContext.version >= 300)
1298         reservedWord();
1299
1300     return keyword;
1301 }
1302
1303 // For a keyword that was never reserved, until it suddenly
1304 // showed up, both in an es version and a non-ES version.
1305 int TScanContext::nonreservedKeyword(int esVersion, int nonEsVersion)
1306 {
1307     if ((parseContext.profile == EEsProfile && parseContext.version < esVersion) ||
1308         (parseContext.profile != EEsProfile && parseContext.version < nonEsVersion)) {
1309         if (parseContext.forwardCompatible)
1310             parseContext.warn(loc, "using future keyword", tokenText, "");
1311
1312         return identifierOrType();
1313     }
1314
1315     return keyword;
1316 }
1317
1318 int TScanContext::precisionKeyword()
1319 {
1320     if (parseContext.profile == EEsProfile || parseContext.version >= 130)
1321         return keyword;
1322
1323     if (parseContext.forwardCompatible)
1324         parseContext.warn(loc, "using ES precision qualifier keyword", tokenText, "");
1325
1326     return identifierOrType();
1327 }
1328
1329 int TScanContext::matNxM()
1330 {
1331     afterType = true;
1332
1333     if (parseContext.version > 110)
1334         return keyword;
1335
1336     if (parseContext.forwardCompatible)
1337         parseContext.warn(loc, "using future non-square matrix type keyword", tokenText, "");
1338
1339     return identifierOrType();
1340 }
1341
1342 int TScanContext::dMat()
1343 {
1344     afterType = true;
1345
1346     if (parseContext.profile == EEsProfile && parseContext.version >= 300) {
1347         reservedWord();
1348
1349         return keyword;
1350     }
1351
1352     if (parseContext.profile != EEsProfile && parseContext.version >= 400)
1353         return keyword;
1354
1355     if (parseContext.forwardCompatible)
1356         parseContext.warn(loc, "using future type keyword", tokenText, "");
1357
1358     return identifierOrType();
1359 }
1360
1361 int TScanContext::firstGenerationImage(bool inEs310)
1362 {
1363     if (parseContext.symbolTable.atBuiltInLevel() ||
1364         (parseContext.profile != EEsProfile && (parseContext.version >= 420 || parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))) ||
1365         (inEs310 && parseContext.profile == EEsProfile && parseContext.version >= 310))
1366         return keyword;
1367
1368     if ((parseContext.profile == EEsProfile && parseContext.version >= 300) ||
1369         (parseContext.profile != EEsProfile && parseContext.version >= 130)) {
1370         reservedWord();
1371
1372         return keyword;
1373     }
1374
1375     if (parseContext.forwardCompatible)
1376         parseContext.warn(loc, "using future type keyword", tokenText, "");
1377
1378     return identifierOrType();
1379 }
1380
1381 int TScanContext::secondGenerationImage()
1382 {
1383     if (parseContext.profile == EEsProfile && parseContext.version >= 310) {
1384         reservedWord();
1385         return keyword;
1386     }
1387
1388     if (parseContext.symbolTable.atBuiltInLevel() ||
1389         (parseContext.profile != EEsProfile &&
1390          (parseContext.version >= 420 || parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))))
1391         return keyword;
1392
1393     if (parseContext.forwardCompatible)
1394         parseContext.warn(loc, "using future type keyword", tokenText, "");
1395
1396     return identifierOrType();
1397 }
1398
1399 } // end namespace glslang