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 16This file contains the Lex specification for GLSL ES preprocessor. 17Based on Microsoft Visual Studio 2010 Preprocessor Grammar: 18http://msdn.microsoft.com/en-us/library/2scxys89.aspx 19 20IF 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#if defined(_MSC_VER) 43#pragma warning(disable: 4005) 44#endif 45 46#include "Tokenizer.h" 47 48#include "DiagnosticsBase.h" 49#include "Token.h" 50 51#if defined(__GNUC__) 52// Triggered by the auto-generated yy_fatal_error function. 53#pragma GCC diagnostic ignored "-Wmissing-noreturn" 54#elif defined(_MSC_VER) 55#pragma warning(disable: 4244) 56#endif 57 58// Workaround for flex using the register keyword, deprecated in C++11. 59#ifdef __cplusplus 60#if __cplusplus > 199711L 61#define register 62#endif 63#endif 64 65typedef std::string YYSTYPE; 66typedef pp::SourceLocation YYLTYPE; 67 68// Use the unused yycolumn variable to track file (string) number. 69#define yyfileno yycolumn 70 71#define YY_USER_INIT \ 72 do { \ 73 yyfileno = 0; \ 74 yylineno = 1; \ 75 yyextra->leadingSpace = false; \ 76 yyextra->lineStart = true; \ 77 } while(0); 78 79#define YY_USER_ACTION \ 80 do \ 81 { \ 82 pp::Input* input = &yyextra->input; \ 83 pp::Input::Location* scanLoc = &yyextra->scanLoc; \ 84 while ((scanLoc->sIndex < input->count()) && \ 85 (scanLoc->cIndex >= input->length(scanLoc->sIndex))) \ 86 { \ 87 scanLoc->cIndex -= input->length(scanLoc->sIndex++); \ 88 ++yyfileno; yylineno = 1; \ 89 } \ 90 yylloc->file = yyfileno; \ 91 yylloc->line = yylineno; \ 92 scanLoc->cIndex += yyleng; \ 93 } while(0); 94 95#define YY_INPUT(buf, result, maxSize) \ 96 result = yyextra->input.read(buf, maxSize, &yylineno); 97 98%} 99 100%option noyywrap nounput never-interactive 101%option reentrant bison-bridge bison-locations 102%option prefix="pp" 103%option extra-type="pp::Tokenizer::Context*" 104%x COMMENT 105 106NEWLINE \n|\r|\r\n 107IDENTIFIER [_a-zA-Z][_a-zA-Z0-9]* 108PUNCTUATOR [][<>(){}.+-/*%^|&~=!:;,?] 109 110DECIMAL_CONSTANT [1-9][0-9]*[uU]? 111OCTAL_CONSTANT 0[0-7]*[uU]? 112HEXADECIMAL_CONSTANT 0[xX][0-9a-fA-F]+[uU]? 113 114DIGIT [0-9] 115EXPONENT_PART [eE][+-]?{DIGIT}+ 116FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".") 117 118%% 119 120 /* Line comment */ 121"//"[^\r\n]* 122 123 /* Block comment */ 124 /* Line breaks are just counted - not returned. */ 125 /* The comment is replaced by a single space. */ 126"/*" { BEGIN(COMMENT); } 127<COMMENT>[^*\r\n]+ 128<COMMENT>"*" 129<COMMENT>{NEWLINE} { 130 if (yylineno == INT_MAX) 131 { 132 *yylval = "Integer overflow on line number"; 133 return pp::Token::GOT_ERROR; 134 } 135 ++yylineno; 136} 137<COMMENT>"*/" { 138 yyextra->leadingSpace = true; 139 BEGIN(INITIAL); 140} 141 142# { 143 // # is only valid at start of line for preprocessor directives. 144 yylval->assign(1, yytext[0]); 145 return yyextra->lineStart ? pp::Token::PP_HASH : pp::Token::PP_OTHER; 146} 147 148{IDENTIFIER} { 149 yylval->assign(yytext, yyleng); 150 return pp::Token::IDENTIFIER; 151} 152 153({DECIMAL_CONSTANT}[uU]?)|({OCTAL_CONSTANT}[uU]?)|({HEXADECIMAL_CONSTANT}[uU]?) { 154 yylval->assign(yytext, yyleng); 155 return pp::Token::CONST_INT; 156} 157 158({DIGIT}+{EXPONENT_PART}[fF]?)|({FRACTIONAL_CONSTANT}{EXPONENT_PART}?[fF]?) { 159 yylval->assign(yytext, yyleng); 160 return pp::Token::CONST_FLOAT; 161} 162 163 /* Anything that starts with a {DIGIT} or .{DIGIT} must be a number. */ 164 /* Rule to catch all invalid integers and floats. */ 165({DIGIT}+[_a-zA-Z0-9.]*)|("."{DIGIT}+[_a-zA-Z0-9.]*) { 166 yylval->assign(yytext, yyleng); 167 return pp::Token::PP_NUMBER; 168} 169 170"++" { 171 yylval->assign(yytext, yyleng); 172 return pp::Token::OP_INC; 173} 174"--" { 175 yylval->assign(yytext, yyleng); 176 return pp::Token::OP_DEC; 177} 178"<<" { 179 yylval->assign(yytext, yyleng); 180 return pp::Token::OP_LEFT; 181} 182">>" { 183 yylval->assign(yytext, yyleng); 184 return pp::Token::OP_RIGHT; 185} 186"<=" { 187 yylval->assign(yytext, yyleng); 188 return pp::Token::OP_LE; 189} 190">=" { 191 yylval->assign(yytext, yyleng); 192 return pp::Token::OP_GE; 193} 194"==" { 195 yylval->assign(yytext, yyleng); 196 return pp::Token::OP_EQ; 197} 198"!=" { 199 yylval->assign(yytext, yyleng); 200 return pp::Token::OP_NE; 201} 202"&&" { 203 yylval->assign(yytext, yyleng); 204 return pp::Token::OP_AND; 205} 206"^^" { 207 yylval->assign(yytext, yyleng); 208 return pp::Token::OP_XOR; 209} 210"||" { 211 yylval->assign(yytext, yyleng); 212 return pp::Token::OP_OR; 213} 214"+=" { 215 yylval->assign(yytext, yyleng); 216 return pp::Token::OP_ADD_ASSIGN; 217} 218"-=" { 219 yylval->assign(yytext, yyleng); 220 return pp::Token::OP_SUB_ASSIGN; 221} 222"*=" { 223 yylval->assign(yytext, yyleng); 224 return pp::Token::OP_MUL_ASSIGN; 225} 226"/=" { 227 yylval->assign(yytext, yyleng); 228 return pp::Token::OP_DIV_ASSIGN; 229} 230"%=" { 231 yylval->assign(yytext, yyleng); 232 return pp::Token::OP_MOD_ASSIGN; 233} 234"<<=" { 235 yylval->assign(yytext, yyleng); 236 return pp::Token::OP_LEFT_ASSIGN; 237} 238">>=" { 239 yylval->assign(yytext, yyleng); 240 return pp::Token::OP_RIGHT_ASSIGN; 241} 242"&=" { 243 yylval->assign(yytext, yyleng); 244 return pp::Token::OP_AND_ASSIGN; 245} 246"^=" { 247 yylval->assign(yytext, yyleng); 248 return pp::Token::OP_XOR_ASSIGN; 249} 250"|=" { 251 yylval->assign(yytext, yyleng); 252 return pp::Token::OP_OR_ASSIGN; 253} 254 255{PUNCTUATOR} { 256 yylval->assign(1, yytext[0]); 257 return yytext[0]; 258} 259 260[ \t\v\f]+ { yyextra->leadingSpace = true; } 261 262{NEWLINE} { 263 if (yylineno == INT_MAX) 264 { 265 *yylval = "Integer overflow on line number"; 266 return pp::Token::GOT_ERROR; 267 } 268 ++yylineno; 269 yylval->assign(1, '\n'); 270 return '\n'; 271} 272 273. { 274 yylval->assign(1, yytext[0]); 275 return pp::Token::PP_OTHER; 276} 277 278<*><<EOF>> { 279 // YY_USER_ACTION is not invoked for handling EOF. 280 // Set the location for EOF token manually. 281 pp::Input* input = &yyextra->input; 282 pp::Input::Location* scanLoc = &yyextra->scanLoc; 283 yy_size_t sIndexMax = input->count() ? input->count() - 1 : 0; 284 if (scanLoc->sIndex != sIndexMax) 285 { 286 // We can only reach here if there are empty strings at the 287 // end of the input. 288 scanLoc->sIndex = sIndexMax; scanLoc->cIndex = 0; 289 // FIXME: this is not 64-bit clean. 290 yyfileno = static_cast<int>(sIndexMax); yylineno = 1; 291 } 292 yylloc->file = yyfileno; 293 yylloc->line = yylineno; 294 yylval->clear(); 295 296 // Line number overflows fake EOFs to exit early, check for this case. 297 if (yylineno == INT_MAX) { 298 yyextra->diagnostics->report(pp::Diagnostics::PP_TOKENIZER_ERROR, 299 pp::SourceLocation(yyfileno, yylineno), 300 "Integer overflow on line number"); 301 } 302 else if (YY_START == COMMENT) 303 { 304 yyextra->diagnostics->report(pp::Diagnostics::PP_EOF_IN_COMMENT, 305 pp::SourceLocation(yyfileno, yylineno), 306 "EOF while in a comment"); 307 } 308 yyterminate(); 309} 310 311%% 312 313namespace pp { 314 315Tokenizer::Tokenizer(Diagnostics *diagnostics) : mHandle(nullptr), mMaxTokenSize(1024) 316{ 317 mContext.diagnostics = diagnostics; 318} 319 320Tokenizer::~Tokenizer() 321{ 322 destroyScanner(); 323} 324 325bool Tokenizer::init(size_t count, const char * const string[], const int length[]) 326{ 327 if ((count > 0) && (string == 0)) 328 return false; 329 330 mContext.input = Input(count, string, length); 331 return initScanner(); 332} 333 334void Tokenizer::setFileNumber(int file) 335{ 336 // We use column number as file number. 337 // See macro yyfileno. 338 yyset_column(file, mHandle); 339} 340 341void Tokenizer::setLineNumber(int line) 342{ 343 yyset_lineno(line, mHandle); 344} 345 346void Tokenizer::setMaxTokenSize(size_t maxTokenSize) 347{ 348 mMaxTokenSize = maxTokenSize; 349} 350 351void Tokenizer::lex(Token *token) 352{ 353 int tokenType = yylex(&token->text, &token->location, mHandle); 354 355 if (tokenType == Token::GOT_ERROR) 356 { 357 mContext.diagnostics->report(Diagnostics::PP_TOKENIZER_ERROR, token->location, token->text); 358 token->type = Token::LAST; 359 } 360 else 361 { 362 token->type = tokenType; 363 } 364 365 if (token->text.size() > mMaxTokenSize) 366 { 367 mContext.diagnostics->report(Diagnostics::PP_TOKEN_TOO_LONG, 368 token->location, token->text); 369 token->text.erase(mMaxTokenSize); 370 } 371 372 token->flags = 0; 373 374 token->setAtStartOfLine(mContext.lineStart); 375 mContext.lineStart = token->type == '\n'; 376 377 token->setHasLeadingSpace(mContext.leadingSpace); 378 mContext.leadingSpace = false; 379} 380 381bool Tokenizer::initScanner() 382{ 383 if ((mHandle == nullptr) && yylex_init_extra(&mContext, &mHandle)) 384 return false; 385 386 yyrestart(0, mHandle); 387 return true; 388} 389 390void Tokenizer::destroyScanner() 391{ 392 if (mHandle == nullptr) 393 return; 394 395 yylex_destroy(mHandle); 396 mHandle = nullptr; 397} 398 399} // namespace pp 400 401