1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/compiler/preprocessor/ExpressionParser.y Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,285 @@ 1.4 +/* 1.5 +// 1.6 +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. 1.7 +// Use of this source code is governed by a BSD-style license that can be 1.8 +// found in the LICENSE file. 1.9 +// 1.10 + 1.11 +This file contains the Yacc grammar for GLSL ES preprocessor expression. 1.12 + 1.13 +IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh, 1.14 +WHICH GENERATES THE GLSL ES preprocessor expression parser. 1.15 +*/ 1.16 + 1.17 +%{ 1.18 +// 1.19 +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. 1.20 +// Use of this source code is governed by a BSD-style license that can be 1.21 +// found in the LICENSE file. 1.22 +// 1.23 + 1.24 +// This file is auto-generated by generate_parser.sh. DO NOT EDIT! 1.25 + 1.26 +#if defined(__GNUC__) 1.27 +// Triggered by the auto-generated pplval variable. 1.28 +#if !defined(__clang__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) 1.29 +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 1.30 +#else 1.31 +#pragma GCC diagnostic ignored "-Wuninitialized" 1.32 +#endif 1.33 +#elif defined(_MSC_VER) 1.34 +#pragma warning(disable: 4065 4701) 1.35 +#endif 1.36 + 1.37 +#include "ExpressionParser.h" 1.38 + 1.39 +#include <cassert> 1.40 +#include <sstream> 1.41 + 1.42 +#include "DiagnosticsBase.h" 1.43 +#include "Lexer.h" 1.44 +#include "Token.h" 1.45 + 1.46 +#if defined(_MSC_VER) 1.47 +typedef __int64 YYSTYPE; 1.48 +#else 1.49 +#include <stdint.h> 1.50 +typedef intmax_t YYSTYPE; 1.51 +#endif // _MSC_VER 1.52 +#define YYENABLE_NLS 0 1.53 +#define YYLTYPE_IS_TRIVIAL 1 1.54 +#define YYSTYPE_IS_TRIVIAL 1 1.55 +#define YYSTYPE_IS_DECLARED 1 1.56 + 1.57 +namespace { 1.58 +struct Context 1.59 +{ 1.60 + pp::Diagnostics* diagnostics; 1.61 + pp::Lexer* lexer; 1.62 + pp::Token* token; 1.63 + int* result; 1.64 +}; 1.65 +} // namespace 1.66 +%} 1.67 + 1.68 +%pure-parser 1.69 +%name-prefix="pp" 1.70 +%parse-param {Context *context} 1.71 +%lex-param {Context *context} 1.72 + 1.73 +%{ 1.74 +static int yylex(YYSTYPE* lvalp, Context* context); 1.75 +static void yyerror(Context* context, const char* reason); 1.76 +%} 1.77 + 1.78 +%token TOK_CONST_INT 1.79 +%left TOK_OP_OR 1.80 +%left TOK_OP_AND 1.81 +%left '|' 1.82 +%left '^' 1.83 +%left '&' 1.84 +%left TOK_OP_EQ TOK_OP_NE 1.85 +%left '<' '>' TOK_OP_LE TOK_OP_GE 1.86 +%left TOK_OP_LEFT TOK_OP_RIGHT 1.87 +%left '+' '-' 1.88 +%left '*' '/' '%' 1.89 +%right TOK_UNARY 1.90 + 1.91 +%% 1.92 + 1.93 +input 1.94 + : expression { 1.95 + *(context->result) = static_cast<int>($1); 1.96 + YYACCEPT; 1.97 + } 1.98 +; 1.99 + 1.100 +expression 1.101 + : TOK_CONST_INT 1.102 + | expression TOK_OP_OR expression { 1.103 + $$ = $1 || $3; 1.104 + } 1.105 + | expression TOK_OP_AND expression { 1.106 + $$ = $1 && $3; 1.107 + } 1.108 + | expression '|' expression { 1.109 + $$ = $1 | $3; 1.110 + } 1.111 + | expression '^' expression { 1.112 + $$ = $1 ^ $3; 1.113 + } 1.114 + | expression '&' expression { 1.115 + $$ = $1 & $3; 1.116 + } 1.117 + | expression TOK_OP_NE expression { 1.118 + $$ = $1 != $3; 1.119 + } 1.120 + | expression TOK_OP_EQ expression { 1.121 + $$ = $1 == $3; 1.122 + } 1.123 + | expression TOK_OP_GE expression { 1.124 + $$ = $1 >= $3; 1.125 + } 1.126 + | expression TOK_OP_LE expression { 1.127 + $$ = $1 <= $3; 1.128 + } 1.129 + | expression '>' expression { 1.130 + $$ = $1 > $3; 1.131 + } 1.132 + | expression '<' expression { 1.133 + $$ = $1 < $3; 1.134 + } 1.135 + | expression TOK_OP_RIGHT expression { 1.136 + $$ = $1 >> $3; 1.137 + } 1.138 + | expression TOK_OP_LEFT expression { 1.139 + $$ = $1 << $3; 1.140 + } 1.141 + | expression '-' expression { 1.142 + $$ = $1 - $3; 1.143 + } 1.144 + | expression '+' expression { 1.145 + $$ = $1 + $3; 1.146 + } 1.147 + | expression '%' expression { 1.148 + if ($3 == 0) { 1.149 + std::ostringstream stream; 1.150 + stream << $1 << " % " << $3; 1.151 + std::string text = stream.str(); 1.152 + context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO, 1.153 + context->token->location, 1.154 + text.c_str()); 1.155 + YYABORT; 1.156 + } else { 1.157 + $$ = $1 % $3; 1.158 + } 1.159 + } 1.160 + | expression '/' expression { 1.161 + if ($3 == 0) { 1.162 + std::ostringstream stream; 1.163 + stream << $1 << " / " << $3; 1.164 + std::string text = stream.str(); 1.165 + context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO, 1.166 + context->token->location, 1.167 + text.c_str()); 1.168 + YYABORT; 1.169 + } else { 1.170 + $$ = $1 / $3; 1.171 + } 1.172 + } 1.173 + | expression '*' expression { 1.174 + $$ = $1 * $3; 1.175 + } 1.176 + | '!' expression %prec TOK_UNARY { 1.177 + $$ = ! $2; 1.178 + } 1.179 + | '~' expression %prec TOK_UNARY { 1.180 + $$ = ~ $2; 1.181 + } 1.182 + | '-' expression %prec TOK_UNARY { 1.183 + $$ = - $2; 1.184 + } 1.185 + | '+' expression %prec TOK_UNARY { 1.186 + $$ = + $2; 1.187 + } 1.188 + | '(' expression ')' { 1.189 + $$ = $2; 1.190 + } 1.191 +; 1.192 + 1.193 +%% 1.194 + 1.195 +int yylex(YYSTYPE* lvalp, Context* context) 1.196 +{ 1.197 + int type = 0; 1.198 + 1.199 + pp::Token* token = context->token; 1.200 + switch (token->type) 1.201 + { 1.202 + case pp::Token::CONST_INT: 1.203 + { 1.204 + unsigned int val = 0; 1.205 + if (!token->uValue(&val)) 1.206 + { 1.207 + context->diagnostics->report(pp::Diagnostics::INTEGER_OVERFLOW, 1.208 + token->location, token->text); 1.209 + } 1.210 + *lvalp = static_cast<YYSTYPE>(val); 1.211 + type = TOK_CONST_INT; 1.212 + break; 1.213 + } 1.214 + case pp::Token::OP_OR: type = TOK_OP_OR; break; 1.215 + case pp::Token::OP_AND: type = TOK_OP_AND; break; 1.216 + case pp::Token::OP_NE: type = TOK_OP_NE; break; 1.217 + case pp::Token::OP_EQ: type = TOK_OP_EQ; break; 1.218 + case pp::Token::OP_GE: type = TOK_OP_GE; break; 1.219 + case pp::Token::OP_LE: type = TOK_OP_LE; break; 1.220 + case pp::Token::OP_RIGHT: type = TOK_OP_RIGHT; break; 1.221 + case pp::Token::OP_LEFT: type = TOK_OP_LEFT; break; 1.222 + case '|': type = '|'; break; 1.223 + case '^': type = '^'; break; 1.224 + case '&': type = '&'; break; 1.225 + case '>': type = '>'; break; 1.226 + case '<': type = '<'; break; 1.227 + case '-': type = '-'; break; 1.228 + case '+': type = '+'; break; 1.229 + case '%': type = '%'; break; 1.230 + case '/': type = '/'; break; 1.231 + case '*': type = '*'; break; 1.232 + case '!': type = '!'; break; 1.233 + case '~': type = '~'; break; 1.234 + case '(': type = '('; break; 1.235 + case ')': type = ')'; break; 1.236 + 1.237 + default: break; 1.238 + } 1.239 + 1.240 + // Advance to the next token if the current one is valid. 1.241 + if (type != 0) context->lexer->lex(token); 1.242 + 1.243 + return type; 1.244 +} 1.245 + 1.246 +void yyerror(Context* context, const char* reason) 1.247 +{ 1.248 + context->diagnostics->report(pp::Diagnostics::INVALID_EXPRESSION, 1.249 + context->token->location, 1.250 + reason); 1.251 +} 1.252 + 1.253 +namespace pp { 1.254 + 1.255 +ExpressionParser::ExpressionParser(Lexer* lexer, Diagnostics* diagnostics) : 1.256 + mLexer(lexer), 1.257 + mDiagnostics(diagnostics) 1.258 +{ 1.259 +} 1.260 + 1.261 +bool ExpressionParser::parse(Token* token, int* result) 1.262 +{ 1.263 + Context context; 1.264 + context.diagnostics = mDiagnostics; 1.265 + context.lexer = mLexer; 1.266 + context.token = token; 1.267 + context.result = result; 1.268 + int ret = yyparse(&context); 1.269 + switch (ret) 1.270 + { 1.271 + case 0: 1.272 + case 1: 1.273 + break; 1.274 + 1.275 + case 2: 1.276 + mDiagnostics->report(Diagnostics::OUT_OF_MEMORY, token->location, ""); 1.277 + break; 1.278 + 1.279 + default: 1.280 + assert(false); 1.281 + mDiagnostics->report(Diagnostics::INTERNAL_ERROR, token->location, ""); 1.282 + break; 1.283 + } 1.284 + 1.285 + return ret == 0; 1.286 +} 1.287 + 1.288 +} // namespace pp