initial import
[vuplus_webkit] / Source / ThirdParty / ANGLE / src / compiler / glslang.l
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