blob: fdc3977a3843b925531977649bd3f97d059cd1ae [file] [log] [blame]
/*
// 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;
}