diff options
author | John Kessenich <cepheus@frii.com> | 2013-07-06 19:54:21 +0000 |
---|---|---|
committer | John Kessenich <cepheus@frii.com> | 2013-07-06 19:54:21 +0000 |
commit | 5f1a0b7998132b39c41fbe28d44bcb4bbd53bcd9 (patch) | |
tree | 3a15de2c3e5b5296c32e76c597528aa4a28adf5a /glslang/MachineIndependent/Scan.cpp | |
parent | 73ed17a87beafc5951b76ff0b823965c040fd1f0 (diff) | |
download | glslang-5f1a0b7998132b39c41fbe28d44bcb4bbd53bcd9.tar.gz |
Eliminate flex as the GLSL lexical analyzer, going from two nested lexical analyzers down to one, leaving just the preprocessor's lexical analysis. A new layer replaces it, to translate from the preprocessor's view of tokenization to glslang's view of tokenization.
Also:
- change source locations from an int to TSourceLoc (shader number, line number) throughout
- various improvements to the preprocessor
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@22277 e7fa87d3-cd2b-0410-9028-fcbf551c1848
Diffstat (limited to 'glslang/MachineIndependent/Scan.cpp')
-rw-r--r-- | glslang/MachineIndependent/Scan.cpp | 815 |
1 files changed, 812 insertions, 3 deletions
diff --git a/glslang/MachineIndependent/Scan.cpp b/glslang/MachineIndependent/Scan.cpp index d7f1119e..ca9af6ac 100644 --- a/glslang/MachineIndependent/Scan.cpp +++ b/glslang/MachineIndependent/Scan.cpp @@ -34,9 +34,24 @@ //POSSIBILITY OF SUCH DAMAGE. // +// +// GLSL scanning, leveraging the scanning done by the preprocessor. +// + #include <string.h> #include "Scan.h" +#include "Include/Types.h" +#include "SymbolTable.h" +#include "glslang_tab.cpp.h" +#include "ParseHelper.h" +#include "ScanContext.h" + +// preprocessor includes +extern "C" { + #include "preprocessor/parser.h" + #include "preprocessor/preprocess.h" +} namespace glslang { @@ -138,10 +153,14 @@ void ConsumeWhitespaceComment(TInputScanner& input, bool& foundNonSpaceTab) } while (true); } -// Returns true if there was non-white space (e.g., a comment, newline) before the #version; -// otherwise, returns true. +// Returns true if there was non-white space (e.g., a comment, newline) before the #version +// or no #version was found; otherwise, returns false. There is no error case, it always +// succeeds, but will leave version == 0 if no #version was found. +// +// N.B. does not attempt to leave input in any particular known state. The assumption +// is that scanning will start anew, following the rules for the chosen version/profile, +// and with a corresponding parsing context. // -// N.B. does not attempt to leave input in any particular known state bool ScanVersion(TInputScanner& input, int& version, EProfile& profile) { // This function doesn't have to get all the semantics correct, @@ -214,3 +233,793 @@ bool ScanVersion(TInputScanner& input, int& version, EProfile& profile) } }; // end glslang namespace + +namespace glslang { + +// This gets filled in by the preprocessor scanner. +class TPpToken{ +public: + yystypepp lexer; +}; + +// Fill this in when doing glslang-level scanning, to hand back to the parser. +class TParserToken { +public: + explicit TParserToken(YYSTYPE& b) : sType(b) { } + + YYSTYPE& sType; +}; + +}; // end namespace glslang + +// This is the function the glslang parser (i.e., bison) calls to get its next token +int yylex(YYSTYPE* glslangTokenDesc, TParseContext& parseContext) +{ + glslang::TParserToken token(*glslangTokenDesc); + + return parseContext.scanContext->tokenize(token); +} + +namespace { + +// A single global usable by all threads, by all versions, by all languages. +// After a single process-level initialization, this is read only and thread safe +std::map<std::string, int>* KeywordMap = 0; +std::set<std::string>* ReservedSet = 0; + +}; + +namespace glslang { + +void TScanContext::fillInKeywordMap() +{ + if (KeywordMap != 0) { + // this is really an error, as this should called only once per process + // but, the only risk is if two threads called simultaneously + return; + } + KeywordMap = new std::map<std::string, int>; + + (*KeywordMap)["const"] = CONST; + (*KeywordMap)["uniform"] = UNIFORM; + (*KeywordMap)["in"] = IN; + (*KeywordMap)["out"] = OUT; + (*KeywordMap)["inout"] = INOUT; + (*KeywordMap)["struct"] = STRUCT; + (*KeywordMap)["break"] = BREAK; + (*KeywordMap)["continue"] = CONTINUE; + (*KeywordMap)["do"] = DO; + (*KeywordMap)["for"] = FOR; + (*KeywordMap)["while"] = WHILE; + (*KeywordMap)["switch"] = SWITCH; + (*KeywordMap)["case"] = CASE; + (*KeywordMap)["default"] = DEFAULT; + (*KeywordMap)["if"] = IF; + (*KeywordMap)["else"] = ELSE; + (*KeywordMap)["discard"] = DISCARD; + (*KeywordMap)["return"] = RETURN; + (*KeywordMap)["void"] = VOID; + (*KeywordMap)["bool"] = BOOL; + (*KeywordMap)["float"] = FLOAT; + (*KeywordMap)["int"] = INT; + (*KeywordMap)["bvec2"] = BVEC2; + (*KeywordMap)["bvec3"] = BVEC3; + (*KeywordMap)["bvec4"] = BVEC4; + (*KeywordMap)["vec2"] = VEC2; + (*KeywordMap)["vec3"] = VEC3; + (*KeywordMap)["vec4"] = VEC4; + (*KeywordMap)["ivec2"] = IVEC2; + (*KeywordMap)["ivec3"] = IVEC3; + (*KeywordMap)["ivec4"] = IVEC4; + (*KeywordMap)["mat2"] = MAT2; + (*KeywordMap)["mat3"] = MAT3; + (*KeywordMap)["mat4"] = MAT4; + (*KeywordMap)["sampler2D"] = SAMPLER2D; + (*KeywordMap)["samplerCube"] = SAMPLERCUBE; + (*KeywordMap)["true"] = BOOLCONSTANT; + (*KeywordMap)["false"] = BOOLCONSTANT; + (*KeywordMap)["attribute"] = ATTRIBUTE; + (*KeywordMap)["varying"] = VARYING; + (*KeywordMap)["buffer"] = BUFFER; + (*KeywordMap)["coherent"] = COHERENT; + (*KeywordMap)["restrict"] = RESTRICT; + (*KeywordMap)["readonly"] = READONLY; + (*KeywordMap)["writeonly"] = WRITEONLY; + (*KeywordMap)["atomic_uint"] = ATOMIC_UINT; + (*KeywordMap)["volatile"] = VOLATILE; + (*KeywordMap)["layout"] = LAYOUT; + (*KeywordMap)["shared"] = SHARED; + (*KeywordMap)["patch"] = PATCH; + (*KeywordMap)["sample"] = SAMPLE; + (*KeywordMap)["subroutine"] = SUBROUTINE; + (*KeywordMap)["highp"] = HIGH_PRECISION; + (*KeywordMap)["mediump"] = MEDIUM_PRECISION; + (*KeywordMap)["lowp"] = LOW_PRECISION; + (*KeywordMap)["precision"] = PRECISION; + (*KeywordMap)["mat2x2"] = MAT2X2; + (*KeywordMap)["mat2x3"] = MAT2X3; + (*KeywordMap)["mat2x4"] = MAT2X4; + (*KeywordMap)["mat3x2"] = MAT3X2; + (*KeywordMap)["mat3x3"] = MAT3X3; + (*KeywordMap)["mat3x4"] = MAT3X4; + (*KeywordMap)["mat4x2"] = MAT4X2; + (*KeywordMap)["mat4x3"] = MAT4X3; + (*KeywordMap)["mat4x4"] = MAT4X4; + (*KeywordMap)["dmat2"] = DMAT2; + (*KeywordMap)["dmat3"] = DMAT3; + (*KeywordMap)["dmat4"] = DMAT4; + (*KeywordMap)["dmat2x2"] = DMAT2X2; + (*KeywordMap)["dmat2x3"] = DMAT2X3; + (*KeywordMap)["dmat2x4"] = DMAT2X4; + (*KeywordMap)["dmat3x2"] = DMAT3X2; + (*KeywordMap)["dmat3x3"] = DMAT3X3; + (*KeywordMap)["dmat3x4"] = DMAT3X4; + (*KeywordMap)["dmat4x2"] = DMAT4X2; + (*KeywordMap)["dmat4x3"] = DMAT4X3; + (*KeywordMap)["dmat4x4"] = DMAT4X4; + (*KeywordMap)["image1D"] = IMAGE1D; + (*KeywordMap)["iimage1D"] = IIMAGE1D; + (*KeywordMap)["uimage1D"] = UIMAGE1D; + (*KeywordMap)["image2D"] = IMAGE2D; + (*KeywordMap)["iimage2D"] = IIMAGE2D; + (*KeywordMap)["uimage2D"] = UIMAGE2D; + (*KeywordMap)["image3D"] = IMAGE3D; + (*KeywordMap)["iimage3D"] = IIMAGE3D; + (*KeywordMap)["uimage3D"] = UIMAGE3D; + (*KeywordMap)["image2DRect"] = IMAGE2DRECT; + (*KeywordMap)["iimage2DRect"] = IIMAGE2DRECT; + (*KeywordMap)["uimage2DRect"] = UIMAGE2DRECT; + (*KeywordMap)["imageCube"] = IMAGECUBE; + (*KeywordMap)["iimageCube"] = IIMAGECUBE; + (*KeywordMap)["uimageCube"] = UIMAGECUBE; + (*KeywordMap)["imageBuffer"] = IMAGEBUFFER; + (*KeywordMap)["iimageBuffer"] = IIMAGEBUFFER; + (*KeywordMap)["uimageBuffer"] = UIMAGEBUFFER; + (*KeywordMap)["image1DArray"] = IMAGE1DARRAY; + (*KeywordMap)["iimage1DArray"] = IIMAGE1DARRAY; + (*KeywordMap)["uimage1DArray"] = UIMAGE1DARRAY; + (*KeywordMap)["image2DArray"] = IMAGE2DARRAY; + (*KeywordMap)["iimage2DArray"] = IIMAGE2DARRAY; + (*KeywordMap)["uimage2DArray"] = UIMAGE2DARRAY; + (*KeywordMap)["imageCubeArray"] = IMAGECUBEARRAY; + (*KeywordMap)["iimageCubeArray"] = IIMAGECUBEARRAY; + (*KeywordMap)["uimageCubeArray"] = UIMAGECUBEARRAY; + (*KeywordMap)["image2DMS"] = IMAGE2DMS; + (*KeywordMap)["iimage2DMS"] = IIMAGE2DMS; + (*KeywordMap)["uimage2DMS"] = UIMAGE2DMS; + (*KeywordMap)["image2DMSArray"] = IMAGE2DMSARRAY; + (*KeywordMap)["iimage2DMSArray"] = IIMAGE2DMSARRAY; + (*KeywordMap)["uimage2DMSArray"] = UIMAGE2DMSARRAY; + (*KeywordMap)["double"] = DOUBLE; + (*KeywordMap)["dvec2"] = DVEC2; + (*KeywordMap)["dvec3"] = DVEC3; + (*KeywordMap)["dvec4"] = DVEC4; + (*KeywordMap)["samplerCubeArray"] = SAMPLERCUBEARRAY; + (*KeywordMap)["samplerCubeArrayShadow"] = SAMPLERCUBEARRAYSHADOW; + (*KeywordMap)["isamplerCubeArray"] = ISAMPLERCUBEARRAY; + (*KeywordMap)["usamplerCubeArray"] = USAMPLERCUBEARRAY; + (*KeywordMap)["sampler1DArrayShadow"] = SAMPLER1DARRAYSHADOW; + (*KeywordMap)["isampler1DArray"] = ISAMPLER1DARRAY; + (*KeywordMap)["usampler1D"] = USAMPLER1D; + (*KeywordMap)["isampler1D"] = ISAMPLER1D; + (*KeywordMap)["usampler1DArray"] = USAMPLER1DARRAY; + (*KeywordMap)["samplerBuffer"] = SAMPLERBUFFER; + (*KeywordMap)["uint"] = UINT; + (*KeywordMap)["uvec2"] = UVEC2; + (*KeywordMap)["uvec3"] = UVEC3; + (*KeywordMap)["uvec4"] = UVEC4; + (*KeywordMap)["samplerCubeShadow"] = SAMPLERCUBESHADOW; + (*KeywordMap)["sampler2DArray"] = SAMPLER2DARRAY; + (*KeywordMap)["sampler2DArrayShadow"] = SAMPLER2DARRAYSHADOW; + (*KeywordMap)["isampler2D"] = ISAMPLER2D; + (*KeywordMap)["isampler3D"] = ISAMPLER3D; + (*KeywordMap)["isamplerCube"] = ISAMPLERCUBE; + (*KeywordMap)["isampler2DArray"] = ISAMPLER2DARRAY; + (*KeywordMap)["usampler2D"] = USAMPLER2D; + (*KeywordMap)["usampler3D"] = USAMPLER3D; + (*KeywordMap)["usamplerCube"] = USAMPLERCUBE; + (*KeywordMap)["usampler2DArray"] = USAMPLER2DARRAY; + (*KeywordMap)["isampler2DRect"] = ISAMPLER2DRECT; + (*KeywordMap)["usampler2DRect"] = USAMPLER2DRECT; + (*KeywordMap)["isamplerBuffer"] = ISAMPLERBUFFER; + (*KeywordMap)["usamplerBuffer"] = USAMPLERBUFFER; + (*KeywordMap)["sampler2DMS"] = SAMPLER2DMS; + (*KeywordMap)["isampler2DMS"] = ISAMPLER2DMS; + (*KeywordMap)["usampler2DMS"] = USAMPLER2DMS; + (*KeywordMap)["sampler2DMSArray"] = SAMPLER2DMSARRAY; + (*KeywordMap)["isampler2DMSArray"] = ISAMPLER2DMSARRAY; + (*KeywordMap)["usampler2DMSArray"] = USAMPLER2DMSARRAY; + (*KeywordMap)["sampler1D"] = SAMPLER1D; + (*KeywordMap)["sampler1DShadow"] = SAMPLER1DSHADOW; + (*KeywordMap)["sampler3D"] = SAMPLER3D; + (*KeywordMap)["sampler2DShadow"] = SAMPLER2DSHADOW; + (*KeywordMap)["sampler2DRect"] = SAMPLER2DRECT; + (*KeywordMap)["sampler2DRectShadow"] = SAMPLER2DRECTSHADOW; + (*KeywordMap)["sampler1DArray"] = SAMPLER1DARRAY; + (*KeywordMap)["noperspective"] = NOPERSPECTIVE; + (*KeywordMap)["smooth"] = SMOOTH; + (*KeywordMap)["flat"] = FLAT; + (*KeywordMap)["centroid"] = CENTROID; + (*KeywordMap)["precise"] = PRECISE; + (*KeywordMap)["invariant"] = INVARIANT; + (*KeywordMap)["packed"] = PACKED; + (*KeywordMap)["resource"] = RESOURCE; + (*KeywordMap)["superp"] = SUPERP; + + ReservedSet = new std::set<std::string>; + + ReservedSet->insert("common"); + ReservedSet->insert("partition"); + ReservedSet->insert("active"); + ReservedSet->insert("asm"); + ReservedSet->insert("class"); + ReservedSet->insert("union"); + ReservedSet->insert("enum"); + ReservedSet->insert("typedef"); + ReservedSet->insert("template"); + ReservedSet->insert("this"); + ReservedSet->insert("goto"); + ReservedSet->insert("inline"); + ReservedSet->insert("noinline"); + ReservedSet->insert("public"); + ReservedSet->insert("static"); + ReservedSet->insert("extern"); + ReservedSet->insert("external"); + ReservedSet->insert("interface"); + ReservedSet->insert("long"); + ReservedSet->insert("short"); + ReservedSet->insert("half"); + ReservedSet->insert("fixed"); + ReservedSet->insert("unsigned"); + ReservedSet->insert("input"); + ReservedSet->insert("output"); + ReservedSet->insert("hvec2"); + ReservedSet->insert("hvec3"); + ReservedSet->insert("hvec4"); + ReservedSet->insert("fvec2"); + ReservedSet->insert("fvec3"); + ReservedSet->insert("fvec4"); + ReservedSet->insert("sampler3DRect"); + ReservedSet->insert("filter"); + ReservedSet->insert("sizeof"); + ReservedSet->insert("cast"); + ReservedSet->insert("namespace"); + ReservedSet->insert("using"); +} + +int TScanContext::tokenize(TParserToken& token) +{ + parserToken = &token; + TPpToken ppTokenStorage; + ppToken = &ppTokenStorage; + tokenText = PpTokenize(&ppToken->lexer); + + loc.string = cpp->tokenLoc->file; + loc.line = cpp->tokenLoc->line; + parserToken->sType.lex.loc = loc; + switch (ppToken->lexer.ppToken) { + case ';': afterType = false; return SEMICOLON; + case ',': afterType = false; return COMMA; + case ':': return COLON; + case '=': afterType = false; return EQUAL; + case '(': afterType = false; return LEFT_PAREN; + case ')': afterType = false; return RIGHT_PAREN; + case '.': field = true; return DOT; + case '!': return BANG; + case '-': return DASH; + case '~': return TILDE; + case '+': return PLUS; + case '*': return STAR; + case '/': return SLASH; + case '%': return PERCENT; + case '<': return LEFT_ANGLE; + case '>': return RIGHT_ANGLE; + case '|': return VERTICAL_BAR; + case '^': return CARET; + case '&': return AMPERSAND; + case '?': return QUESTION; + case '[': return LEFT_BRACKET; + case ']': return RIGHT_BRACKET; + case '{': return LEFT_BRACE; + case '}': return RIGHT_BRACE; + + case CPP_AND_OP: return AND_OP; + case CPP_SUB_ASSIGN: return SUB_ASSIGN; + case CPP_MOD_ASSIGN: return MOD_ASSIGN; + case CPP_ADD_ASSIGN: return ADD_ASSIGN; + case CPP_DIV_ASSIGN: return DIV_ASSIGN; + case CPP_MUL_ASSIGN: return MUL_ASSIGN; + case CPP_EQ_OP: return EQ_OP; + case CPP_XOR_OP: return XOR_OP; + case CPP_GE_OP: return GE_OP; + case CPP_RIGHT_OP: return RIGHT_OP; + case CPP_LE_OP: return LE_OP; + case CPP_LEFT_OP: return LEFT_OP; + case CPP_DEC_OP: return DEC_OP; + case CPP_NE_OP: return NE_OP; + case CPP_OR_OP: return OR_OP; + case CPP_INC_OP: return INC_OP; + case CPP_RIGHT_ASSIGN: return RIGHT_ASSIGN; + case CPP_LEFT_ASSIGN: return LEFT_ASSIGN; + case CPP_AND_ASSIGN: return AND_ASSIGN; + case CPP_OR_ASSIGN: return OR_ASSIGN; + case CPP_XOR_ASSIGN: return XOR_ASSIGN; + + case CPP_INTCONSTANT: parserToken->sType.lex.i = ppToken->lexer.sc_int; return INTCONSTANT; + case CPP_UINTCONSTANT: parserToken->sType.lex.i = ppToken->lexer.sc_int; return UINTCONSTANT; + case CPP_FLOATCONSTANT: parserToken->sType.lex.d = ppToken->lexer.sc_dval; return FLOATCONSTANT; + case CPP_DOUBLECONSTANT: parserToken->sType.lex.d = ppToken->lexer.sc_dval; return DOUBLECONSTANT; + case CPP_IDENTIFIER: return tokenizeIdentifier(); + + case EOF: return 0; + + default: + parseContext.infoSink.info.message(EPrefixInternalError, "Unknown PP token", loc); + return 0; + } +} + +int TScanContext::tokenizeIdentifier() +{ + if (ReservedSet->find(tokenText) != ReservedSet->end()) + return reservedWord(); + + keyword = (*KeywordMap)[tokenText]; + if (keyword == 0) { + // Should have an identifier of some sort + return identifierOrType(); + } + field = false; + + switch (keyword) { + case CONST: + case UNIFORM: + case IN: + case OUT: + case INOUT: + case STRUCT: + case BREAK: + case CONTINUE: + case DO: + case FOR: + case WHILE: + case IF: + case ELSE: + case DISCARD: + case RETURN: + case CASE: + return keyword; + + case SWITCH: + case DEFAULT: + if (parseContext.profile == EEsProfile && parseContext.version < 300 || + parseContext.profile != EEsProfile && parseContext.version < 130) + reservedWord(); + return keyword; + + case VOID: + case BOOL: + case FLOAT: + case INT: + case BVEC2: + case BVEC3: + case BVEC4: + case VEC2: + case VEC3: + case VEC4: + case IVEC2: + case IVEC3: + case IVEC4: + case MAT2: + case MAT3: + case MAT4: + case SAMPLER2D: + case SAMPLERCUBE: + afterType = true; + return keyword; + + case BOOLCONSTANT: + if (strcmp("true", tokenText) == 0) + parserToken->sType.lex.b = true; + else + parserToken->sType.lex.b = false; + return keyword; + + case ATTRIBUTE: + case VARYING: + if (parseContext.profile == EEsProfile && parseContext.version >= 300) + reservedWord(); + return keyword; + + case BUFFER: + if (parseContext.version < 430) + return identifierOrType(); + return keyword; + + case COHERENT: + case RESTRICT: + case READONLY: + case WRITEONLY: + case ATOMIC_UINT: + return es30ReservedFromGLSL(420); + + case VOLATILE: + if (parseContext.profile == EEsProfile || parseContext.version < 420) + reservedWord(); + return keyword; + + case LAYOUT: + case SHARED: + if (parseContext.profile == EEsProfile && parseContext.version < 300 || + parseContext.profile != EEsProfile && parseContext.version < 140) + return identifierOrType(); + return keyword; + + case PATCH: + case SAMPLE: + case SUBROUTINE: + return es30ReservedFromGLSL(400); + + case HIGH_PRECISION: + case MEDIUM_PRECISION: + case LOW_PRECISION: + case PRECISION: + return precisionKeyword(); + + case MAT2X2: + case MAT2X3: + case MAT2X4: + case MAT3X2: + case MAT3X3: + case MAT3X4: + case MAT4X2: + case MAT4X3: + case MAT4X4: + return matNxM(); + + case DMAT2: + case DMAT3: + case DMAT4: + case DMAT2X2: + case DMAT2X3: + case DMAT2X4: + case DMAT3X2: + case DMAT3X3: + case DMAT3X4: + case DMAT4X2: + case DMAT4X3: + case DMAT4X4: + return dMat(); + + case IMAGE1D: + case IIMAGE1D: + case UIMAGE1D: + case IMAGE2D: + case IIMAGE2D: + case UIMAGE2D: + case IMAGE3D: + case IIMAGE3D: + case UIMAGE3D: + case IMAGE2DRECT: + case IIMAGE2DRECT: + case UIMAGE2DRECT: + case IMAGECUBE: + case IIMAGECUBE: + case UIMAGECUBE: + case IMAGEBUFFER: + case IIMAGEBUFFER: + case UIMAGEBUFFER: + case IMAGE1DARRAY: + case IIMAGE1DARRAY: + case UIMAGE1DARRAY: + case IMAGE2DARRAY: + case IIMAGE2DARRAY: + case UIMAGE2DARRAY: + return firstGenerationImage(); + + case IMAGECUBEARRAY: + case IIMAGECUBEARRAY: + case UIMAGECUBEARRAY: + case IMAGE2DMS: + case IIMAGE2DMS: + case UIMAGE2DMS: + case IMAGE2DMSARRAY: + case IIMAGE2DMSARRAY: + case UIMAGE2DMSARRAY: + return secondGenerationImage(); + + case DOUBLE: + case DVEC2: + case DVEC3: + case DVEC4: + case SAMPLERCUBEARRAY: + case SAMPLERCUBEARRAYSHADOW: + case ISAMPLERCUBEARRAY: + case USAMPLERCUBEARRAY: + afterType = true; + if (parseContext.profile == EEsProfile || parseContext.version < 400) + reservedWord(); + return keyword; + + case ISAMPLER1D: + case ISAMPLER1DARRAY: + case SAMPLER1DARRAYSHADOW: + case USAMPLER1D: + case USAMPLER1DARRAY: + case SAMPLERBUFFER: + afterType = true; + return es30ReservedFromGLSL(130); + + case UINT: + case UVEC2: + case UVEC3: + case UVEC4: + case SAMPLERCUBESHADOW: + case SAMPLER2DARRAY: + case SAMPLER2DARRAYSHADOW: + case ISAMPLER2D: + case ISAMPLER3D: + case ISAMPLERCUBE: + case ISAMPLER2DARRAY: + case USAMPLER2D: + case USAMPLER3D: + case USAMPLERCUBE: + case USAMPLER2DARRAY: + afterType = true; + return nonreservedKeyword(300, 130); + + case ISAMPLER2DRECT: + case USAMPLER2DRECT: + case ISAMPLERBUFFER: + case USAMPLERBUFFER: + afterType = true; + return es30ReservedFromGLSL(140); + + case SAMPLER2DMS: + case ISAMPLER2DMS: + case USAMPLER2DMS: + case SAMPLER2DMSARRAY: + case ISAMPLER2DMSARRAY: + case USAMPLER2DMSARRAY: + afterType = true; + return es30ReservedFromGLSL(150); + + case SAMPLER1D: + case SAMPLER1DSHADOW: + afterType = true; + if (parseContext.profile == EEsProfile) + reservedWord(); + return keyword; + + case SAMPLER3D: + case SAMPLER2DSHADOW: + afterType = true; + if (parseContext.profile == EEsProfile && parseContext.version < 300) + reservedWord(); + return keyword; + + case SAMPLER2DRECT: + case SAMPLER2DRECTSHADOW: + afterType = true; + if (parseContext.profile == EEsProfile || + parseContext.profile != EEsProfile && parseContext.version < 140) + reservedWord(); + return keyword; + + case SAMPLER1DARRAY: + afterType = true; + if (parseContext.profile == EEsProfile && parseContext.version == 300) + reservedWord(); + else if (parseContext.profile == EEsProfile && parseContext.version < 300 || + parseContext.profile != EEsProfile && parseContext.version < 130) + return identifierOrType(); + return keyword; + + case NOPERSPECTIVE: + return es30ReservedFromGLSL(130); + + case SMOOTH: + if (parseContext.profile == EEsProfile && parseContext.version < 300 || + parseContext.profile != EEsProfile && parseContext.version < 130) + return identifierOrType(); + return keyword; + + case FLAT: + if (parseContext.profile == EEsProfile && parseContext.version < 300) + reservedWord(); + else if (parseContext.profile != EEsProfile && parseContext.version < 130) + return identifierOrType(); + return keyword; + + case CENTROID: + if (parseContext.version < 120) + return identifierOrType(); + return keyword; + + case PRECISE: + if (parseContext.profile == EEsProfile || + parseContext.profile != EEsProfile && parseContext.version < 400) + return identifierOrType(); + return keyword; + + case INVARIANT: + if (parseContext.profile != EEsProfile && parseContext.version < 120) + return identifierOrType(); + return keyword; + + case PACKED: + if (parseContext.profile == EEsProfile && parseContext.version < 300 || + parseContext.profile != EEsProfile && parseContext.version < 330) + return reservedWord(); + return identifierOrType(); + + case RESOURCE: + { + bool reserved = parseContext.profile == EEsProfile && parseContext.version >= 300 || + parseContext.profile != EEsProfile && parseContext.version >= 420; + return identifierOrReserved(reserved); + } + case SUPERP: + { + bool reserved = parseContext.profile == EEsProfile || parseContext.version >= 130; + return identifierOrReserved(reserved); + } + + default: + parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc); + return 0; + } +} + +int TScanContext::identifierOrType() +{ + parserToken->sType.lex.string = NewPoolTString(tokenText); + if (field) { + field = false; + + return FIELD_SELECTION; + } + + parserToken->sType.lex.symbol = parseContext.symbolTable.find(*parserToken->sType.lex.string); + if (afterType == false && parserToken->sType.lex.symbol) { + if (TVariable* variable = parserToken->sType.lex.symbol->getAsVariable()) { + if (variable->isUserType()) { + afterType = true; + + return TYPE_NAME; + } + } + } + + return IDENTIFIER; +} + +int TScanContext::reservedWord() +{ + ThreadLocalParseContext()->error(loc, "Reserved word.", tokenText, "", ""); + + return 0; +} + +int TScanContext::identifierOrReserved(bool reserved) +{ + if (reserved) { + reservedWord(); + + return 0; + } + + if (parseContext.forwardCompatible) + parseContext.warn(loc, "using future reserved keyword", tokenText, ""); + + return identifierOrType(); +} + +// For keywords that suddenly showed up on non-ES (not previously reserved) +// but then got reserved by ES 3.0. +int TScanContext::es30ReservedFromGLSL(int version) +{ + if (parseContext.profile == EEsProfile && parseContext.version < 300 || + parseContext.profile != EEsProfile && parseContext.version < version) { + if (parseContext.forwardCompatible) + parseContext.warn(loc, "future reserved word in ES 300 and keyword in GLSL", tokenText, ""); + + return identifierOrType(); + } else if (parseContext.profile == EEsProfile && parseContext.version >= 300) + reservedWord(); + + return keyword; +} + +// For a keyword that was never reserved, until it suddenly +// showed up, both in an es version and a non-ES version. +int TScanContext::nonreservedKeyword(int esVersion, int nonEsVersion) +{ + if (parseContext.profile == EEsProfile && parseContext.version < esVersion || + parseContext.profile != EEsProfile && parseContext.version < nonEsVersion) { + if (parseContext.forwardCompatible) + parseContext.warn(loc, "using future keyword", tokenText, ""); + + return identifierOrType(); + } + + return keyword; +} + +int TScanContext::precisionKeyword() +{ + if (parseContext.profile == EEsProfile || parseContext.version >= 130) + return keyword; + + if (parseContext.forwardCompatible) + parseContext.warn(loc, "using ES precision qualifier keyword", tokenText, ""); + + return identifierOrType(); +} + +int TScanContext::matNxM() +{ + afterType = true; + + if (parseContext.version > 110) + return keyword; + + if (parseContext.forwardCompatible) + parseContext.warn(loc, "using future non-square matrix type keyword", tokenText, ""); + + return identifierOrType(); +} + +int TScanContext::dMat() +{ + afterType = true; + + if (parseContext.profile == EEsProfile && parseContext.version >= 300) { + reservedWord(); + + return keyword; + } + + if (parseContext.profile != EEsProfile && parseContext.version >= 400) + return keyword; + + if (parseContext.forwardCompatible) + parseContext.warn(loc, "using future type keyword", tokenText, ""); + + return identifierOrType(); +} + +int TScanContext::firstGenerationImage() +{ + afterType = true; + + if (parseContext.profile != EEsProfile && parseContext.version >= 420) + return keyword; + + if (parseContext.profile == EEsProfile && parseContext.version >= 300 || + parseContext.profile != EEsProfile && parseContext.version >= 130) { + reservedWord(); + + return keyword; + } + + if (parseContext.forwardCompatible) + parseContext.warn(loc, "using future type keyword", tokenText, ""); + + return identifierOrType(); +} + +int TScanContext::secondGenerationImage() +{ + afterType = true; + + if (parseContext.profile != EEsProfile && parseContext.version >= 420) + return keyword; + + if (parseContext.forwardCompatible) + parseContext.warn(loc, "using future type keyword", tokenText, ""); + + return identifierOrType(); +} + +}; |