• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //    http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 This file contains the Yacc grammar for GLSL ES preprocessor expression.
17 
18 IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
19 WHICH GENERATES THE GLSL ES preprocessor expression parser.
20 */
21 
22 %{
23 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
24 //
25 // Licensed under the Apache License, Version 2.0 (the "License");
26 // you may not use this file except in compliance with the License.
27 // You may obtain a copy of the License at
28 //
29 //    http://www.apache.org/licenses/LICENSE-2.0
30 //
31 // Unless required by applicable law or agreed to in writing, software
32 // distributed under the License is distributed on an "AS IS" BASIS,
33 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 // See the License for the specific language governing permissions and
35 // limitations under the License.
36 
37 // This file is auto-generated by generate_parser.sh. DO NOT EDIT!
38 
39 #if defined(__GNUC__)
40 // Triggered by the auto-generated pplval variable.
41 #pragma GCC diagnostic ignored "-Wuninitialized"
42 #elif defined(_MSC_VER)
43 #pragma warning(disable: 4065 4701)
44 #endif
45 
46 #include "ExpressionParser.h"
47 
48 #include <cassert>
49 #include <sstream>
50 
51 #include "Diagnostics.h"
52 #include "Lexer.h"
53 #include "Token.h"
54 
55 #if defined(_MSC_VER)
56 typedef __int64 YYSTYPE;
57 #else
58 #include <stdint.h>
59 typedef intmax_t YYSTYPE;
60 #endif  // _MSC_VER
61 #define YYSTYPE_IS_TRIVIAL 1
62 #define YYSTYPE_IS_DECLARED 1
63 
64 namespace {
65 struct Context
66 {
67     pp::Diagnostics* diagnostics;
68     pp::Lexer* lexer;
69     pp::Token* token;
70     int* result;
71     int shortCircuited;   // Don't produce errors when > 0
72 };
73 }  // namespace
74 %}
75 
76 %pure-parser
77 %name-prefix "pp"
78 %parse-param {Context *context}
79 %lex-param {Context *context}
80 
81 %{
82 static int yylex(YYSTYPE* lvalp, Context* context);
83 static void yyerror(Context* context, const char* reason);
84 %}
85 
86 %token TOK_CONST_INT
87 %left TOK_OP_OR
88 %left TOK_OP_AND
89 %left '|'
90 %left '^'
91 %left '&'
92 %left TOK_OP_EQ TOK_OP_NE
93 %left '<' '>' TOK_OP_LE TOK_OP_GE
94 %left TOK_OP_LEFT TOK_OP_RIGHT
95 %left '+' '-'
96 %left '*' '/' '%'
97 %right TOK_UNARY
98 
99 %%
100 
101 input
102     : expression {
103         *(context->result) = static_cast<int>($1);
104         YYACCEPT;
105     }
106 ;
107 
108 expression
109     : TOK_CONST_INT
110     | expression TOK_OP_OR {
111         if ($1 != 0)
112         {
113             context->shortCircuited++;
114         }
115     } expression {
116         if ($1 != 0)
117         {
118             context->shortCircuited--;
119             $$ = 1;
120         }
121         else
122         {
123             $$ = $1 || $4;
124         }
125     }
126     | expression TOK_OP_AND {
127         if ($1 == 0)
128         {
129             context->shortCircuited++;
130         }
131     } expression {
132         if ($1 == 0)
133         {
134             context->shortCircuited--;
135             $$ = 0;
136         }
137         else
138         {
139             $$ = $1 && $4;
140         }
141     }
142     | expression '|' expression {
143         $$ = $1 | $3;
144     }
145     | expression '^' expression {
146         $$ = $1 ^ $3;
147     }
148     | expression '&' expression {
149         $$ = $1 & $3;
150     }
151     | expression TOK_OP_NE expression {
152         $$ = $1 != $3;
153     }
154     | expression TOK_OP_EQ expression {
155         $$ = $1 == $3;
156     }
157     | expression TOK_OP_GE expression {
158         $$ = $1 >= $3;
159     }
160     | expression TOK_OP_LE expression {
161         $$ = $1 <= $3;
162     }
163     | expression '>' expression {
164         $$ = $1 > $3;
165     }
166     | expression '<' expression {
167         $$ = $1 < $3;
168     }
169     | expression TOK_OP_RIGHT expression {
170         $$ = $1 >> $3;
171     }
172     | expression TOK_OP_LEFT expression {
173         $$ = $1 << $3;
174     }
175     | expression '-' expression {
176         $$ = $1 - $3;
177     }
178     | expression '+' expression {
179         $$ = $1 + $3;
180     }
181     | expression '%' expression {
182         if ($3 == 0)
183         {
184             if (!context->shortCircuited)
185             {
186                 context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO,
187                                              context->token->location, "");
188                 YYABORT;
189             }
190             else
191             {
192                 $$ = 0;
193             }
194         }
195         else
196         {
197             $$ = $1 % $3;
198         }
199     }
200     | expression '/' expression {
201         if ($3 == 0)
202         {
203             if (!context->shortCircuited)
204             {
205                 context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO,
206                                              context->token->location, "");
207                 YYABORT;
208             }
209             else
210             {
211                 $$ = 0;
212             }
213         }
214         else
215         {
216             $$ = $1 / $3;
217         }
218     }
219     | expression '*' expression {
220         $$ = $1 * $3;
221     }
222     | '!' expression %prec TOK_UNARY {
223         $$ = ! $2;
224     }
225     | '~' expression %prec TOK_UNARY {
226         $$ = ~ $2;
227     }
228     | '-' expression %prec TOK_UNARY {
229         $$ = - $2;
230     }
231     | '+' expression %prec TOK_UNARY {
232         $$ = + $2;
233     }
234     | '(' expression ')' {
235         $$ = $2;
236     }
237 ;
238 
239 %%
240 
241 int yylex(YYSTYPE* lvalp, Context* context)
242 {
243     int type = 0;
244 
245     pp::Token* token = context->token;
246     switch (token->type)
247     {
248       case pp::Token::CONST_INT:
249       {
250         unsigned int val = 0;
251         if (!token->uValue(&val))
252         {
253             context->diagnostics->report(pp::Diagnostics::INTEGER_OVERFLOW,
254                                          token->location, token->text);
255         }
256         *lvalp = static_cast<YYSTYPE>(val);
257         type = TOK_CONST_INT;
258         break;
259       }
260       case pp::Token::IDENTIFIER:
261         if (!context->shortCircuited)
262         {
263             // Defined identifiers should have been expanded already.
264             // Unlike the C/C++ preprocessor, it does not default to 0.
265             // Use of such identifiers causes an error.
266             context->diagnostics->report(pp::Diagnostics::UNDEFINED_IDENTIFIER,
267                                          token->location, token->text);
268         }
269 
270         *lvalp = 0;
271         type = TOK_CONST_INT;
272         break;
273       case pp::Token::OP_OR: type = TOK_OP_OR; break;
274       case pp::Token::OP_AND: type = TOK_OP_AND; break;
275       case pp::Token::OP_NE: type = TOK_OP_NE; break;
276       case pp::Token::OP_EQ: type = TOK_OP_EQ; break;
277       case pp::Token::OP_GE: type = TOK_OP_GE; break;
278       case pp::Token::OP_LE: type = TOK_OP_LE; break;
279       case pp::Token::OP_RIGHT: type = TOK_OP_RIGHT; break;
280       case pp::Token::OP_LEFT: type = TOK_OP_LEFT; break;
281       case '|': type = '|'; break;
282       case '^': type = '^'; break;
283       case '&': type = '&'; break;
284       case '>': type = '>'; break;
285       case '<': type = '<'; break;
286       case '-': type = '-'; break;
287       case '+': type = '+'; break;
288       case '%': type = '%'; break;
289       case '/': type = '/'; break;
290       case '*': type = '*'; break;
291       case '!': type = '!'; break;
292       case '~': type = '~'; break;
293       case '(': type = '('; break;
294       case ')': type = ')'; break;
295 
296       default: break;
297     }
298 
299     // Advance to the next token if the current one is valid.
300     if (type != 0) context->lexer->lex(token);
301 
302     return type;
303 }
304 
yyerror(Context * context,const char * reason)305 void yyerror(Context* context, const char* reason)
306 {
307     context->diagnostics->report(pp::Diagnostics::INVALID_EXPRESSION,
308                                  context->token->location,
309                                  reason);
310 }
311 
312 namespace pp {
313 
ExpressionParser(Lexer * lexer,Diagnostics * diagnostics)314 ExpressionParser::ExpressionParser(Lexer* lexer, Diagnostics* diagnostics) :
315     mLexer(lexer),
316     mDiagnostics(diagnostics)
317 {
318 }
319 
parse(Token * token,int * result)320 bool ExpressionParser::parse(Token* token, int* result)
321 {
322     Context context;
323     context.diagnostics = mDiagnostics;
324     context.lexer = mLexer;
325     context.token = token;
326     context.result = result;
327     context.shortCircuited = 0;
328     int ret = yyparse(&context);
329     switch (ret)
330     {
331       case 0:
332       case 1:
333         break;
334 
335       case 2:
336         mDiagnostics->report(Diagnostics::OUT_OF_MEMORY, token->location, "");
337         break;
338 
339       default:
340         assert(false);
341         mDiagnostics->report(Diagnostics::INTERNAL_ERROR, token->location, "");
342         break;
343     }
344 
345     return ret == 0;
346 }
347 
348 }  // namespace pp
349