1/** 2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "parser/parserFlags.h" 17#include "parser/parserStatusContext.h" 18#include "util/helpers.h" 19#include "ir/astNode.h" 20#include "ir/base/catchClause.h" 21#include "ir/base/classDefinition.h" 22#include "ir/base/scriptFunction.h" 23#include "ir/expression.h" 24#include "ir/expressions/arrayExpression.h" 25#include "ir/expressions/binaryExpression.h" 26#include "ir/expressions/conditionalExpression.h" 27#include "ir/expressions/literals/stringLiteral.h" 28#include "ir/expressions/objectExpression.h" 29#include "ir/expressions/sequenceExpression.h" 30#include "ir/module/exportAllDeclaration.h" 31#include "ir/module/exportDefaultDeclaration.h" 32#include "ir/module/exportNamedDeclaration.h" 33#include "ir/module/exportSpecifier.h" 34#include "ir/module/importDeclaration.h" 35#include "ir/module/importDefaultSpecifier.h" 36#include "ir/module/importNamespaceSpecifier.h" 37#include "ir/module/importSpecifier.h" 38#include "ir/statements/assertStatement.h" 39#include "ir/statements/blockStatement.h" 40#include "ir/statements/breakStatement.h" 41#include "ir/statements/classDeclaration.h" 42#include "ir/statements/continueStatement.h" 43#include "ir/statements/debuggerStatement.h" 44#include "ir/statements/doWhileStatement.h" 45#include "ir/statements/emptyStatement.h" 46#include "ir/statements/expressionStatement.h" 47#include "ir/statements/forInStatement.h" 48#include "ir/statements/forOfStatement.h" 49#include "ir/statements/forUpdateStatement.h" 50#include "ir/statements/functionDeclaration.h" 51#include "ir/statements/ifStatement.h" 52#include "ir/statements/labelledStatement.h" 53#include "ir/statements/returnStatement.h" 54#include "ir/statements/switchCaseStatement.h" 55#include "ir/statements/switchStatement.h" 56#include "ir/statements/throwStatement.h" 57#include "ir/statements/tryStatement.h" 58#include "ir/statements/variableDeclaration.h" 59#include "ir/statements/variableDeclarator.h" 60#include "ir/statements/whileStatement.h" 61#include "ir/ets/etsStructDeclaration.h" 62#include "lexer/lexer.h" 63#include "lexer/token/letters.h" 64#include "lexer/token/sourceLocation.h" 65#include "util/ustring.h" 66 67#include "parserImpl.h" 68 69namespace ark::es2panda::parser { 70 71using namespace std::literals::string_literals; 72 73// NOLINTNEXTLINE(google-default-arguments) 74ir::Statement *ParserImpl::ParseStatement(StatementParsingFlags flags) 75{ 76 switch (lexer_->GetToken().Type()) { 77 case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { 78 return ParseBlockStatement(); 79 } 80 case lexer::TokenType::PUNCTUATOR_SEMI_COLON: { 81 return ParseEmptyStatement(); 82 } 83 case lexer::TokenType::KEYW_ASSERT: { 84 return ParseAssertStatement(); 85 } 86 case lexer::TokenType::KEYW_EXPORT: { 87 return ParseExportDeclaration(flags); 88 } 89 case lexer::TokenType::KEYW_IMPORT: { 90 return ParseImportDeclaration(flags); 91 } 92 case lexer::TokenType::KEYW_FUNCTION: { 93 return ParseFunctionStatement(flags); 94 } 95 case lexer::TokenType::KEYW_CLASS: { 96 return ParseClassStatement(flags, ir::ClassDefinitionModifiers::NONE); 97 } 98 case lexer::TokenType::KEYW_VAR: { 99 return ParseVarStatement(); 100 } 101 case lexer::TokenType::KEYW_LET: { 102 return ParseLetStatement(flags); 103 } 104 case lexer::TokenType::KEYW_CONST: { 105 return ParseConstStatement(flags); 106 } 107 case lexer::TokenType::KEYW_IF: { 108 return ParseIfStatement(); 109 } 110 case lexer::TokenType::KEYW_DO: { 111 return ParseDoWhileStatement(); 112 } 113 case lexer::TokenType::KEYW_FOR: { 114 return ParseForStatement(); 115 } 116 case lexer::TokenType::KEYW_TRY: { 117 return ParseTryStatement(); 118 } 119 case lexer::TokenType::KEYW_WHILE: { 120 return ParseWhileStatement(); 121 } 122 case lexer::TokenType::KEYW_BREAK: { 123 return ParseBreakStatement(); 124 } 125 case lexer::TokenType::KEYW_CONTINUE: { 126 return ParseContinueStatement(); 127 } 128 case lexer::TokenType::KEYW_THROW: { 129 return ParseThrowStatement(); 130 } 131 case lexer::TokenType::KEYW_RETURN: { 132 return ParseReturnStatement(); 133 } 134 case lexer::TokenType::KEYW_SWITCH: { 135 return ParseSwitchStatement(); 136 } 137 case lexer::TokenType::KEYW_DEBUGGER: { 138 return ParseDebuggerStatement(); 139 } 140 case lexer::TokenType::LITERAL_IDENT: { 141 if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STRUCT) { 142 return ParseStructStatement(flags, ir::ClassDefinitionModifiers::NONE); 143 } 144 145 if (lexer_->Lookahead() == lexer::LEX_CHAR_COLON) { 146 const auto pos = lexer_->Save(); 147 lexer_->NextToken(); 148 return ParseLabelledStatement(pos); 149 } 150 151 return ParsePotentialExpressionStatement(flags); 152 } 153 case lexer::TokenType::KEYW_WITH: { 154 ThrowSyntaxError("'With' is deprecated and not supported any more."); 155 } 156 case lexer::TokenType::KEYW_ENUM: { 157 return ParseEnumDeclaration(); 158 } 159 case lexer::TokenType::KEYW_INTERFACE: { 160 return ParseInterfaceDeclaration(false); 161 } 162 case lexer::TokenType::PUNCTUATOR_FORMAT: { 163 if (lexer_->Lookahead() == static_cast<char32_t>(STATEMENT_FORMAT_NODE)) { 164 return ParseStatementFormatPlaceholder(); 165 } 166 [[fallthrough]]; 167 } 168 default: { 169 return ParseExpressionStatement(flags); 170 } 171 } 172} 173 174ir::Statement *ParserImpl::ParseVarStatement() 175{ 176 auto *variableDecl = ParseVariableDeclaration(VariableParsingFlags::VAR); 177 ConsumeSemicolon(variableDecl); 178 return variableDecl; 179} 180 181ir::Statement *ParserImpl::ParseLetStatement(StatementParsingFlags flags) 182{ 183 if ((flags & StatementParsingFlags::ALLOW_LEXICAL) == 0) { 184 ThrowSyntaxError("Lexical declaration is not allowed in single statement context"); 185 } 186 187 auto *variableDecl = ParseVariableDeclaration(VariableParsingFlags::LET); 188 ConsumeSemicolon(variableDecl); 189 return variableDecl; 190} 191 192ir::Statement *ParserImpl::ParseConstStatement(StatementParsingFlags flags) 193{ 194 if ((flags & StatementParsingFlags::ALLOW_LEXICAL) == 0) { 195 ThrowSyntaxError("Lexical declaration is not allowed in single statement context"); 196 } 197 198 lexer::SourcePosition constVarStar = lexer_->GetToken().Start(); 199 lexer_->NextToken(); 200 201 auto *variableDecl = ParseVariableDeclaration(VariableParsingFlags::CONST | VariableParsingFlags::NO_SKIP_VAR_KIND); 202 variableDecl->SetStart(constVarStar); 203 ConsumeSemicolon(variableDecl); 204 205 return variableDecl; 206} 207 208ir::EmptyStatement *ParserImpl::ParseEmptyStatement() 209{ 210 auto *empty = AllocNode<ir::EmptyStatement>(); 211 empty->SetRange(lexer_->GetToken().Loc()); 212 lexer_->NextToken(); 213 return empty; 214} 215 216ir::DebuggerStatement *ParserImpl::ParseDebuggerStatement() 217{ 218 auto *debuggerNode = AllocNode<ir::DebuggerStatement>(); 219 debuggerNode->SetRange(lexer_->GetToken().Loc()); 220 lexer_->NextToken(); 221 ConsumeSemicolon(debuggerNode); 222 return debuggerNode; 223} 224 225ir::Statement *ParserImpl::ParseFunctionStatement(StatementParsingFlags flags) 226{ 227 CheckFunctionDeclaration(flags); 228 229 if ((flags & StatementParsingFlags::STMT_LEXICAL_SCOPE_NEEDED) == 0) { 230 return ParseFunctionDeclaration(false, ParserStatus::NO_OPTS); 231 } 232 233 auto *funcDecl = ParseFunctionDeclaration(false, ParserStatus::NO_OPTS); 234 if (funcDecl == nullptr) { // Error processing. 235 return nullptr; 236 } 237 238 ArenaVector<ir::Statement *> stmts(Allocator()->Adapter()); 239 stmts.push_back(funcDecl); 240 241 auto *localBlockStmt = AllocNode<ir::BlockStatement>(Allocator(), std::move(stmts)); 242 localBlockStmt->SetRange(funcDecl->Range()); 243 244 return funcDecl; 245} 246 247ir::Statement *ParserImpl::ParsePotentialExpressionStatement(StatementParsingFlags flags) 248{ 249 return ParseExpressionStatement(flags); 250} 251 252// NOLINTNEXTLINE(google-default-arguments) 253ir::ETSStructDeclaration *ParserImpl::ParseStructStatement([[maybe_unused]] StatementParsingFlags flags, 254 [[maybe_unused]] ir::ClassDefinitionModifiers modifiers, 255 [[maybe_unused]] ir::ModifierFlags modFlags) 256{ 257 ThrowSyntaxError("Illegal start of expression", Lexer()->GetToken().Start()); 258} 259 260// NOLINTNEXTLINE(google-default-arguments) 261ir::ClassDeclaration *ParserImpl::ParseClassStatement(StatementParsingFlags flags, 262 ir::ClassDefinitionModifiers modifiers, 263 ir::ModifierFlags modFlags) 264{ 265 if ((flags & StatementParsingFlags::ALLOW_LEXICAL) == 0) { 266 ThrowSyntaxError("Lexical declaration is not allowed in single statement context"); 267 } 268 269 return ParseClassDeclaration(modifiers, modFlags); 270} 271 272ir::ETSStructDeclaration *ParserImpl::ParseStructDeclaration(ir::ClassDefinitionModifiers modifiers, 273 ir::ModifierFlags flags) 274{ 275 const lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 276 modifiers |= ir::ClassDefinitionModifiers::DECLARATION; 277 if (IsExternal()) { 278 modifiers |= ir::ClassDefinitionModifiers::FROM_EXTERNAL; 279 } 280 281 if ((flags & ir::ModifierFlags::ABSTRACT) != 0U) { 282 ThrowSyntaxError("struct declaration is not allowed to use 'abstract' modifiers."); 283 } 284 285 ir::ClassDefinition *classDefinition = ParseClassDefinition(modifiers, flags); 286 287 if ((classDefinition->Modifiers() & ir::ClassDefinitionModifiers::HAS_SUPER) != 0U) { 288 ThrowSyntaxError("struct declaration cannot extends form other class"); 289 } 290 291 lexer::SourcePosition endLoc = classDefinition->End(); 292 auto *structDecl = AllocNode<ir::ETSStructDeclaration>(classDefinition, Allocator()); 293 structDecl->SetRange({startLoc, endLoc}); 294 return structDecl; 295} 296 297ir::ClassDeclaration *ParserImpl::ParseClassDeclaration(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags) 298{ 299 const lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 300 modifiers |= ir::ClassDefinitionModifiers::DECLARATION; 301 if (IsExternal()) { 302 modifiers |= ir::ClassDefinitionModifiers::FROM_EXTERNAL; 303 } 304 305 ir::ClassDefinition *classDefinition = ParseClassDefinition(modifiers, flags); 306 307 lexer::SourcePosition endLoc = classDefinition->End(); 308 auto *classDecl = AllocNode<ir::ClassDeclaration>(classDefinition, Allocator()); 309 classDecl->SetRange({startLoc, endLoc}); 310 return classDecl; 311} 312 313void ParserImpl::CheckFunctionDeclaration(StatementParsingFlags flags) 314{ 315 if ((flags & StatementParsingFlags::LABELLED) != 0) { 316 ThrowSyntaxError( 317 "In strict mode code, functions can only be " 318 "declared at top level, inside a block, " 319 "or " 320 "as the body of an if statement"); 321 } 322 323 if ((flags & StatementParsingFlags::ALLOW_LEXICAL) == 0) { 324 if ((flags & (StatementParsingFlags::IF_ELSE | StatementParsingFlags::LABELLED)) == 0) { 325 ThrowSyntaxError("Lexical declaration is not allowed in single statement context"); 326 } 327 328 if (lexer_->Lookahead() == lexer::LEX_CHAR_ASTERISK) { 329 ThrowSyntaxError("Generators can only be declared at the top level or inside a block"); 330 } 331 } 332} 333 334void ParserImpl::ConsumeSemicolon(ir::Statement *statement) 335{ 336 auto tokenType = lexer_->GetToken().Type(); 337 if (tokenType == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 338 statement->SetEnd(lexer_->GetToken().End()); 339 lexer_->NextToken(); 340 return; 341 } 342 343 if (!lexer_->GetToken().NewLine() && tokenType != lexer::TokenType::EOS && 344 tokenType != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 345 LogSyntaxError({"Unexpected token '", TokenToString(tokenType), "'."}); 346 } 347} 348 349ArenaVector<ir::Statement *> ParserImpl::ParseStatementList(StatementParsingFlags flags) 350{ 351 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT && 352 lexer_->Lookahead() == static_cast<char32_t>(ARRAY_FORMAT_NODE)) { 353 return std::move(ParseStatementsArrayFormatPlaceholder()); 354 } 355 356 ArenaVector<ir::Statement *> statements(Allocator()->Adapter()); 357 ParseDirectivePrologue(&statements); 358 359 auto endType = 360 (flags & StatementParsingFlags::GLOBAL) != 0 ? lexer::TokenType::EOS : lexer::TokenType::PUNCTUATOR_RIGHT_BRACE; 361 362 while (lexer_->GetToken().Type() != endType) { 363 if (auto statement = ParseStatement(flags); statement != nullptr) { // Error processing. 364 statements.push_back(statement); 365 } 366 } 367 368 return statements; 369} 370 371bool ParserImpl::ParseDirective(ArenaVector<ir::Statement *> *statements) 372{ 373 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING); 374 375 const util::StringView &str = lexer_->GetToken().String(); 376 377 const auto status = static_cast<ParserStatus>( 378 context_.Status() & (ParserStatus::CONSTRUCTOR_FUNCTION | ParserStatus::HAS_COMPLEX_PARAM)); 379 if (status == ParserStatus::HAS_COMPLEX_PARAM && str.Is("use strict")) { 380 ThrowSyntaxError( 381 "Illegal 'use strict' directive in function with " 382 "non-simple parameter list"); 383 } 384 385 ir::Expression *exprNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 386 bool isDirective = exprNode->IsStringLiteral(); 387 388 auto *exprStatement = AllocNode<ir::ExpressionStatement>(exprNode); 389 exprStatement->SetRange(exprNode->Range()); 390 391 ConsumeSemicolon(exprStatement); 392 statements->push_back(exprStatement); 393 394 return isDirective; 395} 396 397void ParserImpl::ParseDirectivePrologue(ArenaVector<ir::Statement *> *statements) 398{ 399 while (true) { 400 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING || !ParseDirective(statements)) { 401 break; 402 } 403 } 404} 405 406ir::Statement *ParserImpl::ParseAssertStatement() 407{ 408 return nullptr; 409} 410 411void ParserImpl::ValidateLabeledStatement([[maybe_unused]] lexer::TokenType type) {} 412 413ir::BlockStatement *ParserImpl::ParseBlockStatement() 414{ 415 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE); 416 417 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 418 lexer_->NextToken(); 419 auto statements = ParseStatementList(); 420 421 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 422 ThrowSyntaxError("Expected a '}'"); 423 } 424 425 auto *blockNode = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements)); 426 blockNode->SetRange({startLoc, lexer_->GetToken().End()}); 427 428 lexer_->NextToken(); 429 return blockNode; 430} 431 432void ParserImpl::ThrowPossibleOutOfBoundaryJumpError([[maybe_unused]] bool allowBreak) {} 433 434void ParserImpl::ThrowIllegalBreakError() 435{ 436 ThrowSyntaxError("Illegal break statement"); 437} 438 439ir::BreakStatement *ParserImpl::ParseBreakStatement() 440{ 441 bool allowBreak = (context_.Status() & (ParserStatus::IN_ITERATION | ParserStatus::IN_SWITCH)) != 0; 442 443 ThrowPossibleOutOfBoundaryJumpError(allowBreak); 444 445 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 446 lexer_->NextToken(); 447 448 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON || 449 lexer_->GetToken().Type() == lexer::TokenType::EOS || lexer_->GetToken().NewLine() || 450 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 451 if (!allowBreak) { 452 ThrowIllegalBreakError(); 453 } 454 455 auto *breakStatement = AllocNode<ir::BreakStatement>(); 456 breakStatement->SetRange({startLoc, lexer_->GetToken().End()}); 457 458 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 459 lexer_->NextToken(); 460 } 461 462 return breakStatement; 463 } 464 465 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 466 ThrowSyntaxError("Unexpected token."); 467 } 468 469 const auto &label = lexer_->GetToken().Ident(); 470 if (!ValidateBreakLabel(label)) { 471 ThrowSyntaxError("Undefined label"); 472 } 473 474 auto *identNode = AllocNode<ir::Identifier>(label, Allocator()); 475 identNode->SetReference(); 476 identNode->SetRange(lexer_->GetToken().Loc()); 477 478 auto *breakStatement = AllocNode<ir::BreakStatement>(identNode); 479 breakStatement->SetRange({startLoc, lexer_->GetToken().End()}); 480 481 lexer_->NextToken(); 482 ConsumeSemicolon(breakStatement); 483 484 return breakStatement; 485} 486 487void ParserImpl::ThrowIllegalContinueError() 488{ 489 ThrowSyntaxError("Illegal continue statement"); 490} 491 492ir::ContinueStatement *ParserImpl::ParseContinueStatement() 493{ 494 ThrowPossibleOutOfBoundaryJumpError((context_.Status() & (ParserStatus::IN_ITERATION | ParserStatus::IN_SWITCH)) != 495 0U); 496 497 if ((context_.Status() & ParserStatus::IN_ITERATION) == 0) { 498 ThrowIllegalContinueError(); 499 } 500 501 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 502 lexer::SourcePosition endLoc = lexer_->GetToken().End(); 503 lexer_->NextToken(); 504 505 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 506 auto *continueStatement = AllocNode<ir::ContinueStatement>(); 507 continueStatement->SetRange({startLoc, lexer_->GetToken().End()}); 508 lexer_->NextToken(); 509 return continueStatement; 510 } 511 512 if (lexer_->GetToken().NewLine() || lexer_->GetToken().Type() == lexer::TokenType::EOS || 513 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 514 auto *continueStatement = AllocNode<ir::ContinueStatement>(); 515 continueStatement->SetRange({startLoc, endLoc}); 516 return continueStatement; 517 } 518 519 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 520 ThrowSyntaxError("Unexpected token."); 521 } 522 523 const auto &label = lexer_->GetToken().Ident(); 524 if (!ValidateContinueLabel(label)) { 525 ThrowSyntaxError("Undefined label"); 526 } 527 528 auto *identNode = AllocNode<ir::Identifier>(label, Allocator()); 529 identNode->SetReference(); 530 identNode->SetRange(lexer_->GetToken().Loc()); 531 532 auto *continueStatement = AllocNode<ir::ContinueStatement>(identNode); 533 continueStatement->SetRange({startLoc, lexer_->GetToken().End()}); 534 535 lexer_->NextToken(); 536 ConsumeSemicolon(continueStatement); 537 538 return continueStatement; 539} 540 541ir::DoWhileStatement *ParserImpl::ParseDoWhileStatement() 542{ 543 IterationContext iterCtx(&context_); 544 545 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 546 lexer_->NextToken(); 547 ir::Statement *body = ParseStatement(); 548 549 if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_WHILE) { 550 ThrowSyntaxError("Missing 'while' keyword in a 'DoWhileStatement'"); 551 } 552 553 lexer_->NextToken(); 554 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { 555 ThrowSyntaxError("Missing left parenthesis in a 'DoWhileStatement'"); 556 } 557 558 lexer_->NextToken(); 559 560 ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 561 562 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 563 ThrowSyntaxError("Missing right parenthesis in a 'DoWhileStatement'"); 564 } 565 566 auto *doWhileStatement = AllocNode<ir::DoWhileStatement>(body, test); 567 doWhileStatement->SetRange({startLoc, lexer_->GetToken().End()}); 568 569 lexer_->NextToken(); 570 571 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 572 doWhileStatement->SetEnd(lexer_->GetToken().End()); 573 lexer_->NextToken(); 574 } 575 576 return doWhileStatement; 577} 578 579ir::FunctionDeclaration *ParserImpl::ParseFunctionDeclaration(bool canBeAnonymous, ParserStatus newStatus) 580{ 581 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 582 583 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION); 584 ParserStatus savedStatus = context_.Status(); 585 586 lexer_->NextToken(); 587 588 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) { 589 newStatus |= ParserStatus::GENERATOR_FUNCTION; 590 lexer_->NextToken(); 591 } 592 593 context_.Status() = savedStatus; 594 595 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 596 if (canBeAnonymous) { 597 ir::ScriptFunction *func = ParseFunction(newStatus | ParserStatus::NEED_RETURN_TYPE); 598 func->SetStart(startLoc); 599 600 auto *funcDecl = AllocNode<ir::FunctionDeclaration>(Allocator(), func, true); 601 funcDecl->SetRange(func->Range()); 602 return funcDecl; 603 } 604 605 ThrowSyntaxError("Unexpected token, expected identifier after 'function' keyword"); 606 } 607 608 CheckRestrictedBinding(); 609 auto *identNode = ExpectIdentifier(); 610 611 newStatus |= ParserStatus::FUNCTION_DECLARATION; 612 ir::ScriptFunction *func = ParseFunction(newStatus | ParserStatus::NEED_RETURN_TYPE); 613 614 func->SetIdent(identNode); 615 func->SetStart(startLoc); 616 auto *funcDecl = AllocNode<ir::FunctionDeclaration>(Allocator(), func); 617 funcDecl->SetRange(func->Range()); 618 619 if (func->IsOverload() && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 620 lexer_->NextToken(); 621 } 622 623 return funcDecl; 624} 625 626ir::Statement *ParserImpl::ParseExpressionStatement(StatementParsingFlags flags) 627{ 628 const auto startPos = lexer_->Save(); 629 ParserStatus savedStatus = context_.Status(); 630 631 auto tokenType = lexer_->GetToken().Type(); 632 if (tokenType == lexer::TokenType::KEYW_PUBLIC || tokenType == lexer::TokenType::KEYW_PRIVATE || 633 tokenType == lexer::TokenType::KEYW_PROTECTED) { 634 lexer_->NextToken(); 635 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_CLASS || 636 lexer_->GetToken().Type() == lexer::TokenType::KEYW_INTERFACE) { 637 ThrowSyntaxError("A local class or interface declaration can not have access modifier", 638 startPos.GetToken().Start()); 639 } 640 lexer_->Rewind(startPos); 641 } 642 643 if (lexer_->GetToken().IsAsyncModifier()) { 644 lexer_->NextToken(); 645 646 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION && !lexer_->GetToken().NewLine()) { 647 if ((flags & StatementParsingFlags::ALLOW_LEXICAL) == 0) { 648 ThrowSyntaxError("Lexical declaration is not allowed in single statement context"); 649 } 650 651 ir::FunctionDeclaration *functionDecl = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION); 652 functionDecl->SetStart(startPos.GetToken().Start()); 653 654 return functionDecl; 655 } 656 657 lexer_->Rewind(startPos); 658 } 659 660 ir::Expression *exprNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 661 context_.Status() = savedStatus; 662 lexer::SourcePosition endPos = exprNode->End(); 663 664 auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(exprNode); 665 exprStatementNode->SetRange({startPos.GetToken().Start(), endPos}); 666 ConsumeSemicolon(exprStatementNode); 667 668 return exprStatementNode; 669} 670 671// NOLINTBEGIN(cert-err58-cpp) 672static std::string const INVALID_LEFT_HAND_IN_FOR_OF = 673 "Invalid left-hand side in 'for' statement: must have a single binding."s; 674static std::string const UNEXPECTED_TOKEN = "Unexpected token"s; 675static std::string const MISSING_LEFT_IN_FOR = "Missing left parenthesis in 'for' statement."s; 676static std::string const MISSING_RIGHT_IN_FOR = "Missing right parenthesis in 'for' statement."s; 677static std::string const INVALID_TYPE_ANNOTATION_IN_FOR = 678 "Type annotation is not allowed when existing variable is used as loop iterator in 'for' statement."s; 679// NOLINTEND(cert-err58-cpp) 680 681std::tuple<ForStatementKind, ir::Expression *, ir::Expression *> ParserImpl::ParseForInOf( 682 ir::AstNode *initNode, ExpressionParseFlags exprFlags, bool isAwait) 683{ 684 ForStatementKind forKind = ForStatementKind::UPDATE; 685 ir::Expression *updateNode = nullptr; 686 ir::Expression *rightNode = nullptr; 687 688 if (lexer_->GetToken().IsForInOf()) { 689 const ir::VariableDeclarator *varDecl = initNode->AsVariableDeclaration()->Declarators().front(); 690 691 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN) { 692 if (varDecl->Init() != nullptr) { 693 ThrowSyntaxError("for-in loop variable declaration may not have an initializer"); 694 } 695 forKind = ForStatementKind::IN; 696 exprFlags = ExpressionParseFlags::ACCEPT_COMMA; 697 ValidateForInStatement(); 698 } else { 699 if (varDecl->Init() != nullptr) { 700 ThrowSyntaxError("for-of loop variable declaration may not have an initializer"); 701 } 702 703 forKind = ForStatementKind::OF; 704 } 705 706 lexer_->NextToken(); 707 rightNode = ParseExpression(exprFlags); 708 } else { 709 if (isAwait) { 710 ThrowSyntaxError("Unexpected token"); 711 } 712 713 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 714 ThrowSyntaxError("Invalid left-hand side in 'For[In/Of]Statement'"); 715 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 716 lexer_->NextToken(); 717 } else { 718 rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::IN_FOR); 719 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 720 ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'."); 721 } 722 lexer_->NextToken(); 723 } 724 725 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 726 updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::IN_FOR); 727 } 728 } 729 730 return {forKind, rightNode, updateNode}; 731} 732 733std::tuple<ForStatementKind, ir::AstNode *, ir::Expression *, ir::Expression *> ParserImpl::ParseIsForInOf( 734 ir::Expression *leftNode, ExpressionParseFlags exprFlags) 735{ 736 ASSERT(lexer_->GetToken().IsForInOf()); 737 ForStatementKind forKind = ForStatementKind::OF; 738 739 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN) { 740 forKind = ForStatementKind::IN; 741 exprFlags = ExpressionParseFlags::ACCEPT_COMMA; 742 ValidateForInStatement(); 743 } 744 745 bool isValid = true; 746 switch (leftNode->Type()) { 747 case ir::AstNodeType::IDENTIFIER: 748 case ir::AstNodeType::MEMBER_EXPRESSION: { 749 break; 750 } 751 case ir::AstNodeType::ARRAY_EXPRESSION: { 752 isValid = leftNode->AsArrayExpression()->ConvertibleToArrayPattern(); 753 break; 754 } 755 case ir::AstNodeType::OBJECT_EXPRESSION: { 756 isValid = leftNode->AsObjectExpression()->ConvertibleToObjectPattern(); 757 break; 758 } 759 default: { 760 isValid = false; 761 } 762 } 763 764 if (!isValid) { 765 ValidateLvalueAssignmentTarget(leftNode); 766 } 767 768 lexer_->NextToken(); 769 770 return {forKind, leftNode, ParseExpression(exprFlags), nullptr}; 771} 772 773std::tuple<ForStatementKind, ir::AstNode *, ir::Expression *, ir::Expression *> ParserImpl::ParseForInOf( 774 ir::Expression *leftNode, ExpressionParseFlags exprFlags, bool isAwait) 775{ 776 ir::Expression *updateNode = nullptr; 777 ir::Expression *rightNode = nullptr; 778 if (lexer_->GetToken().IsForInOf()) { 779 return ParseIsForInOf(leftNode, exprFlags); 780 } 781 782 if (isAwait) { 783 ThrowSyntaxError("Unexpected token"); 784 } 785 786 ir::Expression *expr = ParseAssignmentExpression(leftNode); 787 788 ir::AstNode *initNode = 789 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA ? ParseSequenceExpression(expr) : expr; 790 791 if (initNode->IsConditionalExpression()) { 792 ir::ConditionalExpression *condExpr = initNode->AsConditionalExpression(); 793 if (condExpr->Alternate()->IsBinaryExpression() && 794 condExpr->Alternate()->AsBinaryExpression()->OperatorType() == lexer::TokenType::KEYW_IN) { 795 ThrowSyntaxError("Invalid left-hand side in for-in statement"); 796 } 797 } 798 799 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 800 ThrowSyntaxError("Invalid left-hand side in 'For[In/Of]Statement'"); 801 } 802 803 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 804 ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'."); 805 } 806 807 lexer_->NextToken(); 808 809 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 810 lexer_->NextToken(); 811 } else { 812 rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::IN_FOR); 813 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 814 ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'."); 815 } 816 lexer_->NextToken(); 817 } 818 819 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 820 updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::IN_FOR); 821 } 822 823 return {ForStatementKind::UPDATE, initNode, rightNode, updateNode}; 824} 825 826std::tuple<ir::Expression *, ir::Expression *> ParserImpl::ParseForUpdate(bool isAwait) 827{ 828 if (isAwait) { 829 ThrowSyntaxError("Unexpected token"); 830 } 831 832 ir::Expression *updateNode = nullptr; 833 ir::Expression *rightNode = nullptr; 834 835 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 836 lexer_->NextToken(); 837 } else { 838 rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::IN_FOR); 839 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 840 ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'."); 841 } 842 lexer_->NextToken(); 843 } 844 845 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 846 updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::IN_FOR); 847 } 848 849 return {rightNode, updateNode}; 850} 851 852std::tuple<ir::Expression *, ir::AstNode *> ParserImpl::ParseForLoopInitializer() 853{ 854 VariableParsingFlags varFlags = VariableParsingFlags::IN_FOR; 855 856 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) { 857 varFlags |= VariableParsingFlags::DISALLOW_INIT; 858 lexer_->NextToken(); 859 } 860 861 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { 862 ThrowSyntaxError(MISSING_LEFT_IN_FOR, lexer_->GetToken().Start()); 863 } 864 lexer_->NextToken(); 865 866 lexer::TokenType tokenType; 867 auto const currentPosition = lexer_->Save(); 868 do { 869 tokenType = lexer_->GetToken().Type(); 870 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OF) { 871 varFlags |= VariableParsingFlags::FOR_OF; 872 break; 873 } 874 if (tokenType == lexer::TokenType::KEYW_IN) { 875 varFlags |= VariableParsingFlags::STOP_AT_IN; 876 break; 877 } 878 lexer_->NextToken(); 879 } while (tokenType != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS && 880 tokenType != lexer::TokenType::PUNCTUATOR_LEFT_BRACE && 881 tokenType != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS && tokenType != lexer::TokenType::EOS); 882 lexer_->Rewind(currentPosition); 883 884 switch (lexer_->GetToken().Type()) { 885 case lexer::TokenType::KEYW_VAR: { 886 return {nullptr, ParseVariableDeclaration(varFlags | VariableParsingFlags::VAR)}; 887 } 888 case lexer::TokenType::KEYW_LET: { 889 return {nullptr, ParseVariableDeclaration(varFlags | VariableParsingFlags::LET)}; 890 } 891 case lexer::TokenType::KEYW_CONST: { 892 return {nullptr, ParseVariableDeclaration(varFlags | VariableParsingFlags::CONST | 893 VariableParsingFlags::ACCEPT_CONST_NO_INIT)}; 894 } 895 case lexer::TokenType::PUNCTUATOR_SEMI_COLON: { 896 if ((varFlags & VariableParsingFlags::DISALLOW_INIT) != 0 /*isAsync*/) { 897 ThrowSyntaxError(UNEXPECTED_TOKEN, lexer_->GetToken().Start()); 898 } 899 900 lexer_->NextToken(); 901 return {nullptr, nullptr}; 902 } 903 default: { 904 return {ParseUnaryOrPrefixUpdateExpression(ExpressionParseFlags::POTENTIALLY_IN_PATTERN), nullptr}; 905 } 906 } 907} 908 909ir::Statement *ParserImpl::ParseForStatement() 910{ 911 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 912 ForStatementKind forKind = ForStatementKind::UPDATE; 913 ir::AstNode *initNode = nullptr; 914 ir::Expression *updateNode = nullptr; 915 ir::Expression *leftNode = nullptr; 916 ir::Expression *rightNode = nullptr; 917 918 lexer_->NextToken(); 919 bool isAwait = lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT; 920 std::tie(leftNode, initNode) = ParseForLoopInitializer(); 921 bool canBeForInOf = (leftNode != nullptr) || (initNode != nullptr); 922 923 IterationContext iterCtx(&context_); 924 925 if (initNode != nullptr) { 926 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 927 lexer_->NextToken(); 928 canBeForInOf = false; 929 } else if (initNode->AsVariableDeclaration()->Declarators().size() > 1 && lexer_->GetToken().IsForInOf()) { 930 ThrowSyntaxError(INVALID_LEFT_HAND_IN_FOR_OF, initNode->AsVariableDeclaration()->Declarators()[1]->Start()); 931 } 932 } 933 934 // VariableDeclaration->DeclarationSize > 1 or seen semi_colon 935 if (!canBeForInOf) { 936 std::tie(rightNode, updateNode) = ParseForUpdate(isAwait); 937 } else if (leftNode != nullptr) { 938 // initNode was parsed as LHS 939 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { 940 ThrowSyntaxError(INVALID_TYPE_ANNOTATION_IN_FOR, lexer_->GetToken().Start()); 941 } 942 std::tie(forKind, initNode, rightNode, updateNode) = 943 ParseForInOf(leftNode, ExpressionParseFlags::NO_OPTS, isAwait); 944 } else if (initNode != nullptr) { 945 // initNode was parsed as VariableDeclaration and declaration size = 1 946 std::tie(forKind, rightNode, updateNode) = ParseForInOf(initNode, ExpressionParseFlags::NO_OPTS, isAwait); 947 } 948 949 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) { 950 lexer_->NextToken(); 951 } 952 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 953 ThrowSyntaxError(MISSING_RIGHT_IN_FOR, lexer_->GetToken().Start()); 954 } 955 lexer_->NextToken(); 956 957 ir::Statement *bodyNode = ParseStatement(); 958 ir::Statement *forStatement = nullptr; 959 960 if (forKind == ForStatementKind::UPDATE) { 961 forStatement = AllocNode<ir::ForUpdateStatement>(initNode, rightNode, updateNode, bodyNode); 962 } else if (forKind == ForStatementKind::IN) { 963 forStatement = AllocNode<ir::ForInStatement>(initNode, rightNode, bodyNode); 964 } else { 965 forStatement = AllocNode<ir::ForOfStatement>(initNode, rightNode, bodyNode, isAwait); 966 } 967 968 forStatement->SetRange({startLoc, bodyNode->End()}); 969 970 return forStatement; 971} 972 973void ParserImpl::ThrowIfBodyEmptyError([[maybe_unused]] ir::Statement *consequent) {} 974 975ir::IfStatement *ParserImpl::ParseIfStatement() 976{ 977 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 978 lexer::SourcePosition endLoc; 979 lexer_->NextToken(); 980 981 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { 982 ThrowSyntaxError("Missing left parenthesis in an 'IfStatement'"); 983 } 984 985 lexer_->NextToken(); 986 ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 987 988 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 989 ThrowSyntaxError("Missing right parenthesis in an 'IfStatement'"); 990 } 991 992 lexer_->NextToken(); 993 ir::Statement *consequent = ParseStatement(StatementParsingFlags::IF_ELSE | StatementParsingFlags::ALLOW_LEXICAL); 994 995 ThrowIfBodyEmptyError(consequent); 996 997 endLoc = consequent->End(); 998 ir::Statement *alternate = nullptr; 999 1000 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_ELSE) { 1001 lexer_->NextToken(); // eat ELSE keyword 1002 alternate = ParseStatement(StatementParsingFlags::IF_ELSE | StatementParsingFlags::ALLOW_LEXICAL); 1003 endLoc = alternate->End(); 1004 } 1005 1006 auto *ifStatement = AllocNode<ir::IfStatement>(test, consequent, alternate); 1007 ifStatement->SetRange({startLoc, endLoc}); 1008 return ifStatement; 1009} 1010 1011ir::LabelledStatement *ParserImpl::ParseLabelledStatement(const lexer::LexerPosition &pos) 1012{ 1013 const util::StringView &actualLabel = pos.GetToken().Ident(); 1014 1015 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AWAIT && context_.IsModule()) { 1016 ThrowSyntaxError("'await' is a reserved identifier in module code", pos.GetToken().Start()); 1017 } 1018 1019 if (context_.FindLabel(actualLabel) != nullptr) { 1020 ThrowSyntaxError("Label already declared", pos.GetToken().Start()); 1021 } 1022 1023 SavedParserContext newCtx(this, ParserStatus::IN_LABELED, actualLabel); 1024 1025 auto *identNode = AllocNode<ir::Identifier>(actualLabel, Allocator()); 1026 identNode->SetReference(); 1027 identNode->SetRange(pos.GetToken().Loc()); 1028 1029 lexer_->NextToken(); 1030 1031 ValidateLabeledStatement(Lexer()->GetToken().Type()); 1032 1033 ir::Statement *body = ParseStatement(StatementParsingFlags::LABELLED); 1034 1035 auto *labeledStatement = AllocNode<ir::LabelledStatement>(identNode, body); 1036 labeledStatement->SetRange({pos.GetToken().Start(), body->End()}); 1037 1038 return labeledStatement; 1039} 1040 1041ir::ReturnStatement *ParserImpl::ParseReturnStatement() 1042{ 1043 if ((context_.Status() & ParserStatus::FUNCTION) == 0) { 1044 ThrowSyntaxError("return keyword should be used in function body"); 1045 } 1046 1047 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 1048 lexer::SourcePosition endLoc = lexer_->GetToken().End(); 1049 lexer_->NextToken(); 1050 1051 bool hasArgument = (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON && 1052 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE && 1053 lexer_->GetToken().Type() != lexer::TokenType::EOS && !lexer_->GetToken().NewLine()); 1054 1055 ir::ReturnStatement *returnStatement = nullptr; 1056 1057 if (hasArgument) { 1058 ir::Expression *expression = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 1059 endLoc = expression->End(); 1060 returnStatement = AllocNode<ir::ReturnStatement>(expression); 1061 } else { 1062 returnStatement = AllocNode<ir::ReturnStatement>(); 1063 } 1064 1065 returnStatement->SetRange({startLoc, endLoc}); 1066 ConsumeSemicolon(returnStatement); 1067 1068 context_.Status() |= ParserStatus::FUNCTION_HAS_RETURN_STATEMENT; 1069 return returnStatement; 1070} 1071 1072void ParserImpl::ThrowMultipleDefaultError() 1073{ 1074 ThrowSyntaxError("Multiple default clauses."); 1075} 1076 1077ir::SwitchCaseStatement *ParserImpl::ParseSwitchCaseStatement(bool *seenDefault) 1078{ 1079 lexer::SourcePosition caseStartLoc = lexer_->GetToken().Start(); 1080 ir::Expression *testExpr = nullptr; 1081 1082 switch (lexer_->GetToken().KeywordType()) { 1083 case lexer::TokenType::KEYW_CASE: { 1084 lexer_->NextToken(); 1085 testExpr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 1086 break; 1087 } 1088 case lexer::TokenType::KEYW_DEFAULT: { 1089 if (*seenDefault) { 1090 ThrowMultipleDefaultError(); 1091 } 1092 *seenDefault = true; 1093 lexer_->NextToken(); 1094 break; 1095 } 1096 default: { 1097 ThrowSyntaxError("Unexpected token, expected 'case' or 'default'."); 1098 } 1099 } 1100 1101 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) { 1102 ThrowSyntaxError("Unexpected token, expected ':'"); 1103 } 1104 1105 ArenaVector<ir::Statement *> consequents(Allocator()->Adapter()); 1106 lexer::SourcePosition caseEndLoc = lexer_->GetToken().End(); 1107 1108 lexer_->NextToken(); 1109 1110 while (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CASE && 1111 lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_DEFAULT && 1112 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 1113 ir::Statement *consequent = ParseStatement(StatementParsingFlags::ALLOW_LEXICAL); 1114 caseEndLoc = consequent->End(); 1115 consequents.push_back(consequent); 1116 } 1117 1118 auto *caseNode = AllocNode<ir::SwitchCaseStatement>(testExpr, std::move(consequents)); 1119 caseNode->SetRange({caseStartLoc, caseEndLoc}); 1120 return caseNode; 1121} 1122 1123ir::SwitchStatement *ParserImpl::ParseSwitchStatement() 1124{ 1125 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 1126 lexer_->NextToken(); 1127 if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS)) { 1128 ThrowSyntaxError("Unexpected token, expected '('"); 1129 } 1130 1131 lexer_->NextToken(); 1132 ir::Expression *discriminant = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 1133 1134 if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS)) { 1135 ThrowSyntaxError("Unexpected token, expected ')'"); 1136 } 1137 1138 lexer_->NextToken(); 1139 SwitchContext switchContext(&context_); 1140 1141 if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE)) { 1142 ThrowSyntaxError("Unexpected token, expected '{'"); 1143 } 1144 1145 lexer_->NextToken(); 1146 bool seenDefault = false; 1147 ArenaVector<ir::SwitchCaseStatement *> cases(Allocator()->Adapter()); 1148 1149 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 1150 cases.push_back(ParseSwitchCaseStatement(&seenDefault)); 1151 } 1152 1153 auto *switchStatement = AllocNode<ir::SwitchStatement>(discriminant, std::move(cases)); 1154 switchStatement->SetRange({startLoc, lexer_->GetToken().End()}); 1155 1156 lexer_->NextToken(); 1157 1158 return switchStatement; 1159} 1160 1161void ParserImpl::ThrowIllegalNewLineErrorAfterThrow() 1162{ 1163 ThrowSyntaxError("Illegal newline after throw"); 1164} 1165 1166ir::ThrowStatement *ParserImpl::ParseThrowStatement() 1167{ 1168 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 1169 lexer_->NextToken(); 1170 1171 if (lexer_->GetToken().NewLine()) { 1172 ThrowIllegalNewLineErrorAfterThrow(); 1173 } 1174 1175 ir::Expression *expression = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 1176 lexer::SourcePosition endLoc = expression->End(); 1177 1178 auto *throwStatement = AllocNode<ir::ThrowStatement>(expression); 1179 throwStatement->SetRange({startLoc, endLoc}); 1180 ConsumeSemicolon(throwStatement); 1181 1182 return throwStatement; 1183} 1184 1185void ParserImpl::ParseCatchParamTypeAnnotation([[maybe_unused]] ir::AnnotatedExpression *param) {} 1186 1187ir::Expression *ParserImpl::ParseCatchParam() 1188{ 1189 ir::AnnotatedExpression *param = nullptr; 1190 1191 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { 1192 return param; 1193 } 1194 1195 lexer_->NextToken(); // eat left paren 1196 1197 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) { 1198 CheckRestrictedBinding(); 1199 param = ExpectIdentifier(); 1200 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) { 1201 param = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN); 1202 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 1203 param = ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN); 1204 } else { 1205 ThrowSyntaxError("Unexpected token in catch parameter"); 1206 } 1207 1208 ParseCatchParamTypeAnnotation(param); 1209 1210 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 1211 ThrowSyntaxError("Unexpected token, expected ')'"); 1212 } 1213 1214 lexer_->NextToken(); 1215 1216 return param; 1217} 1218 1219ir::CatchClause *ParserImpl::ParseCatchClause() 1220{ 1221 lexer::SourcePosition catchStartLoc = lexer_->GetToken().Start(); 1222 lexer_->NextToken(); // eat 'catch' keyword 1223 1224 ir::Expression *param = ParseCatchParam(); 1225 1226 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 1227 ThrowSyntaxError("Unexpected token, expected '{'"); 1228 } 1229 1230 ir::BlockStatement *catchBlock = ParseBlockStatement(); 1231 lexer::SourcePosition endLoc = catchBlock->End(); 1232 1233 auto *catchClause = AllocNode<ir::CatchClause>(param, catchBlock); 1234 catchClause->SetRange({catchStartLoc, endLoc}); 1235 1236 return catchClause; 1237} 1238 1239ir::Statement *ParserImpl::ParseTryStatement() 1240{ 1241 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 1242 lexer::SourcePosition endLoc = lexer_->GetToken().End(); 1243 1244 lexer_->NextToken(); 1245 1246 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 1247 ThrowSyntaxError("Unexpected token, expected '{'"); 1248 } 1249 1250 ir::BlockStatement *body = ParseBlockStatement(); 1251 1252 if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CATCH && 1253 lexer_->GetToken().Type() != lexer::TokenType::KEYW_FINALLY) { 1254 ThrowSyntaxError("Missing catch or finally clause"); 1255 } 1256 1257 ir::CatchClause *catchClause = nullptr; 1258 ir::BlockStatement *finallyClause = nullptr; 1259 ArenaVector<ir::CatchClause *> catchClauses(Allocator()->Adapter()); 1260 1261 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_CATCH) { 1262 catchClause = ParseCatchClause(); 1263 endLoc = catchClause->End(); 1264 catchClauses.push_back(catchClause); 1265 } 1266 1267 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FINALLY) { 1268 lexer_->NextToken(); // eat 'finally' keyword 1269 1270 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 1271 ThrowSyntaxError("Unexpected token, expected '{'"); 1272 } 1273 1274 finallyClause = ParseBlockStatement(); 1275 endLoc = finallyClause->End(); 1276 } 1277 1278 ArenaVector<std::pair<compiler::LabelPair, const ir::Statement *>> finalizerInsertions(Allocator()->Adapter()); 1279 1280 auto *tryStatement = AllocNode<ir::TryStatement>(body, std::move(catchClauses), finallyClause, finalizerInsertions); 1281 tryStatement->SetRange({startLoc, endLoc}); 1282 return tryStatement; 1283} 1284 1285void ParserImpl::ValidateDeclaratorId() 1286{ 1287 if (InAmbientContext()) { 1288 return; 1289 } 1290 1291 CheckRestrictedBinding(); 1292} 1293 1294ir::VariableDeclarator *ParserImpl::ParseVariableDeclaratorInitializer(ir::Expression *init, VariableParsingFlags flags, 1295 const lexer::SourcePosition &startLoc) 1296{ 1297 if ((flags & VariableParsingFlags::DISALLOW_INIT) != 0) { 1298 ThrowSyntaxError("for-await-of loop variable declaration may not have an initializer"); 1299 } 1300 1301 lexer_->NextToken(); 1302 1303 if (InAmbientContext() && (flags & VariableParsingFlags::CONST) == 0) { 1304 ThrowSyntaxError("Initializers are not allowed in ambient contexts."); 1305 } 1306 1307 auto exprFlags = ((flags & VariableParsingFlags::STOP_AT_IN) != 0 ? ExpressionParseFlags::STOP_AT_IN 1308 : ExpressionParseFlags::NO_OPTS); 1309 1310 ir::Expression *initializer = ParseExpression(exprFlags); 1311 lexer::SourcePosition endLoc = initializer->End(); 1312 1313 auto *declarator = AllocNode<ir::VariableDeclarator>(GetFlag(flags), init, initializer); 1314 declarator->SetRange({startLoc, endLoc}); 1315 1316 return declarator; 1317} 1318 1319ir::AnnotatedExpression *ParserImpl::ParseVariableDeclaratorKey([[maybe_unused]] VariableParsingFlags flags) 1320{ 1321 switch (lexer_->GetToken().Type()) { 1322 case lexer::TokenType::LITERAL_IDENT: { 1323 ValidateDeclaratorId(); 1324 return ExpectIdentifier(true); 1325 } 1326 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: { 1327 return ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN); 1328 } 1329 case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { 1330 return ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN); 1331 } 1332 default: { 1333 break; 1334 } 1335 } 1336 1337 ThrowSyntaxError("Unexpected token in variable declaration"); 1338 return nullptr; 1339} 1340 1341ir::VariableDeclaratorFlag ParserImpl::GetFlag(VariableParsingFlags flags) 1342{ 1343 constexpr auto VARIABLE_FLAGS = 1344 (VariableParsingFlags::VAR | VariableParsingFlags::LET | VariableParsingFlags::CONST); 1345 switch (static_cast<VariableParsingFlags>(flags & VARIABLE_FLAGS)) { 1346 case VariableParsingFlags::CONST: 1347 return ir::VariableDeclaratorFlag::CONST; 1348 case VariableParsingFlags::VAR: 1349 return ir::VariableDeclaratorFlag::VAR; 1350 case VariableParsingFlags::LET: 1351 return ir::VariableDeclaratorFlag::LET; 1352 default: 1353 UNREACHABLE(); 1354 } 1355} 1356 1357ir::VariableDeclarator *ParserImpl::ParseVariableDeclarator(ir::Expression *init, lexer::SourcePosition startLoc, 1358 VariableParsingFlags flags) 1359{ 1360 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { 1361 return ParseVariableDeclaratorInitializer(init, flags, startLoc); 1362 } 1363 1364 if ((flags & VariableParsingFlags::CONST) != 0U && (flags & VariableParsingFlags::ACCEPT_CONST_NO_INIT) == 0U) { 1365 ThrowSyntaxError("Missing initializer in const declaration"); 1366 } 1367 1368 if ((flags & VariableParsingFlags::IN_FOR) == 0U && (init->IsArrayPattern() || init->IsObjectPattern())) { 1369 ThrowSyntaxError("Missing initializer in destructuring declaration"); 1370 } 1371 1372 lexer::SourcePosition endLoc = init->End(); 1373 auto declarator = AllocNode<ir::VariableDeclarator>(GetFlag(flags), init); 1374 declarator->SetRange({startLoc, endLoc}); 1375 1376 return declarator; 1377} 1378 1379ir::VariableDeclarator *ParserImpl::ParseVariableDeclarator(VariableParsingFlags flags) 1380{ 1381 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 1382 ir::Expression *init = ParseVariableDeclaratorKey(flags); 1383 ir::VariableDeclarator *declarator = ParseVariableDeclarator(init, startLoc, flags); 1384 1385 return declarator; 1386} 1387 1388ir::Statement *ParserImpl::ParsePotentialConstEnum([[maybe_unused]] VariableParsingFlags flags) 1389{ 1390 ThrowSyntaxError("Variable declaration expected."); 1391} 1392 1393void ParserImpl::ThrowIfVarDeclaration([[maybe_unused]] VariableParsingFlags flags) {} 1394 1395ir::Statement *ParserImpl::ParseVariableDeclaration(VariableParsingFlags flags) 1396{ 1397 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 1398 1399 if ((flags & VariableParsingFlags::NO_SKIP_VAR_KIND) == 0) { 1400 lexer_->NextToken(); 1401 } 1402 1403 ThrowIfVarDeclaration(flags); 1404 1405 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_ENUM) { 1406 return ParsePotentialConstEnum(flags); 1407 } 1408 1409 ArenaVector<ir::VariableDeclarator *> declarators(Allocator()->Adapter()); 1410 1411 while (true) { 1412 ir::VariableDeclarator *declarator = ParseVariableDeclarator(flags); 1413 1414 declarators.push_back(declarator); 1415 1416 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) { 1417 break; 1418 } 1419 lexer_->NextToken(); 1420 } 1421 1422 auto varKind = ir::VariableDeclaration::VariableDeclarationKind::VAR; 1423 1424 if ((flags & VariableParsingFlags::LET) != 0) { 1425 varKind = ir::VariableDeclaration::VariableDeclarationKind::LET; 1426 } else if ((flags & VariableParsingFlags::CONST) != 0) { 1427 varKind = ir::VariableDeclaration::VariableDeclarationKind::CONST; 1428 } 1429 1430 lexer::SourcePosition endLoc = declarators.back()->End(); 1431 auto *declaration = 1432 AllocNode<ir::VariableDeclaration>(varKind, Allocator(), std::move(declarators), InAmbientContext()); 1433 declaration->SetRange({startLoc, endLoc}); 1434 1435 return declaration; 1436} 1437 1438ir::WhileStatement *ParserImpl::ParseWhileStatement() 1439{ 1440 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 1441 lexer_->NextToken(); 1442 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { 1443 ThrowSyntaxError("Unexpected token, expected '('"); 1444 } 1445 1446 lexer_->NextToken(); 1447 ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 1448 1449 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 1450 ThrowSyntaxError("Unexpected token, expected ')'"); 1451 } 1452 1453 lexer_->NextToken(); 1454 IterationContext iterCtx(&context_); 1455 ir::Statement *body = ParseStatement(); 1456 1457 lexer::SourcePosition endLoc = body->End(); 1458 auto *whileStatement = AllocNode<ir::WhileStatement>(test, body); 1459 whileStatement->SetRange({startLoc, endLoc}); 1460 1461 return whileStatement; 1462} 1463 1464// NOLINTNEXTLINE(google-default-arguments) 1465ir::ExportDefaultDeclaration *ParserImpl::ParseExportDefaultDeclaration(const lexer::SourcePosition &startLoc, 1466 bool isExportEquals) 1467{ 1468 lexer_->NextToken(); // eat `default` keyword or `=` 1469 1470 ir::AstNode *declNode = nullptr; 1471 bool eatSemicolon = false; 1472 1473 switch (lexer_->GetToken().Type()) { 1474 case lexer::TokenType::KEYW_FUNCTION: { 1475 declNode = ParseFunctionDeclaration(true); 1476 break; 1477 } 1478 case lexer::TokenType::KEYW_CLASS: { 1479 declNode = ParseClassDeclaration(ir::ClassDefinitionModifiers::NONE); 1480 break; 1481 } 1482 case lexer::TokenType::LITERAL_IDENT: { 1483 switch (lexer_->GetToken().KeywordType()) { 1484 case lexer::TokenType::KEYW_STRUCT: { 1485 declNode = ParseStructDeclaration(ir::ClassDefinitionModifiers::NONE); 1486 break; 1487 } 1488 case lexer::TokenType::KEYW_ASYNC: { 1489 if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) == 0) { 1490 lexer_->NextToken(); // eat `async` 1491 declNode = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION); 1492 break; 1493 } 1494 1495 [[fallthrough]]; 1496 } 1497 default: { 1498 declNode = ParseExpression(); 1499 eatSemicolon = true; 1500 break; 1501 } 1502 } 1503 1504 break; 1505 } 1506 default: { 1507 declNode = ParseExpression(); 1508 eatSemicolon = true; 1509 break; 1510 } 1511 } 1512 1513 lexer::SourcePosition endLoc = declNode->End(); 1514 auto *exportDeclaration = AllocNode<ir::ExportDefaultDeclaration>(declNode, isExportEquals); 1515 exportDeclaration->SetRange({startLoc, endLoc}); 1516 1517 if (eatSemicolon) { 1518 ConsumeSemicolon(exportDeclaration); 1519 } 1520 1521 return exportDeclaration; 1522} 1523 1524ir::Identifier *ParserImpl::ParseNamedExport(const lexer::Token &exportedToken) 1525{ 1526 if (exportedToken.Type() != lexer::TokenType::LITERAL_IDENT) { 1527 ThrowSyntaxError("Unexpected token, expected an identifier."); 1528 } 1529 1530 CheckRestrictedBinding(exportedToken.KeywordType()); 1531 1532 const util::StringView &exportedString = exportedToken.Ident(); 1533 1534 auto *exported = AllocNode<ir::Identifier>(exportedString, Allocator()); 1535 exported->SetRange(exportedToken.Loc()); 1536 1537 return exported; 1538} 1539 1540ir::ExportAllDeclaration *ParserImpl::ParseExportAllDeclaration(const lexer::SourcePosition &startLoc) 1541{ 1542 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); // eat `*` character 1543 1544 ir::Identifier *exported = nullptr; 1545 1546 if (CheckModuleAsModifier()) { 1547 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); 1548 exported = ParseNamedExport(lexer_->GetToken()); 1549 lexer_->NextToken(); // eat exported name 1550 } 1551 1552 ir::StringLiteral *source = ParseFromClause(); 1553 lexer::SourcePosition endLoc = source->End(); 1554 1555 auto *exportDeclaration = AllocNode<ir::ExportAllDeclaration>(source, exported); 1556 exportDeclaration->SetRange({startLoc, endLoc}); 1557 1558 ConsumeSemicolon(exportDeclaration); 1559 1560 return exportDeclaration; 1561} 1562 1563ir::ExportNamedDeclaration *ParserImpl::ParseExportNamedSpecifiers(const lexer::SourcePosition &startLoc) 1564{ 1565 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); // eat `{` character 1566 1567 ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter()); 1568 1569 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 1570 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 1571 ThrowSyntaxError("Unexpected token"); 1572 } 1573 1574 lexer::Token localToken = lexer_->GetToken(); 1575 auto *local = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator()); 1576 local->SetRange(lexer_->GetToken().Loc()); 1577 1578 lexer_->NextToken(); // eat local name 1579 1580 ir::Identifier *exported = nullptr; 1581 1582 if (CheckModuleAsModifier()) { 1583 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); // eat `as` literal 1584 exported = ParseNamedExport(lexer_->GetToken()); 1585 lexer_->NextToken(); // eat exported name 1586 } else { 1587 exported = ParseNamedExport(localToken); 1588 } 1589 1590 auto *specifier = AllocNode<ir::ExportSpecifier>(local, exported); 1591 specifier->SetRange({local->Start(), exported->End()}); 1592 1593 specifiers.push_back(specifier); 1594 1595 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) { 1596 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); // eat comma 1597 } 1598 } 1599 1600 lexer::SourcePosition endPos = lexer_->GetToken().End(); 1601 lexer_->NextToken(); // eat right brace 1602 1603 ir::StringLiteral *source = nullptr; 1604 1605 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_FROM) { 1606 source = ParseFromClause(); 1607 } 1608 1609 auto *exportDeclaration = AllocNode<ir::ExportNamedDeclaration>(Allocator(), source, std::move(specifiers)); 1610 exportDeclaration->SetRange({startLoc, endPos}); 1611 ConsumeSemicolon(exportDeclaration); 1612 1613 return exportDeclaration; 1614} 1615 1616ir::ExportNamedDeclaration *ParserImpl::ParseNamedExportDeclaration(const lexer::SourcePosition &startLoc) 1617{ 1618 ir::Statement *decl = nullptr; 1619 1620 switch (lexer_->GetToken().Type()) { 1621 case lexer::TokenType::KEYW_VAR: { 1622 decl = ParseVariableDeclaration(VariableParsingFlags::VAR); 1623 break; 1624 } 1625 case lexer::TokenType::KEYW_CONST: { 1626 decl = ParseVariableDeclaration(VariableParsingFlags::CONST); 1627 break; 1628 } 1629 case lexer::TokenType::KEYW_LET: { 1630 decl = ParseVariableDeclaration(VariableParsingFlags::LET); 1631 break; 1632 } 1633 case lexer::TokenType::KEYW_FUNCTION: { 1634 decl = ParseFunctionDeclaration(false, ParserStatus::NO_OPTS); 1635 break; 1636 } 1637 case lexer::TokenType::KEYW_CLASS: { 1638 decl = ParseClassDeclaration(ir::ClassDefinitionModifiers::ID_REQUIRED); 1639 break; 1640 } 1641 case lexer::TokenType::LITERAL_IDENT: { 1642 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_STRUCT) { 1643 decl = ParseStructDeclaration(ir::ClassDefinitionModifiers::NONE); 1644 break; 1645 } 1646 [[fallthrough]]; 1647 } 1648 default: { 1649 if (!lexer_->GetToken().IsAsyncModifier()) { 1650 ThrowSyntaxError("Unexpected token"); 1651 } 1652 1653 lexer_->NextToken(); // eat `async` keyword 1654 decl = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION); 1655 } 1656 } 1657 1658 if (decl->IsVariableDeclaration()) { 1659 ConsumeSemicolon(decl); 1660 } 1661 1662 lexer::SourcePosition endLoc = decl->End(); 1663 ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter()); 1664 auto *exportDeclaration = AllocNode<ir::ExportNamedDeclaration>(Allocator(), decl, std::move(specifiers)); 1665 exportDeclaration->SetRange({startLoc, endLoc}); 1666 1667 return exportDeclaration; 1668} 1669 1670ir::Statement *ParserImpl::ParseExportDeclaration(StatementParsingFlags flags) 1671{ 1672 if ((flags & StatementParsingFlags::GLOBAL) == 0) { 1673 ThrowSyntaxError("'import' and 'export' may only appear at the top level"); 1674 } 1675 1676 if (!context_.IsModule()) { 1677 ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'"); 1678 } 1679 1680 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 1681 lexer_->NextToken(); // eat `export` keyword 1682 1683 switch (lexer_->GetToken().Type()) { 1684 case lexer::TokenType::PUNCTUATOR_MULTIPLY: { 1685 return ParseExportAllDeclaration(startLoc); 1686 } 1687 case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { 1688 return ParseExportNamedSpecifiers(startLoc); 1689 } 1690 default: { 1691 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DEFAULT) { 1692 return ParseExportDefaultDeclaration(startLoc); 1693 } 1694 return ParseNamedExportDeclaration(startLoc); 1695 } 1696 } 1697} 1698 1699void ParserImpl::ParseNameSpaceImport(ArenaVector<ir::AstNode *> *specifiers) 1700{ 1701 lexer::SourcePosition namespaceStart = lexer_->GetToken().Start(); 1702 lexer_->NextToken(); // eat `*` character 1703 1704 if (!CheckModuleAsModifier()) { 1705 ThrowSyntaxError("Unexpected token."); 1706 } 1707 1708 lexer_->NextToken(); // eat `as` literal 1709 1710 ir::Identifier *local = ParseNamedImport(lexer_->GetToken()); 1711 1712 auto *specifier = AllocNode<ir::ImportNamespaceSpecifier>(local); 1713 specifier->SetRange({namespaceStart, lexer_->GetToken().End()}); 1714 specifiers->push_back(specifier); 1715 1716 lexer_->NextToken(); // eat local name 1717} 1718 1719ir::Identifier *ParserImpl::ParseNamedImport(const lexer::Token &importedToken) 1720{ 1721 if (importedToken.Type() != lexer::TokenType::LITERAL_IDENT) { 1722 ThrowSyntaxError("Unexpected token"); 1723 } 1724 1725 CheckRestrictedBinding(importedToken.KeywordType()); 1726 1727 auto *local = AllocNode<ir::Identifier>(importedToken.Ident(), Allocator()); 1728 local->SetReference(); 1729 local->SetRange(importedToken.Loc()); 1730 1731 return local; 1732} 1733 1734void ParserImpl::ParseNamedImportSpecifiers(ArenaVector<ir::AstNode *> *specifiers) 1735{ 1736 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); // eat `{` character 1737 1738 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 1739 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 1740 ThrowSyntaxError("Unexpected token"); 1741 } 1742 1743 lexer::Token importedToken = lexer_->GetToken(); 1744 auto *imported = AllocNode<ir::Identifier>(importedToken.Ident(), Allocator()); 1745 ir::Identifier *local = nullptr; 1746 imported->SetReference(); 1747 imported->SetRange(lexer_->GetToken().Loc()); 1748 1749 lexer_->NextToken(); // eat import name 1750 1751 if (CheckModuleAsModifier()) { 1752 lexer_->NextToken(); // eat `as` literal 1753 local = ParseNamedImport(lexer_->GetToken()); 1754 lexer_->NextToken(); // eat local name 1755 } else { 1756 local = ParseNamedImport(importedToken); 1757 } 1758 1759 auto *specifier = AllocNode<ir::ImportSpecifier>(imported, local); 1760 specifier->SetRange({imported->Start(), local->End()}); 1761 specifiers->push_back(specifier); 1762 1763 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) { 1764 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); // eat comma 1765 } 1766 } 1767 1768 lexer_->NextToken(); // eat right brace 1769} 1770 1771ir::AstNode *ParserImpl::ParseImportDefaultSpecifier(ArenaVector<ir::AstNode *> *specifiers) 1772{ 1773 ir::Identifier *local = ParseNamedImport(lexer_->GetToken()); 1774 lexer_->NextToken(); // eat local name 1775 1776 auto *specifier = AllocNode<ir::ImportDefaultSpecifier>(local); 1777 specifier->SetRange(specifier->Local()->Range()); 1778 specifiers->push_back(specifier); 1779 1780 lexer_->NextToken(); // eat specifier name 1781 1782 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) { 1783 lexer_->NextToken(); // eat comma 1784 } 1785 1786 return nullptr; 1787} 1788 1789ir::StringLiteral *ParserImpl::ParseFromClause(bool requireFrom) 1790{ 1791 if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) { 1792 if (requireFrom) { 1793 ThrowSyntaxError("Unexpected token."); 1794 } 1795 } else { 1796 lexer_->NextToken(); // eat `from` literal 1797 } 1798 1799 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) { 1800 ThrowSyntaxError("Unexpected token."); 1801 } 1802 1803 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING); 1804 1805 auto *source = AllocNode<ir::StringLiteral>(lexer_->GetToken().String()); 1806 source->SetRange(lexer_->GetToken().Loc()); 1807 1808 lexer_->NextToken(); 1809 1810 return source; 1811} 1812 1813ir::AstNode *ParserImpl::ParseImportSpecifiers(ArenaVector<ir::AstNode *> *specifiers) 1814{ 1815 ASSERT(specifiers->empty()); 1816 1817 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) { 1818 ir::AstNode *astNode = ParseImportDefaultSpecifier(specifiers); 1819 1820 if (astNode != nullptr) { 1821 return astNode; 1822 } 1823 } 1824 1825 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) { 1826 ParseNameSpaceImport(specifiers); 1827 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 1828 ParseNamedImportSpecifiers(specifiers); 1829 } 1830 return nullptr; 1831} 1832 1833ir::Statement *ParserImpl::ParseImportDeclaration(StatementParsingFlags flags) 1834{ 1835 if ((flags & StatementParsingFlags::GLOBAL) == 0) { 1836 ThrowSyntaxError("'import' and 'export' may only appear at the top level"); 1837 } 1838 1839 if (!context_.IsModule()) { 1840 ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'"); 1841 } 1842 1843 char32_t nextChar = lexer_->Lookahead(); 1844 if (nextChar == lexer::LEX_CHAR_LEFT_PAREN || nextChar == lexer::LEX_CHAR_DOT) { 1845 return ParseExpressionStatement(); 1846 } 1847 1848 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 1849 lexer_->NextToken(); // eat import 1850 1851 ArenaVector<ir::AstNode *> specifiers(Allocator()->Adapter()); 1852 1853 ir::StringLiteral *source = nullptr; 1854 1855 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) { 1856 ParseImportSpecifiers(&specifiers); 1857 source = ParseFromClause(true); 1858 } else { 1859 source = ParseFromClause(false); 1860 } 1861 1862 lexer::SourcePosition endLoc = source->End(); 1863 auto *importDeclaration = AllocNode<ir::ImportDeclaration>(source, std::move(specifiers)); 1864 importDeclaration->SetRange({startLoc, endLoc}); 1865 1866 ConsumeSemicolon(importDeclaration); 1867 1868 return importDeclaration; 1869} 1870} // namespace ark::es2panda::parser 1871