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