/* // Copyright 2016 The SwiftShader Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. This file contains the Lex specification for GLSL ES. Based on ANSI C grammar, Lex specification: http://www.lysator.liu.se/c/ANSI-C-grammar-l.html IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh, WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). */ %top{ // Copyright 2016 The SwiftShader Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // This file is auto-generated by generate_parser.sh. DO NOT EDIT! // Ignore errors in auto-generated code. #if defined(__GNUC__) #pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wunused-variable" #pragma GCC diagnostic ignored "-Wswitch-enum" #elif defined(_MSC_VER) #pragma warning(disable: 4065) #pragma warning(disable: 4189) #pragma warning(disable: 4505) #pragma warning(disable: 4701) #endif } %{ #include "glslang.h" #include "ParseHelper.h" #include "preprocessor/Token.h" #include "util.h" #include "glslang_tab.h" /* windows only pragma */ #ifdef _MSC_VER #pragma warning(disable : 4102) #endif #define YY_USER_ACTION \ yylloc->first_file = yylloc->last_file = yycolumn; \ yylloc->first_line = yylloc->last_line = yylineno; #define YY_INPUT(buf, result, max_size) \ result = string_input(buf, max_size, yyscanner); static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner); static int check_type(yyscan_t yyscanner); static int reserved_word(yyscan_t yyscanner); static int ES2_reserved_ES3_keyword(TParseContext *context, int token); static int ES2_keyword_ES3_reserved(TParseContext *context, int token); static int ES2_identifier_ES3_keyword(TParseContext *context, int token); static int uint_constant(TParseContext *context); static int int_constant(yyscan_t yyscanner); static int float_constant(yyscan_t yyscanner); static int floatsuffix_check(TParseContext* context); %} %option noyywrap nounput never-interactive %option yylineno reentrant bison-bridge bison-locations %option extra-type="TParseContext*" %x COMMENT FIELDS D [0-9] L [a-zA-Z_] H [a-fA-F0-9] E [Ee][+-]?{D}+ O [0-7] %% %{ TParseContext* context = yyextra; %} "invariant" { return(INVARIANT); } "highp" { return(HIGH_PRECISION); } "mediump" { return(MEDIUM_PRECISION); } "lowp" { return(LOW_PRECISION); } "precision" { return(PRECISION); } "attribute" { return ES2_keyword_ES3_reserved(context, ATTRIBUTE); } "const" { return(CONST_QUAL); } "uniform" { return(UNIFORM); } "varying" { return ES2_keyword_ES3_reserved(context, VARYING); } "break" { return(BREAK); } "continue" { return(CONTINUE); } "do" { return(DO); } "for" { return(FOR); } "while" { return(WHILE); } "if" { return(IF); } "else" { return(ELSE); } "switch" { return ES2_reserved_ES3_keyword(context, SWITCH); } "case" { return ES2_reserved_ES3_keyword(context, CASE); } "default" { return ES2_reserved_ES3_keyword(context, DEFAULT); } "centroid" { return ES2_reserved_ES3_keyword(context, CENTROID); } "flat" { return ES2_reserved_ES3_keyword(context, FLAT); } "smooth" { return ES2_reserved_ES3_keyword(context, SMOOTH); } "in" { return(IN_QUAL); } "out" { return(OUT_QUAL); } "inout" { return(INOUT_QUAL); } "float" { context->lexAfterType = true; return(FLOAT_TYPE); } "int" { context->lexAfterType = true; return(INT_TYPE); } "uint" { return ES2_identifier_ES3_keyword(context, UINT_TYPE); } "void" { context->lexAfterType = true; return(VOID_TYPE); } "bool" { context->lexAfterType = true; return(BOOL_TYPE); } "true" { yylval->lex.b = true; return(BOOLCONSTANT); } "false" { yylval->lex.b = false; return(BOOLCONSTANT); } "discard" { return(DISCARD); } "return" { return(RETURN); } "mat2" { context->lexAfterType = true; return(MATRIX2); } "mat3" { context->lexAfterType = true; return(MATRIX3); } "mat4" { context->lexAfterType = true; return(MATRIX4); } "mat2x2" { return ES2_identifier_ES3_keyword(context, MATRIX2); } "mat3x3" { return ES2_identifier_ES3_keyword(context, MATRIX3); } "mat4x4" { return ES2_identifier_ES3_keyword(context, MATRIX4); } "mat2x3" { return ES2_identifier_ES3_keyword(context, MATRIX2x3); } "mat3x2" { return ES2_identifier_ES3_keyword(context, MATRIX3x2); } "mat2x4" { return ES2_identifier_ES3_keyword(context, MATRIX2x4); } "mat4x2" { return ES2_identifier_ES3_keyword(context, MATRIX4x2); } "mat3x4" { return ES2_identifier_ES3_keyword(context, MATRIX3x4); } "mat4x3" { return ES2_identifier_ES3_keyword(context, MATRIX4x3); } "vec2" { context->lexAfterType = true; return (VEC2); } "vec3" { context->lexAfterType = true; return (VEC3); } "vec4" { context->lexAfterType = true; return (VEC4); } "ivec2" { context->lexAfterType = true; return (IVEC2); } "ivec3" { context->lexAfterType = true; return (IVEC3); } "ivec4" { context->lexAfterType = true; return (IVEC4); } "uvec2" { return ES2_identifier_ES3_keyword(context, UVEC2); } "uvec3" { return ES2_identifier_ES3_keyword(context, UVEC3); } "uvec4" { return ES2_identifier_ES3_keyword(context, UVEC4); } "bvec2" { context->lexAfterType = true; return (BVEC2); } "bvec3" { context->lexAfterType = true; return (BVEC3); } "bvec4" { context->lexAfterType = true; return (BVEC4); } "sampler2D" { context->lexAfterType = true; return SAMPLER2D; } "samplerCube" { context->lexAfterType = true; return SAMPLERCUBE; } "sampler2DRect" { context->lexAfterType = true; return SAMPLER2DRECT; } "samplerExternalOES" { context->lexAfterType = true; return SAMPLER_EXTERNAL_OES; } "sampler3D" { context->lexAfterType = true; return SAMPLER3D; } "sampler3DRect" { return ES2_reserved_ES3_keyword(context, SAMPLER3DRECT); } "sampler2DArray" { return ES2_identifier_ES3_keyword(context, SAMPLER2DARRAY); } "isampler2D" { return ES2_identifier_ES3_keyword(context, ISAMPLER2D); } "isampler3D" { return ES2_identifier_ES3_keyword(context, ISAMPLER3D); } "isamplerCube" { return ES2_identifier_ES3_keyword(context, ISAMPLERCUBE); } "isampler2DArray" { return ES2_identifier_ES3_keyword(context, ISAMPLER2DARRAY); } "usampler2D" { return ES2_identifier_ES3_keyword(context, USAMPLER2D); } "usampler3D" { return ES2_identifier_ES3_keyword(context, USAMPLER3D); } "usamplerCube" { return ES2_identifier_ES3_keyword(context, USAMPLERCUBE); } "usampler2DArray" { return ES2_identifier_ES3_keyword(context, USAMPLER2DARRAY); } "sampler2DShadow" { return ES2_reserved_ES3_keyword(context, SAMPLER2DSHADOW); } "samplerCubeShadow" { return ES2_identifier_ES3_keyword(context, SAMPLERCUBESHADOW); } "sampler2DArrayShadow" { return ES2_identifier_ES3_keyword(context, SAMPLER2DARRAYSHADOW); } "struct" { context->lexAfterType = true; return(STRUCT); } "layout" { return ES2_identifier_ES3_keyword(context, LAYOUT); } /* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */ "coherent" | "restrict" | "readonly" | "writeonly" | "resource" | "atomic_uint" | "noperspective" | "patch" | "sample" | "subroutine" | "common" | "partition" | "active" | "filter" | "image1D" | "image2D" | "image3D" | "imageCube" | "iimage1D" | "iimage2D" | "iimage3D" | "iimageCube" | "uimage1D" | "uimage2D" | "uimage3D" | "uimageCube" | "image1DArray" | "image2DArray" | "iimage1DArray" | "iimage2DArray" | "uimage1DArray" | "uimage2DArray" | "image1DShadow" | "image2DShadow" | "image1DArrayShadow" | "image2DArrayShadow" | "imageBuffer" | "iimageBuffer" | "uimageBuffer" | "sampler1DArray" | "sampler1DArrayShadow" | "isampler1D" | "isampler1DArray" | "usampler1D" | "usampler1DArray" | "isampler2DRect" | "usampler2DRect" | "samplerBuffer" | "isamplerBuffer" | "usamplerBuffer" | "sampler2DMS" | "isampler2DMS" | "usampler2DMS" | "sampler2DMSArray" | "isampler2DMSArray" | "usampler2DMSArray" { if (context->getShaderVersion() < 300) { yylval->lex.string = NewPoolTString(yytext); return check_type(yyscanner); } return reserved_word(yyscanner); } /* Reserved keywords in GLSL ES 1.00 that are not reserved in GLSL ES 3.00 */ "packed" { if (context->getShaderVersion() >= 300) { yylval->lex.string = NewPoolTString(yytext); return check_type(yyscanner); } return reserved_word(yyscanner); } /* Reserved keywords */ "asm" | "class" | "union" | "enum" | "typedef" | "template" | "this" | "goto" | "inline" | "noinline" | "volatile" | "public" | "static" | "extern" | "external" | "interface" | "long" | "short" | "double" | "half" | "fixed" | "unsigned" | "superp" | "input" | "output" | "hvec2" | "hvec3" | "hvec4" | "dvec2" | "dvec3" | "dvec4" | "fvec2" | "fvec3" | "fvec4" | "sampler1D" | "sampler1DShadow" | "sampler2DRectShadow" | "sizeof" | "cast" | "namespace" | "using" { return reserved_word(yyscanner); } {L}({L}|{D})* { yylval->lex.string = NewPoolTString(yytext); return check_type(yyscanner); } 0[xX]{H}+ { return int_constant(yyscanner); } 0{O}+ { return int_constant(yyscanner); } {D}+ { return int_constant(yyscanner); } 0[xX]{H}+[uU] { return uint_constant(context); } 0{O}+[uU] { return uint_constant(context); } {D}+[uU] { return uint_constant(context); } {D}+{E} { return float_constant(yyscanner); } {D}+"."{D}*({E})? { return float_constant(yyscanner); } "."{D}+({E})? { return float_constant(yyscanner); } {D}+{E}[fF] { return floatsuffix_check(context); } {D}+"."{D}*({E})?[fF] { return floatsuffix_check(context); } "."{D}+({E})?[fF] { return floatsuffix_check(context); } "+=" { return(ADD_ASSIGN); } "-=" { return(SUB_ASSIGN); } "*=" { return(MUL_ASSIGN); } "/=" { return(DIV_ASSIGN); } "%=" { return(MOD_ASSIGN); } "<<=" { return(LEFT_ASSIGN); } ">>=" { return(RIGHT_ASSIGN); } "&=" { return(AND_ASSIGN); } "^=" { return(XOR_ASSIGN); } "|=" { return(OR_ASSIGN); } "++" { return(INC_OP); } "--" { return(DEC_OP); } "&&" { return(AND_OP); } "||" { return(OR_OP); } "^^" { return(XOR_OP); } "<=" { return(LE_OP); } ">=" { return(GE_OP); } "==" { return(EQ_OP); } "!=" { return(NE_OP); } "<<" { return(LEFT_OP); } ">>" { return(RIGHT_OP); } ";" { context->lexAfterType = false; return(SEMICOLON); } ("{"|"<%") { context->lexAfterType = false; return(LEFT_BRACE); } ("}"|"%>") { return(RIGHT_BRACE); } "," { if (context->inTypeParen) context->lexAfterType = false; return(COMMA); } ":" { return(COLON); } "=" { context->lexAfterType = false; return(EQUAL); } "(" { context->lexAfterType = false; context->inTypeParen = true; return(LEFT_PAREN); } ")" { context->inTypeParen = false; return(RIGHT_PAREN); } ("["|"<:") { return(LEFT_BRACKET); } ("]"|":>") { return(RIGHT_BRACKET); } "." { BEGIN(FIELDS); return(DOT); } "!" { return(BANG); } "-" { return(DASH); } "~" { return(TILDE); } "+" { return(PLUS); } "*" { return(STAR); } "/" { return(SLASH); } "%" { return(PERCENT); } "<" { return(LEFT_ANGLE); } ">" { return(RIGHT_ANGLE); } "|" { return(VERTICAL_BAR); } "^" { return(CARET); } "&" { return(AMPERSAND); } "?" { return(QUESTION); } <FIELDS>{L}({L}|{D})* { BEGIN(INITIAL); yylval->lex.string = NewPoolTString(yytext); return FIELD_SELECTION; } <FIELDS>[ \t\v\f\r] {} [ \t\v\n\f\r] { } <*><<EOF>> { context->AfterEOF = true; yyterminate(); } <*>. { context->warning(*yylloc, "Unknown char", yytext, ""); return 0; } %% yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) { pp::Token token; yyget_extra(yyscanner)->getPreprocessor().lex(&token); yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size(); if (len < max_size) memcpy(buf, token.text.c_str(), len); yyset_column(token.location.file, yyscanner); yyset_lineno(token.location.line, yyscanner); if (len >= max_size) YY_FATAL_ERROR("Input buffer overflow"); else if (len > 0) buf[len++] = ' '; return len; } int check_type(yyscan_t yyscanner) { struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; int token = IDENTIFIER; TSymbol* symbol = yyextra->symbolTable.find(yytext, yyextra->getShaderVersion()); if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) { TVariable* variable = static_cast<TVariable*>(symbol); if (variable->isUserType()) { yyextra->lexAfterType = true; token = TYPE_NAME; } } yylval->lex.symbol = symbol; return token; } int reserved_word(yyscan_t yyscanner) { struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; yyextra->error(*yylloc, "Illegal use of reserved word", yytext, ""); yyextra->recover(); return 0; } int ES2_reserved_ES3_keyword(TParseContext *context, int token) { yyscan_t yyscanner = (yyscan_t) context->getScanner(); if (context->getShaderVersion() < 300) { return reserved_word(yyscanner); } return token; } int ES2_keyword_ES3_reserved(TParseContext *context, int token) { yyscan_t yyscanner = (yyscan_t) context->getScanner(); if (context->getShaderVersion() >= 300) { return reserved_word(yyscanner); } return token; } int ES2_identifier_ES3_keyword(TParseContext *context, int token) { struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); yyscan_t yyscanner = (yyscan_t) context->getScanner(); // not a reserved word in GLSL ES 1.00, so could be used as an identifier/type name if (context->getShaderVersion() < 300) { yylval->lex.string = NewPoolTString(yytext); return check_type(yyscanner); } return token; } int uint_constant(TParseContext *context) { struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); if (context->getShaderVersion() < 300) { context->error(*yylloc, "Unsigned integers are unsupported prior to GLSL ES 3.00", yytext, ""); context->recover(); return 0; } if (!atou_clamp(yytext, &(yylval->lex.u))) yyextra->warning(*yylloc, "Integer overflow", yytext, ""); return UINTCONSTANT; } int floatsuffix_check(TParseContext* context) { struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); if (context->getShaderVersion() < 300) { context->error(*yylloc, "Floating-point suffix unsupported prior to GLSL ES 3.00", yytext); context->recover(); return 0; } if (!atof_clamp(yytext, &(yylval->lex.f))) yyextra->warning(*yylloc, "Float overflow", yytext, ""); return(FLOATCONSTANT); } int int_constant(yyscan_t yyscanner) { struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; if (!atoi_clamp(yytext, &(yylval->lex.i))) yyextra->warning(*yylloc, "Integer overflow", yytext, ""); return INTCONSTANT; } int float_constant(yyscan_t yyscanner) { struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; if (!atof_clamp(yytext, &(yylval->lex.f))) yyextra->warning(*yylloc, "Float overflow", yytext, ""); return FLOATCONSTANT; } void yyerror(YYLTYPE* lloc, TParseContext* context, void* scanner, const char* reason) { struct yyguts_t* yyg = (struct yyguts_t*) scanner; if (context->AfterEOF) { context->error(*lloc, reason, "unexpected EOF"); } else { context->error(*lloc, reason, yytext); } context->recover(); } int glslang_initialize(TParseContext* context) { yyscan_t scanner = NULL; if (yylex_init_extra(context, &scanner)) return 1; context->setScanner(scanner); return 0; } int glslang_finalize(TParseContext* context) { yyscan_t scanner = context->getScanner(); if (scanner == NULL) return 0; context->setScanner(NULL); yylex_destroy(scanner); return 0; } int glslang_scan(size_t count, const char* const string[], const int length[], TParseContext* context) { yyrestart(NULL, context->getScanner()); yyset_column(0, context->getScanner()); yyset_lineno(1, context->getScanner()); context->AfterEOF = false; // Initialize preprocessor. if (!context->getPreprocessor().init(count, string, length)) return 1; // Define extension macros. const TExtensionBehavior& extBehavior = context->extensionBehavior(); for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); iter != extBehavior.end(); ++iter) { context->getPreprocessor().predefineMacro(iter->first.c_str(), 1); } context->getPreprocessor().predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1); return 0; }