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