michael@0: /* michael@0: // michael@0: // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: // michael@0: michael@0: This file contains the Lex specification for GLSL ES. michael@0: Based on ANSI C grammar, Lex specification: michael@0: http://www.lysator.liu.se/c/ANSI-C-grammar-l.html michael@0: michael@0: IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh, michael@0: WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). michael@0: */ michael@0: michael@0: %top{ michael@0: // michael@0: // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: // michael@0: michael@0: // This file is auto-generated by generate_parser.sh. DO NOT EDIT! michael@0: michael@0: // Ignore errors in auto-generated code. michael@0: #if defined(__GNUC__) michael@0: #pragma GCC diagnostic ignored "-Wunused-function" michael@0: #pragma GCC diagnostic ignored "-Wunused-variable" michael@0: #pragma GCC diagnostic ignored "-Wswitch-enum" michael@0: #elif defined(_MSC_VER) michael@0: #pragma warning(disable: 4065) michael@0: #pragma warning(disable: 4189) michael@0: #pragma warning(disable: 4505) michael@0: #pragma warning(disable: 4701) michael@0: #endif michael@0: } michael@0: michael@0: %{ michael@0: #include "compiler/glslang.h" michael@0: #include "compiler/ParseHelper.h" michael@0: #include "compiler/preprocessor/Token.h" michael@0: #include "compiler/util.h" michael@0: #include "glslang_tab.h" michael@0: michael@0: /* windows only pragma */ michael@0: #ifdef _MSC_VER michael@0: #pragma warning(disable : 4102) michael@0: #endif michael@0: michael@0: #define YY_USER_ACTION \ michael@0: yylloc->first_file = yylloc->last_file = yycolumn; \ michael@0: yylloc->first_line = yylloc->last_line = yylineno; michael@0: michael@0: #define YY_INPUT(buf, result, max_size) \ michael@0: result = string_input(buf, max_size, yyscanner); michael@0: michael@0: static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner); michael@0: static int check_type(yyscan_t yyscanner); michael@0: static int reserved_word(yyscan_t yyscanner); michael@0: %} michael@0: michael@0: %option noyywrap nounput never-interactive michael@0: %option yylineno reentrant bison-bridge bison-locations michael@0: %option extra-type="TParseContext*" michael@0: michael@0: D [0-9] michael@0: L [a-zA-Z_] michael@0: H [a-fA-F0-9] michael@0: E [Ee][+-]?{D}+ michael@0: O [0-7] michael@0: michael@0: %% michael@0: michael@0: "invariant" { return INVARIANT; } michael@0: "highp" { return HIGH_PRECISION; } michael@0: "mediump" { return MEDIUM_PRECISION; } michael@0: "lowp" { return LOW_PRECISION; } michael@0: "precision" { return PRECISION; } michael@0: michael@0: "attribute" { return ATTRIBUTE; } michael@0: "const" { return CONST_QUAL; } michael@0: "uniform" { return UNIFORM; } michael@0: "varying" { return VARYING; } michael@0: michael@0: "break" { return BREAK; } michael@0: "continue" { return CONTINUE; } michael@0: "do" { return DO; } michael@0: "for" { return FOR; } michael@0: "while" { return WHILE; } michael@0: michael@0: "if" { return IF; } michael@0: "else" { return ELSE; } michael@0: michael@0: "in" { return IN_QUAL; } michael@0: "out" { return OUT_QUAL; } michael@0: "inout" { return INOUT_QUAL; } michael@0: michael@0: "float" { return FLOAT_TYPE; } michael@0: "int" { return INT_TYPE; } michael@0: "void" { return VOID_TYPE; } michael@0: "bool" { return BOOL_TYPE; } michael@0: "true" { yylval->lex.b = true; return BOOLCONSTANT; } michael@0: "false" { yylval->lex.b = false; return BOOLCONSTANT; } michael@0: michael@0: "discard" { return DISCARD; } michael@0: "return" { return RETURN; } michael@0: michael@0: "mat2" { return MATRIX2; } michael@0: "mat3" { return MATRIX3; } michael@0: "mat4" { return MATRIX4; } michael@0: michael@0: "vec2" { return VEC2; } michael@0: "vec3" { return VEC3; } michael@0: "vec4" { return VEC4; } michael@0: "ivec2" { return IVEC2; } michael@0: "ivec3" { return IVEC3; } michael@0: "ivec4" { return IVEC4; } michael@0: "bvec2" { return BVEC2; } michael@0: "bvec3" { return BVEC3; } michael@0: "bvec4" { return BVEC4; } michael@0: michael@0: "sampler2D" { return SAMPLER2D; } michael@0: "samplerCube" { return SAMPLERCUBE; } michael@0: "samplerExternalOES" { return SAMPLER_EXTERNAL_OES; } michael@0: "sampler2DRect" { return SAMPLER2DRECT; } michael@0: michael@0: "struct" { return STRUCT; } michael@0: michael@0: "asm" { return reserved_word(yyscanner); } michael@0: michael@0: "class" { return reserved_word(yyscanner); } michael@0: "union" { return reserved_word(yyscanner); } michael@0: "enum" { return reserved_word(yyscanner); } michael@0: "typedef" { return reserved_word(yyscanner); } michael@0: "template" { return reserved_word(yyscanner); } michael@0: "this" { return reserved_word(yyscanner); } michael@0: "packed" { return reserved_word(yyscanner); } michael@0: michael@0: "goto" { return reserved_word(yyscanner); } michael@0: "switch" { return reserved_word(yyscanner); } michael@0: "default" { return reserved_word(yyscanner); } michael@0: michael@0: "inline" { return reserved_word(yyscanner); } michael@0: "noinline" { return reserved_word(yyscanner); } michael@0: "volatile" { return reserved_word(yyscanner); } michael@0: "public" { return reserved_word(yyscanner); } michael@0: "static" { return reserved_word(yyscanner); } michael@0: "extern" { return reserved_word(yyscanner); } michael@0: "external" { return reserved_word(yyscanner); } michael@0: "interface" { return reserved_word(yyscanner); } michael@0: "flat" { return reserved_word(yyscanner); } michael@0: michael@0: "long" { return reserved_word(yyscanner); } michael@0: "short" { return reserved_word(yyscanner); } michael@0: "double" { return reserved_word(yyscanner); } michael@0: "half" { return reserved_word(yyscanner); } michael@0: "fixed" { return reserved_word(yyscanner); } michael@0: "unsigned" { return reserved_word(yyscanner); } michael@0: "superp" { return reserved_word(yyscanner); } michael@0: michael@0: "input" { return reserved_word(yyscanner); } michael@0: "output" { return reserved_word(yyscanner); } michael@0: michael@0: "hvec2" { return reserved_word(yyscanner); } michael@0: "hvec3" { return reserved_word(yyscanner); } michael@0: "hvec4" { return reserved_word(yyscanner); } michael@0: "dvec2" { return reserved_word(yyscanner); } michael@0: "dvec3" { return reserved_word(yyscanner); } michael@0: "dvec4" { return reserved_word(yyscanner); } michael@0: "fvec2" { return reserved_word(yyscanner); } michael@0: "fvec3" { return reserved_word(yyscanner); } michael@0: "fvec4" { return reserved_word(yyscanner); } michael@0: michael@0: "sampler1D" { return reserved_word(yyscanner); } michael@0: "sampler3D" { return reserved_word(yyscanner); } michael@0: "sampler1DShadow" { return reserved_word(yyscanner); } michael@0: "sampler2DShadow" { return reserved_word(yyscanner); } michael@0: "sampler3DRect" { return reserved_word(yyscanner); } michael@0: "sampler2DRectShadow" { return reserved_word(yyscanner); } michael@0: michael@0: "sizeof" { return reserved_word(yyscanner); } michael@0: "cast" { return reserved_word(yyscanner); } michael@0: michael@0: "namespace" { return reserved_word(yyscanner); } michael@0: "using" { return reserved_word(yyscanner); } michael@0: michael@0: {L}({L}|{D})* { michael@0: yylval->lex.string = NewPoolTString(yytext); michael@0: return check_type(yyscanner); michael@0: } michael@0: michael@0: 0[xX]{H}+ { yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return INTCONSTANT; } michael@0: 0{O}+ { yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return INTCONSTANT; } michael@0: {D}+ { yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return INTCONSTANT; } michael@0: michael@0: {D}+{E} { yylval->lex.f = static_cast(atof_dot(yytext)); return FLOATCONSTANT; } michael@0: {D}+"."{D}*({E})? { yylval->lex.f = static_cast(atof_dot(yytext)); return FLOATCONSTANT; } michael@0: "."{D}+({E})? { yylval->lex.f = static_cast(atof_dot(yytext)); return FLOATCONSTANT; } michael@0: michael@0: "+=" { return ADD_ASSIGN; } michael@0: "-=" { return SUB_ASSIGN; } michael@0: "*=" { return MUL_ASSIGN; } michael@0: "/=" { return DIV_ASSIGN; } michael@0: "%=" { return MOD_ASSIGN; } michael@0: "<<=" { return LEFT_ASSIGN; } michael@0: ">>=" { return RIGHT_ASSIGN; } michael@0: "&=" { return AND_ASSIGN; } michael@0: "^=" { return XOR_ASSIGN; } michael@0: "|=" { return OR_ASSIGN; } michael@0: michael@0: "++" { return INC_OP; } michael@0: "--" { return DEC_OP; } michael@0: "&&" { return AND_OP; } michael@0: "||" { return OR_OP; } michael@0: "^^" { return XOR_OP; } michael@0: "<=" { return LE_OP; } michael@0: ">=" { return GE_OP; } michael@0: "==" { return EQ_OP; } michael@0: "!=" { return NE_OP; } michael@0: "<<" { return LEFT_OP; } michael@0: ">>" { return RIGHT_OP; } michael@0: ";" { return SEMICOLON; } michael@0: ("{"|"<%") { return LEFT_BRACE; } michael@0: ("}"|"%>") { return RIGHT_BRACE; } michael@0: "," { return COMMA; } michael@0: ":" { return COLON; } michael@0: "=" { return EQUAL; } michael@0: "(" { return LEFT_PAREN; } michael@0: ")" { return RIGHT_PAREN; } michael@0: ("["|"<:") { return LEFT_BRACKET; } michael@0: ("]"|":>") { return RIGHT_BRACKET; } michael@0: "." { return DOT; } michael@0: "!" { return BANG; } michael@0: "-" { return DASH; } michael@0: "~" { return TILDE; } michael@0: "+" { return PLUS; } michael@0: "*" { return STAR; } michael@0: "/" { return SLASH; } michael@0: "%" { return PERCENT; } michael@0: "<" { return LEFT_ANGLE; } michael@0: ">" { return RIGHT_ANGLE; } michael@0: "|" { return VERTICAL_BAR; } michael@0: "^" { return CARET; } michael@0: "&" { return AMPERSAND; } michael@0: "?" { return QUESTION; } michael@0: michael@0: [ \t\v\n\f\r] { } michael@0: <> { yyterminate(); } michael@0: . { assert(false); return 0; } michael@0: michael@0: %% michael@0: michael@0: yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) { michael@0: pp::Token token; michael@0: yyget_extra(yyscanner)->preprocessor.lex(&token); michael@0: yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size(); michael@0: if (len < max_size) michael@0: memcpy(buf, token.text.c_str(), len); michael@0: yyset_column(token.location.file, yyscanner); michael@0: yyset_lineno(token.location.line, yyscanner); michael@0: michael@0: if (len >= max_size) michael@0: YY_FATAL_ERROR("Input buffer overflow"); michael@0: else if (len > 0) michael@0: buf[len++] = ' '; michael@0: return len; michael@0: } michael@0: michael@0: int check_type(yyscan_t yyscanner) { michael@0: struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; michael@0: michael@0: int token = IDENTIFIER; michael@0: TSymbol* symbol = yyextra->symbolTable.find(yytext); michael@0: if (symbol && symbol->isVariable()) { michael@0: TVariable* variable = static_cast(symbol); michael@0: if (variable->isUserType()) michael@0: token = TYPE_NAME; michael@0: } michael@0: yylval->lex.symbol = symbol; michael@0: return token; michael@0: } michael@0: michael@0: int reserved_word(yyscan_t yyscanner) { michael@0: struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; michael@0: michael@0: yyextra->error(*yylloc, "Illegal use of reserved word", yytext, ""); michael@0: yyextra->recover(); michael@0: return 0; michael@0: } michael@0: michael@0: int glslang_initialize(TParseContext* context) { michael@0: yyscan_t scanner = NULL; michael@0: if (yylex_init_extra(context, &scanner)) michael@0: return 1; michael@0: michael@0: context->scanner = scanner; michael@0: return 0; michael@0: } michael@0: michael@0: int glslang_finalize(TParseContext* context) { michael@0: yyscan_t scanner = context->scanner; michael@0: if (scanner == NULL) return 0; michael@0: michael@0: context->scanner = NULL; michael@0: yylex_destroy(scanner); michael@0: michael@0: return 0; michael@0: } michael@0: michael@0: int glslang_scan(size_t count, const char* const string[], const int length[], michael@0: TParseContext* context) { michael@0: yyrestart(NULL, context->scanner); michael@0: yyset_column(0, context->scanner); michael@0: yyset_lineno(1, context->scanner); michael@0: michael@0: // Initialize preprocessor. michael@0: if (!context->preprocessor.init(count, string, length)) michael@0: return 1; michael@0: michael@0: // Define extension macros. michael@0: const TExtensionBehavior& extBehavior = context->extensionBehavior(); michael@0: for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); michael@0: iter != extBehavior.end(); ++iter) { michael@0: context->preprocessor.predefineMacro(iter->first.c_str(), 1); michael@0: } michael@0: if (context->fragmentPrecisionHigh) michael@0: context->preprocessor.predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1); michael@0: michael@0: return 0; michael@0: } michael@0: