1/* 2// 3// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. 4// Use of this source code is governed by a BSD-style license that can be 5// found in the LICENSE file. 6// 7 8This file contains the Lex specification for GLSL ES. 9Based on ANSI C grammar, Lex specification: 10http://www.lysator.liu.se/c/ANSI-C-grammar-l.html 11 12IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_glslang_lexer.sh, 13WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). 14*/ 15 16%top{ 17// 18// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved. 19// Use of this source code is governed by a BSD-style license that can be 20// found in the LICENSE file. 21// 22 23// This file is auto-generated by generate_glslang_lexer.sh. DO NOT EDIT! 24} 25 26%{ 27#include "compiler/glslang.h" 28#include "compiler/ParseHelper.h" 29#include "compiler/util.h" 30#include "glslang_tab.h" 31 32/* windows only pragma */ 33#ifdef _MSC_VER 34#pragma warning(disable : 4102) 35#endif 36 37#define YY_USER_ACTION yylval->lex.line = yylineno; 38#define YY_INPUT(buf, result, max_size) \ 39 result = string_input(buf, max_size, yyscanner); 40 41static int string_input(char* buf, int max_size, yyscan_t yyscanner); 42static int check_type(yyscan_t yyscanner); 43static int reserved_word(yyscan_t yyscanner); 44%} 45 46%option noyywrap nounput never-interactive 47%option yylineno reentrant bison-bridge 48%option stack 49%option extra-type="TParseContext*" 50%x COMMENT FIELDS 51 52D [0-9] 53L [a-zA-Z_] 54H [a-fA-F0-9] 55E [Ee][+-]?{D}+ 56O [0-7] 57 58%% 59 60%{ 61 TParseContext* context = yyextra; 62%} 63 64 /* Single-line comments */ 65"//"[^\n]* ; 66 67 /* Multi-line comments */ 68"/*" { yy_push_state(COMMENT, yyscanner); } 69<COMMENT>. | 70<COMMENT>\n ; 71<COMMENT>"*/" { yy_pop_state(yyscanner); } 72 73"invariant" { return(INVARIANT); } 74"highp" { return(HIGH_PRECISION); } 75"mediump" { return(MEDIUM_PRECISION); } 76"lowp" { return(LOW_PRECISION); } 77"precision" { return(PRECISION); } 78 79"attribute" { return(ATTRIBUTE); } 80"const" { return(CONST_QUAL); } 81"uniform" { return(UNIFORM); } 82"varying" { return(VARYING); } 83 84"break" { return(BREAK); } 85"continue" { return(CONTINUE); } 86"do" { return(DO); } 87"for" { return(FOR); } 88"while" { return(WHILE); } 89 90"if" { return(IF); } 91"else" { return(ELSE); } 92 93"in" { return(IN_QUAL); } 94"out" { return(OUT_QUAL); } 95"inout" { return(INOUT_QUAL); } 96 97"float" { context->lexAfterType = true; return(FLOAT_TYPE); } 98"int" { context->lexAfterType = true; return(INT_TYPE); } 99"void" { context->lexAfterType = true; return(VOID_TYPE); } 100"bool" { context->lexAfterType = true; return(BOOL_TYPE); } 101"true" { yylval->lex.b = true; return(BOOLCONSTANT); } 102"false" { yylval->lex.b = false; return(BOOLCONSTANT); } 103 104"discard" { return(DISCARD); } 105"return" { return(RETURN); } 106 107"mat2" { context->lexAfterType = true; return(MATRIX2); } 108"mat3" { context->lexAfterType = true; return(MATRIX3); } 109"mat4" { context->lexAfterType = true; return(MATRIX4); } 110 111"vec2" { context->lexAfterType = true; return (VEC2); } 112"vec3" { context->lexAfterType = true; return (VEC3); } 113"vec4" { context->lexAfterType = true; return (VEC4); } 114"ivec2" { context->lexAfterType = true; return (IVEC2); } 115"ivec3" { context->lexAfterType = true; return (IVEC3); } 116"ivec4" { context->lexAfterType = true; return (IVEC4); } 117"bvec2" { context->lexAfterType = true; return (BVEC2); } 118"bvec3" { context->lexAfterType = true; return (BVEC3); } 119"bvec4" { context->lexAfterType = true; return (BVEC4); } 120 121"sampler2D" { context->lexAfterType = true; return SAMPLER2D; } 122"samplerCube" { context->lexAfterType = true; return SAMPLERCUBE; } 123 124"struct" { context->lexAfterType = true; return(STRUCT); } 125 126"asm" { return reserved_word(yyscanner); } 127 128"class" { return reserved_word(yyscanner); } 129"union" { return reserved_word(yyscanner); } 130"enum" { return reserved_word(yyscanner); } 131"typedef" { return reserved_word(yyscanner); } 132"template" { return reserved_word(yyscanner); } 133"this" { return reserved_word(yyscanner); } 134"packed" { return reserved_word(yyscanner); } 135 136"goto" { return reserved_word(yyscanner); } 137"switch" { return reserved_word(yyscanner); } 138"default" { return reserved_word(yyscanner); } 139 140"inline" { return reserved_word(yyscanner); } 141"noinline" { return reserved_word(yyscanner); } 142"volatile" { return reserved_word(yyscanner); } 143"public" { return reserved_word(yyscanner); } 144"static" { return reserved_word(yyscanner); } 145"extern" { return reserved_word(yyscanner); } 146"external" { return reserved_word(yyscanner); } 147"interface" { return reserved_word(yyscanner); } 148 149"long" { return reserved_word(yyscanner); } 150"short" { return reserved_word(yyscanner); } 151"double" { return reserved_word(yyscanner); } 152"half" { return reserved_word(yyscanner); } 153"fixed" { return reserved_word(yyscanner); } 154"unsigned" { return reserved_word(yyscanner); } 155 156"input" { return reserved_word(yyscanner); } 157"output" { return reserved_word(yyscanner); } 158 159"hvec2" { return reserved_word(yyscanner); } 160"hvec3" { return reserved_word(yyscanner); } 161"hvec4" { return reserved_word(yyscanner); } 162"fvec2" { return reserved_word(yyscanner); } 163"fvec3" { return reserved_word(yyscanner); } 164"fvec4" { return reserved_word(yyscanner); } 165"dvec2" { return reserved_word(yyscanner); } 166"dvec3" { return reserved_word(yyscanner); } 167"dvec4" { return reserved_word(yyscanner); } 168 169"sizeof" { return reserved_word(yyscanner); } 170"cast" { return reserved_word(yyscanner); } 171 172"namespace" { return reserved_word(yyscanner); } 173"using" { return reserved_word(yyscanner); } 174 175{L}({L}|{D})* { 176 yylval->lex.string = NewPoolTString(yytext); 177 return check_type(yyscanner); 178} 179 1800[xX]{H}+ { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } 1810{O}+ { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } 1820{D}+ { context->error(yylineno, "Invalid Octal number.", yytext, "", ""); context->recover(); return 0;} 183{D}+ { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } 184 185{D}+{E} { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); } 186{D}+"."{D}*({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); } 187"."{D}+({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return(FLOATCONSTANT); } 188 189"+=" { return(ADD_ASSIGN); } 190"-=" { return(SUB_ASSIGN); } 191"*=" { return(MUL_ASSIGN); } 192"/=" { return(DIV_ASSIGN); } 193"%=" { return(MOD_ASSIGN); } 194"<<=" { return(LEFT_ASSIGN); } 195">>=" { return(RIGHT_ASSIGN); } 196"&=" { return(AND_ASSIGN); } 197"^=" { return(XOR_ASSIGN); } 198"|=" { return(OR_ASSIGN); } 199 200"++" { return(INC_OP); } 201"--" { return(DEC_OP); } 202"&&" { return(AND_OP); } 203"||" { return(OR_OP); } 204"^^" { return(XOR_OP); } 205"<=" { return(LE_OP); } 206">=" { return(GE_OP); } 207"==" { return(EQ_OP); } 208"!=" { return(NE_OP); } 209"<<" { return(LEFT_OP); } 210">>" { return(RIGHT_OP); } 211";" { context->lexAfterType = false; return(SEMICOLON); } 212("{"|"<%") { context->lexAfterType = false; return(LEFT_BRACE); } 213("}"|"%>") { return(RIGHT_BRACE); } 214"," { if (context->inTypeParen) context->lexAfterType = false; return(COMMA); } 215":" { return(COLON); } 216"=" { context->lexAfterType = false; return(EQUAL); } 217"(" { context->lexAfterType = false; context->inTypeParen = true; return(LEFT_PAREN); } 218")" { context->inTypeParen = false; return(RIGHT_PAREN); } 219("["|"<:") { return(LEFT_BRACKET); } 220("]"|":>") { return(RIGHT_BRACKET); } 221"." { BEGIN(FIELDS); return(DOT); } 222"!" { return(BANG); } 223"-" { return(DASH); } 224"~" { return(TILDE); } 225"+" { return(PLUS); } 226"*" { return(STAR); } 227"/" { return(SLASH); } 228"%" { return(PERCENT); } 229"<" { return(LEFT_ANGLE); } 230">" { return(RIGHT_ANGLE); } 231"|" { return(VERTICAL_BAR); } 232"^" { return(CARET); } 233"&" { return(AMPERSAND); } 234"?" { return(QUESTION); } 235 236<FIELDS>{L}({L}|{D})* { 237 BEGIN(INITIAL); 238 yylval->lex.string = NewPoolTString(yytext); 239 return FIELD_SELECTION; 240} 241<FIELDS>[ \t\v\f\r] {} 242 243[ \t\v\n\f\r] { } 244<*><<EOF>> { context->AfterEOF = true; yyterminate(); } 245<*>. { context->warning(yylineno, "Unknown char", yytext, ""); return 0; } 246 247%% 248 249extern "C" { 250// Preprocessor interface. 251#include "compiler/preprocessor/preprocess.h" 252 253#define SETUP_CONTEXT(pp) \ 254 TParseContext* context = (TParseContext*) pp->pC; \ 255 struct yyguts_t* yyg = (struct yyguts_t*) context->scanner; 256 257// Preprocessor callbacks. 258void CPPDebugLogMsg(const char *msg) 259{ 260 SETUP_CONTEXT(cpp); 261 context->infoSink.debug.message(EPrefixNone, msg); 262} 263 264void CPPWarningToInfoLog(const char *msg) 265{ 266 SETUP_CONTEXT(cpp); 267 context->warning(yylineno, msg, "", ""); 268} 269 270void CPPShInfoLogMsg(const char *msg) 271{ 272 SETUP_CONTEXT(cpp); 273 context->error(yylineno, msg, "", ""); 274 context->recover(); 275} 276 277void CPPErrorToInfoLog(char *msg) 278{ 279 SETUP_CONTEXT(cpp); 280 context->error(yylineno, msg, "", ""); 281 context->recover(); 282} 283 284void SetLineNumber(int line) 285{ 286 SETUP_CONTEXT(cpp); 287 int string = 0; 288 DecodeSourceLoc(yylineno, &string, NULL); 289 yylineno = EncodeSourceLoc(string, line); 290} 291 292void SetStringNumber(int string) 293{ 294 SETUP_CONTEXT(cpp); 295 int line = 0; 296 DecodeSourceLoc(yylineno, NULL, &line); 297 yylineno = EncodeSourceLoc(string, line); 298} 299 300int GetStringNumber() 301{ 302 SETUP_CONTEXT(cpp); 303 int string = 0; 304 DecodeSourceLoc(yylineno, &string, NULL); 305 return string; 306} 307 308int GetLineNumber() 309{ 310 SETUP_CONTEXT(cpp); 311 int line = 0; 312 DecodeSourceLoc(yylineno, NULL, &line); 313 return line; 314} 315 316void IncLineNumber() 317{ 318 SETUP_CONTEXT(cpp); 319 int string = 0, line = 0; 320 DecodeSourceLoc(yylineno, &string, &line); 321 yylineno = EncodeSourceLoc(string, ++line); 322} 323 324void DecLineNumber() 325{ 326 SETUP_CONTEXT(cpp); 327 int string = 0, line = 0; 328 DecodeSourceLoc(yylineno, &string, &line); 329 yylineno = EncodeSourceLoc(string, --line); 330} 331 332void HandlePragma(const char **tokens, int numTokens) 333{ 334 SETUP_CONTEXT(cpp); 335 if (!strcmp(tokens[0], "optimize")) { 336 if (numTokens != 4) { 337 CPPShInfoLogMsg("optimize pragma syntax is incorrect"); 338 return; 339 } 340 341 if (strcmp(tokens[1], "(")) { 342 CPPShInfoLogMsg("\"(\" expected after 'optimize' keyword"); 343 return; 344 } 345 346 if (!strcmp(tokens[2], "on")) 347 context->contextPragma.optimize = true; 348 else if (!strcmp(tokens[2], "off")) 349 context->contextPragma.optimize = false; 350 else { 351 CPPShInfoLogMsg("\"on\" or \"off\" expected after '(' for 'optimize' pragma"); 352 return; 353 } 354 355 if (strcmp(tokens[3], ")")) { 356 CPPShInfoLogMsg("\")\" expected to end 'optimize' pragma"); 357 return; 358 } 359 } else if (!strcmp(tokens[0], "debug")) { 360 if (numTokens != 4) { 361 CPPShInfoLogMsg("debug pragma syntax is incorrect"); 362 return; 363 } 364 365 if (strcmp(tokens[1], "(")) { 366 CPPShInfoLogMsg("\"(\" expected after 'debug' keyword"); 367 return; 368 } 369 370 if (!strcmp(tokens[2], "on")) 371 context->contextPragma.debug = true; 372 else if (!strcmp(tokens[2], "off")) 373 context->contextPragma.debug = false; 374 else { 375 CPPShInfoLogMsg("\"on\" or \"off\" expected after '(' for 'debug' pragma"); 376 return; 377 } 378 379 if (strcmp(tokens[3], ")")) { 380 CPPShInfoLogMsg("\")\" expected to end 'debug' pragma"); 381 return; 382 } 383 } else { 384#ifdef PRAGMA_TABLE 385 // 386 // implementation specific pragma 387 // use ((TParseContext *)cpp->pC)->contextPragma.pragmaTable to store the information about pragma 388 // For now, just ignore the pragma that the implementation cannot recognize 389 // An Example of one such implementation for a pragma that has a syntax like 390 // #pragma pragmaname(pragmavalue) 391 // This implementation stores the current pragmavalue against the pragma name in pragmaTable. 392 // 393 if (numTokens == 4 && !strcmp(tokens[1], "(") && !strcmp(tokens[3], ")")) { 394 TPragmaTable& pragmaTable = ((TParseContext *)cpp->pC)->contextPragma.pragmaTable; 395 TPragmaTable::iterator iter; 396 iter = pragmaTable.find(TString(tokens[0])); 397 if (iter != pragmaTable.end()) { 398 iter->second = tokens[2]; 399 } else { 400 pragmaTable[ tokens[0] ] = tokens[2]; 401 } 402 } else if (numTokens >= 2) { 403 TPragmaTable& pragmaTable = ((TParseContext *)cpp->pC)->contextPragma.pragmaTable; 404 TPragmaTable::iterator iter; 405 iter = pragmaTable.find(TString(tokens[0])); 406 if (iter != pragmaTable.end()) { 407 iter->second = tokens[1]; 408 } else { 409 pragmaTable[ tokens[0] ] = tokens[1]; 410 } 411 } 412#endif // PRAGMA_TABLE 413 } 414} 415 416void StoreStr(char *string) 417{ 418 SETUP_CONTEXT(cpp); 419 TString strSrc; 420 strSrc = TString(string); 421 422 context->HashErrMsg = context->HashErrMsg + " " + strSrc; 423} 424 425const char* GetStrfromTStr(void) 426{ 427 SETUP_CONTEXT(cpp); 428 cpp->ErrMsg = context->HashErrMsg.c_str(); 429 return cpp->ErrMsg; 430} 431 432void ResetTString(void) 433{ 434 SETUP_CONTEXT(cpp); 435 context->HashErrMsg = ""; 436} 437 438TBehavior GetBehavior(const char* behavior) 439{ 440 if (!strcmp("require", behavior)) 441 return EBhRequire; 442 else if (!strcmp("enable", behavior)) 443 return EBhEnable; 444 else if (!strcmp("disable", behavior)) 445 return EBhDisable; 446 else if (!strcmp("warn", behavior)) 447 return EBhWarn; 448 else { 449 CPPShInfoLogMsg((TString("behavior '") + behavior + "' is not supported").c_str()); 450 return EBhDisable; 451 } 452} 453 454void updateExtensionBehavior(const char* extName, const char* behavior) 455{ 456 SETUP_CONTEXT(cpp); 457 TBehavior behaviorVal = GetBehavior(behavior); 458 TMap<TString, TBehavior>:: iterator iter; 459 TString msg; 460 461 // special cased for all extension 462 if (!strcmp(extName, "all")) { 463 if (behaviorVal == EBhRequire || behaviorVal == EBhEnable) { 464 CPPShInfoLogMsg("extension 'all' cannot have 'require' or 'enable' behavior"); 465 return; 466 } else { 467 for (iter = context->extensionBehavior.begin(); iter != context->extensionBehavior.end(); ++iter) 468 iter->second = behaviorVal; 469 } 470 } else { 471 iter = context->extensionBehavior.find(TString(extName)); 472 if (iter == context->extensionBehavior.end()) { 473 switch (behaviorVal) { 474 case EBhRequire: 475 CPPShInfoLogMsg((TString("extension '") + extName + "' is not supported").c_str()); 476 break; 477 case EBhEnable: 478 case EBhWarn: 479 case EBhDisable: 480 msg = TString("extension '") + extName + "' is not supported"; 481 context->infoSink.info.message(EPrefixWarning, msg.c_str(), yylineno); 482 break; 483 } 484 return; 485 } else 486 iter->second = behaviorVal; 487 } 488} 489} // extern "C" 490 491int string_input(char* buf, int max_size, yyscan_t yyscanner) { 492 int len; 493 494 if ((len = yylex_CPP(buf, max_size)) == 0) 495 return 0; 496 if (len >= max_size) 497 YY_FATAL_ERROR("input buffer overflow, can't enlarge buffer because scanner uses REJECT"); 498 499 buf[len] = ' '; 500 return len+1; 501} 502 503int check_type(yyscan_t yyscanner) { 504 struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; 505 506 int token = IDENTIFIER; 507 TSymbol* symbol = yyextra->symbolTable.find(yytext); 508 if (yyextra->lexAfterType == false && symbol && symbol->isVariable()) { 509 TVariable* variable = static_cast<TVariable*>(symbol); 510 if (variable->isUserType()) { 511 yyextra->lexAfterType = true; 512 token = TYPE_NAME; 513 } 514 } 515 yylval->lex.symbol = symbol; 516 return token; 517} 518 519int reserved_word(yyscan_t yyscanner) { 520 struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; 521 522 yyextra->error(yylineno, "Illegal use of reserved word", yytext, ""); 523 yyextra->recover(); 524 return 0; 525} 526 527void yyerror(TParseContext* context, const char* reason) { 528 struct yyguts_t* yyg = (struct yyguts_t*) context->scanner; 529 530 if (context->AfterEOF) { 531 context->error(yylineno, reason, "unexpected EOF", ""); 532 } else { 533 context->error(yylineno, reason, yytext, ""); 534 } 535 context->recover(); 536} 537 538int glslang_initialize(TParseContext* context) { 539 yyscan_t scanner = NULL; 540 if (yylex_init_extra(context, &scanner)) 541 return 1; 542 543 context->scanner = scanner; 544 return 0; 545} 546 547int glslang_finalize(TParseContext* context) { 548 yyscan_t scanner = context->scanner; 549 if (scanner == NULL) return 0; 550 551 context->scanner = NULL; 552 return yylex_destroy(scanner); 553} 554 555void glslang_scan(int count, const char* const string[], const int length[], 556 TParseContext* context) { 557 yyrestart(NULL, context->scanner); 558 yyset_lineno(EncodeSourceLoc(0, 1), context->scanner); 559 context->AfterEOF = false; 560 561 // Init preprocessor. 562 cpp->pC = context; 563 cpp->PaWhichStr = 0; 564 cpp->PaArgv = string; 565 cpp->PaArgc = count; 566 cpp->PaStrLen = length; 567 cpp->pastFirstStatement = 0; 568 ScanFromString(string[0]); 569} 570 571