blob: c984b56072d4d747913a1bb9b3de31523112fc06 [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)
Minmin Gong794e0002015-04-07 18:31:54 -070031#pragma warning(disable: 4065 4244 4701 4702)
alokp@chromium.org04d7d222012-05-16 19:24:07 +000032#endif
33
34#include "ExpressionParser.h"
35
Jamie Madilla738f082013-11-01 17:45:04 -040036#if defined(_MSC_VER)
Jamie Madilld7f21352013-10-30 17:53:15 -040037#include <malloc.h>
Jamie Madilla738f082013-11-01 17:45:04 -040038#else
39#include <stdlib.h>
40#endif
41
alokp@chromium.org04d7d222012-05-16 19:24:07 +000042#include <cassert>
43#include <sstream>
44
daniel@transgaming.comb3077d02013-01-11 04:12:09 +000045#include "DiagnosticsBase.h"
alokp@chromium.org04d7d222012-05-16 19:24:07 +000046#include "Lexer.h"
47#include "Token.h"
48
alokp@chromium.orgd39ec4c2012-06-26 04:37:55 +000049#if defined(_MSC_VER)
50typedef __int64 YYSTYPE;
alokp@chromium.orgd39ec4c2012-06-26 04:37:55 +000051#else
52#include <stdint.h>
53typedef intmax_t YYSTYPE;
54#endif // _MSC_VER
daniel@transgaming.comb3077d02013-01-11 04:12:09 +000055#define YYENABLE_NLS 0
56#define YYLTYPE_IS_TRIVIAL 1
alokp@chromium.orgd39ec4c2012-06-26 04:37:55 +000057#define YYSTYPE_IS_TRIVIAL 1
58#define YYSTYPE_IS_DECLARED 1
59
alokp@chromium.org04d7d222012-05-16 19:24:07 +000060namespace {
61struct Context
62{
alokp@chromium.org2c958ee2012-05-17 20:35:42 +000063 pp::Diagnostics* diagnostics;
alokp@chromium.org04d7d222012-05-16 19:24:07 +000064 pp::Lexer* lexer;
65 pp::Token* token;
66 int* result;
Olli Etuaho6ffe6132015-08-26 14:30:57 +030067
68 void startIgnoreErrors() { ++ignoreErrors; }
69 void endIgnoreErrors() { --ignoreErrors; }
70
71 bool isIgnoringErrors() { return ignoreErrors > 0; }
72
73 int ignoreErrors;
alokp@chromium.org04d7d222012-05-16 19:24:07 +000074};
75} // namespace
76%}
77
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +000078%pure-parser
Jamie Madill185de882014-12-22 15:17:52 -050079%name-prefix "pp"
alokp@chromium.org04d7d222012-05-16 19:24:07 +000080%parse-param {Context *context}
81%lex-param {Context *context}
82
83%{
alokp@chromium.orgd39ec4c2012-06-26 04:37:55 +000084static int yylex(YYSTYPE* lvalp, Context* context);
alokp@chromium.org04d7d222012-05-16 19:24:07 +000085static void yyerror(Context* context, const char* reason);
86%}
87
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +000088%token TOK_CONST_INT
Olli Etuaho6ffe6132015-08-26 14:30:57 +030089%token TOK_IDENTIFIER
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +000090%left TOK_OP_OR
91%left TOK_OP_AND
alokp@chromium.org04d7d222012-05-16 19:24:07 +000092%left '|'
93%left '^'
94%left '&'
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +000095%left TOK_OP_EQ TOK_OP_NE
96%left '<' '>' TOK_OP_LE TOK_OP_GE
97%left TOK_OP_LEFT TOK_OP_RIGHT
alokp@chromium.org04d7d222012-05-16 19:24:07 +000098%left '+' '-'
99%left '*' '/' '%'
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000100%right TOK_UNARY
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000101
102%%
103
104input
105 : expression {
alokp@chromium.orgd39ec4c2012-06-26 04:37:55 +0000106 *(context->result) = static_cast<int>($1);
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000107 }
108;
109
110expression
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000111 : TOK_CONST_INT
Olli Etuaho6ffe6132015-08-26 14:30:57 +0300112 | TOK_IDENTIFIER {
113 if (!context->isIgnoringErrors())
114 {
115 YYABORT;
116 }
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000117 }
Olli Etuaho6ffe6132015-08-26 14:30:57 +0300118 | expression TOK_OP_OR {
119 if ($1 != 0)
120 {
121 // Ignore errors in the short-circuited part of the expression.
122 // ESSL3.00 section 3.4:
123 // If an operand is not evaluated, the presence of undefined identifiers
124 // in the operand will not cause an error.
125 // Unevaluated division by zero should not cause an error either.
126 context->startIgnoreErrors();
127 }
128 } expression {
129 if ($1 != 0)
130 {
131 context->endIgnoreErrors();
132 // Make sure that short-circuited version of || works consistently
133 // with the normal version even for values other than 0 and 1.
134 $$ = $1 || 0;
135 }
136 else
137 {
138 $$ = $1 || $4;
139 }
140 }
141 | expression TOK_OP_AND {
142 if ($1 == 0)
143 {
144 // Ignore errors in the short-circuited part of the expression.
145 // ESSL3.00 section 3.4:
146 // If an operand is not evaluated, the presence of undefined identifiers
147 // in the operand will not cause an error.
148 // Unevaluated division by zero should not cause an error either.
149 context->startIgnoreErrors();
150 }
151 } expression {
152 if ($1 == 0)
153 {
154 context->endIgnoreErrors();
155 // Make sure that short-circuited version of && works consistently
156 // with the normal version even for values other than 0 and 1.
157 $$ = $1 && 0;
158 }
159 else
160 {
161 $$ = $1 && $4;
162 }
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000163 }
164 | expression '|' expression {
165 $$ = $1 | $3;
166 }
167 | expression '^' expression {
168 $$ = $1 ^ $3;
169 }
170 | expression '&' expression {
171 $$ = $1 & $3;
172 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000173 | expression TOK_OP_NE expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000174 $$ = $1 != $3;
175 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000176 | expression TOK_OP_EQ expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000177 $$ = $1 == $3;
178 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000179 | expression TOK_OP_GE expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000180 $$ = $1 >= $3;
181 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000182 | expression TOK_OP_LE expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000183 $$ = $1 <= $3;
184 }
185 | expression '>' expression {
186 $$ = $1 > $3;
187 }
188 | expression '<' expression {
189 $$ = $1 < $3;
190 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000191 | expression TOK_OP_RIGHT expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000192 $$ = $1 >> $3;
193 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000194 | expression TOK_OP_LEFT expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000195 $$ = $1 << $3;
196 }
197 | expression '-' expression {
198 $$ = $1 - $3;
199 }
200 | expression '+' expression {
201 $$ = $1 + $3;
202 }
203 | expression '%' expression {
Olli Etuaho6ffe6132015-08-26 14:30:57 +0300204 if ($3 == 0)
205 {
206 if (context->isIgnoringErrors())
207 {
208 $$ = static_cast<YYSTYPE>(0);
209 }
210 else
211 {
212 std::ostringstream stream;
213 stream << $1 << " % " << $3;
214 std::string text = stream.str();
215 context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
216 context->token->location,
217 text.c_str());
218 YYABORT;
219 }
220 }
221 else
222 {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000223 $$ = $1 % $3;
224 }
225 }
226 | expression '/' expression {
Olli Etuaho6ffe6132015-08-26 14:30:57 +0300227 if ($3 == 0)
228 {
229 if (context->isIgnoringErrors())
230 {
231 $$ = static_cast<YYSTYPE>(0);
232 }
233 else
234 {
235 std::ostringstream stream;
236 stream << $1 << " / " << $3;
237 std::string text = stream.str();
238 context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
239 context->token->location,
240 text.c_str());
241 YYABORT;
242 }
243 }
244 else
245 {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000246 $$ = $1 / $3;
247 }
248 }
249 | expression '*' expression {
250 $$ = $1 * $3;
251 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000252 | '!' expression %prec TOK_UNARY {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000253 $$ = ! $2;
254 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000255 | '~' expression %prec TOK_UNARY {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000256 $$ = ~ $2;
257 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000258 | '-' expression %prec TOK_UNARY {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000259 $$ = - $2;
260 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000261 | '+' expression %prec TOK_UNARY {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000262 $$ = + $2;
263 }
264 | '(' expression ')' {
265 $$ = $2;
266 }
267;
268
269%%
270
Zhenyao Mod526f982014-05-13 14:51:19 -0700271int yylex(YYSTYPE *lvalp, Context *context)
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000272{
273 int type = 0;
274
Zhenyao Mod526f982014-05-13 14:51:19 -0700275 pp::Token *token = context->token;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000276 switch (token->type)
277 {
Zhenyao Mod526f982014-05-13 14:51:19 -0700278 case pp::Token::CONST_INT: {
alokp@chromium.org2e818912012-06-29 21:26:03 +0000279 unsigned int val = 0;
280 if (!token->uValue(&val))
281 {
Jamie Madillc9f140d2014-02-18 15:27:21 -0500282 context->diagnostics->report(pp::Diagnostics::PP_INTEGER_OVERFLOW,
alokp@chromium.org2e818912012-06-29 21:26:03 +0000283 token->location, token->text);
284 }
285 *lvalp = static_cast<YYSTYPE>(val);
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000286 type = TOK_CONST_INT;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000287 break;
alokp@chromium.org2e818912012-06-29 21:26:03 +0000288 }
Olli Etuaho6ffe6132015-08-26 14:30:57 +0300289 case pp::Token::IDENTIFIER:
290 if (!context->isIgnoringErrors())
291 {
292 context->diagnostics->report(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
293 token->location, token->text);
294 }
295 *lvalp = static_cast<YYSTYPE>(-1);
296 type = TOK_IDENTIFIER;
297 break;
Zhenyao Mod526f982014-05-13 14:51:19 -0700298 case pp::Token::OP_OR:
299 type = TOK_OP_OR;
300 break;
301 case pp::Token::OP_AND:
302 type = TOK_OP_AND;
303 break;
304 case pp::Token::OP_NE:
305 type = TOK_OP_NE;
306 break;
307 case pp::Token::OP_EQ:
308 type = TOK_OP_EQ;
309 break;
310 case pp::Token::OP_GE:
311 type = TOK_OP_GE;
312 break;
313 case pp::Token::OP_LE:
314 type = TOK_OP_LE;
315 break;
316 case pp::Token::OP_RIGHT:
317 type = TOK_OP_RIGHT;
318 break;
319 case pp::Token::OP_LEFT:
320 type = TOK_OP_LEFT;
321 break;
322 case '|':
323 case '^':
324 case '&':
325 case '>':
326 case '<':
327 case '-':
328 case '+':
329 case '%':
330 case '/':
331 case '*':
332 case '!':
333 case '~':
334 case '(':
335 case ')':
336 type = token->type;
337 break;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000338
Zhenyao Mod526f982014-05-13 14:51:19 -0700339 default:
340 break;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000341 }
342
343 // Advance to the next token if the current one is valid.
Zhenyao Mod526f982014-05-13 14:51:19 -0700344 if (type != 0)
345 context->lexer->lex(token);
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000346
347 return type;
348}
349
Zhenyao Mod526f982014-05-13 14:51:19 -0700350void yyerror(Context *context, const char *reason)
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000351{
Jamie Madillc9f140d2014-02-18 15:27:21 -0500352 context->diagnostics->report(pp::Diagnostics::PP_INVALID_EXPRESSION,
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000353 context->token->location,
354 reason);
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000355}
356
357namespace pp {
358
Zhenyao Mod526f982014-05-13 14:51:19 -0700359ExpressionParser::ExpressionParser(Lexer *lexer, Diagnostics *diagnostics)
360 : mLexer(lexer),
361 mDiagnostics(diagnostics)
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000362{
363}
364
Zhenyao Mod526f982014-05-13 14:51:19 -0700365bool ExpressionParser::parse(Token *token, int *result)
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000366{
367 Context context;
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000368 context.diagnostics = mDiagnostics;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000369 context.lexer = mLexer;
370 context.token = token;
371 context.result = result;
Olli Etuaho6ffe6132015-08-26 14:30:57 +0300372 context.ignoreErrors = 0;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000373 int ret = yyparse(&context);
374 switch (ret)
375 {
376 case 0:
377 case 1:
378 break;
379
380 case 2:
Jamie Madillc9f140d2014-02-18 15:27:21 -0500381 mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token->location, "");
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000382 break;
383
384 default:
385 assert(false);
Jamie Madillc9f140d2014-02-18 15:27:21 -0500386 mDiagnostics->report(Diagnostics::PP_INTERNAL_ERROR, token->location, "");
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000387 break;
388 }
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000389
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000390 return ret == 0;
391}
392
393} // namespace pp