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