blob: 558013873e8e71e78378e1a48847cf73aea5b1ae [file] [log] [blame]
alokp@chromium.org4e4b8072011-08-07 05:36:04 +00001/*
2//
Jamie Madill88f6e942014-02-19 10:27:53 -05003// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
alokp@chromium.org4e4b8072011-08-07 05:36:04 +00004// 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 Lex specification for GLSL ES preprocessor.
9Based on Microsoft Visual Studio 2010 Preprocessor Grammar:
10http://msdn.microsoft.com/en-us/library/2scxys89.aspx
11
12IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh.
13*/
14
15%top{
16//
Jamie Madill88f6e942014-02-19 10:27:53 -050017// Copyright (c) 2011-2014 The ANGLE Project Authors. All rights reserved.
alokp@chromium.org4e4b8072011-08-07 05:36:04 +000018// Use of this source code is governed by a BSD-style license that can be
19// found in the LICENSE file.
20//
21
22// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
23}
24
25%{
Scott Grahama8975422015-05-01 11:09:12 -070026#if defined(_MSC_VER)
27#pragma warning(disable: 4005)
28#endif
29
Corentin Wallez054f7ed2016-09-20 17:15:59 -040030#include "compiler/preprocessor/Tokenizer.h"
alokp@chromium.org2c958ee2012-05-17 20:35:42 +000031
Corentin Wallez054f7ed2016-09-20 17:15:59 -040032#include "compiler/preprocessor/DiagnosticsBase.h"
33#include "compiler/preprocessor/Token.h"
alokp@chromium.org4e4b8072011-08-07 05:36:04 +000034
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +000035#if defined(__GNUC__)
36// Triggered by the auto-generated yy_fatal_error function.
37#pragma GCC diagnostic ignored "-Wmissing-noreturn"
Minmin Gong794e0002015-04-07 18:31:54 -070038#elif defined(_MSC_VER)
39#pragma warning(disable: 4244)
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +000040#endif
Nico Weber41b072b2018-02-09 10:01:32 -050041#if defined(__clang__)
42// Flex uses `/*FALLTHROUGH*/` instead of dedicated statements.
43#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
44#endif
maxvujovic@gmail.comc6b3b3c2012-06-27 22:49:39 +000045
Jamie Madill2dc8bf82015-04-30 15:56:52 -040046// Workaround for flex using the register keyword, deprecated in C++11.
47#ifdef __cplusplus
48#if __cplusplus > 199711L
49#define register
50#endif
51#endif
52
alokp@chromium.org4b2a5222012-04-03 17:19:42 +000053typedef std::string YYSTYPE;
alokp@chromium.org2c958ee2012-05-17 20:35:42 +000054typedef pp::SourceLocation YYLTYPE;
alokp@chromium.org4b2a5222012-04-03 17:19:42 +000055
alokp@chromium.org98eec912012-05-01 10:04:08 +000056// Use the unused yycolumn variable to track file (string) number.
57#define yyfileno yycolumn
58
alokp@chromium.org04d7d222012-05-16 19:24:07 +000059#define YY_USER_INIT \
60 do { \
61 yyfileno = 0; \
62 yylineno = 1; \
63 yyextra->leadingSpace = false; \
64 yyextra->lineStart = true; \
alokp@chromium.org4e4b8072011-08-07 05:36:04 +000065 } while(0);
alokp@chromium.orgb81c4012011-08-21 06:53:11 +000066
alokp@chromium.org19d7aa62012-05-31 17:34:05 +000067#define YY_USER_ACTION \
68 do \
69 { \
70 pp::Input* input = &yyextra->input; \
71 pp::Input::Location* scanLoc = &yyextra->scanLoc; \
72 while ((scanLoc->sIndex < input->count()) && \
73 (scanLoc->cIndex >= input->length(scanLoc->sIndex))) \
74 { \
75 scanLoc->cIndex -= input->length(scanLoc->sIndex++); \
76 ++yyfileno; yylineno = 1; \
77 } \
78 yylloc->file = yyfileno; \
79 yylloc->line = yylineno; \
80 scanLoc->cIndex += yyleng; \
alokp@chromium.org98eec912012-05-01 10:04:08 +000081 } while(0);
82
83#define YY_INPUT(buf, result, maxSize) \
Olli Etuaho26e355b2015-08-14 14:16:19 +030084 result = yyextra->input.read(buf, maxSize, &yylineno);
alokp@chromium.org128d9192012-04-26 22:39:21 +000085
alokp@chromium.org4e4b8072011-08-07 05:36:04 +000086%}
87
alokp@chromium.org98eec912012-05-01 10:04:08 +000088%option noyywrap nounput never-interactive
alokp@chromium.orgd08bb0c2012-04-23 19:27:13 +000089%option reentrant bison-bridge bison-locations
alokp@chromium.org4e4b8072011-08-07 05:36:04 +000090%option prefix="pp"
alokp@chromium.org04d7d222012-05-16 19:24:07 +000091%option extra-type="pp::Tokenizer::Context*"
alokp@chromium.org85f2b2c2012-04-25 06:06:33 +000092%x COMMENT
alokp@chromium.org4e4b8072011-08-07 05:36:04 +000093
alokp@chromium.org85f2b2c2012-04-25 06:06:33 +000094NEWLINE \n|\r|\r\n
alokp@chromium.org4e4b8072011-08-07 05:36:04 +000095IDENTIFIER [_a-zA-Z][_a-zA-Z0-9]*
96PUNCTUATOR [][<>(){}.+-/*%^|&~=!:;,?]
97
shannonwoods@chromium.orgc8100b82013-05-30 00:20:34 +000098DECIMAL_CONSTANT [1-9][0-9]*[uU]?
99OCTAL_CONSTANT 0[0-7]*[uU]?
100HEXADECIMAL_CONSTANT 0[xX][0-9a-fA-F]+[uU]?
alokp@chromium.org4e4b8072011-08-07 05:36:04 +0000101
alokp@chromium.orgb81c4012011-08-21 06:53:11 +0000102DIGIT [0-9]
103EXPONENT_PART [eE][+-]?{DIGIT}+
104FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
105
alokp@chromium.org4e4b8072011-08-07 05:36:04 +0000106%%
107
alokp@chromium.org85f2b2c2012-04-25 06:06:33 +0000108 /* Line comment */
109"//"[^\r\n]*
110
111 /* Block comment */
alokp@chromium.orga11a6ab2012-04-27 10:00:38 +0000112 /* Line breaks are just counted - not returned. */
Jamie Madillb96687d2015-04-30 15:56:51 -0400113 /* The comment is replaced by a single space. */
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000114"/*" { BEGIN(COMMENT); }
alokp@chromium.orga11a6ab2012-04-27 10:00:38 +0000115<COMMENT>[^*\r\n]+
116<COMMENT>"*"
Corentin Wallezdc0fa462017-02-01 14:44:43 -0500117<COMMENT>{NEWLINE} {
118 if (yylineno == INT_MAX)
119 {
120 *yylval = "Integer overflow on line number";
121 return pp::Token::GOT_ERROR;
122 }
123 ++yylineno;
124}
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000125<COMMENT>"*/" {
126 yyextra->leadingSpace = true;
127 BEGIN(INITIAL);
128}
alokp@chromium.org85f2b2c2012-04-25 06:06:33 +0000129
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000130# {
131 // # is only valid at start of line for preprocessor directives.
alokp@chromium.org432d6fc2012-06-27 22:13:21 +0000132 yylval->assign(1, yytext[0]);
133 return yyextra->lineStart ? pp::Token::PP_HASH : pp::Token::PP_OTHER;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000134}
alokp@chromium.org4e4b8072011-08-07 05:36:04 +0000135
136{IDENTIFIER} {
alokp@chromium.org4b2a5222012-04-03 17:19:42 +0000137 yylval->assign(yytext, yyleng);
138 return pp::Token::IDENTIFIER;
alokp@chromium.org4e4b8072011-08-07 05:36:04 +0000139}
140
shannonwoods@chromium.org3f83e292013-05-30 00:21:34 +0000141({DECIMAL_CONSTANT}[uU]?)|({OCTAL_CONSTANT}[uU]?)|({HEXADECIMAL_CONSTANT}[uU]?) {
alokp@chromium.org4b2a5222012-04-03 17:19:42 +0000142 yylval->assign(yytext, yyleng);
143 return pp::Token::CONST_INT;
alokp@chromium.orgb81c4012011-08-21 06:53:11 +0000144}
145
shannonwoods@chromium.org2a5436f2013-05-30 00:21:41 +0000146({DIGIT}+{EXPONENT_PART}[fF]?)|({FRACTIONAL_CONSTANT}{EXPONENT_PART}?[fF]?) {
alokp@chromium.org4b2a5222012-04-03 17:19:42 +0000147 yylval->assign(yytext, yyleng);
148 return pp::Token::CONST_FLOAT;
alokp@chromium.org4e4b8072011-08-07 05:36:04 +0000149}
150
alokp@chromium.org78a35192012-04-19 17:16:26 +0000151 /* Anything that starts with a {DIGIT} or .{DIGIT} must be a number. */
152 /* Rule to catch all invalid integers and floats. */
153({DIGIT}+[_a-zA-Z0-9.]*)|("."{DIGIT}+[_a-zA-Z0-9.]*) {
alokp@chromium.org432d6fc2012-06-27 22:13:21 +0000154 yylval->assign(yytext, yyleng);
155 return pp::Token::PP_NUMBER;
alokp@chromium.org78a35192012-04-19 17:16:26 +0000156}
157
alokp@chromium.org07d921d2012-05-22 20:22:08 +0000158"++" {
159 yylval->assign(yytext, yyleng);
160 return pp::Token::OP_INC;
161}
162"--" {
163 yylval->assign(yytext, yyleng);
164 return pp::Token::OP_DEC;
165}
166"<<" {
167 yylval->assign(yytext, yyleng);
168 return pp::Token::OP_LEFT;
169}
170">>" {
171 yylval->assign(yytext, yyleng);
172 return pp::Token::OP_RIGHT;
173}
174"<=" {
175 yylval->assign(yytext, yyleng);
176 return pp::Token::OP_LE;
177}
178">=" {
179 yylval->assign(yytext, yyleng);
180 return pp::Token::OP_GE;
181}
182"==" {
183 yylval->assign(yytext, yyleng);
184 return pp::Token::OP_EQ;
185}
186"!=" {
187 yylval->assign(yytext, yyleng);
188 return pp::Token::OP_NE;
189}
190"&&" {
191 yylval->assign(yytext, yyleng);
192 return pp::Token::OP_AND;
193}
194"^^" {
195 yylval->assign(yytext, yyleng);
196 return pp::Token::OP_XOR;
197}
198"||" {
199 yylval->assign(yytext, yyleng);
200 return pp::Token::OP_OR;
201}
202"+=" {
203 yylval->assign(yytext, yyleng);
204 return pp::Token::OP_ADD_ASSIGN;
205}
206"-=" {
207 yylval->assign(yytext, yyleng);
208 return pp::Token::OP_SUB_ASSIGN;
209}
210"*=" {
211 yylval->assign(yytext, yyleng);
212 return pp::Token::OP_MUL_ASSIGN;
213}
214"/=" {
215 yylval->assign(yytext, yyleng);
216 return pp::Token::OP_DIV_ASSIGN;
217}
218"%=" {
219 yylval->assign(yytext, yyleng);
220 return pp::Token::OP_MOD_ASSIGN;
221}
222"<<=" {
223 yylval->assign(yytext, yyleng);
224 return pp::Token::OP_LEFT_ASSIGN;
225}
226">>=" {
227 yylval->assign(yytext, yyleng);
228 return pp::Token::OP_RIGHT_ASSIGN;
229}
230"&=" {
231 yylval->assign(yytext, yyleng);
232 return pp::Token::OP_AND_ASSIGN;
233}
234"^=" {
235 yylval->assign(yytext, yyleng);
236 return pp::Token::OP_XOR_ASSIGN;
237}
238"|=" {
239 yylval->assign(yytext, yyleng);
240 return pp::Token::OP_OR_ASSIGN;
241}
alokp@chromium.org3f990c42012-04-03 19:50:35 +0000242
alokp@chromium.org07d921d2012-05-22 20:22:08 +0000243{PUNCTUATOR} {
244 yylval->assign(1, yytext[0]);
245 return yytext[0];
246}
247
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000248[ \t\v\f]+ { yyextra->leadingSpace = true; }
alokp@chromium.orgd08bb0c2012-04-23 19:27:13 +0000249
250{NEWLINE} {
Corentin Wallezdc0fa462017-02-01 14:44:43 -0500251 if (yylineno == INT_MAX)
252 {
253 *yylval = "Integer overflow on line number";
254 return pp::Token::GOT_ERROR;
255 }
alokp@chromium.orgd08bb0c2012-04-23 19:27:13 +0000256 ++yylineno;
alokp@chromium.org07d921d2012-05-22 20:22:08 +0000257 yylval->assign(1, '\n');
alokp@chromium.orgd08bb0c2012-04-23 19:27:13 +0000258 return '\n';
259}
alokp@chromium.org4e4b8072011-08-07 05:36:04 +0000260
alokp@chromium.org78a35192012-04-19 17:16:26 +0000261. {
alokp@chromium.org432d6fc2012-06-27 22:13:21 +0000262 yylval->assign(1, yytext[0]);
263 return pp::Token::PP_OTHER;
alokp@chromium.org78a35192012-04-19 17:16:26 +0000264}
265
alokp@chromium.org07d921d2012-05-22 20:22:08 +0000266<*><<EOF>> {
alokp@chromium.org19d7aa62012-05-31 17:34:05 +0000267 // YY_USER_ACTION is not invoked for handling EOF.
268 // Set the location for EOF token manually.
269 pp::Input* input = &yyextra->input;
270 pp::Input::Location* scanLoc = &yyextra->scanLoc;
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000271 yy_size_t sIndexMax = input->count() ? input->count() - 1 : 0;
alokp@chromium.org19d7aa62012-05-31 17:34:05 +0000272 if (scanLoc->sIndex != sIndexMax)
273 {
274 // We can only reach here if there are empty strings at the
275 // end of the input.
276 scanLoc->sIndex = sIndexMax; scanLoc->cIndex = 0;
shannon.woods@transgaming.comd64b3da2013-02-28 23:19:26 +0000277 // FIXME: this is not 64-bit clean.
278 yyfileno = static_cast<int>(sIndexMax); yylineno = 1;
alokp@chromium.org19d7aa62012-05-31 17:34:05 +0000279 }
280 yylloc->file = yyfileno;
281 yylloc->line = yylineno;
282 yylval->clear();
283
Corentin Wallezd78e33a2017-10-30 12:33:52 -0400284 // Line number overflows fake EOFs to exit early, check for this case.
285 if (yylineno == INT_MAX) {
286 yyextra->diagnostics->report(pp::Diagnostics::PP_TOKENIZER_ERROR,
287 pp::SourceLocation(yyfileno, yylineno),
288 "Integer overflow on line number");
289 }
290 else if (YY_START == COMMENT)
alokp@chromium.org07d921d2012-05-22 20:22:08 +0000291 {
Jamie Madillc9f140d2014-02-18 15:27:21 -0500292 yyextra->diagnostics->report(pp::Diagnostics::PP_EOF_IN_COMMENT,
alokp@chromium.org07d921d2012-05-22 20:22:08 +0000293 pp::SourceLocation(yyfileno, yylineno),
Corentin Wallezd78e33a2017-10-30 12:33:52 -0400294 "EOF while in a comment");
alokp@chromium.org07d921d2012-05-22 20:22:08 +0000295 }
alokp@chromium.org07d921d2012-05-22 20:22:08 +0000296 yyterminate();
297}
alokp@chromium.org4e4b8072011-08-07 05:36:04 +0000298
299%%
300
alokp@chromium.org3a01d1b2011-08-30 05:10:53 +0000301namespace pp {
alokp@chromium.org4e4b8072011-08-07 05:36:04 +0000302
Corentin Wallez054f7ed2016-09-20 17:15:59 -0400303Tokenizer::Tokenizer(Diagnostics *diagnostics) : mHandle(nullptr), mMaxTokenSize(256)
alokp@chromium.org3a01d1b2011-08-30 05:10:53 +0000304{
alokp@chromium.org2c958ee2012-05-17 20:35:42 +0000305 mContext.diagnostics = diagnostics;
alokp@chromium.org4e4b8072011-08-07 05:36:04 +0000306}
307
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000308Tokenizer::~Tokenizer()
309{
310 destroyScanner();
311}
312
Zhenyao Mod526f982014-05-13 14:51:19 -0700313bool Tokenizer::init(size_t count, const char * const string[], const int length[])
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000314{
Zhenyao Mod526f982014-05-13 14:51:19 -0700315 if ((count > 0) && (string == 0))
316 return false;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000317
318 mContext.input = Input(count, string, length);
319 return initScanner();
320}
321
alokp@chromium.org46aa13d2012-06-15 15:40:27 +0000322void Tokenizer::setFileNumber(int file)
323{
324 // We use column number as file number.
325 // See macro yyfileno.
326 yyset_column(file, mHandle);
327}
328
329void Tokenizer::setLineNumber(int line)
330{
331 yyset_lineno(line, mHandle);
332}
333
Jamie Madill5508f392014-02-20 13:31:36 -0500334void Tokenizer::setMaxTokenSize(size_t maxTokenSize)
335{
336 mMaxTokenSize = maxTokenSize;
337}
338
Zhenyao Mod526f982014-05-13 14:51:19 -0700339void Tokenizer::lex(Token *token)
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000340{
Corentin Wallezdc0fa462017-02-01 14:44:43 -0500341 int tokenType = yylex(&token->text, &token->location, mHandle);
342
343 if (tokenType == Token::GOT_ERROR)
344 {
345 mContext.diagnostics->report(Diagnostics::PP_TOKENIZER_ERROR, token->location, token->text);
346 token->type = Token::LAST;
347 }
348 else
349 {
350 token->type = tokenType;
351 }
352
Jamie Madill5508f392014-02-20 13:31:36 -0500353 if (token->text.size() > mMaxTokenSize)
alokp@chromium.orgc022c3a2012-07-09 15:56:42 +0000354 {
Jamie Madillc9f140d2014-02-18 15:27:21 -0500355 mContext.diagnostics->report(Diagnostics::PP_TOKEN_TOO_LONG,
alokp@chromium.orgc022c3a2012-07-09 15:56:42 +0000356 token->location, token->text);
Jamie Madill5508f392014-02-20 13:31:36 -0500357 token->text.erase(mMaxTokenSize);
alokp@chromium.orgc022c3a2012-07-09 15:56:42 +0000358 }
359
alokp@chromium.org7fc38dd2012-06-14 18:23:23 +0000360 token->flags = 0;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000361
alokp@chromium.org19d7aa62012-05-31 17:34:05 +0000362 token->setAtStartOfLine(mContext.lineStart);
363 mContext.lineStart = token->type == '\n';
364
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000365 token->setHasLeadingSpace(mContext.leadingSpace);
366 mContext.leadingSpace = false;
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000367}
368
369bool Tokenizer::initScanner()
alokp@chromium.org4e4b8072011-08-07 05:36:04 +0000370{
Corentin Wallez054f7ed2016-09-20 17:15:59 -0400371 if ((mHandle == nullptr) && yylex_init_extra(&mContext, &mHandle))
alokp@chromium.org4e4b8072011-08-07 05:36:04 +0000372 return false;
373
alokp@chromium.org98eec912012-05-01 10:04:08 +0000374 yyrestart(0, mHandle);
alokp@chromium.org4e4b8072011-08-07 05:36:04 +0000375 return true;
376}
377
alokp@chromium.org04d7d222012-05-16 19:24:07 +0000378void Tokenizer::destroyScanner()
alokp@chromium.org4e4b8072011-08-07 05:36:04 +0000379{
Corentin Wallez054f7ed2016-09-20 17:15:59 -0400380 if (mHandle == nullptr)
alokp@chromium.org01fd4312012-03-30 21:33:30 +0000381 return;
alokp@chromium.org4e4b8072011-08-07 05:36:04 +0000382
alokp@chromium.org01fd4312012-03-30 21:33:30 +0000383 yylex_destroy(mHandle);
Corentin Wallez054f7ed2016-09-20 17:15:59 -0400384 mHandle = nullptr;
alokp@chromium.org4e4b8072011-08-07 05:36:04 +0000385}
386
387} // namespace pp
388