blob: b6d3143e605483efd658c5a5c65483d9159bed44 [file] [log] [blame]
alokp@chromium.org04d7d222012-05-16 19:24:07 +00001/*
2//
3// Copyright (c) 2012 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 Yacc grammar for GLSL ES preprocessor expression.
9
10IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
11WHICH GENERATES THE GLSL ES preprocessor expression parser.
12*/
13
14%{
15//
16// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
17// Use of this source code is governed by a BSD-style license that can be
18// found in the LICENSE file.
19//
20
21// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
22
23#if defined(__GNUC__)
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +000024// Triggered by the auto-generated pplval variable.
shannon.woods@transgaming.comeb68fd02013-02-28 23:20:01 +000025#if !defined(__clang__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
daniel@transgaming.comb3077d02013-01-11 04:12:09 +000026#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
shannon.woods@transgaming.comeb68fd02013-02-28 23:20:01 +000027#else
28#pragma GCC diagnostic ignored "-Wuninitialized"
shannon.woods@transgaming.come36fddf2013-01-25 21:57:50 +000029#endif
alokp@chromium.org04d7d222012-05-16 19:24:07 +000030#elif defined(_MSC_VER)
31#pragma warning(disable: 4065 4701)
32#endif
33
34#include "ExpressionParser.h"
35
36#include <cassert>
37#include <sstream>
38
daniel@transgaming.comb3077d02013-01-11 04:12:09 +000039#include "DiagnosticsBase.h"
alokp@chromium.org04d7d222012-05-16 19:24:07 +000040#include "Lexer.h"
41#include "Token.h"
42
alokp@chromium.orgd39ec4c2012-06-26 04:37:55 +000043#if defined(_MSC_VER)
44typedef __int64 YYSTYPE;
alokp@chromium.orgd39ec4c2012-06-26 04:37:55 +000045#else
46#include <stdint.h>
47typedef intmax_t YYSTYPE;
48#endif // _MSC_VER
daniel@transgaming.comb3077d02013-01-11 04:12:09 +000049#define YYENABLE_NLS 0
50#define YYLTYPE_IS_TRIVIAL 1
alokp@chromium.orgd39ec4c2012-06-26 04:37:55 +000051#define YYSTYPE_IS_TRIVIAL 1
52#define YYSTYPE_IS_DECLARED 1
53
alokp@chromium.org04d7d222012-05-16 19:24:07 +000054namespace {
55struct Context
56{
alokp@chromium.org2c958ee2012-05-17 20:35:42 +000057 pp::Diagnostics* diagnostics;
alokp@chromium.org04d7d222012-05-16 19:24:07 +000058 pp::Lexer* lexer;
59 pp::Token* token;
60 int* result;
61};
62} // namespace
63%}
64
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +000065%pure-parser
alokp@chromium.org04d7d222012-05-16 19:24:07 +000066%name-prefix="pp"
67%parse-param {Context *context}
68%lex-param {Context *context}
69
70%{
alokp@chromium.orgd39ec4c2012-06-26 04:37:55 +000071static int yylex(YYSTYPE* lvalp, Context* context);
alokp@chromium.org04d7d222012-05-16 19:24:07 +000072static void yyerror(Context* context, const char* reason);
73%}
74
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +000075%token TOK_CONST_INT
76%left TOK_OP_OR
77%left TOK_OP_AND
alokp@chromium.org04d7d222012-05-16 19:24:07 +000078%left '|'
79%left '^'
80%left '&'
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +000081%left TOK_OP_EQ TOK_OP_NE
82%left '<' '>' TOK_OP_LE TOK_OP_GE
83%left TOK_OP_LEFT TOK_OP_RIGHT
alokp@chromium.org04d7d222012-05-16 19:24:07 +000084%left '+' '-'
85%left '*' '/' '%'
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +000086%right TOK_UNARY
alokp@chromium.org04d7d222012-05-16 19:24:07 +000087
88%%
89
90input
91 : expression {
alokp@chromium.orgd39ec4c2012-06-26 04:37:55 +000092 *(context->result) = static_cast<int>($1);
alokp@chromium.org04d7d222012-05-16 19:24:07 +000093 YYACCEPT;
94 }
95;
96
97expression
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +000098 : TOK_CONST_INT
99 | expression TOK_OP_OR expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000100 $$ = $1 || $3;
101 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000102 | expression TOK_OP_AND expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000103 $$ = $1 && $3;
104 }
105 | expression '|' expression {
106 $$ = $1 | $3;
107 }
108 | expression '^' expression {
109 $$ = $1 ^ $3;
110 }
111 | expression '&' expression {
112 $$ = $1 & $3;
113 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000114 | expression TOK_OP_NE expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000115 $$ = $1 != $3;
116 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000117 | expression TOK_OP_EQ expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000118 $$ = $1 == $3;
119 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000120 | expression TOK_OP_GE expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000121 $$ = $1 >= $3;
122 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000123 | expression TOK_OP_LE expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000124 $$ = $1 <= $3;
125 }
126 | expression '>' expression {
127 $$ = $1 > $3;
128 }
129 | expression '<' expression {
130 $$ = $1 < $3;
131 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000132 | expression TOK_OP_RIGHT expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000133 $$ = $1 >> $3;
134 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000135 | expression TOK_OP_LEFT expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000136 $$ = $1 << $3;
137 }
138 | expression '-' expression {
139 $$ = $1 - $3;
140 }
141 | expression '+' expression {
142 $$ = $1 + $3;
143 }
144 | expression '%' expression {
145 if ($3 == 0) {
alokp@chromium.org2e818912012-06-29 21:26:03 +0000146 std::ostringstream stream;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000147 stream << $1 << " % " << $3;
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000148 std::string text = stream.str();
149 context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO,
150 context->token->location,
151 text.c_str());
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000152 YYABORT;
153 } else {
154 $$ = $1 % $3;
155 }
156 }
157 | expression '/' expression {
158 if ($3 == 0) {
alokp@chromium.org2e818912012-06-29 21:26:03 +0000159 std::ostringstream stream;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000160 stream << $1 << " / " << $3;
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000161 std::string text = stream.str();
162 context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO,
163 context->token->location,
164 text.c_str());
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000165 YYABORT;
166 } else {
167 $$ = $1 / $3;
168 }
169 }
170 | expression '*' expression {
171 $$ = $1 * $3;
172 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000173 | '!' expression %prec TOK_UNARY {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000174 $$ = ! $2;
175 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000176 | '~' expression %prec TOK_UNARY {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000177 $$ = ~ $2;
178 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000179 | '-' expression %prec TOK_UNARY {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000180 $$ = - $2;
181 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000182 | '+' expression %prec TOK_UNARY {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000183 $$ = + $2;
184 }
185 | '(' expression ')' {
186 $$ = $2;
187 }
188;
189
190%%
191
alokp@chromium.orgd39ec4c2012-06-26 04:37:55 +0000192int yylex(YYSTYPE* lvalp, Context* context)
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000193{
194 int type = 0;
195
196 pp::Token* token = context->token;
197 switch (token->type)
198 {
199 case pp::Token::CONST_INT:
alokp@chromium.org2e818912012-06-29 21:26:03 +0000200 {
201 unsigned int val = 0;
202 if (!token->uValue(&val))
203 {
204 context->diagnostics->report(pp::Diagnostics::INTEGER_OVERFLOW,
205 token->location, token->text);
206 }
207 *lvalp = static_cast<YYSTYPE>(val);
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000208 type = TOK_CONST_INT;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000209 break;
alokp@chromium.org2e818912012-06-29 21:26:03 +0000210 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000211 case pp::Token::OP_OR: type = TOK_OP_OR; break;
212 case pp::Token::OP_AND: type = TOK_OP_AND; break;
213 case pp::Token::OP_NE: type = TOK_OP_NE; break;
214 case pp::Token::OP_EQ: type = TOK_OP_EQ; break;
215 case pp::Token::OP_GE: type = TOK_OP_GE; break;
216 case pp::Token::OP_LE: type = TOK_OP_LE; break;
217 case pp::Token::OP_RIGHT: type = TOK_OP_RIGHT; break;
218 case pp::Token::OP_LEFT: type = TOK_OP_LEFT; break;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000219 case '|': type = '|'; break;
220 case '^': type = '^'; break;
221 case '&': type = '&'; break;
222 case '>': type = '>'; break;
223 case '<': type = '<'; break;
224 case '-': type = '-'; break;
225 case '+': type = '+'; break;
226 case '%': type = '%'; break;
227 case '/': type = '/'; break;
228 case '*': type = '*'; break;
229 case '!': type = '!'; break;
230 case '~': type = '~'; break;
231 case '(': type = '('; break;
232 case ')': type = ')'; break;
233
234 default: break;
235 }
236
237 // Advance to the next token if the current one is valid.
238 if (type != 0) context->lexer->lex(token);
239
240 return type;
241}
242
243void yyerror(Context* context, const char* reason)
244{
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000245 context->diagnostics->report(pp::Diagnostics::INVALID_EXPRESSION,
246 context->token->location,
247 reason);
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000248}
249
250namespace pp {
251
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000252ExpressionParser::ExpressionParser(Lexer* lexer, Diagnostics* diagnostics) :
253 mLexer(lexer),
254 mDiagnostics(diagnostics)
255{
256}
257
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000258bool ExpressionParser::parse(Token* token, int* result)
259{
260 Context context;
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000261 context.diagnostics = mDiagnostics;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000262 context.lexer = mLexer;
263 context.token = token;
264 context.result = result;
265 int ret = yyparse(&context);
266 switch (ret)
267 {
268 case 0:
269 case 1:
270 break;
271
272 case 2:
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000273 mDiagnostics->report(Diagnostics::OUT_OF_MEMORY, token->location, "");
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000274 break;
275
276 default:
277 assert(false);
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000278 mDiagnostics->report(Diagnostics::INTERNAL_ERROR, token->location, "");
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000279 break;
280 }
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000281
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000282 return ret == 0;
283}
284
285} // namespace pp