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