blob: 8df2f91a08ee3f5f544e2166b4e29e131958a2a5 [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 Etuaho809ec542015-08-26 14:30:57 +030068
69 void startIgnoreErrors() { ++ignoreErrors; }
70 void endIgnoreErrors() { --ignoreErrors; }
71
72 bool isIgnoringErrors() { return ignoreErrors > 0; }
73
74 int ignoreErrors;
alokp@chromium.org04d7d222012-05-16 19:24:07 +000075};
76} // namespace
77%}
78
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +000079%pure-parser
Jamie Madill185de882014-12-22 15:17:52 -050080%name-prefix "pp"
alokp@chromium.org04d7d222012-05-16 19:24:07 +000081%parse-param {Context *context}
82%lex-param {Context *context}
83
84%{
alokp@chromium.orgd39ec4c2012-06-26 04:37:55 +000085static int yylex(YYSTYPE* lvalp, Context* context);
alokp@chromium.org04d7d222012-05-16 19:24:07 +000086static void yyerror(Context* context, const char* reason);
87%}
88
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +000089%token TOK_CONST_INT
Olli Etuaho809ec542015-08-26 14:30:57 +030090%token TOK_IDENTIFIER
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +000091%left TOK_OP_OR
92%left TOK_OP_AND
alokp@chromium.org04d7d222012-05-16 19:24:07 +000093%left '|'
94%left '^'
95%left '&'
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +000096%left TOK_OP_EQ TOK_OP_NE
97%left '<' '>' TOK_OP_LE TOK_OP_GE
98%left TOK_OP_LEFT TOK_OP_RIGHT
alokp@chromium.org04d7d222012-05-16 19:24:07 +000099%left '+' '-'
100%left '*' '/' '%'
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000101%right TOK_UNARY
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000102
103%%
104
105input
106 : expression {
alokp@chromium.orgd39ec4c2012-06-26 04:37:55 +0000107 *(context->result) = static_cast<int>($1);
Olli Etuaho3187a382015-09-09 12:00:12 +0300108 YYACCEPT;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000109 }
110;
111
112expression
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000113 : TOK_CONST_INT
Olli Etuaho809ec542015-08-26 14:30:57 +0300114 | TOK_IDENTIFIER {
115 if (!context->isIgnoringErrors())
116 {
Olli Etuaho3187a382015-09-09 12:00:12 +0300117 // This rule should be applied right after the token is lexed, so we can
118 // refer to context->token in the error message.
119 context->diagnostics->report(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
120 context->token->location, context->token->text);
Olli Etuaho809ec542015-08-26 14:30:57 +0300121 }
Olli Etuaho3187a382015-09-09 12:00:12 +0300122 $$ = $1;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000123 }
Olli Etuaho809ec542015-08-26 14:30:57 +0300124 | expression TOK_OP_OR {
125 if ($1 != 0)
126 {
127 // Ignore errors in the short-circuited part of the expression.
128 // ESSL3.00 section 3.4:
129 // If an operand is not evaluated, the presence of undefined identifiers
130 // in the operand will not cause an error.
131 // Unevaluated division by zero should not cause an error either.
132 context->startIgnoreErrors();
133 }
134 } expression {
135 if ($1 != 0)
136 {
137 context->endIgnoreErrors();
138 $$ = static_cast<YYSTYPE>(1);
139 }
140 else
141 {
142 $$ = $1 || $4;
143 }
144 }
145 | expression TOK_OP_AND {
146 if ($1 == 0)
147 {
148 // Ignore errors in the short-circuited part of the expression.
149 // ESSL3.00 section 3.4:
150 // If an operand is not evaluated, the presence of undefined identifiers
151 // in the operand will not cause an error.
152 // Unevaluated division by zero should not cause an error either.
153 context->startIgnoreErrors();
154 }
155 } expression {
156 if ($1 == 0)
157 {
158 context->endIgnoreErrors();
159 $$ = static_cast<YYSTYPE>(0);
160 }
161 else
162 {
163 $$ = $1 && $4;
164 }
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000165 }
166 | expression '|' expression {
167 $$ = $1 | $3;
168 }
169 | expression '^' expression {
170 $$ = $1 ^ $3;
171 }
172 | expression '&' expression {
173 $$ = $1 & $3;
174 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000175 | expression TOK_OP_NE expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000176 $$ = $1 != $3;
177 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000178 | expression TOK_OP_EQ expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000179 $$ = $1 == $3;
180 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000181 | expression TOK_OP_GE expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000182 $$ = $1 >= $3;
183 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000184 | expression TOK_OP_LE expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000185 $$ = $1 <= $3;
186 }
187 | expression '>' expression {
188 $$ = $1 > $3;
189 }
190 | expression '<' expression {
191 $$ = $1 < $3;
192 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000193 | expression TOK_OP_RIGHT expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000194 $$ = $1 >> $3;
195 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000196 | expression TOK_OP_LEFT expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000197 $$ = $1 << $3;
198 }
199 | expression '-' expression {
200 $$ = $1 - $3;
201 }
202 | expression '+' expression {
203 $$ = $1 + $3;
204 }
205 | expression '%' expression {
Olli Etuaho809ec542015-08-26 14:30:57 +0300206 if ($3 == 0)
207 {
Olli Etuaho3187a382015-09-09 12:00:12 +0300208 if (!context->isIgnoringErrors())
Olli Etuaho809ec542015-08-26 14:30:57 +0300209 {
210 std::ostringstream stream;
211 stream << $1 << " % " << $3;
212 std::string text = stream.str();
213 context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
214 context->token->location,
215 text.c_str());
Olli Etuaho809ec542015-08-26 14:30:57 +0300216 }
Olli Etuaho3187a382015-09-09 12:00:12 +0300217 $$ = static_cast<YYSTYPE>(0);
Olli Etuaho809ec542015-08-26 14:30:57 +0300218 }
219 else
220 {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000221 $$ = $1 % $3;
222 }
223 }
224 | expression '/' expression {
Olli Etuaho809ec542015-08-26 14:30:57 +0300225 if ($3 == 0)
226 {
Olli Etuaho3187a382015-09-09 12:00:12 +0300227 if (!context->isIgnoringErrors())
Olli Etuaho809ec542015-08-26 14:30:57 +0300228 {
229 std::ostringstream stream;
230 stream << $1 << " / " << $3;
231 std::string text = stream.str();
232 context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
233 context->token->location,
234 text.c_str());
Olli Etuaho809ec542015-08-26 14:30:57 +0300235 }
Olli Etuaho3187a382015-09-09 12:00:12 +0300236 $$ = static_cast<YYSTYPE>(0);
Olli Etuaho809ec542015-08-26 14:30:57 +0300237 }
238 else
239 {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000240 $$ = $1 / $3;
241 }
242 }
243 | expression '*' expression {
244 $$ = $1 * $3;
245 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000246 | '!' expression %prec TOK_UNARY {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000247 $$ = ! $2;
248 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000249 | '~' expression %prec TOK_UNARY {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000250 $$ = ~ $2;
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 }
258 | '(' expression ')' {
259 $$ = $2;
260 }
261;
262
263%%
264
Zhenyao Mod526f982014-05-13 14:51:19 -0700265int yylex(YYSTYPE *lvalp, Context *context)
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000266{
Olli Etuaho3187a382015-09-09 12:00:12 +0300267 pp::Token *token = context->token;
268 context->lexer->lex(token);
269
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000270 int type = 0;
271
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000272 switch (token->type)
273 {
Zhenyao Mod526f982014-05-13 14:51:19 -0700274 case pp::Token::CONST_INT: {
alokp@chromium.org2e818912012-06-29 21:26:03 +0000275 unsigned int val = 0;
276 if (!token->uValue(&val))
277 {
Jamie Madillc9f140d2014-02-18 15:27:21 -0500278 context->diagnostics->report(pp::Diagnostics::PP_INTEGER_OVERFLOW,
alokp@chromium.org2e818912012-06-29 21:26:03 +0000279 token->location, token->text);
280 }
281 *lvalp = static_cast<YYSTYPE>(val);
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000282 type = TOK_CONST_INT;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000283 break;
alokp@chromium.org2e818912012-06-29 21:26:03 +0000284 }
Olli Etuaho809ec542015-08-26 14:30:57 +0300285 case pp::Token::IDENTIFIER:
Olli Etuaho809ec542015-08-26 14:30:57 +0300286 *lvalp = static_cast<YYSTYPE>(-1);
287 type = TOK_IDENTIFIER;
288 break;
Zhenyao Mod526f982014-05-13 14:51:19 -0700289 case pp::Token::OP_OR:
290 type = TOK_OP_OR;
291 break;
292 case pp::Token::OP_AND:
293 type = TOK_OP_AND;
294 break;
295 case pp::Token::OP_NE:
296 type = TOK_OP_NE;
297 break;
298 case pp::Token::OP_EQ:
299 type = TOK_OP_EQ;
300 break;
301 case pp::Token::OP_GE:
302 type = TOK_OP_GE;
303 break;
304 case pp::Token::OP_LE:
305 type = TOK_OP_LE;
306 break;
307 case pp::Token::OP_RIGHT:
308 type = TOK_OP_RIGHT;
309 break;
310 case pp::Token::OP_LEFT:
311 type = TOK_OP_LEFT;
312 break;
313 case '|':
314 case '^':
315 case '&':
316 case '>':
317 case '<':
318 case '-':
319 case '+':
320 case '%':
321 case '/':
322 case '*':
323 case '!':
324 case '~':
325 case '(':
326 case ')':
327 type = token->type;
328 break;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000329
Zhenyao Mod526f982014-05-13 14:51:19 -0700330 default:
331 break;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000332 }
333
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000334 return type;
335}
336
Zhenyao Mod526f982014-05-13 14:51:19 -0700337void yyerror(Context *context, const char *reason)
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000338{
Jamie Madillc9f140d2014-02-18 15:27:21 -0500339 context->diagnostics->report(pp::Diagnostics::PP_INVALID_EXPRESSION,
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000340 context->token->location,
341 reason);
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000342}
343
344namespace pp {
345
Zhenyao Mod526f982014-05-13 14:51:19 -0700346ExpressionParser::ExpressionParser(Lexer *lexer, Diagnostics *diagnostics)
347 : mLexer(lexer),
348 mDiagnostics(diagnostics)
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000349{
350}
351
Zhenyao Mod526f982014-05-13 14:51:19 -0700352bool ExpressionParser::parse(Token *token, int *result)
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000353{
354 Context context;
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000355 context.diagnostics = mDiagnostics;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000356 context.lexer = mLexer;
357 context.token = token;
358 context.result = result;
Olli Etuaho809ec542015-08-26 14:30:57 +0300359 context.ignoreErrors = 0;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000360 int ret = yyparse(&context);
361 switch (ret)
362 {
363 case 0:
364 case 1:
365 break;
366
367 case 2:
Jamie Madillc9f140d2014-02-18 15:27:21 -0500368 mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token->location, "");
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000369 break;
370
371 default:
372 assert(false);
Jamie Madillc9f140d2014-02-18 15:27:21 -0500373 mDiagnostics->report(Diagnostics::PP_INTERNAL_ERROR, token->location, "");
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000374 break;
375 }
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000376
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000377 return ret == 0;
378}
379
380} // namespace pp