• 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 Lex specification for GLSL ES preprocessor.
17 Based on Microsoft Visual Studio 2010 Preprocessor Grammar:
18 http://msdn.microsoft.com/en-us/library/2scxys89.aspx
19 
20 IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh.
21 */
22 
23 %top{
24 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
25 //
26 // Licensed under the Apache License, Version 2.0 (the "License");
27 // you may not use this file except in compliance with the License.
28 // You may obtain a copy of the License at
29 //
30 //    http://www.apache.org/licenses/LICENSE-2.0
31 //
32 // Unless required by applicable law or agreed to in writing, software
33 // distributed under the License is distributed on an "AS IS" BASIS,
34 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
35 // See the License for the specific language governing permissions and
36 // limitations under the License.
37 
38 // This file is auto-generated by generate_parser.sh. DO NOT EDIT!
39 }
40 
41 %{
42 #include "Tokenizer.h"
43 
44 #include "Diagnostics.h"
45 #include "Token.h"
46 
47 #if defined(__GNUC__)
48 // Triggered by the auto-generated yy_fatal_error function.
49 #pragma GCC diagnostic ignored "-Wmissing-noreturn"
50 #endif
51 
52 typedef std::string YYSTYPE;
53 typedef pp::SourceLocation YYLTYPE;
54 
55 // Use the unused yycolumn variable to track file (string) number.
56 #define yyfileno yycolumn
57 
58 #define YY_USER_INIT                   \
59     do {                               \
60         yyfileno = 0;                  \
61         yylineno = 1;                  \
62         yyextra->leadingSpace = false; \
63         yyextra->lineStart = true;     \
64     } while(0);
65 
66 #define YY_USER_ACTION                                              \
67     do                                                              \
68     {                                                               \
69         pp::Input* input = &yyextra->input;                         \
70         pp::Input::Location* scanLoc = &yyextra->scanLoc;           \
71         while ((scanLoc->sIndex < input->count()) &&                \
72                (scanLoc->cIndex >= input->length(scanLoc->sIndex))) \
73         {                                                           \
74             scanLoc->cIndex -= input->length(scanLoc->sIndex++);    \
75             ++yyfileno; yylineno = 1;                               \
76         }                                                           \
77         yylloc->file = yyfileno;                                    \
78         yylloc->line = yylineno;                                    \
79         scanLoc->cIndex += yyleng;                                  \
80     } while(0);
81 
82 #define YY_INPUT(buf, result, maxSize) \
83     result = yyextra->input.read(buf, maxSize);
84 
85 %}
86 
87 %option noyywrap nounput never-interactive
88 %option reentrant bison-bridge bison-locations
89 %option prefix="pp"
90 %option extra-type="pp::Tokenizer::Context*"
91 %x COMMENT
92 
93 NEWLINE     \n|\r|\r\n
94 IDENTIFIER  [_a-zA-Z][_a-zA-Z0-9]*
95 PUNCTUATOR  [][<>(){}.+-/*%^|&~=!:;,?]
96 
97 DECIMAL_CONSTANT      [1-9][0-9]*[uU]?
98 OCTAL_CONSTANT        0[0-7]*[uU]?
99 HEXADECIMAL_CONSTANT  0[xX][0-9a-fA-F]+[uU]?
100 
101 DIGIT                [0-9]
102 EXPONENT_PART        [eE][+-]?{DIGIT}+
103 FRACTIONAL_CONSTANT  ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
104 
105 %%
106 
107     /* Line comment */
108 "//"[^\r\n]*
109 
110     /* Block comment */
111     /* Line breaks are just counted - not returned. */
112     /* The comment is replaced by a single space. */
113 "/*" { BEGIN(COMMENT); }
114 <COMMENT>[^*\r\n]+
115 <COMMENT>"*"
116 <COMMENT>{NEWLINE} { ++yylineno; }
117 <COMMENT>"*/" {
118     yyextra->leadingSpace = true;
119     BEGIN(INITIAL);
120 }
121 
122 # {
123     // # is only valid at start of line for preprocessor directives.
124     yylval->assign(1, yytext[0]);
125     return yyextra->lineStart ? pp::Token::PP_HASH : pp::Token::PP_OTHER;
126 }
127 
128 {IDENTIFIER} {
129     yylval->assign(yytext, yyleng);
130     return pp::Token::IDENTIFIER;
131 }
132 
133 ({DECIMAL_CONSTANT}[uU]?)|({OCTAL_CONSTANT}[uU]?)|({HEXADECIMAL_CONSTANT}[uU]?) {
134     yylval->assign(yytext, yyleng);
135     return pp::Token::CONST_INT;
136 }
137 
138 ({DIGIT}+{EXPONENT_PART}[fF]?)|({FRACTIONAL_CONSTANT}{EXPONENT_PART}?[fF]?) {
139     yylval->assign(yytext, yyleng);
140     return pp::Token::CONST_FLOAT;
141 }
142 
143     /* Anything that starts with a {DIGIT} or .{DIGIT} must be a number. */
144     /* Rule to catch all invalid integers and floats. */
145 ({DIGIT}+[_a-zA-Z0-9.]*)|("."{DIGIT}+[_a-zA-Z0-9.]*) {
146     yylval->assign(yytext, yyleng);
147     return pp::Token::PP_NUMBER;
148 }
149 
150 "++" {
151     yylval->assign(yytext, yyleng);
152     return pp::Token::OP_INC;
153 }
154 "--" {
155     yylval->assign(yytext, yyleng);
156     return pp::Token::OP_DEC;
157 }
158 "<<" {
159     yylval->assign(yytext, yyleng);
160     return pp::Token::OP_LEFT;
161 }
162 ">>" {
163     yylval->assign(yytext, yyleng);
164     return pp::Token::OP_RIGHT;
165 }
166 "<=" {
167     yylval->assign(yytext, yyleng);
168     return pp::Token::OP_LE;
169 }
170 ">=" {
171     yylval->assign(yytext, yyleng);
172     return pp::Token::OP_GE;
173 }
174 "==" {
175     yylval->assign(yytext, yyleng);
176     return pp::Token::OP_EQ;
177 }
178 "!=" {
179     yylval->assign(yytext, yyleng);
180     return pp::Token::OP_NE;
181 }
182 "&&" {
183     yylval->assign(yytext, yyleng);
184     return pp::Token::OP_AND;
185 }
186 "^^" {
187     yylval->assign(yytext, yyleng);
188     return pp::Token::OP_XOR;
189 }
190 "||" {
191     yylval->assign(yytext, yyleng);
192     return pp::Token::OP_OR;
193 }
194 "+=" {
195     yylval->assign(yytext, yyleng);
196     return pp::Token::OP_ADD_ASSIGN;
197 }
198 "-=" {
199     yylval->assign(yytext, yyleng);
200     return pp::Token::OP_SUB_ASSIGN;
201 }
202 "*=" {
203     yylval->assign(yytext, yyleng);
204     return pp::Token::OP_MUL_ASSIGN;
205 }
206 "/=" {
207     yylval->assign(yytext, yyleng);
208     return pp::Token::OP_DIV_ASSIGN;
209 }
210 "%=" {
211     yylval->assign(yytext, yyleng);
212     return pp::Token::OP_MOD_ASSIGN;
213 }
214 "<<=" {
215     yylval->assign(yytext, yyleng);
216     return pp::Token::OP_LEFT_ASSIGN;
217 }
218 ">>=" {
219     yylval->assign(yytext, yyleng);
220     return pp::Token::OP_RIGHT_ASSIGN;
221 }
222 "&=" {
223     yylval->assign(yytext, yyleng);
224     return pp::Token::OP_AND_ASSIGN;
225 }
226 "^=" {
227     yylval->assign(yytext, yyleng);
228     return pp::Token::OP_XOR_ASSIGN;
229 }
230 "|=" {
231     yylval->assign(yytext, yyleng);
232     return pp::Token::OP_OR_ASSIGN;
233 }
234 
235 {PUNCTUATOR} {
236     yylval->assign(1, yytext[0]);
237     return yytext[0];
238 }
239 
240 [ \t\v\f]+   { yyextra->leadingSpace = true; }
241 
242 {NEWLINE} {
243     ++yylineno;
244     yylval->assign(1, '\n');
245     return '\n';
246 }
247 
248 \\{NEWLINE} { ++yylineno; }
249 
250 . {
251     yylval->assign(1, yytext[0]);
252     return pp::Token::PP_OTHER;
253 }
254 
255 <*><<EOF>> {
256     // YY_USER_ACTION is not invoked for handling EOF.
257     // Set the location for EOF token manually.
258     pp::Input* input = &yyextra->input;
259     pp::Input::Location* scanLoc = &yyextra->scanLoc;
260     int sIndexMax = std::max(0, input->count() - 1);
261     if (scanLoc->sIndex != sIndexMax)
262     {
263         // We can only reach here if there are empty strings at the
264         // end of the input.
265         scanLoc->sIndex = sIndexMax; scanLoc->cIndex = 0;
266         yyfileno = sIndexMax; yylineno = 1;
267     }
268     yylloc->file = yyfileno;
269     yylloc->line = yylineno;
270     yylval->clear();
271 
272     if (YY_START == COMMENT)
273     {
274         yyextra->diagnostics->report(pp::Diagnostics::EOF_IN_COMMENT,
275                                      pp::SourceLocation(yyfileno, yylineno),
276                                      "");
277     }
278     yyterminate();
279 }
280 
281 %%
282 
283 namespace pp {
284 
285 // TODO(alokp): Maximum token length should ideally be specified by
286 // the preprocessor client, i.e., the compiler.
287 const size_t Tokenizer::kMaxTokenLength = 256;
288 
289 Tokenizer::Tokenizer(Diagnostics* diagnostics) : mHandle(0)
290 {
291     mContext.diagnostics = diagnostics;
292 }
293 
294 Tokenizer::~Tokenizer()
295 {
296     destroyScanner();
297 }
298 
299 bool Tokenizer::init(int count, const char* const string[], const int length[])
300 {
301     if (count < 0) return false;
302     if ((count > 0) && (string == 0)) return false;
303 
304     mContext.input = Input(count, string, length);
305     return initScanner();
306 }
307 
308 void Tokenizer::setFileNumber(int file)
309 {
310     // We use column number as file number.
311     // See macro yyfileno.
312     yyset_column(file, mHandle);
313 }
314 
315 void Tokenizer::setLineNumber(int line)
316 {
317     yyset_lineno(line, mHandle);
318 }
319 
320 void Tokenizer::lex(Token* token)
321 {
322     token->type = yylex(&token->text, &token->location, mHandle);
323     if (token->text.size() > kMaxTokenLength)
324     {
325         mContext.diagnostics->report(Diagnostics::TOKEN_TOO_LONG,
326                                      token->location, token->text);
327         token->text.erase(kMaxTokenLength);
328     }
329 
330     token->flags = 0;
331 
332     token->setAtStartOfLine(mContext.lineStart);
333     mContext.lineStart = token->type == '\n';
334 
335     token->setHasLeadingSpace(mContext.leadingSpace);
336     mContext.leadingSpace = false;
337 }
338 
339 bool Tokenizer::initScanner()
340 {
341     if ((mHandle == NULL) && yylex_init_extra(&mContext, &mHandle))
342         return false;
343 
344     yyrestart(0, mHandle);
345     return true;
346 }
347 
348 void Tokenizer::destroyScanner()
349 {
350     if (mHandle == NULL)
351         return;
352 
353     yylex_destroy(mHandle);
354     mHandle = NULL;
355 }
356 
357 }  // namespace pp
358 
359