blob: 7b5d9e9cee96ec1cd5e0850f3e2013fdf1204443 [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
Olli Etuaho3187a382015-09-09 12:00:12 +030055
daniel@transgaming.comb3077d02013-01-11 04:12:09 +000056#define YYENABLE_NLS 0
57#define YYLTYPE_IS_TRIVIAL 1
alokp@chromium.orgd39ec4c2012-06-26 04:37:55 +000058#define YYSTYPE_IS_TRIVIAL 1
59#define YYSTYPE_IS_DECLARED 1
60
alokp@chromium.org04d7d222012-05-16 19:24:07 +000061namespace {
62struct Context
63{
alokp@chromium.org2c958ee2012-05-17 20:35:42 +000064 pp::Diagnostics* diagnostics;
alokp@chromium.org04d7d222012-05-16 19:24:07 +000065 pp::Lexer* lexer;
66 pp::Token* token;
67 int* result;
Olli Etuaho247374c2015-09-09 15:07:24 +030068 bool parsePresetToken;
69
70 pp::ExpressionParser::ErrorSettings errorSettings;
71 bool *valid;
Olli Etuaho809ec542015-08-26 14:30:57 +030072
73 void startIgnoreErrors() { ++ignoreErrors; }
74 void endIgnoreErrors() { --ignoreErrors; }
75
76 bool isIgnoringErrors() { return ignoreErrors > 0; }
77
78 int ignoreErrors;
alokp@chromium.org04d7d222012-05-16 19:24:07 +000079};
80} // namespace
81%}
82
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +000083%pure-parser
Jamie Madill185de882014-12-22 15:17:52 -050084%name-prefix "pp"
alokp@chromium.org04d7d222012-05-16 19:24:07 +000085%parse-param {Context *context}
86%lex-param {Context *context}
87
88%{
alokp@chromium.orgd39ec4c2012-06-26 04:37:55 +000089static int yylex(YYSTYPE* lvalp, Context* context);
alokp@chromium.org04d7d222012-05-16 19:24:07 +000090static void yyerror(Context* context, const char* reason);
91%}
92
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +000093%token TOK_CONST_INT
Olli Etuaho809ec542015-08-26 14:30:57 +030094%token TOK_IDENTIFIER
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +000095%left TOK_OP_OR
96%left TOK_OP_AND
alokp@chromium.org04d7d222012-05-16 19:24:07 +000097%left '|'
98%left '^'
99%left '&'
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000100%left TOK_OP_EQ TOK_OP_NE
101%left '<' '>' TOK_OP_LE TOK_OP_GE
102%left TOK_OP_LEFT TOK_OP_RIGHT
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000103%left '+' '-'
104%left '*' '/' '%'
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000105%right TOK_UNARY
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000106
107%%
108
109input
110 : expression {
alokp@chromium.orgd39ec4c2012-06-26 04:37:55 +0000111 *(context->result) = static_cast<int>($1);
Olli Etuaho3187a382015-09-09 12:00:12 +0300112 YYACCEPT;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000113 }
114;
115
116expression
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000117 : TOK_CONST_INT
Olli Etuaho809ec542015-08-26 14:30:57 +0300118 | TOK_IDENTIFIER {
119 if (!context->isIgnoringErrors())
120 {
Olli Etuaho3187a382015-09-09 12:00:12 +0300121 // This rule should be applied right after the token is lexed, so we can
122 // refer to context->token in the error message.
Olli Etuaho247374c2015-09-09 15:07:24 +0300123 context->diagnostics->report(context->errorSettings.unexpectedIdentifier,
Olli Etuaho3187a382015-09-09 12:00:12 +0300124 context->token->location, context->token->text);
Olli Etuaho247374c2015-09-09 15:07:24 +0300125 *(context->valid) = false;
Olli Etuaho809ec542015-08-26 14:30:57 +0300126 }
Olli Etuaho3187a382015-09-09 12:00:12 +0300127 $$ = $1;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000128 }
Olli Etuaho809ec542015-08-26 14:30:57 +0300129 | expression TOK_OP_OR {
130 if ($1 != 0)
131 {
132 // Ignore errors in the short-circuited part of the expression.
133 // ESSL3.00 section 3.4:
134 // If an operand is not evaluated, the presence of undefined identifiers
135 // in the operand will not cause an error.
136 // Unevaluated division by zero should not cause an error either.
137 context->startIgnoreErrors();
138 }
139 } expression {
140 if ($1 != 0)
141 {
142 context->endIgnoreErrors();
143 $$ = static_cast<YYSTYPE>(1);
144 }
145 else
146 {
147 $$ = $1 || $4;
148 }
149 }
150 | expression TOK_OP_AND {
151 if ($1 == 0)
152 {
153 // Ignore errors in the short-circuited part of the expression.
154 // ESSL3.00 section 3.4:
155 // If an operand is not evaluated, the presence of undefined identifiers
156 // in the operand will not cause an error.
157 // Unevaluated division by zero should not cause an error either.
158 context->startIgnoreErrors();
159 }
160 } expression {
161 if ($1 == 0)
162 {
163 context->endIgnoreErrors();
164 $$ = static_cast<YYSTYPE>(0);
165 }
166 else
167 {
168 $$ = $1 && $4;
169 }
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000170 }
171 | expression '|' expression {
172 $$ = $1 | $3;
173 }
174 | expression '^' expression {
175 $$ = $1 ^ $3;
176 }
177 | expression '&' expression {
178 $$ = $1 & $3;
179 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000180 | expression TOK_OP_NE expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000181 $$ = $1 != $3;
182 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000183 | expression TOK_OP_EQ expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000184 $$ = $1 == $3;
185 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000186 | expression TOK_OP_GE expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000187 $$ = $1 >= $3;
188 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000189 | expression TOK_OP_LE expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000190 $$ = $1 <= $3;
191 }
192 | expression '>' expression {
193 $$ = $1 > $3;
194 }
195 | expression '<' expression {
196 $$ = $1 < $3;
197 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000198 | expression TOK_OP_RIGHT expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000199 $$ = $1 >> $3;
200 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000201 | expression TOK_OP_LEFT expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000202 $$ = $1 << $3;
203 }
204 | expression '-' expression {
205 $$ = $1 - $3;
206 }
207 | expression '+' expression {
208 $$ = $1 + $3;
209 }
210 | expression '%' expression {
Olli Etuaho809ec542015-08-26 14:30:57 +0300211 if ($3 == 0)
212 {
Olli Etuaho3187a382015-09-09 12:00:12 +0300213 if (!context->isIgnoringErrors())
Olli Etuaho809ec542015-08-26 14:30:57 +0300214 {
215 std::ostringstream stream;
216 stream << $1 << " % " << $3;
217 std::string text = stream.str();
218 context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
219 context->token->location,
220 text.c_str());
Olli Etuaho247374c2015-09-09 15:07:24 +0300221 *(context->valid) = false;
Olli Etuaho809ec542015-08-26 14:30:57 +0300222 }
Olli Etuaho3187a382015-09-09 12:00:12 +0300223 $$ = static_cast<YYSTYPE>(0);
Olli Etuaho809ec542015-08-26 14:30:57 +0300224 }
225 else
226 {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000227 $$ = $1 % $3;
228 }
229 }
230 | expression '/' expression {
Olli Etuaho809ec542015-08-26 14:30:57 +0300231 if ($3 == 0)
232 {
Olli Etuaho3187a382015-09-09 12:00:12 +0300233 if (!context->isIgnoringErrors())
Olli Etuaho809ec542015-08-26 14:30:57 +0300234 {
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());
Olli Etuaho247374c2015-09-09 15:07:24 +0300241 *(context->valid) = false;
Olli Etuaho809ec542015-08-26 14:30:57 +0300242 }
Olli Etuaho3187a382015-09-09 12:00:12 +0300243 $$ = static_cast<YYSTYPE>(0);
Olli Etuaho809ec542015-08-26 14:30:57 +0300244 }
245 else
246 {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000247 $$ = $1 / $3;
248 }
249 }
250 | expression '*' expression {
251 $$ = $1 * $3;
252 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000253 | '!' expression %prec TOK_UNARY {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000254 $$ = ! $2;
255 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000256 | '~' expression %prec TOK_UNARY {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000257 $$ = ~ $2;
258 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000259 | '-' expression %prec TOK_UNARY {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000260 $$ = - $2;
261 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000262 | '+' expression %prec TOK_UNARY {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000263 $$ = + $2;
264 }
265 | '(' expression ')' {
266 $$ = $2;
267 }
268;
269
270%%
271
Zhenyao Mod526f982014-05-13 14:51:19 -0700272int yylex(YYSTYPE *lvalp, Context *context)
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000273{
Olli Etuaho3187a382015-09-09 12:00:12 +0300274 pp::Token *token = context->token;
Olli Etuaho247374c2015-09-09 15:07:24 +0300275 if (!context->parsePresetToken)
276 {
277 context->lexer->lex(token);
278 }
279 context->parsePresetToken = false;
Olli Etuaho3187a382015-09-09 12:00:12 +0300280
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000281 int type = 0;
282
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000283 switch (token->type)
284 {
Zhenyao Mod526f982014-05-13 14:51:19 -0700285 case pp::Token::CONST_INT: {
alokp@chromium.org2e818912012-06-29 21:26:03 +0000286 unsigned int val = 0;
Olli Etuaho247374c2015-09-09 15:07:24 +0300287 int testVal = 0;
288 if (!token->uValue(&val) || (!token->iValue(&testVal) &&
289 context->errorSettings.integerLiteralsMustFit32BitSignedRange))
alokp@chromium.org2e818912012-06-29 21:26:03 +0000290 {
Jamie Madillc9f140d2014-02-18 15:27:21 -0500291 context->diagnostics->report(pp::Diagnostics::PP_INTEGER_OVERFLOW,
alokp@chromium.org2e818912012-06-29 21:26:03 +0000292 token->location, token->text);
Olli Etuaho247374c2015-09-09 15:07:24 +0300293 *(context->valid) = false;
alokp@chromium.org2e818912012-06-29 21:26:03 +0000294 }
295 *lvalp = static_cast<YYSTYPE>(val);
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000296 type = TOK_CONST_INT;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000297 break;
alokp@chromium.org2e818912012-06-29 21:26:03 +0000298 }
Olli Etuaho809ec542015-08-26 14:30:57 +0300299 case pp::Token::IDENTIFIER:
Olli Etuaho809ec542015-08-26 14:30:57 +0300300 *lvalp = static_cast<YYSTYPE>(-1);
301 type = TOK_IDENTIFIER;
302 break;
Zhenyao Mod526f982014-05-13 14:51:19 -0700303 case pp::Token::OP_OR:
304 type = TOK_OP_OR;
305 break;
306 case pp::Token::OP_AND:
307 type = TOK_OP_AND;
308 break;
309 case pp::Token::OP_NE:
310 type = TOK_OP_NE;
311 break;
312 case pp::Token::OP_EQ:
313 type = TOK_OP_EQ;
314 break;
315 case pp::Token::OP_GE:
316 type = TOK_OP_GE;
317 break;
318 case pp::Token::OP_LE:
319 type = TOK_OP_LE;
320 break;
321 case pp::Token::OP_RIGHT:
322 type = TOK_OP_RIGHT;
323 break;
324 case pp::Token::OP_LEFT:
325 type = TOK_OP_LEFT;
326 break;
327 case '|':
328 case '^':
329 case '&':
330 case '>':
331 case '<':
332 case '-':
333 case '+':
334 case '%':
335 case '/':
336 case '*':
337 case '!':
338 case '~':
339 case '(':
340 case ')':
341 type = token->type;
342 break;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000343
Zhenyao Mod526f982014-05-13 14:51:19 -0700344 default:
345 break;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000346 }
347
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000348 return type;
349}
350
Zhenyao Mod526f982014-05-13 14:51:19 -0700351void yyerror(Context *context, const char *reason)
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000352{
Jamie Madillc9f140d2014-02-18 15:27:21 -0500353 context->diagnostics->report(pp::Diagnostics::PP_INVALID_EXPRESSION,
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000354 context->token->location,
355 reason);
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000356}
357
358namespace pp {
359
Zhenyao Mod526f982014-05-13 14:51:19 -0700360ExpressionParser::ExpressionParser(Lexer *lexer, Diagnostics *diagnostics)
361 : mLexer(lexer),
362 mDiagnostics(diagnostics)
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000363{
364}
365
Olli Etuaho247374c2015-09-09 15:07:24 +0300366bool ExpressionParser::parse(Token *token,
367 int *result,
368 bool parsePresetToken,
369 const ErrorSettings &errorSettings,
370 bool *valid)
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000371{
372 Context context;
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000373 context.diagnostics = mDiagnostics;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000374 context.lexer = mLexer;
375 context.token = token;
376 context.result = result;
Olli Etuaho809ec542015-08-26 14:30:57 +0300377 context.ignoreErrors = 0;
Olli Etuaho247374c2015-09-09 15:07:24 +0300378 context.parsePresetToken = parsePresetToken;
379 context.errorSettings = errorSettings;
380 context.valid = valid;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000381 int ret = yyparse(&context);
382 switch (ret)
383 {
384 case 0:
385 case 1:
386 break;
387
388 case 2:
Jamie Madillc9f140d2014-02-18 15:27:21 -0500389 mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token->location, "");
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000390 break;
391
392 default:
393 assert(false);
Jamie Madillc9f140d2014-02-18 15:27:21 -0500394 mDiagnostics->report(Diagnostics::PP_INTERNAL_ERROR, token->location, "");
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000395 break;
396 }
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000397
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000398 return ret == 0;
399}
400
401} // namespace pp