Home | History | Annotate | Download | only in compiler
      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 
      8 This file contains the Lex specification for GLSL ES.
      9 Based on ANSI C grammar, Lex specification:
     10 http://www.lysator.liu.se/c/ANSI-C-grammar-l.html
     11 
     12 IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_glslang_lexer.sh,
     13 WHICH 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 
     41 static int string_input(char* buf, int max_size, yyscan_t yyscanner);
     42 static int check_type(yyscan_t yyscanner);
     43 static 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 
     52 D           [0-9]
     53 L           [a-zA-Z_]
     54 H           [a-fA-F0-9]
     55 E           [Ee][+-]?{D}+
     56 O           [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 
    180 0[xX]{H}+         { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
    181 0{O}+             { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
    182 0{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 
    249 extern "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.
    258 void CPPDebugLogMsg(const char *msg)
    259 {
    260     SETUP_CONTEXT(cpp);
    261     context->infoSink.debug.message(EPrefixNone, msg);
    262 }
    263 
    264 void CPPWarningToInfoLog(const char *msg)
    265 {
    266     SETUP_CONTEXT(cpp);
    267     context->warning(yylineno, msg, "", "");
    268 }
    269 
    270 void CPPShInfoLogMsg(const char *msg)
    271 {
    272     SETUP_CONTEXT(cpp);
    273     context->error(yylineno, msg, "", "");
    274     context->recover();
    275 }
    276 
    277 void CPPErrorToInfoLog(char *msg)
    278 {
    279     SETUP_CONTEXT(cpp);
    280     context->error(yylineno, msg, "", "");
    281     context->recover();
    282 }
    283 
    284 void SetLineNumber(int line)
    285 {
    286     SETUP_CONTEXT(cpp);
    287     int string = 0;
    288     DecodeSourceLoc(yylineno, &string, NULL);
    289     yylineno = EncodeSourceLoc(string, line);
    290 }
    291 
    292 void SetStringNumber(int string)
    293 {
    294     SETUP_CONTEXT(cpp);
    295     int line = 0;
    296     DecodeSourceLoc(yylineno, NULL, &line);
    297     yylineno = EncodeSourceLoc(string, line);
    298 }
    299 
    300 int GetStringNumber()
    301 {
    302     SETUP_CONTEXT(cpp);
    303     int string = 0;
    304     DecodeSourceLoc(yylineno, &string, NULL);
    305     return string;
    306 }
    307 
    308 int GetLineNumber()
    309 {
    310     SETUP_CONTEXT(cpp);
    311     int line = 0;
    312     DecodeSourceLoc(yylineno, NULL, &line);
    313     return line;
    314 }
    315 
    316 void IncLineNumber()
    317 {
    318     SETUP_CONTEXT(cpp);
    319     int string = 0, line = 0;
    320     DecodeSourceLoc(yylineno, &string, &line);
    321     yylineno = EncodeSourceLoc(string, ++line);
    322 }
    323 
    324 void DecLineNumber()
    325 {
    326     SETUP_CONTEXT(cpp);
    327     int string = 0, line = 0;
    328     DecodeSourceLoc(yylineno, &string, &line);
    329     yylineno = EncodeSourceLoc(string, --line);
    330 }
    331 
    332 void 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 
    416 void StoreStr(char *string)
    417 {
    418     SETUP_CONTEXT(cpp);
    419     TString strSrc;
    420     strSrc = TString(string);
    421 
    422     context->HashErrMsg = context->HashErrMsg + " " + strSrc;
    423 }
    424 
    425 const char* GetStrfromTStr(void)
    426 {
    427     SETUP_CONTEXT(cpp);
    428     cpp->ErrMsg = context->HashErrMsg.c_str();
    429     return cpp->ErrMsg;
    430 }
    431 
    432 void ResetTString(void)
    433 {
    434     SETUP_CONTEXT(cpp);
    435     context->HashErrMsg = "";
    436 }
    437 
    438 TBehavior 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 
    454 void 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 
    491 int 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 
    503 int 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 
    519 int 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 
    527 void 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 
    538 int 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 
    547 int 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 
    555 void 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