| /* |
| // |
| // Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| |
| This file contains the Yacc grammar for GLSL ES preprocessor. |
| Based on Microsoft Visual Studio 2010 Preprocessor Grammar: |
| http://msdn.microsoft.com/en-us/library/2scxys89.aspx |
| |
| IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_glsl_parser.sh, |
| WHICH GENERATES THE GLSL ES PARSER. |
| */ |
| |
| %{ |
| // |
| // Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| |
| // This file is auto-generated by generate_glslang_parser.sh. DO NOT EDIT! |
| |
| #include "Context.h" |
| |
| #define YYLEX_PARAM context->lexer() |
| #define YYDEBUG 1 |
| %} |
| |
| %pure-parser |
| %name-prefix="pp" |
| %locations |
| %parse-param {pp::Context* context} |
| |
| %union { |
| int ival; |
| std::string* sval; |
| pp::Token* tval; |
| pp::TokenVector* tlist; |
| } |
| |
| %{ |
| extern int yylex(YYSTYPE* lvalp, YYLTYPE* llocp, void* lexer); |
| static void yyerror(YYLTYPE* llocp, |
| pp::Context* context, |
| const char* reason); |
| |
| static void pushConditionalBlock(pp::Context* context, bool condition); |
| static void popConditionalBlock(pp::Context* context); |
| %} |
| |
| %token HASH HASH_UNDEF |
| %token HASH_IF HASH_IFDEF HASH_IFNDEF HASH_ELSE HASH_ELIF HASH_ENDIF DEFINED |
| %token HASH_ERROR HASH_PRAGMA HASH_EXTENSION HASH_VERSION HASH_LINE |
| %token <sval> HASH_DEFINE_OBJ HASH_DEFINE_FUNC |
| %token <sval> INT_CONSTANT FLOAT_CONSTANT IDENTIFIER |
| %type <ival> operator |
| %type <tval> conditional_token token |
| %type <tlist> parameter_list replacement_list conditional_list token_list |
| %% |
| |
| input |
| : /* empty */ |
| | input line |
| ; |
| |
| line |
| : text_line |
| | control_line |
| ; |
| |
| text_line |
| : '\n' |
| | token_list '\n' { |
| // TODO(alokp): Expand macros. |
| pp::TokenVector* out = context->output(); |
| out->insert(out->end(), $1->begin(), $1->end()); |
| delete $1; |
| } |
| ; |
| |
| control_line |
| : HASH '\n' |
| | HASH_DEFINE_OBJ replacement_list '\n' { |
| context->defineMacro(@1.first_line, pp::Macro::kTypeObj, $1, NULL, $2); |
| } |
| | HASH_DEFINE_FUNC '(' parameter_list ')' replacement_list '\n' { |
| context->defineMacro(@1.first_line, pp::Macro::kTypeFunc, $1, $3, $5); |
| } |
| | HASH_UNDEF IDENTIFIER '\n' { |
| context->undefineMacro($2); |
| } |
| | HASH_IF conditional_list '\n' { |
| pushConditionalBlock(context, $2 ? true : false); |
| } |
| | HASH_IFDEF IDENTIFIER '\n' { |
| pushConditionalBlock(context, context->isMacroDefined($2)); |
| } |
| | HASH_IFNDEF IDENTIFIER '\n' { |
| pushConditionalBlock(context, !context->isMacroDefined($2)); |
| } |
| | HASH_ELIF conditional_list '\n' { |
| } |
| | HASH_ELSE '\n' { |
| } |
| | HASH_ENDIF '\n' { |
| popConditionalBlock(context); |
| } |
| | HASH_ERROR '\n' |
| | HASH_PRAGMA '\n' |
| | HASH_EXTENSION '\n' |
| | HASH_VERSION '\n' |
| | HASH_LINE '\n' |
| ; |
| |
| replacement_list |
| : /* empty */ { $$ = NULL; } |
| | token_list |
| |
| parameter_list |
| : /* empty */ { $$ = NULL; } |
| | IDENTIFIER { |
| $$ = new pp::TokenVector; |
| $$->push_back(new pp::Token(@1.first_line, IDENTIFIER, $1)); |
| } |
| | parameter_list ',' IDENTIFIER { |
| $$ = $1; |
| $$->push_back(new pp::Token(@3.first_line, IDENTIFIER, $3)); |
| } |
| |
| conditional_list |
| : conditional_token { |
| $$ = new pp::TokenVector; |
| $$->push_back($1); |
| } |
| | conditional_list conditional_token { |
| $$ = $1; |
| $$->push_back($2); |
| } |
| ; |
| |
| token_list |
| : token { |
| $$ = new pp::TokenVector; |
| $$->push_back($1); |
| } |
| | token_list token { |
| $$ = $1; |
| $$->push_back($2); |
| } |
| ; |
| |
| conditional_token |
| : DEFINED IDENTIFIER { |
| } |
| | DEFINED '(' IDENTIFIER ')' { |
| } |
| | token |
| ; |
| |
| token |
| : operator { |
| $$ = new pp::Token(@1.first_line, $1, NULL); |
| } |
| | INT_CONSTANT { |
| $$ = new pp::Token(@1.first_line, INT_CONSTANT, $1); |
| } |
| | FLOAT_CONSTANT { |
| $$ = new pp::Token(@1.first_line, FLOAT_CONSTANT, $1); |
| } |
| | IDENTIFIER { |
| $$ = new pp::Token(@1.first_line, IDENTIFIER, $1); |
| } |
| ; |
| |
| operator |
| : '[' { $$ = '['; } |
| | ']' { $$ = ']'; } |
| | '<' { $$ = '<'; } |
| | '>' { $$ = '>'; } |
| | '(' { $$ = '('; } |
| | ')' { $$ = ')'; } |
| | '{' { $$ = '{'; } |
| | '}' { $$ = '}'; } |
| | '.' { $$ = '.'; } |
| | '+' { $$ = '+'; } |
| | '-' { $$ = '-'; } |
| | '/' { $$ = '/'; } |
| | '*' { $$ = '*'; } |
| | '%' { $$ = '%'; } |
| | '^' { $$ = '^'; } |
| | '|' { $$ = '|'; } |
| | '&' { $$ = '&'; } |
| | '~' { $$ = '~'; } |
| | '=' { $$ = '='; } |
| | '!' { $$ = '!'; } |
| | ':' { $$ = ':'; } |
| | ';' { $$ = ';'; } |
| | ',' { $$ = ','; } |
| | '?' { $$ = '?'; } |
| ; |
| |
| %% |
| |
| void yyerror(YYLTYPE* llocp, pp::Context* context, const char* reason) |
| { |
| } |
| |
| void pushConditionalBlock(pp::Context* context, bool condition) |
| { |
| } |
| |
| void popConditionalBlock(pp::Context* context) |
| { |
| } |
| |
| namespace pp { |
| bool Context::parse() |
| { |
| yydebug = 1; |
| return yyparse(this) == 0 ? true : false; |
| } |
| } // namespace pp |
| |