3 // Copyright (c) 2002-2013 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.
8 This file contains the Lex specification for GLSL ES preprocessor.
9 Based on Microsoft Visual Studio 2010 Preprocessor Grammar:
10 http://msdn.microsoft.com/en-us/library/2scxys89.aspx
12 IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh.
17 // Copyright (c) 2011-2013 The ANGLE Project Authors. All rights reserved.
18 // Use of this source code is governed by a BSD-style license that can be
19 // found in the LICENSE file.
22 // This file is auto-generated by generate_parser.sh. DO NOT EDIT!
26 #include "Tokenizer.h"
28 #include "Diagnostics.h"
32 // Triggered by the auto-generated yy_fatal_error function.
33 #pragma GCC diagnostic ignored "-Wmissing-noreturn"
36 typedef std::string YYSTYPE;
37 typedef pp::SourceLocation YYLTYPE;
39 // Use the unused yycolumn variable to track file (string) number.
40 #define yyfileno yycolumn
42 #define YY_USER_INIT \
46 yyextra->leadingSpace = false; \
47 yyextra->lineStart = true; \
50 #define YY_USER_ACTION \
53 pp::Input* input = &yyextra->input; \
54 pp::Input::Location* scanLoc = &yyextra->scanLoc; \
55 while ((scanLoc->sIndex < input->count()) && \
56 (scanLoc->cIndex >= input->length(scanLoc->sIndex))) \
58 scanLoc->cIndex -= input->length(scanLoc->sIndex++); \
59 ++yyfileno; yylineno = 1; \
61 yylloc->file = yyfileno; \
62 yylloc->line = yylineno; \
63 scanLoc->cIndex += yyleng; \
66 #define YY_INPUT(buf, result, maxSize) \
67 result = yyextra->input.read(buf, maxSize);
71 %option noyywrap nounput never-interactive
72 %option reentrant bison-bridge bison-locations
74 %option extra-type="pp::Tokenizer::Context*"
78 IDENTIFIER [_a-zA-Z][_a-zA-Z0-9]*
79 PUNCTUATOR [][<>(){}.+-/*%^|&~=!:;,?]
81 DECIMAL_CONSTANT [1-9][0-9]*
82 OCTAL_CONSTANT 0[0-7]*
83 HEXADECIMAL_CONSTANT 0[xX][0-9a-fA-F]+
86 EXPONENT_PART [eE][+-]?{DIGIT}+
87 FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
95 /* Line breaks are just counted - not returned. */
96 /* The comment is replaced by a single space. */
97 "/*" { BEGIN(COMMENT); }
100 <COMMENT>{NEWLINE} { ++yylineno; }
102 yyextra->leadingSpace = true;
107 // # is only valid at start of line for preprocessor directives.
108 yylval->assign(1, yytext[0]);
109 return yyextra->lineStart ? pp::Token::PP_HASH : pp::Token::PP_OTHER;
113 yylval->assign(yytext, yyleng);
114 return pp::Token::IDENTIFIER;
117 {DECIMAL_CONSTANT}|{OCTAL_CONSTANT}|{HEXADECIMAL_CONSTANT} {
118 yylval->assign(yytext, yyleng);
119 return pp::Token::CONST_INT;
122 ({DIGIT}+{EXPONENT_PART})|({FRACTIONAL_CONSTANT}{EXPONENT_PART}?) {
123 yylval->assign(yytext, yyleng);
124 return pp::Token::CONST_FLOAT;
127 /* Anything that starts with a {DIGIT} or .{DIGIT} must be a number. */
128 /* Rule to catch all invalid integers and floats. */
129 ({DIGIT}+[_a-zA-Z0-9.]*)|("."{DIGIT}+[_a-zA-Z0-9.]*) {
130 yylval->assign(yytext, yyleng);
131 return pp::Token::PP_NUMBER;
135 yylval->assign(yytext, yyleng);
136 return pp::Token::OP_INC;
139 yylval->assign(yytext, yyleng);
140 return pp::Token::OP_DEC;
143 yylval->assign(yytext, yyleng);
144 return pp::Token::OP_LEFT;
147 yylval->assign(yytext, yyleng);
148 return pp::Token::OP_RIGHT;
151 yylval->assign(yytext, yyleng);
152 return pp::Token::OP_LE;
155 yylval->assign(yytext, yyleng);
156 return pp::Token::OP_GE;
159 yylval->assign(yytext, yyleng);
160 return pp::Token::OP_EQ;
163 yylval->assign(yytext, yyleng);
164 return pp::Token::OP_NE;
167 yylval->assign(yytext, yyleng);
168 return pp::Token::OP_AND;
171 yylval->assign(yytext, yyleng);
172 return pp::Token::OP_XOR;
175 yylval->assign(yytext, yyleng);
176 return pp::Token::OP_OR;
179 yylval->assign(yytext, yyleng);
180 return pp::Token::OP_ADD_ASSIGN;
183 yylval->assign(yytext, yyleng);
184 return pp::Token::OP_SUB_ASSIGN;
187 yylval->assign(yytext, yyleng);
188 return pp::Token::OP_MUL_ASSIGN;
191 yylval->assign(yytext, yyleng);
192 return pp::Token::OP_DIV_ASSIGN;
195 yylval->assign(yytext, yyleng);
196 return pp::Token::OP_MOD_ASSIGN;
199 yylval->assign(yytext, yyleng);
200 return pp::Token::OP_LEFT_ASSIGN;
203 yylval->assign(yytext, yyleng);
204 return pp::Token::OP_RIGHT_ASSIGN;
207 yylval->assign(yytext, yyleng);
208 return pp::Token::OP_AND_ASSIGN;
211 yylval->assign(yytext, yyleng);
212 return pp::Token::OP_XOR_ASSIGN;
215 yylval->assign(yytext, yyleng);
216 return pp::Token::OP_OR_ASSIGN;
220 yylval->assign(1, yytext[0]);
224 [ \t\v\f]+ { yyextra->leadingSpace = true; }
228 yylval->assign(1, '\n');
232 \\{NEWLINE} { ++yylineno; }
235 yylval->assign(1, yytext[0]);
236 return pp::Token::PP_OTHER;
240 // YY_USER_ACTION is not invoked for handling EOF.
241 // Set the location for EOF token manually.
242 pp::Input* input = &yyextra->input;
243 pp::Input::Location* scanLoc = &yyextra->scanLoc;
244 int sIndexMax = std::max(0, input->count() - 1);
245 if (scanLoc->sIndex != sIndexMax)
247 // We can only reach here if there are empty strings at the
249 scanLoc->sIndex = sIndexMax; scanLoc->cIndex = 0;
250 yyfileno = sIndexMax; yylineno = 1;
252 yylloc->file = yyfileno;
253 yylloc->line = yylineno;
256 if (YY_START == COMMENT)
258 yyextra->diagnostics->report(pp::Diagnostics::EOF_IN_COMMENT,
259 pp::SourceLocation(yyfileno, yylineno),
269 // TODO(alokp): Maximum token length should ideally be specified by
270 // the preprocessor client, i.e., the compiler.
271 const size_t Tokenizer::kMaxTokenLength = 256;
273 Tokenizer::Tokenizer(Diagnostics* diagnostics) : mHandle(0)
275 mContext.diagnostics = diagnostics;
278 Tokenizer::~Tokenizer()
283 bool Tokenizer::init(int count, const char* const string[], const int length[])
285 if (count < 0) return false;
286 if ((count > 0) && (string == 0)) return false;
288 mContext.input = Input(count, string, length);
289 return initScanner();
292 void Tokenizer::setFileNumber(int file)
294 // We use column number as file number.
295 // See macro yyfileno.
296 yyset_column(file, mHandle);
299 void Tokenizer::setLineNumber(int line)
301 yyset_lineno(line, mHandle);
304 void Tokenizer::lex(Token* token)
306 token->type = yylex(&token->text, &token->location, mHandle);
307 if (token->text.size() > kMaxTokenLength)
309 mContext.diagnostics->report(Diagnostics::TOKEN_TOO_LONG,
310 token->location, token->text);
311 token->text.erase(kMaxTokenLength);
316 token->setAtStartOfLine(mContext.lineStart);
317 mContext.lineStart = token->type == '\n';
319 token->setHasLeadingSpace(mContext.leadingSpace);
320 mContext.leadingSpace = false;
323 bool Tokenizer::initScanner()
325 if ((mHandle == NULL) && yylex_init_extra(&mContext, &mHandle))
328 yyrestart(0, mHandle);
332 void Tokenizer::destroyScanner()
337 yylex_destroy(mHandle);