blob: d82c767d2083da47ad8d4d72f93fe40d599f4e1f [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 Etuaho809ec542015-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 Etuaho809ec542015-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 Etuaho809ec542015-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 Etuaho809ec542015-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 $$ = static_cast<YYSTYPE>(1);
133 }
134 else
135 {
136 $$ = $1 || $4;
137 }
138 }
139 | expression TOK_OP_AND {
140 if ($1 == 0)
141 {
142 // Ignore errors in the short-circuited part of the expression.
143 // ESSL3.00 section 3.4:
144 // If an operand is not evaluated, the presence of undefined identifiers
145 // in the operand will not cause an error.
146 // Unevaluated division by zero should not cause an error either.
147 context->startIgnoreErrors();
148 }
149 } expression {
150 if ($1 == 0)
151 {
152 context->endIgnoreErrors();
153 $$ = static_cast<YYSTYPE>(0);
154 }
155 else
156 {
157 $$ = $1 && $4;
158 }
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000159 }
160 | expression '|' expression {
161 $$ = $1 | $3;
162 }
163 | expression '^' expression {
164 $$ = $1 ^ $3;
165 }
166 | expression '&' expression {
167 $$ = $1 & $3;
168 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000169 | expression TOK_OP_NE expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000170 $$ = $1 != $3;
171 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000172 | expression TOK_OP_EQ expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000173 $$ = $1 == $3;
174 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000175 | expression TOK_OP_GE 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_LE expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000179 $$ = $1 <= $3;
180 }
181 | expression '>' expression {
182 $$ = $1 > $3;
183 }
184 | expression '<' expression {
185 $$ = $1 < $3;
186 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000187 | expression TOK_OP_RIGHT expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000188 $$ = $1 >> $3;
189 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000190 | expression TOK_OP_LEFT expression {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000191 $$ = $1 << $3;
192 }
193 | expression '-' expression {
194 $$ = $1 - $3;
195 }
196 | expression '+' expression {
197 $$ = $1 + $3;
198 }
199 | expression '%' expression {
Olli Etuaho809ec542015-08-26 14:30:57 +0300200 if ($3 == 0)
201 {
202 if (context->isIgnoringErrors())
203 {
204 $$ = static_cast<YYSTYPE>(0);
205 }
206 else
207 {
208 std::ostringstream stream;
209 stream << $1 << " % " << $3;
210 std::string text = stream.str();
211 context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
212 context->token->location,
213 text.c_str());
214 YYABORT;
215 }
216 }
217 else
218 {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000219 $$ = $1 % $3;
220 }
221 }
222 | expression '/' expression {
Olli Etuaho809ec542015-08-26 14:30:57 +0300223 if ($3 == 0)
224 {
225 if (context->isIgnoringErrors())
226 {
227 $$ = static_cast<YYSTYPE>(0);
228 }
229 else
230 {
231 std::ostringstream stream;
232 stream << $1 << " / " << $3;
233 std::string text = stream.str();
234 context->diagnostics->report(pp::Diagnostics::PP_DIVISION_BY_ZERO,
235 context->token->location,
236 text.c_str());
237 YYABORT;
238 }
239 }
240 else
241 {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000242 $$ = $1 / $3;
243 }
244 }
245 | expression '*' expression {
246 $$ = $1 * $3;
247 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000248 | '!' expression %prec TOK_UNARY {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000249 $$ = ! $2;
250 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000251 | '~' expression %prec TOK_UNARY {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000252 $$ = ~ $2;
253 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000254 | '-' expression %prec TOK_UNARY {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000255 $$ = - $2;
256 }
maxvujovic@gmail.come640ef82012-07-13 18:42:40 +0000257 | '+' expression %prec TOK_UNARY {
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000258 $$ = + $2;
259 }
260 | '(' expression ')' {
261 $$ = $2;
262 }
263;
264
265%%
266
Zhenyao Mod526f982014-05-13 14:51:19 -0700267int yylex(YYSTYPE *lvalp, Context *context)
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000268{
269 int type = 0;
270
Zhenyao Mod526f982014-05-13 14:51:19 -0700271 pp::Token *token = context->token;
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:
286 if (!context->isIgnoringErrors())
287 {
288 context->diagnostics->report(pp::Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
289 token->location, token->text);
290 }
291 *lvalp = static_cast<YYSTYPE>(-1);
292 type = TOK_IDENTIFIER;
293 break;
Zhenyao Mod526f982014-05-13 14:51:19 -0700294 case pp::Token::OP_OR:
295 type = TOK_OP_OR;
296 break;
297 case pp::Token::OP_AND:
298 type = TOK_OP_AND;
299 break;
300 case pp::Token::OP_NE:
301 type = TOK_OP_NE;
302 break;
303 case pp::Token::OP_EQ:
304 type = TOK_OP_EQ;
305 break;
306 case pp::Token::OP_GE:
307 type = TOK_OP_GE;
308 break;
309 case pp::Token::OP_LE:
310 type = TOK_OP_LE;
311 break;
312 case pp::Token::OP_RIGHT:
313 type = TOK_OP_RIGHT;
314 break;
315 case pp::Token::OP_LEFT:
316 type = TOK_OP_LEFT;
317 break;
318 case '|':
319 case '^':
320 case '&':
321 case '>':
322 case '<':
323 case '-':
324 case '+':
325 case '%':
326 case '/':
327 case '*':
328 case '!':
329 case '~':
330 case '(':
331 case ')':
332 type = token->type;
333 break;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000334
Zhenyao Mod526f982014-05-13 14:51:19 -0700335 default:
336 break;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000337 }
338
339 // Advance to the next token if the current one is valid.
Zhenyao Mod526f982014-05-13 14:51:19 -0700340 if (type != 0)
341 context->lexer->lex(token);
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000342
343 return type;
344}
345
Zhenyao Mod526f982014-05-13 14:51:19 -0700346void yyerror(Context *context, const char *reason)
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000347{
Jamie Madillc9f140d2014-02-18 15:27:21 -0500348 context->diagnostics->report(pp::Diagnostics::PP_INVALID_EXPRESSION,
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000349 context->token->location,
350 reason);
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000351}
352
353namespace pp {
354
Zhenyao Mod526f982014-05-13 14:51:19 -0700355ExpressionParser::ExpressionParser(Lexer *lexer, Diagnostics *diagnostics)
356 : mLexer(lexer),
357 mDiagnostics(diagnostics)
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000358{
359}
360
Zhenyao Mod526f982014-05-13 14:51:19 -0700361bool ExpressionParser::parse(Token *token, int *result)
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000362{
363 Context context;
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000364 context.diagnostics = mDiagnostics;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000365 context.lexer = mLexer;
366 context.token = token;
367 context.result = result;
Olli Etuaho809ec542015-08-26 14:30:57 +0300368 context.ignoreErrors = 0;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000369 int ret = yyparse(&context);
370 switch (ret)
371 {
372 case 0:
373 case 1:
374 break;
375
376 case 2:
Jamie Madillc9f140d2014-02-18 15:27:21 -0500377 mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token->location, "");
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000378 break;
379
380 default:
381 assert(false);
Jamie Madillc9f140d2014-02-18 15:27:21 -0500382 mDiagnostics->report(Diagnostics::PP_INTERNAL_ERROR, token->location, "");
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000383 break;
384 }
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000385
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000386 return ret == 0;
387}
388
389} // namespace pp