SkSLParser.cpp revision d214d6ae69c1dd9ef49fdce8fac699d00bffcdcd
1/* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "stdio.h" 9#include "SkSLParser.h" 10#include "SkSLToken.h" 11 12#define register 13#ifdef __clang__ 14#pragma clang diagnostic push 15#pragma clang diagnostic ignored "-Wunneeded-internal-declaration" 16#pragma clang diagnostic ignored "-Wnull-conversion" 17#pragma clang diagnostic ignored "-Wsign-compare" 18#endif 19#ifdef __GNUC__ 20#pragma GCC diagnostic push 21#pragma GCC diagnostic ignored "-Wsign-compare" 22#endif 23#ifdef _MSC_VER 24#pragma warning(push) 25#pragma warning(disable:4018) 26#endif 27#include "lex.sksl.c" 28#ifdef __clang__ 29#pragma clang diagnostic pop 30#endif 31#ifdef __GNUC__ 32#pragma GCC diagnostic pop 33#endif 34#ifdef _MSC_VER 35#pragma warning(pop) 36#endif 37#undef register 38 39#include "ast/SkSLASTBinaryExpression.h" 40#include "ast/SkSLASTBlock.h" 41#include "ast/SkSLASTBoolLiteral.h" 42#include "ast/SkSLASTBreakStatement.h" 43#include "ast/SkSLASTCallSuffix.h" 44#include "ast/SkSLASTContinueStatement.h" 45#include "ast/SkSLASTDiscardStatement.h" 46#include "ast/SkSLASTDoStatement.h" 47#include "ast/SkSLASTExpression.h" 48#include "ast/SkSLASTExpressionStatement.h" 49#include "ast/SkSLASTExtension.h" 50#include "ast/SkSLASTFieldSuffix.h" 51#include "ast/SkSLASTFloatLiteral.h" 52#include "ast/SkSLASTForStatement.h" 53#include "ast/SkSLASTFunction.h" 54#include "ast/SkSLASTIdentifier.h" 55#include "ast/SkSLASTIfStatement.h" 56#include "ast/SkSLASTIndexSuffix.h" 57#include "ast/SkSLASTInterfaceBlock.h" 58#include "ast/SkSLASTIntLiteral.h" 59#include "ast/SkSLASTParameter.h" 60#include "ast/SkSLASTPrefixExpression.h" 61#include "ast/SkSLASTReturnStatement.h" 62#include "ast/SkSLASTStatement.h" 63#include "ast/SkSLASTSuffixExpression.h" 64#include "ast/SkSLASTTernaryExpression.h" 65#include "ast/SkSLASTType.h" 66#include "ast/SkSLASTVarDeclaration.h" 67#include "ast/SkSLASTVarDeclarationStatement.h" 68#include "ast/SkSLASTWhileStatement.h" 69#include "ir/SkSLSymbolTable.h" 70#include "ir/SkSLType.h" 71 72namespace SkSL { 73 74Parser::Parser(std::string text, SymbolTable& types, ErrorReporter& errors) 75: fPushback(Position(-1, -1), Token::INVALID_TOKEN, "") 76, fTypes(types) 77, fErrors(errors) { 78 sksllex_init(&fScanner); 79 fBuffer = sksl_scan_string(text.c_str(), fScanner); 80 skslset_lineno(1, fScanner); 81 82 if (false) { 83 // avoid unused warning 84 yyunput(0, nullptr, fScanner); 85 } 86} 87 88Parser::~Parser() { 89 sksl_delete_buffer(fBuffer, fScanner); 90 sksllex_destroy(fScanner); 91} 92 93/* (precision | directive | declaration)* END_OF_FILE */ 94std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() { 95 std::vector<std::unique_ptr<ASTDeclaration>> result; 96 for (;;) { 97 switch (this->peek().fKind) { 98 case Token::END_OF_FILE: 99 return result; 100 case Token::PRECISION: 101 this->precision(); 102 break; 103 case Token::DIRECTIVE: { 104 std::unique_ptr<ASTDeclaration> decl = this->directive(); 105 if (decl) { 106 result.push_back(std::move(decl)); 107 } 108 break; 109 } 110 default: { 111 std::unique_ptr<ASTDeclaration> decl = this->declaration(); 112 if (!decl) { 113 continue; 114 } 115 result.push_back(std::move(decl)); 116 } 117 } 118 } 119} 120 121Token Parser::nextToken() { 122 if (fPushback.fKind != Token::INVALID_TOKEN) { 123 Token result = fPushback; 124 fPushback.fKind = Token::INVALID_TOKEN; 125 fPushback.fText = ""; 126 return result; 127 } 128 int token = sksllex(fScanner); 129 return Token(Position(skslget_lineno(fScanner), -1), (Token::Kind) token, 130 token == Token::END_OF_FILE ? "<end of file>" : 131 std::string(skslget_text(fScanner))); 132} 133 134void Parser::pushback(Token t) { 135 ASSERT(fPushback.fKind == Token::INVALID_TOKEN); 136 fPushback = t; 137} 138 139Token Parser::peek() { 140 fPushback = this->nextToken(); 141 return fPushback; 142} 143 144bool Parser::expect(Token::Kind kind, std::string expected, Token* result) { 145 Token next = this->nextToken(); 146 if (next.fKind == kind) { 147 if (result) { 148 *result = next; 149 } 150 return true; 151 } else { 152 this->error(next.fPosition, "expected " + expected + ", but found '" + next.fText + "'"); 153 return false; 154 } 155} 156 157void Parser::error(Position p, std::string msg) { 158 fErrors.error(p, msg); 159} 160 161bool Parser::isType(std::string name) { 162 return nullptr != fTypes[name]; 163} 164 165/* PRECISION (LOWP | MEDIUMP | HIGHP) type SEMICOLON */ 166void Parser::precision() { 167 if (!this->expect(Token::PRECISION, "'precision'")) { 168 return; 169 } 170 Token p = this->nextToken(); 171 switch (p.fKind) { 172 case Token::LOWP: // fall through 173 case Token::MEDIUMP: // fall through 174 case Token::HIGHP: 175 // ignored for now 176 break; 177 default: 178 this->error(p.fPosition, "expected 'lowp', 'mediump', or 'highp', but found '" + 179 p.fText + "'"); 180 return; 181 } 182 if (!this->type()) { 183 return; 184 } 185 this->expect(Token::SEMICOLON, "';'"); 186} 187 188/* DIRECTIVE(#version) INT_LITERAL | DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */ 189std::unique_ptr<ASTDeclaration> Parser::directive() { 190 Token start; 191 if (!this->expect(Token::DIRECTIVE, "a directive", &start)) { 192 return nullptr; 193 } 194 if (start.fText == "#version") { 195 this->expect(Token::INT_LITERAL, "a version number"); 196 // ignored for now 197 return nullptr; 198 } else if (start.fText == "#extension") { 199 Token name; 200 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) { 201 return nullptr; 202 } 203 if (!this->expect(Token::COLON, "':'")) { 204 return nullptr; 205 } 206 // FIXME: need to start paying attention to this token 207 if (!this->expect(Token::IDENTIFIER, "an identifier")) { 208 return nullptr; 209 } 210 return std::unique_ptr<ASTDeclaration>(new ASTExtension(start.fPosition, 211 std::move(name.fText))); 212 } else { 213 this->error(start.fPosition, "unsupported directive '" + start.fText + "'"); 214 return nullptr; 215 } 216} 217 218/* modifiers (structVarDeclaration | type IDENTIFIER ((LPAREN parameter 219 (COMMA parameter)* RPAREN (block | SEMICOLON)) | SEMICOLON) | interfaceBlock) */ 220std::unique_ptr<ASTDeclaration> Parser::declaration() { 221 ASTModifiers modifiers = this->modifiers(); 222 Token lookahead = this->peek(); 223 if (lookahead.fKind == Token::IDENTIFIER && !this->isType(lookahead.fText)) { 224 // we have an identifier that's not a type, could be the start of an interface block 225 return this->interfaceBlock(modifiers); 226 } 227 if (lookahead.fKind == Token::STRUCT) { 228 return this->structVarDeclaration(modifiers); 229 } 230 std::unique_ptr<ASTType> type(this->type()); 231 if (!type) { 232 return nullptr; 233 } 234 if (type->fKind == ASTType::kStruct_Kind && peek().fKind == Token::SEMICOLON) { 235 this->nextToken(); 236 return nullptr; 237 } 238 Token name; 239 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) { 240 return nullptr; 241 } 242 if (!modifiers.fFlags && this->peek().fKind == Token::LPAREN) { 243 this->nextToken(); 244 std::vector<std::unique_ptr<ASTParameter>> parameters; 245 while (this->peek().fKind != Token::RPAREN) { 246 if (parameters.size() > 0) { 247 if (!this->expect(Token::COMMA, "','")) { 248 return nullptr; 249 } 250 } 251 std::unique_ptr<ASTParameter> parameter = this->parameter(); 252 if (!parameter) { 253 return nullptr; 254 } 255 parameters.push_back(std::move(parameter)); 256 } 257 this->nextToken(); 258 std::unique_ptr<ASTBlock> body; 259 if (this->peek().fKind == Token::SEMICOLON) { 260 this->nextToken(); 261 } else { 262 body = this->block(); 263 if (!body) { 264 return nullptr; 265 } 266 } 267 return std::unique_ptr<ASTDeclaration>(new ASTFunction(name.fPosition, std::move(type), 268 std::move(name.fText), 269 std::move(parameters), 270 std::move(body))); 271 } else { 272 return this->varDeclarationEnd(modifiers, std::move(type), name.fText); 273 } 274} 275 276/* modifiers type IDENTIFIER varDeclarationEnd */ 277std::unique_ptr<ASTVarDeclarations> Parser::varDeclarations() { 278 ASTModifiers modifiers = this->modifiers(); 279 std::unique_ptr<ASTType> type(this->type()); 280 if (!type) { 281 return nullptr; 282 } 283 Token name; 284 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) { 285 return nullptr; 286 } 287 return this->varDeclarationEnd(modifiers, std::move(type), std::move(name.fText)); 288} 289 290/* STRUCT IDENTIFIER LBRACE varDeclaration* RBRACE */ 291std::unique_ptr<ASTType> Parser::structDeclaration() { 292 if (!this->expect(Token::STRUCT, "'struct'")) { 293 return nullptr; 294 } 295 Token name; 296 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) { 297 return nullptr; 298 } 299 if (!this->expect(Token::LBRACE, "'{'")) { 300 return nullptr; 301 } 302 std::vector<Type::Field> fields; 303 while (this->peek().fKind != Token::RBRACE) { 304 std::unique_ptr<ASTVarDeclarations> decl = this->varDeclarations(); 305 if (!decl) { 306 return nullptr; 307 } 308 for (const auto& var : decl->fVars) { 309 auto type = (const Type*) fTypes[decl->fType->fName]; 310 for (int i = (int) var.fSizes.size() - 1; i >= 0; i--) { 311 if (var.fSizes[i]->fKind != ASTExpression::kInt_Kind) { 312 this->error(decl->fPosition, "array size in struct field must be a constant"); 313 } 314 uint64_t columns = ((ASTIntLiteral&) *var.fSizes[i]).fValue; 315 std::string name = type->name() + "[" + to_string(columns) + "]"; 316 type = new Type(name, Type::kArray_Kind, *type, (int) columns); 317 fTypes.takeOwnership((Type*) type); 318 } 319 fields.push_back(Type::Field(decl->fModifiers, var.fName, type)); 320 if (var.fValue) { 321 this->error(decl->fPosition, "initializers are not permitted on struct fields"); 322 } 323 } 324 } 325 if (!this->expect(Token::RBRACE, "'}'")) { 326 return nullptr; 327 } 328 fTypes.add(name.fText, std::unique_ptr<Type>(new Type(name.fText, fields))); 329 return std::unique_ptr<ASTType>(new ASTType(name.fPosition, name.fText, 330 ASTType::kStruct_Kind)); 331} 332 333/* structDeclaration ((IDENTIFIER varDeclarationEnd) | SEMICOLON) */ 334std::unique_ptr<ASTVarDeclarations> Parser::structVarDeclaration(ASTModifiers modifiers) { 335 std::unique_ptr<ASTType> type = this->structDeclaration(); 336 if (!type) { 337 return nullptr; 338 } 339 if (peek().fKind == Token::IDENTIFIER) { 340 Token name = this->nextToken(); 341 std::unique_ptr<ASTVarDeclarations> result = this->varDeclarationEnd(modifiers, 342 std::move(type), 343 std::move(name.fText)); 344 if (result) { 345 for (const auto& var : result->fVars) { 346 if (var.fValue) { 347 this->error(var.fValue->fPosition, 348 "struct variables cannot be initialized"); 349 } 350 } 351 } 352 return result; 353 } 354 this->expect(Token::SEMICOLON, "';'"); 355 return nullptr; 356} 357 358/* (LBRACKET expression? RBRACKET)* (EQ expression)? (COMMA IDENTIFER 359 (LBRACKET expression? RBRACKET)* (EQ expression)?)* SEMICOLON */ 360std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(ASTModifiers mods, 361 std::unique_ptr<ASTType> type, 362 std::string name) { 363 std::vector<ASTVarDeclaration> vars; 364 std::vector<std::unique_ptr<ASTExpression>> currentVarSizes; 365 while (this->peek().fKind == Token::LBRACKET) { 366 this->nextToken(); 367 if (this->peek().fKind == Token::RBRACKET) { 368 this->nextToken(); 369 currentVarSizes.push_back(nullptr); 370 } else { 371 std::unique_ptr<ASTExpression> size(this->expression()); 372 if (!size) { 373 return nullptr; 374 } 375 currentVarSizes.push_back(std::move(size)); 376 if (!this->expect(Token::RBRACKET, "']'")) { 377 return nullptr; 378 } 379 } 380 } 381 std::unique_ptr<ASTExpression> value; 382 if (this->peek().fKind == Token::EQ) { 383 this->nextToken(); 384 value = this->expression(); 385 if (!value) { 386 return nullptr; 387 } 388 } 389 vars.emplace_back(std::move(name), std::move(currentVarSizes), std::move(value)); 390 while (this->peek().fKind == Token::COMMA) { 391 this->nextToken(); 392 Token name; 393 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) { 394 return nullptr; 395 } 396 currentVarSizes.clear(); 397 value.reset(); 398 while (this->peek().fKind == Token::LBRACKET) { 399 this->nextToken(); 400 if (this->peek().fKind == Token::RBRACKET) { 401 this->nextToken(); 402 currentVarSizes.push_back(nullptr); 403 } else { 404 std::unique_ptr<ASTExpression> size(this->expression()); 405 if (!size) { 406 return nullptr; 407 } 408 currentVarSizes.push_back(std::move(size)); 409 if (!this->expect(Token::RBRACKET, "']'")) { 410 return nullptr; 411 } 412 } 413 } 414 if (this->peek().fKind == Token::EQ) { 415 this->nextToken(); 416 value = this->expression(); 417 if (!value) { 418 return nullptr; 419 } 420 } 421 vars.emplace_back(std::move(name.fText), std::move(currentVarSizes), std::move(value)); 422 } 423 if (!this->expect(Token::SEMICOLON, "';'")) { 424 return nullptr; 425 } 426 return std::unique_ptr<ASTVarDeclarations>(new ASTVarDeclarations(std::move(mods), 427 std::move(type), 428 std::move(vars))); 429} 430 431/* modifiers type IDENTIFIER (LBRACKET INT_LITERAL RBRACKET)? */ 432std::unique_ptr<ASTParameter> Parser::parameter() { 433 ASTModifiers modifiers = this->modifiersWithDefaults(ASTModifiers::kIn_Flag); 434 std::unique_ptr<ASTType> type = this->type(); 435 if (!type) { 436 return nullptr; 437 } 438 Token name; 439 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) { 440 return nullptr; 441 } 442 std::vector<int> sizes; 443 while (this->peek().fKind == Token::LBRACKET) { 444 this->nextToken(); 445 Token sizeToken; 446 if (!this->expect(Token::INT_LITERAL, "a positive integer", &sizeToken)) { 447 return nullptr; 448 } 449 sizes.push_back(SkSL::stoi(sizeToken.fText)); 450 if (!this->expect(Token::RBRACKET, "']'")) { 451 return nullptr; 452 } 453 } 454 return std::unique_ptr<ASTParameter>(new ASTParameter(name.fPosition, modifiers, 455 std::move(type), name.fText, 456 std::move(sizes))); 457} 458 459/** (EQ INT_LITERAL)? */ 460int Parser::layoutInt() { 461 if (!this->expect(Token::EQ, "'='")) { 462 return -1; 463 } 464 Token resultToken; 465 if (this->expect(Token::INT_LITERAL, "a non-negative integer", &resultToken)) { 466 return SkSL::stoi(resultToken.fText); 467 } 468 return -1; 469} 470 471/* LAYOUT LPAREN IDENTIFIER EQ INT_LITERAL (COMMA IDENTIFIER EQ INT_LITERAL)* 472 RPAREN */ 473ASTLayout Parser::layout() { 474 int location = -1; 475 int binding = -1; 476 int index = -1; 477 int set = -1; 478 int builtin = -1; 479 bool originUpperLeft = false; 480 if (this->peek().fKind == Token::LAYOUT) { 481 this->nextToken(); 482 if (!this->expect(Token::LPAREN, "'('")) { 483 return ASTLayout(location, binding, index, set, builtin, originUpperLeft); 484 } 485 for (;;) { 486 Token t = this->nextToken(); 487 if (t.fText == "location") { 488 location = this->layoutInt(); 489 } else if (t.fText == "binding") { 490 binding = this->layoutInt(); 491 } else if (t.fText == "index") { 492 index = this->layoutInt(); 493 } else if (t.fText == "set") { 494 set = this->layoutInt(); 495 } else if (t.fText == "builtin") { 496 builtin = this->layoutInt(); 497 } else if (t.fText == "origin_upper_left") { 498 originUpperLeft = true; 499 } else { 500 this->error(t.fPosition, ("'" + t.fText + 501 "' is not a valid layout qualifier").c_str()); 502 } 503 if (this->peek().fKind == Token::RPAREN) { 504 this->nextToken(); 505 break; 506 } 507 if (!this->expect(Token::COMMA, "','")) { 508 break; 509 } 510 } 511 } 512 return ASTLayout(location, binding, index, set, builtin, originUpperLeft); 513} 514 515/* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE)* */ 516ASTModifiers Parser::modifiers() { 517 ASTLayout layout = this->layout(); 518 int flags = 0; 519 for (;;) { 520 // TODO: handle duplicate / incompatible flags 521 switch (peek().fKind) { 522 case Token::UNIFORM: 523 this->nextToken(); 524 flags |= ASTModifiers::kUniform_Flag; 525 break; 526 case Token::CONST: 527 this->nextToken(); 528 flags |= ASTModifiers::kConst_Flag; 529 break; 530 case Token::IN: 531 this->nextToken(); 532 flags |= ASTModifiers::kIn_Flag; 533 break; 534 case Token::OUT: 535 this->nextToken(); 536 flags |= ASTModifiers::kOut_Flag; 537 break; 538 case Token::INOUT: 539 this->nextToken(); 540 flags |= ASTModifiers::kIn_Flag; 541 flags |= ASTModifiers::kOut_Flag; 542 break; 543 case Token::LOWP: 544 this->nextToken(); 545 flags |= ASTModifiers::kLowp_Flag; 546 break; 547 case Token::MEDIUMP: 548 this->nextToken(); 549 flags |= ASTModifiers::kMediump_Flag; 550 break; 551 case Token::HIGHP: 552 this->nextToken(); 553 flags |= ASTModifiers::kHighp_Flag; 554 break; 555 case Token::FLAT: 556 this->nextToken(); 557 flags |= ASTModifiers::kFlat_Flag; 558 break; 559 case Token::NOPERSPECTIVE: 560 this->nextToken(); 561 flags |= ASTModifiers::kNoPerspective_Flag; 562 break; 563 default: 564 return ASTModifiers(layout, flags); 565 } 566 } 567} 568 569ASTModifiers Parser::modifiersWithDefaults(int defaultFlags) { 570 ASTModifiers result = this->modifiers(); 571 if (!result.fFlags) { 572 return ASTModifiers(result.fLayout, defaultFlags); 573 } 574 return result; 575} 576 577/* ifStatement | forStatement | doStatement | whileStatement | block | expression */ 578std::unique_ptr<ASTStatement> Parser::statement() { 579 Token start = this->peek(); 580 switch (start.fKind) { 581 case Token::IF: 582 return this->ifStatement(); 583 case Token::FOR: 584 return this->forStatement(); 585 case Token::DO: 586 return this->doStatement(); 587 case Token::WHILE: 588 return this->whileStatement(); 589 case Token::RETURN: 590 return this->returnStatement(); 591 case Token::BREAK: 592 return this->breakStatement(); 593 case Token::CONTINUE: 594 return this->continueStatement(); 595 case Token::DISCARD: 596 return this->discardStatement(); 597 case Token::LBRACE: 598 return this->block(); 599 case Token::SEMICOLON: 600 this->nextToken(); 601 return std::unique_ptr<ASTStatement>(new ASTBlock(start.fPosition, 602 std::vector<std::unique_ptr<ASTStatement>>())); 603 case Token::CONST: // fall through 604 case Token::HIGHP: // fall through 605 case Token::MEDIUMP: // fall through 606 case Token::LOWP: { 607 auto decl = this->varDeclarations(); 608 if (!decl) { 609 return nullptr; 610 } 611 return std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(std::move(decl))); 612 } 613 case Token::IDENTIFIER: 614 if (this->isType(start.fText)) { 615 auto decl = this->varDeclarations(); 616 if (!decl) { 617 return nullptr; 618 } 619 return std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement( 620 std::move(decl))); 621 } 622 // fall through 623 default: 624 return this->expressionStatement(); 625 } 626} 627 628/* IDENTIFIER(type) */ 629std::unique_ptr<ASTType> Parser::type() { 630 Token type; 631 if (!this->expect(Token::IDENTIFIER, "a type", &type)) { 632 return nullptr; 633 } 634 if (!this->isType(type.fText)) { 635 this->error(type.fPosition, ("no type named '" + type.fText + "'").c_str()); 636 return nullptr; 637 } 638 return std::unique_ptr<ASTType>(new ASTType(type.fPosition, std::move(type.fText), 639 ASTType::kIdentifier_Kind)); 640} 641 642/* IDENTIFIER LBRACE varDeclaration* RBRACE */ 643std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(ASTModifiers mods) { 644 Token name; 645 if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) { 646 return nullptr; 647 } 648 if (peek().fKind != Token::LBRACE) { 649 // we only get into interfaceBlock if we found a top-level identifier which was not a type. 650 // 99% of the time, the user was not actually intending to create an interface block, so 651 // it's better to report it as an unknown type 652 this->error(name.fPosition, "no type named '" + name.fText + "'"); 653 return nullptr; 654 } 655 this->nextToken(); 656 std::vector<std::unique_ptr<ASTVarDeclarations>> decls; 657 while (this->peek().fKind != Token::RBRACE) { 658 std::unique_ptr<ASTVarDeclarations> decl = this->varDeclarations(); 659 if (!decl) { 660 return nullptr; 661 } 662 decls.push_back(std::move(decl)); 663 } 664 this->nextToken(); 665 std::string valueName; 666 if (this->peek().fKind == Token::IDENTIFIER) { 667 valueName = this->nextToken().fText; 668 } 669 this->expect(Token::SEMICOLON, "';'"); 670 return std::unique_ptr<ASTDeclaration>(new ASTInterfaceBlock(name.fPosition, mods, 671 name.fText, std::move(valueName), 672 std::move(decls))); 673} 674 675/* IF LPAREN expression RPAREN statement (ELSE statement)? */ 676std::unique_ptr<ASTIfStatement> Parser::ifStatement() { 677 Token start; 678 if (!this->expect(Token::IF, "'if'", &start)) { 679 return nullptr; 680 } 681 if (!this->expect(Token::LPAREN, "'('")) { 682 return nullptr; 683 } 684 std::unique_ptr<ASTExpression> test(this->expression()); 685 if (!test) { 686 return nullptr; 687 } 688 if (!this->expect(Token::RPAREN, "')'")) { 689 return nullptr; 690 } 691 std::unique_ptr<ASTStatement> ifTrue(this->statement()); 692 if (!ifTrue) { 693 return nullptr; 694 } 695 std::unique_ptr<ASTStatement> ifFalse; 696 if (this->peek().fKind == Token::ELSE) { 697 this->nextToken(); 698 ifFalse = this->statement(); 699 if (!ifFalse) { 700 return nullptr; 701 } 702 } 703 return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fPosition, std::move(test), 704 std::move(ifTrue), 705 std::move(ifFalse))); 706} 707 708/* DO statement WHILE LPAREN expression RPAREN SEMICOLON */ 709std::unique_ptr<ASTDoStatement> Parser::doStatement() { 710 Token start; 711 if (!this->expect(Token::DO, "'do'", &start)) { 712 return nullptr; 713 } 714 std::unique_ptr<ASTStatement> statement(this->statement()); 715 if (!statement) { 716 return nullptr; 717 } 718 if (!this->expect(Token::WHILE, "'while'")) { 719 return nullptr; 720 } 721 if (!this->expect(Token::LPAREN, "'('")) { 722 return nullptr; 723 } 724 std::unique_ptr<ASTExpression> test(this->expression()); 725 if (!test) { 726 return nullptr; 727 } 728 if (!this->expect(Token::RPAREN, "')'")) { 729 return nullptr; 730 } 731 if (!this->expect(Token::SEMICOLON, "';'")) { 732 return nullptr; 733 } 734 return std::unique_ptr<ASTDoStatement>(new ASTDoStatement(start.fPosition, 735 std::move(statement), 736 std::move(test))); 737} 738 739/* WHILE LPAREN expression RPAREN STATEMENT */ 740std::unique_ptr<ASTWhileStatement> Parser::whileStatement() { 741 Token start; 742 if (!this->expect(Token::WHILE, "'while'", &start)) { 743 return nullptr; 744 } 745 if (!this->expect(Token::LPAREN, "'('")) { 746 return nullptr; 747 } 748 std::unique_ptr<ASTExpression> test(this->expression()); 749 if (!test) { 750 return nullptr; 751 } 752 if (!this->expect(Token::RPAREN, "')'")) { 753 return nullptr; 754 } 755 std::unique_ptr<ASTStatement> statement(this->statement()); 756 if (!statement) { 757 return nullptr; 758 } 759 return std::unique_ptr<ASTWhileStatement>(new ASTWhileStatement(start.fPosition, 760 std::move(test), 761 std::move(statement))); 762} 763 764/* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN 765 STATEMENT */ 766std::unique_ptr<ASTForStatement> Parser::forStatement() { 767 Token start; 768 if (!this->expect(Token::FOR, "'for'", &start)) { 769 return nullptr; 770 } 771 if (!this->expect(Token::LPAREN, "'('")) { 772 return nullptr; 773 } 774 std::unique_ptr<ASTStatement> initializer; 775 Token nextToken = this->peek(); 776 switch (nextToken.fKind) { 777 case Token::SEMICOLON: 778 break; 779 case Token::CONST: 780 initializer = std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement( 781 this->varDeclarations())); 782 break; 783 case Token::IDENTIFIER: 784 if (this->isType(nextToken.fText)) { 785 initializer = std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement( 786 this->varDeclarations())); 787 break; 788 } 789 // fall through 790 default: 791 initializer = this->expressionStatement(); 792 } 793 std::unique_ptr<ASTExpression> test; 794 if (this->peek().fKind != Token::SEMICOLON) { 795 test = this->expression(); 796 if (!test) { 797 return nullptr; 798 } 799 } 800 if (!this->expect(Token::SEMICOLON, "';'")) { 801 return nullptr; 802 } 803 std::unique_ptr<ASTExpression> next; 804 if (this->peek().fKind != Token::SEMICOLON) { 805 next = this->expression(); 806 if (!next) { 807 return nullptr; 808 } 809 } 810 if (!this->expect(Token::RPAREN, "')'")) { 811 return nullptr; 812 } 813 std::unique_ptr<ASTStatement> statement(this->statement()); 814 if (!statement) { 815 return nullptr; 816 } 817 return std::unique_ptr<ASTForStatement>(new ASTForStatement(start.fPosition, 818 std::move(initializer), 819 std::move(test), std::move(next), 820 std::move(statement))); 821} 822 823/* RETURN expression? SEMICOLON */ 824std::unique_ptr<ASTReturnStatement> Parser::returnStatement() { 825 Token start; 826 if (!this->expect(Token::RETURN, "'return'", &start)) { 827 return nullptr; 828 } 829 std::unique_ptr<ASTExpression> expression; 830 if (this->peek().fKind != Token::SEMICOLON) { 831 expression = this->expression(); 832 if (!expression) { 833 return nullptr; 834 } 835 } 836 if (!this->expect(Token::SEMICOLON, "';'")) { 837 return nullptr; 838 } 839 return std::unique_ptr<ASTReturnStatement>(new ASTReturnStatement(start.fPosition, 840 std::move(expression))); 841} 842 843/* BREAK SEMICOLON */ 844std::unique_ptr<ASTBreakStatement> Parser::breakStatement() { 845 Token start; 846 if (!this->expect(Token::BREAK, "'break'", &start)) { 847 return nullptr; 848 } 849 if (!this->expect(Token::SEMICOLON, "';'")) { 850 return nullptr; 851 } 852 return std::unique_ptr<ASTBreakStatement>(new ASTBreakStatement(start.fPosition)); 853} 854 855/* CONTINUE SEMICOLON */ 856std::unique_ptr<ASTContinueStatement> Parser::continueStatement() { 857 Token start; 858 if (!this->expect(Token::CONTINUE, "'continue'", &start)) { 859 return nullptr; 860 } 861 if (!this->expect(Token::SEMICOLON, "';'")) { 862 return nullptr; 863 } 864 return std::unique_ptr<ASTContinueStatement>(new ASTContinueStatement(start.fPosition)); 865} 866 867/* DISCARD SEMICOLON */ 868std::unique_ptr<ASTDiscardStatement> Parser::discardStatement() { 869 Token start; 870 if (!this->expect(Token::DISCARD, "'continue'", &start)) { 871 return nullptr; 872 } 873 if (!this->expect(Token::SEMICOLON, "';'")) { 874 return nullptr; 875 } 876 return std::unique_ptr<ASTDiscardStatement>(new ASTDiscardStatement(start.fPosition)); 877} 878 879/* LBRACE statement* RBRACE */ 880std::unique_ptr<ASTBlock> Parser::block() { 881 Token start; 882 if (!this->expect(Token::LBRACE, "'{'", &start)) { 883 return nullptr; 884 } 885 std::vector<std::unique_ptr<ASTStatement>> statements; 886 for (;;) { 887 switch (this->peek().fKind) { 888 case Token::RBRACE: 889 this->nextToken(); 890 return std::unique_ptr<ASTBlock>(new ASTBlock(start.fPosition, 891 std::move(statements))); 892 case Token::END_OF_FILE: 893 this->error(this->peek().fPosition, "expected '}', but found end of file"); 894 return nullptr; 895 default: { 896 std::unique_ptr<ASTStatement> statement = this->statement(); 897 if (!statement) { 898 return nullptr; 899 } 900 statements.push_back(std::move(statement)); 901 } 902 } 903 } 904} 905 906/* expression SEMICOLON */ 907std::unique_ptr<ASTExpressionStatement> Parser::expressionStatement() { 908 std::unique_ptr<ASTExpression> expr = this->expression(); 909 if (expr) { 910 if (this->expect(Token::SEMICOLON, "';'")) { 911 ASTExpressionStatement* result = new ASTExpressionStatement(std::move(expr)); 912 return std::unique_ptr<ASTExpressionStatement>(result); 913 } 914 } 915 return nullptr; 916} 917 918/* assignmentExpression */ 919std::unique_ptr<ASTExpression> Parser::expression() { 920 return this->assignmentExpression(); 921} 922 923/* ternaryExpression ((EQEQ | STAREQ | SLASHEQ | PERCENTEQ | PLUSEQ | MINUSEQ | SHLEQ | SHREQ | 924 BITWISEANDEQ | BITWISEXOREQ | BITWISEOREQ | LOGICALANDEQ | LOGICALXOREQ | LOGICALOREQ) 925 assignmentExpression)* 926 */ 927std::unique_ptr<ASTExpression> Parser::assignmentExpression() { 928 std::unique_ptr<ASTExpression> result = this->ternaryExpression(); 929 if (!result) { 930 return nullptr; 931 } 932 for (;;) { 933 switch (this->peek().fKind) { 934 case Token::EQ: // fall through 935 case Token::STAREQ: // fall through 936 case Token::SLASHEQ: // fall through 937 case Token::PERCENTEQ: // fall through 938 case Token::PLUSEQ: // fall through 939 case Token::MINUSEQ: // fall through 940 case Token::SHLEQ: // fall through 941 case Token::SHREQ: // fall through 942 case Token::BITWISEANDEQ: // fall through 943 case Token::BITWISEXOREQ: // fall through 944 case Token::BITWISEOREQ: // fall through 945 case Token::LOGICALANDEQ: // fall through 946 case Token::LOGICALXOREQ: // fall through 947 case Token::LOGICALOREQ: { 948 Token t = this->nextToken(); 949 std::unique_ptr<ASTExpression> right = this->assignmentExpression(); 950 if (!right) { 951 return nullptr; 952 } 953 result = std::unique_ptr<ASTExpression>(new ASTBinaryExpression(std::move(result), 954 t, 955 std::move(right))); 956 } 957 default: 958 return result; 959 } 960 } 961} 962 963/* logicalOrExpression ('?' expression ':' assignmentExpression)? */ 964std::unique_ptr<ASTExpression> Parser::ternaryExpression() { 965 std::unique_ptr<ASTExpression> result = this->logicalOrExpression(); 966 if (!result) { 967 return nullptr; 968 } 969 if (this->peek().fKind == Token::QUESTION) { 970 Token question = this->nextToken(); 971 std::unique_ptr<ASTExpression> trueExpr = this->expression(); 972 if (!trueExpr) { 973 return nullptr; 974 } 975 if (this->expect(Token::COLON, "':'")) { 976 std::unique_ptr<ASTExpression> falseExpr = this->assignmentExpression(); 977 return std::unique_ptr<ASTExpression>(new ASTTernaryExpression(std::move(result), 978 std::move(trueExpr), 979 std::move(falseExpr))); 980 } 981 return nullptr; 982 } 983 return result; 984} 985 986/* logicalXorExpression (LOGICALOR logicalXorExpression)* */ 987std::unique_ptr<ASTExpression> Parser::logicalOrExpression() { 988 std::unique_ptr<ASTExpression> result = this->logicalXorExpression(); 989 if (!result) { 990 return nullptr; 991 } 992 while (this->peek().fKind == Token::LOGICALOR) { 993 Token t = this->nextToken(); 994 std::unique_ptr<ASTExpression> right = this->logicalXorExpression(); 995 if (!right) { 996 return nullptr; 997 } 998 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right))); 999 } 1000 return result; 1001} 1002 1003/* logicalAndExpression (LOGICALXOR logicalAndExpression)* */ 1004std::unique_ptr<ASTExpression> Parser::logicalXorExpression() { 1005 std::unique_ptr<ASTExpression> result = this->logicalAndExpression(); 1006 if (!result) { 1007 return nullptr; 1008 } 1009 while (this->peek().fKind == Token::LOGICALXOR) { 1010 Token t = this->nextToken(); 1011 std::unique_ptr<ASTExpression> right = this->logicalAndExpression(); 1012 if (!right) { 1013 return nullptr; 1014 } 1015 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right))); 1016 } 1017 return result; 1018} 1019 1020/* bitwiseOrExpression (LOGICALAND bitwiseOrExpression)* */ 1021std::unique_ptr<ASTExpression> Parser::logicalAndExpression() { 1022 std::unique_ptr<ASTExpression> result = this->bitwiseOrExpression(); 1023 if (!result) { 1024 return nullptr; 1025 } 1026 while (this->peek().fKind == Token::LOGICALAND) { 1027 Token t = this->nextToken(); 1028 std::unique_ptr<ASTExpression> right = this->bitwiseOrExpression(); 1029 if (!right) { 1030 return nullptr; 1031 } 1032 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right))); 1033 } 1034 return result; 1035} 1036 1037/* bitwiseXorExpression (BITWISEOR bitwiseXorExpression)* */ 1038std::unique_ptr<ASTExpression> Parser::bitwiseOrExpression() { 1039 std::unique_ptr<ASTExpression> result = this->bitwiseXorExpression(); 1040 if (!result) { 1041 return nullptr; 1042 } 1043 while (this->peek().fKind == Token::BITWISEOR) { 1044 Token t = this->nextToken(); 1045 std::unique_ptr<ASTExpression> right = this->bitwiseXorExpression(); 1046 if (!right) { 1047 return nullptr; 1048 } 1049 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right))); 1050 } 1051 return result; 1052} 1053 1054/* bitwiseAndExpression (BITWISEXOR bitwiseAndExpression)* */ 1055std::unique_ptr<ASTExpression> Parser::bitwiseXorExpression() { 1056 std::unique_ptr<ASTExpression> result = this->bitwiseAndExpression(); 1057 if (!result) { 1058 return nullptr; 1059 } 1060 while (this->peek().fKind == Token::BITWISEXOR) { 1061 Token t = this->nextToken(); 1062 std::unique_ptr<ASTExpression> right = this->bitwiseAndExpression(); 1063 if (!right) { 1064 return nullptr; 1065 } 1066 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right))); 1067 } 1068 return result; 1069} 1070 1071/* equalityExpression (BITWISEAND equalityExpression)* */ 1072std::unique_ptr<ASTExpression> Parser::bitwiseAndExpression() { 1073 std::unique_ptr<ASTExpression> result = this->equalityExpression(); 1074 if (!result) { 1075 return nullptr; 1076 } 1077 while (this->peek().fKind == Token::BITWISEAND) { 1078 Token t = this->nextToken(); 1079 std::unique_ptr<ASTExpression> right = this->equalityExpression(); 1080 if (!right) { 1081 return nullptr; 1082 } 1083 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right))); 1084 } 1085 return result; 1086} 1087 1088/* relationalExpression ((EQEQ | NEQ) relationalExpression)* */ 1089std::unique_ptr<ASTExpression> Parser::equalityExpression() { 1090 std::unique_ptr<ASTExpression> result = this->relationalExpression(); 1091 if (!result) { 1092 return nullptr; 1093 } 1094 for (;;) { 1095 switch (this->peek().fKind) { 1096 case Token::EQEQ: // fall through 1097 case Token::NEQ: { 1098 Token t = this->nextToken(); 1099 std::unique_ptr<ASTExpression> right = this->relationalExpression(); 1100 if (!right) { 1101 return nullptr; 1102 } 1103 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right))); 1104 break; 1105 } 1106 default: 1107 return result; 1108 } 1109 } 1110} 1111 1112/* shiftExpression ((LT | GT | LTEQ | GTEQ) shiftExpression)* */ 1113std::unique_ptr<ASTExpression> Parser::relationalExpression() { 1114 std::unique_ptr<ASTExpression> result = this->shiftExpression(); 1115 if (!result) { 1116 return nullptr; 1117 } 1118 for (;;) { 1119 switch (this->peek().fKind) { 1120 case Token::LT: // fall through 1121 case Token::GT: // fall through 1122 case Token::LTEQ: // fall through 1123 case Token::GTEQ: { 1124 Token t = this->nextToken(); 1125 std::unique_ptr<ASTExpression> right = this->shiftExpression(); 1126 if (!right) { 1127 return nullptr; 1128 } 1129 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right))); 1130 break; 1131 } 1132 default: 1133 return result; 1134 } 1135 } 1136} 1137 1138/* additiveExpression ((SHL | SHR) additiveExpression)* */ 1139std::unique_ptr<ASTExpression> Parser::shiftExpression() { 1140 std::unique_ptr<ASTExpression> result = this->additiveExpression(); 1141 if (!result) { 1142 return nullptr; 1143 } 1144 for (;;) { 1145 switch (this->peek().fKind) { 1146 case Token::SHL: // fall through 1147 case Token::SHR: { 1148 Token t = this->nextToken(); 1149 std::unique_ptr<ASTExpression> right = this->additiveExpression(); 1150 if (!right) { 1151 return nullptr; 1152 } 1153 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right))); 1154 break; 1155 } 1156 default: 1157 return result; 1158 } 1159 } 1160} 1161 1162/* multiplicativeExpression ((PLUS | MINUS) multiplicativeExpression)* */ 1163std::unique_ptr<ASTExpression> Parser::additiveExpression() { 1164 std::unique_ptr<ASTExpression> result = this->multiplicativeExpression(); 1165 if (!result) { 1166 return nullptr; 1167 } 1168 for (;;) { 1169 switch (this->peek().fKind) { 1170 case Token::PLUS: // fall through 1171 case Token::MINUS: { 1172 Token t = this->nextToken(); 1173 std::unique_ptr<ASTExpression> right = this->multiplicativeExpression(); 1174 if (!right) { 1175 return nullptr; 1176 } 1177 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right))); 1178 break; 1179 } 1180 default: 1181 return result; 1182 } 1183 } 1184} 1185 1186/* unaryExpression ((STAR | SLASH | PERCENT) unaryExpression)* */ 1187std::unique_ptr<ASTExpression> Parser::multiplicativeExpression() { 1188 std::unique_ptr<ASTExpression> result = this->unaryExpression(); 1189 if (!result) { 1190 return nullptr; 1191 } 1192 for (;;) { 1193 switch (this->peek().fKind) { 1194 case Token::STAR: // fall through 1195 case Token::SLASH: // fall through 1196 case Token::PERCENT: { 1197 Token t = this->nextToken(); 1198 std::unique_ptr<ASTExpression> right = this->unaryExpression(); 1199 if (!right) { 1200 return nullptr; 1201 } 1202 result.reset(new ASTBinaryExpression(std::move(result), t, std::move(right))); 1203 break; 1204 } 1205 default: 1206 return result; 1207 } 1208 } 1209} 1210 1211/* postfixExpression | (PLUS | MINUS | NOT | PLUSPLUS | MINUSMINUS) unaryExpression */ 1212std::unique_ptr<ASTExpression> Parser::unaryExpression() { 1213 switch (this->peek().fKind) { 1214 case Token::PLUS: // fall through 1215 case Token::MINUS: // fall through 1216 case Token::NOT: // fall through 1217 case Token::PLUSPLUS: // fall through 1218 case Token::MINUSMINUS: { 1219 Token t = this->nextToken(); 1220 std::unique_ptr<ASTExpression> expr = this->unaryExpression(); 1221 if (!expr) { 1222 return nullptr; 1223 } 1224 return std::unique_ptr<ASTExpression>(new ASTPrefixExpression(t, std::move(expr))); 1225 } 1226 default: 1227 return this->postfixExpression(); 1228 } 1229} 1230 1231/* term suffix* */ 1232std::unique_ptr<ASTExpression> Parser::postfixExpression() { 1233 std::unique_ptr<ASTExpression> result = this->term(); 1234 if (!result) { 1235 return nullptr; 1236 } 1237 for (;;) { 1238 switch (this->peek().fKind) { 1239 case Token::LBRACKET: // fall through 1240 case Token::DOT: // fall through 1241 case Token::LPAREN: // fall through 1242 case Token::PLUSPLUS: // fall through 1243 case Token::MINUSMINUS: { 1244 std::unique_ptr<ASTSuffix> s = this->suffix(); 1245 if (!s) { 1246 return nullptr; 1247 } 1248 result.reset(new ASTSuffixExpression(std::move(result), std::move(s))); 1249 break; 1250 } 1251 default: 1252 return result; 1253 } 1254 } 1255} 1256 1257/* LBRACKET expression RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN | 1258 PLUSPLUS | MINUSMINUS */ 1259std::unique_ptr<ASTSuffix> Parser::suffix() { 1260 Token next = this->nextToken(); 1261 switch (next.fKind) { 1262 case Token::LBRACKET: { 1263 std::unique_ptr<ASTExpression> e = this->expression(); 1264 if (!e) { 1265 return nullptr; 1266 } 1267 this->expect(Token::RBRACKET, "']' to complete array access expression"); 1268 return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(std::move(e))); 1269 } 1270 case Token::DOT: { 1271 Position pos = this->peek().fPosition; 1272 std::string text; 1273 if (this->identifier(&text)) { 1274 return std::unique_ptr<ASTSuffix>(new ASTFieldSuffix(pos, std::move(text))); 1275 } 1276 return nullptr; 1277 } 1278 case Token::LPAREN: { 1279 std::vector<std::unique_ptr<ASTExpression>> parameters; 1280 if (this->peek().fKind != Token::RPAREN) { 1281 for (;;) { 1282 std::unique_ptr<ASTExpression> expr = this->expression(); 1283 if (!expr) { 1284 return nullptr; 1285 } 1286 parameters.push_back(std::move(expr)); 1287 if (this->peek().fKind != Token::COMMA) { 1288 break; 1289 } 1290 this->nextToken(); 1291 } 1292 } 1293 this->expect(Token::RPAREN, "')' to complete function parameters"); 1294 return std::unique_ptr<ASTSuffix>(new ASTCallSuffix(next.fPosition, 1295 std::move(parameters))); 1296 } 1297 case Token::PLUSPLUS: 1298 return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition, 1299 ASTSuffix::kPostIncrement_Kind)); 1300 case Token::MINUSMINUS: 1301 return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition, 1302 ASTSuffix::kPostDecrement_Kind)); 1303 default: { 1304 this->error(next.fPosition, "expected expression suffix, but found '" + next.fText + 1305 "'\n"); 1306 return nullptr; 1307 } 1308 } 1309} 1310 1311/* IDENTIFIER | intLiteral | floatLiteral | boolLiteral | '(' expression ')' */ 1312std::unique_ptr<ASTExpression> Parser::term() { 1313 std::unique_ptr<ASTExpression> result; 1314 Token t = this->peek(); 1315 switch (t.fKind) { 1316 case Token::IDENTIFIER: { 1317 std::string text; 1318 if (this->identifier(&text)) { 1319 result.reset(new ASTIdentifier(t.fPosition, std::move(text))); 1320 } 1321 break; 1322 } 1323 case Token::INT_LITERAL: { 1324 int64_t i; 1325 if (this->intLiteral(&i)) { 1326 result.reset(new ASTIntLiteral(t.fPosition, i)); 1327 } 1328 break; 1329 } 1330 case Token::FLOAT_LITERAL: { 1331 double f; 1332 if (this->floatLiteral(&f)) { 1333 result.reset(new ASTFloatLiteral(t.fPosition, f)); 1334 } 1335 break; 1336 } 1337 case Token::TRUE_LITERAL: // fall through 1338 case Token::FALSE_LITERAL: { 1339 bool b; 1340 if (this->boolLiteral(&b)) { 1341 result.reset(new ASTBoolLiteral(t.fPosition, b)); 1342 } 1343 break; 1344 } 1345 case Token::LPAREN: { 1346 this->nextToken(); 1347 result = this->expression(); 1348 if (result) { 1349 this->expect(Token::RPAREN, "')' to complete expression"); 1350 } 1351 break; 1352 } 1353 default: 1354 this->nextToken(); 1355 this->error(t.fPosition, "expected expression, but found '" + t.fText + "'\n"); 1356 result = nullptr; 1357 } 1358 return result; 1359} 1360 1361/* INT_LITERAL */ 1362bool Parser::intLiteral(int64_t* dest) { 1363 Token t; 1364 if (this->expect(Token::INT_LITERAL, "integer literal", &t)) { 1365 *dest = SkSL::stol(t.fText); 1366 return true; 1367 } 1368 return false; 1369} 1370 1371/* FLOAT_LITERAL */ 1372bool Parser::floatLiteral(double* dest) { 1373 Token t; 1374 if (this->expect(Token::FLOAT_LITERAL, "float literal", &t)) { 1375 *dest = SkSL::stod(t.fText); 1376 return true; 1377 } 1378 return false; 1379} 1380 1381/* TRUE_LITERAL | FALSE_LITERAL */ 1382bool Parser::boolLiteral(bool* dest) { 1383 Token t = this->nextToken(); 1384 switch (t.fKind) { 1385 case Token::TRUE_LITERAL: 1386 *dest = true; 1387 return true; 1388 case Token::FALSE_LITERAL: 1389 *dest = false; 1390 return true; 1391 default: 1392 this->error(t.fPosition, "expected 'true' or 'false', but found '" + t.fText + "'\n"); 1393 return false; 1394 } 1395} 1396 1397/* IDENTIFIER */ 1398bool Parser::identifier(std::string* dest) { 1399 Token t; 1400 if (this->expect(Token::IDENTIFIER, "identifier", &t)) { 1401 *dest = t.fText; 1402 return true; 1403 } 1404 return false; 1405} 1406 1407} // namespace 1408