1/** 2 * Copyright (c) 2021 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 <util/helpers.h> 17#include <binder/tsBinding.h> 18#include <ir/astNode.h> 19#include <ir/base/annotation.h> 20#include <ir/base/catchClause.h> 21#include <ir/base/classDefinition.h> 22#include <ir/base/decorator.h> 23#include <ir/base/scriptFunction.h> 24#include <ir/expression.h> 25#include <ir/expressions/arrayExpression.h> 26#include <ir/expressions/assignmentExpression.h> 27#include <ir/expressions/binaryExpression.h> 28#include <ir/expressions/conditionalExpression.h> 29#include <ir/expressions/literals/stringLiteral.h> 30#include <ir/expressions/objectExpression.h> 31#include <ir/expressions/sequenceExpression.h> 32#include <ir/module/exportAllDeclaration.h> 33#include <ir/module/exportDefaultDeclaration.h> 34#include <ir/module/exportNamedDeclaration.h> 35#include <ir/module/exportSpecifier.h> 36#include <ir/module/importDeclaration.h> 37#include <ir/module/importDefaultSpecifier.h> 38#include <ir/module/importNamespaceSpecifier.h> 39#include <ir/module/importSpecifier.h> 40#include <ir/statements/blockStatement.h> 41#include <ir/statements/breakStatement.h> 42#include <ir/statements/classDeclaration.h> 43#include <ir/statements/continueStatement.h> 44#include <ir/statements/debuggerStatement.h> 45#include <ir/statements/doWhileStatement.h> 46#include <ir/statements/emptyStatement.h> 47#include <ir/statements/expressionStatement.h> 48#include <ir/statements/forInStatement.h> 49#include <ir/statements/forOfStatement.h> 50#include <ir/statements/forUpdateStatement.h> 51#include <ir/statements/functionDeclaration.h> 52#include <ir/statements/ifStatement.h> 53#include <ir/statements/labelledStatement.h> 54#include <ir/statements/returnStatement.h> 55#include <ir/statements/switchCaseStatement.h> 56#include <ir/statements/switchStatement.h> 57#include <ir/statements/throwStatement.h> 58#include <ir/statements/tryStatement.h> 59#include <ir/statements/variableDeclaration.h> 60#include <ir/statements/variableDeclarator.h> 61#include <ir/statements/whileStatement.h> 62#include <ir/ts/tsEnumDeclaration.h> 63#include <ir/ts/tsExternalModuleReference.h> 64#include <ir/ts/tsImportEqualsDeclaration.h> 65#include <ir/ts/tsInterfaceBody.h> 66#include <ir/ts/tsInterfaceDeclaration.h> 67#include <ir/ts/tsInterfaceHeritage.h> 68#include <ir/ts/tsModuleBlock.h> 69#include <ir/ts/tsModuleDeclaration.h> 70#include <ir/ts/tsNamespaceExportDeclaration.h> 71#include <ir/ts/tsTypeAliasDeclaration.h> 72#include <ir/ts/tsTypeParameter.h> 73#include <ir/ts/tsTypeParameterDeclaration.h> 74#include <ir/ts/tsTypeParameterInstantiation.h> 75#include <ir/ts/tsTypeReference.h> 76#include <lexer/lexer.h> 77#include <lexer/token/letters.h> 78#include <lexer/token/sourceLocation.h> 79#include <util/ustring.h> 80 81#include <tuple> 82 83#include "parserImpl.h" 84 85namespace panda::es2panda::parser { 86 87bool ParserImpl::CheckDeclare() 88{ 89 ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE); 90 91 const auto startPos = lexer_->Save(); 92 lexer_->NextToken(); // eat 'declare' 93 if (lexer_->GetToken().NewLine()) { 94 lexer_->Rewind(startPos); 95 return false; 96 } 97 switch (lexer_->GetToken().Type()) { 98 case lexer::TokenType::KEYW_VAR: 99 case lexer::TokenType::KEYW_LET: 100 case lexer::TokenType::KEYW_CONST: 101 case lexer::TokenType::KEYW_FUNCTION: 102 case lexer::TokenType::KEYW_CLASS: { 103 break; 104 } 105 case lexer::TokenType::LITERAL_IDENT: { 106 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE || 107 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_MODULE || 108 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_GLOBAL || 109 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NAMESPACE || 110 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ENUM || 111 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT || 112 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_INTERFACE) { 113 break; 114 } 115 116 [[fallthrough]]; 117 } 118 default: { 119 lexer_->Rewind(startPos); 120 return false; 121 } 122 } 123 124 if (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT) { 125 lexer_->Rewind(startPos); 126 ThrowSyntaxError("A 'declare' modifier cannot be used in an already ambient context."); 127 } 128 129 return true; 130} 131 132bool ParserImpl::IsLabelFollowedByIterationStatement() 133{ 134 lexer_->NextToken(); 135 136 switch (lexer_->GetToken().Type()) { 137 case lexer::TokenType::KEYW_DO: 138 case lexer::TokenType::KEYW_FOR: 139 case lexer::TokenType::KEYW_WHILE: { 140 return true; 141 } 142 case lexer::TokenType::LITERAL_IDENT: { 143 if (lexer_->Lookahead() == LEX_CHAR_COLON) { 144 lexer_->NextToken(); 145 return IsLabelFollowedByIterationStatement(); 146 } 147 148 [[fallthrough]]; 149 } 150 default: 151 return false; 152 } 153 return false; 154} 155 156bool ParserImpl::IsTsDeclarationStatement() const 157{ 158 const auto startPos = lexer_->Save(); 159 bool isTsDeclarationStatement = false; 160 161 auto keywordType = lexer_->GetToken().KeywordType(); 162 lexer_->NextToken(); 163 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) { 164 lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT); 165 } 166 switch (keywordType) { 167 case lexer::TokenType::KEYW_MODULE: 168 case lexer::TokenType::KEYW_NAMESPACE: { 169 isTsDeclarationStatement = !lexer_->GetToken().NewLine() && 170 (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT || 171 lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING); 172 break; 173 } 174 case lexer::TokenType::KEYW_GLOBAL: { 175 isTsDeclarationStatement = lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT || 176 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE || 177 lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXPORT; 178 break; 179 } 180 case lexer::TokenType::KEYW_INTERFACE: 181 case lexer::TokenType::KEYW_TYPE: { 182 isTsDeclarationStatement = !lexer_->GetToken().NewLine() && 183 lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT; 184 break; 185 } 186 case lexer::TokenType::KEYW_ENUM: { 187 isTsDeclarationStatement = true; 188 break; 189 } 190 default: { 191 break; 192 } 193 } 194 195 lexer_->Rewind(startPos); 196 return isTsDeclarationStatement; 197} 198 199ir::Statement *ParserImpl::ParseStatement(StatementParsingFlags flags) 200{ 201 bool isDeclare = false; 202 auto decoratorsAndAnnotations = ParseDecoratorsAndAnnotations(); 203 auto decorators = decoratorsAndAnnotations.first; 204 auto annotations = decoratorsAndAnnotations.second; 205 206 if (Extension() == ScriptExtension::TS) { 207 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) { 208 isDeclare = CheckDeclare(); 209 } 210 211 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_AT) { 212 lexer_->NextToken(); // eat @ symbol 213 if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_INTERFACE) { 214 ThrowSyntaxError("'interface' keyword expected."); 215 } 216 if (!decorators.empty()) { 217 ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start()); 218 } 219 if (!annotations.empty()) { 220 ThrowSyntaxError("Annotations can not be used with annotation declaration", 221 annotations.front()->Start()); 222 } 223 return ParseClassDeclaration(true, std::move(decorators), std::move(annotations), isDeclare, false, 224 false, true); 225 } 226 227 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT) { 228 const auto startPos = lexer_->Save(); 229 lexer_->NextToken(); // eat abstract keyword 230 231 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) { 232 if (isDeclare) { 233 ThrowSyntaxError("'declare' modifier already seen."); 234 } 235 lexer_->NextToken(); 236 isDeclare = true; 237 } 238 239 if (!annotations.empty()) { 240 ThrowSyntaxError("Annotations can not be used with abstract classes", annotations.front()->Start()); 241 } 242 243 if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS) { 244 lexer_->Rewind(startPos); 245 } else { 246 return ParseClassStatement(flags, isDeclare, std::move(decorators), std::move(annotations), true); 247 } 248 } 249 250 if ((lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_GLOBAL || 251 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_MODULE || 252 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NAMESPACE) && 253 IsTsDeclarationStatement()) { 254 auto savedStatus = context_.Status(); 255 if (isDeclare) { 256 context_.Status() |= ParserStatus::IN_AMBIENT_CONTEXT; 257 } 258 ir::TSModuleDeclaration *decl = ParseTsModuleDeclaration(isDeclare); 259 context_.Status() = savedStatus; 260 return decl; 261 } 262 } 263 264 switch (lexer_->GetToken().Type()) { 265 case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { 266 return ParseBlockStatement(); 267 } 268 case lexer::TokenType::PUNCTUATOR_SEMI_COLON: { 269 return ParseEmptyStatement(); 270 } 271 case lexer::TokenType::KEYW_EXPORT: { 272 return ParseExportDeclaration(flags, std::move(decorators), std::move(annotations)); 273 } 274 case lexer::TokenType::KEYW_IMPORT: { 275 return ParseImportDeclaration(flags); 276 } 277 case lexer::TokenType::KEYW_FUNCTION: { 278 return ParseFunctionStatement(flags, isDeclare); 279 } 280 case lexer::TokenType::KEYW_CLASS: { 281 return ParseClassStatement(flags, isDeclare, std::move(decorators), std::move(annotations)); 282 } 283 case lexer::TokenType::KEYW_VAR: { 284 return ParseVarStatement(isDeclare); 285 } 286 case lexer::TokenType::KEYW_LET: { 287 return ParseLetStatement(flags, isDeclare); 288 } 289 case lexer::TokenType::KEYW_CONST: { 290 return ParseConstStatement(flags, isDeclare); 291 } 292 case lexer::TokenType::KEYW_IF: { 293 return ParseIfStatement(); 294 } 295 case lexer::TokenType::KEYW_DO: { 296 return ParseDoWhileStatement(); 297 } 298 case lexer::TokenType::KEYW_FOR: { 299 return ParseForStatement(); 300 } 301 case lexer::TokenType::KEYW_TRY: { 302 return ParseTryStatement(); 303 } 304 case lexer::TokenType::KEYW_WHILE: { 305 return ParseWhileStatement(); 306 } 307 case lexer::TokenType::KEYW_BREAK: { 308 return ParseBreakStatement(); 309 } 310 case lexer::TokenType::KEYW_CONTINUE: { 311 return ParseContinueStatement(); 312 } 313 case lexer::TokenType::KEYW_THROW: { 314 return ParseThrowStatement(); 315 } 316 case lexer::TokenType::KEYW_RETURN: { 317 return ParseReturnStatement(); 318 } 319 case lexer::TokenType::KEYW_SWITCH: { 320 return ParseSwitchStatement(); 321 } 322 case lexer::TokenType::KEYW_DEBUGGER: { 323 return ParseDebuggerStatement(); 324 } 325 case lexer::TokenType::LITERAL_IDENT: { 326 return ParsePotentialExpressionStatement(flags, isDeclare); 327 } 328 default: { 329 break; 330 } 331 } 332 333 return ParseExpressionStatement(flags); 334} 335 336ir::TSModuleDeclaration *ParserImpl::ParseTsModuleDeclaration(bool isDeclare, bool isExport) 337{ 338 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 339 context_.Status() |= ParserStatus::TS_MODULE; 340 341 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_GLOBAL) { 342 return ParseTsAmbientExternalModuleDeclaration(startLoc, isDeclare); 343 } 344 345 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NAMESPACE) { 346 lexer_->NextToken(); 347 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) { 348 lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT); 349 } 350 } else { 351 ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_MODULE); 352 lexer_->NextToken(); 353 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) { 354 lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT); 355 } 356 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) { 357 return ParseTsAmbientExternalModuleDeclaration(startLoc, isDeclare); 358 } 359 } 360 361 return ParseTsModuleOrNamespaceDelaration(startLoc, isDeclare, isExport); 362} 363 364ir::TSModuleDeclaration *ParserImpl::ParseTsAmbientExternalModuleDeclaration(const lexer::SourcePosition &startLoc, 365 bool isDeclare) 366{ 367 bool isGlobal = false; 368 ir::Expression *name = nullptr; 369 370 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_GLOBAL) { 371 isGlobal = true; 372 name = AllocNode<ir::Identifier>(lexer_->GetToken().Ident()); 373 } else { 374 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING); 375 376 if (!isDeclare && !(context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT)) { 377 ThrowSyntaxError("Only ambient modules can use quoted names"); 378 } 379 380 name = AllocNode<ir::StringLiteral>(lexer_->GetToken().String()); 381 } 382 383 name->SetRange(lexer_->GetToken().Loc()); 384 385 lexer_->NextToken(); 386 387 binder::ExportBindings *exportBindings = Allocator()->New<binder::ExportBindings>(Allocator()); 388 auto localCtx = binder::LexicalScope<binder::TSModuleScope>(Binder(), exportBindings); 389 390 ir::Statement *body = nullptr; 391 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 392 body = ParseTsModuleBlock(); 393 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 394 lexer_->NextToken(); 395 } else if (!lexer_->GetToken().NewLine()) { 396 ThrowSyntaxError("';' expected"); 397 } 398 399 auto *moduleDecl = AllocNode<ir::TSModuleDeclaration>(localCtx.GetScope(), name, body, isDeclare, isGlobal); 400 moduleDecl->SetRange({startLoc, lexer_->GetToken().End()}); 401 localCtx.GetScope()->BindNode(moduleDecl); 402 403 return moduleDecl; 404} 405 406ir::TSModuleDeclaration *ParserImpl::ParseTsModuleOrNamespaceDelaration(const lexer::SourcePosition &startLoc, 407 bool isDeclare, bool isExport) 408{ 409 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 410 ThrowSyntaxError("Identifier expected"); 411 } 412 413 auto name = lexer_->GetToken().Ident(); 414 auto *parentScope = Binder()->GetScope(); 415 binder::Variable *res = parentScope->FindLocalTSVariable<binder::TSBindingType::NAMESPACE>(name); 416 if (!res && isExport && parentScope->IsTSModuleScope()) { 417 res = parentScope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::NAMESPACE>(name); 418 if (res != nullptr) { 419 parentScope->AddLocalTSVariable<binder::TSBindingType::NAMESPACE>(name, res); 420 } 421 } 422 if (res == nullptr) { 423 Binder()->AddTsDecl<binder::NamespaceDecl>(lexer_->GetToken().Start(), isDeclare, Allocator(), name); 424 res = parentScope->FindLocalTSVariable<binder::TSBindingType::NAMESPACE>(name); 425 if (isExport && parentScope->IsTSModuleScope()) { 426 parentScope->AsTSModuleScope()->AddExportTSVariable<binder::TSBindingType::NAMESPACE>(name, res); 427 } 428 res->AsNamespaceVariable()->SetExportBindings(Allocator()->New<binder::ExportBindings>(Allocator())); 429 } 430 binder::ExportBindings *exportBindings = res->AsNamespaceVariable()->GetExportBindings(); 431 432 auto *identNode = AllocNode<ir::Identifier>(name); 433 identNode->SetRange(lexer_->GetToken().Loc()); 434 435 lexer_->NextToken(); 436 437 ir::Statement *body = nullptr; 438 439 auto savedStatus = context_.Status(); 440 if (isDeclare) { 441 context_.Status() |= ParserStatus::IN_AMBIENT_CONTEXT; 442 } 443 444 auto localCtx = binder::LexicalScope<binder::TSModuleScope>(Binder(), exportBindings); 445 446 bool isInstantiated = IsInstantiatedInTsModuleBlock(&body); 447 if (isDeclare) { 448 isInstantiated = false; 449 } 450 451 context_.Status() = savedStatus; 452 453 auto *moduleDecl = AllocNode<ir::TSModuleDeclaration>(localCtx.GetScope(), identNode, body, 454 isDeclare, false, isInstantiated); 455 moduleDecl->SetRange({startLoc, lexer_->GetToken().End()}); 456 localCtx.GetScope()->BindNode(moduleDecl); 457 res->Declaration()->AsNamespaceDecl()->Add(moduleDecl); 458 459 return moduleDecl; 460} 461 462bool ParserImpl::IsInstantiatedInTsModuleBlock(ir::Statement **body) 463{ 464 bool isInstantiated = false; 465 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) { 466 lexer_->NextToken(); 467 lexer::SourcePosition moduleStart = lexer_->GetToken().Start(); 468 *body = ParseTsModuleOrNamespaceDelaration(moduleStart, false, true); 469 isInstantiated = (*body)->AsTSModuleDeclaration()->IsInstantiated(); 470 } else { 471 *body = ParseTsModuleBlock(); 472 auto statements = (*body)->AsTSModuleBlock()->Statements(); 473 for (auto *it : statements) { 474 auto statement = it; 475 if (LIKELY(statement != nullptr) && statement->IsExportNamedDeclaration()) { 476 statement = statement->AsExportNamedDeclaration()->Decl(); 477 } 478 if (statement != nullptr && !statement->IsTSInterfaceDeclaration() && 479 !statement->IsTSTypeAliasDeclaration() && 480 (!statement->IsTSModuleDeclaration() || statement->AsTSModuleDeclaration()->IsInstantiated())) { 481 isInstantiated = true; 482 break; 483 } 484 } 485 } 486 return isInstantiated; 487} 488 489ir::TSImportEqualsDeclaration *ParserImpl::ParseTsImportEqualsDeclaration(const lexer::SourcePosition &startLoc, 490 bool isExport) 491{ 492 ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_IMPORT); 493 lexer_->NextToken(); 494 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 495 ThrowSyntaxError("Unexpected token"); 496 } 497 498 auto *id = AllocNode<ir::Identifier>(lexer_->GetToken().Ident()); 499 id->SetRange(lexer_->GetToken().Loc()); 500 lexer_->NextToken(); // eat id name 501 502 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { 503 ThrowSyntaxError("'=' expected"); 504 } 505 lexer_->NextToken(); // eat substitution 506 507 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 508 ThrowSyntaxError("identifier expected"); 509 } 510 511 if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_REQUIRE || 512 lexer_->Lookahead() != LEX_CHAR_LEFT_PAREN) { 513 binder::DeclarationFlags declflag = binder::DeclarationFlags::NONE; 514 auto *decl = Binder()->AddDecl<binder::ImportEqualsDecl>(id->Start(), declflag, false, id->Name()); 515 decl->BindNode(id); 516 auto *scope = Binder()->GetScope(); 517 auto name = id->Name(); 518 auto *var = scope->FindLocalTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name); 519 CHECK_NOT_NULL(var); 520 var->AsImportEqualsVariable()->SetScope(scope); 521 if (isExport && scope->IsTSModuleScope()) { 522 scope->AsTSModuleScope()->AddExportTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name, var); 523 } 524 } 525 526 auto *importEqualsDecl = AllocNode<ir::TSImportEqualsDeclaration>(id, ParseModuleReference(), isExport); 527 importEqualsDecl->SetRange({startLoc, lexer_->GetToken().End()}); 528 529 ConsumeSemicolon(importEqualsDecl); 530 531 return importEqualsDecl; 532} 533 534ir::TSNamespaceExportDeclaration *ParserImpl::ParseTsNamespaceExportDeclaration(const lexer::SourcePosition &startLoc) 535{ 536 if (!IsDtsFile()) { 537 ThrowSyntaxError("namespace export declaration is only supported in TypeScript '.d.ts'"); 538 } 539 ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS); 540 lexer_->NextToken(); // eat as keyword 541 if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_NAMESPACE) { 542 ThrowSyntaxError("'namespace' expected"); 543 } 544 lexer_->NextToken(); // eat namespace keyword 545 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 546 ThrowSyntaxError("identifier expected"); 547 } 548 549 auto *id = AllocNode<ir::Identifier>(lexer_->GetToken().Ident()); 550 id->SetRange(lexer_->GetToken().Loc()); 551 lexer_->NextToken(); // eat identifier 552 553 auto *namespaceExportDecl = AllocNode<ir::TSNamespaceExportDeclaration>(id); 554 namespaceExportDecl->SetRange({startLoc, lexer_->GetToken().End()}); 555 556 ConsumeSemicolon(namespaceExportDecl); 557 558 return namespaceExportDecl; 559} 560 561ir::TSModuleBlock *ParserImpl::ParseTsModuleBlock() 562{ 563 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 564 ThrowSyntaxError("'{' expected."); 565 } 566 567 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 568 lexer_->NextToken(); 569 auto statements = ParseStatementList(); 570 571 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 572 ThrowSyntaxError("Expected a '}'"); 573 } 574 575 auto *blockNode = AllocNode<ir::TSModuleBlock>(std::move(statements)); 576 blockNode->SetRange({startLoc, lexer_->GetToken().End()}); 577 578 lexer_->NextToken(); 579 return blockNode; 580} 581 582ir::Statement *ParserImpl::ParseVarStatement(bool isDeclare) 583{ 584 auto *variableDecl = ParseVariableDeclaration(VariableParsingFlags::VAR, isDeclare); 585 ConsumeSemicolon(variableDecl); 586 return variableDecl; 587} 588 589ir::Statement *ParserImpl::ParseLetStatement(StatementParsingFlags flags, bool isDeclare) 590{ 591 if (!(flags & StatementParsingFlags::ALLOW_LEXICAL)) { 592 ThrowSyntaxError("The 'let' declarations can only be declared at the top level or inside a block."); 593 } 594 595 auto *variableDecl = ParseVariableDeclaration(VariableParsingFlags::LET, isDeclare); 596 ConsumeSemicolon(variableDecl); 597 return variableDecl; 598} 599 600ir::Statement *ParserImpl::ParseConstStatement(StatementParsingFlags flags, bool isDeclare) 601{ 602 lexer::SourcePosition constVarStar = lexer_->GetToken().Start(); 603 lexer_->NextToken(); 604 605 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ENUM) { 606 if (Extension() == ScriptExtension::TS) { 607 return ParseEnumDeclaration(false, isDeclare, true); 608 } 609 ThrowSyntaxError("Unexpected token"); 610 } 611 612 if (!(flags & StatementParsingFlags::ALLOW_LEXICAL)) { 613 ThrowSyntaxError("The 'const' declarations can only be declared at the top level or inside a block."); 614 } 615 616 auto *variableDecl = 617 ParseVariableDeclaration(VariableParsingFlags::CONST | VariableParsingFlags::NO_SKIP_VAR_KIND, isDeclare); 618 variableDecl->SetStart(constVarStar); 619 ConsumeSemicolon(variableDecl); 620 621 return variableDecl; 622} 623 624ir::EmptyStatement *ParserImpl::ParseEmptyStatement() 625{ 626 auto *empty = AllocNode<ir::EmptyStatement>(); 627 empty->SetRange(lexer_->GetToken().Loc()); 628 lexer_->NextToken(); 629 return empty; 630} 631 632ir::DebuggerStatement *ParserImpl::ParseDebuggerStatement() 633{ 634 auto *debuggerNode = AllocNode<ir::DebuggerStatement>(); 635 debuggerNode->SetRange(lexer_->GetToken().Loc()); 636 lexer_->NextToken(); 637 ConsumeSemicolon(debuggerNode); 638 return debuggerNode; 639} 640 641ir::Statement *ParserImpl::ParseFunctionStatement(StatementParsingFlags flags, bool isDeclare) 642{ 643 CheckFunctionDeclaration(flags); 644 645 if (!(flags & StatementParsingFlags::STMT_LEXICAL_SCOPE_NEEDED)) { 646 return ParseFunctionDeclaration(false, ParserStatus::NO_OPTS, isDeclare); 647 } 648 649 auto localCtx = binder::LexicalScope<binder::LocalScope>(Binder()); 650 ArenaVector<ir::Statement *> stmts(Allocator()->Adapter()); 651 auto *funcDecl = ParseFunctionDeclaration(false, ParserStatus::NO_OPTS, isDeclare); 652 stmts.push_back(funcDecl); 653 654 auto *localBlockStmt = AllocNode<ir::BlockStatement>(localCtx.GetScope(), std::move(stmts)); 655 localBlockStmt->SetRange(funcDecl->Range()); 656 localCtx.GetScope()->BindNode(localBlockStmt); 657 658 return funcDecl; 659} 660 661ir::Statement *ParserImpl::ParsePotentialExpressionStatement(StatementParsingFlags flags, bool isDeclare) 662{ 663 if (lexer_->Lookahead() == LEX_CHAR_COLON) { 664 const auto pos = lexer_->Save(); 665 lexer_->NextToken(); 666 return ParseLabelledStatement(pos); 667 } 668 669 if (Extension() == ScriptExtension::TS && IsTsDeclarationStatement()) { 670 switch (lexer_->GetToken().KeywordType()) { 671 case lexer::TokenType::KEYW_ENUM: { 672 return ParseEnumDeclaration(false, isDeclare, false); 673 } 674 case lexer::TokenType::KEYW_TYPE: { 675 return ParseTsTypeAliasDeclaration(isDeclare); 676 } 677 case lexer::TokenType::KEYW_INTERFACE: { 678 return ParseTsInterfaceDeclaration(isDeclare); 679 } 680 default: 681 break; 682 } 683 } 684 685 return ParseExpressionStatement(flags); 686} 687 688ir::ClassDeclaration *ParserImpl::ParseClassStatement(StatementParsingFlags flags, bool isDeclare, 689 ArenaVector<ir::Decorator *> &&decorators, 690 ArenaVector<ir::Annotation *> &&annotations, bool isAbstract) 691{ 692 if (!(flags & StatementParsingFlags::ALLOW_LEXICAL)) { 693 ThrowSyntaxError("Lexical 'class' declaration is not allowed in single statement context"); 694 } 695 696 return ParseClassDeclaration(true, std::move(decorators), std::move(annotations), isDeclare, isAbstract, false, 697 false); 698} 699 700ir::ClassDeclaration *ParserImpl::ParseClassDeclaration(bool idRequired, ArenaVector<ir::Decorator *> &&decorators, 701 ArenaVector<ir::Annotation *> &&annotations, bool isDeclare, 702 bool isAbstract, bool isExported, bool isAnnotation) 703{ 704 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 705 ir::ClassDefinition *classDefinition = ParseClassDefinition(true, idRequired, isDeclare, isAbstract); 706 if (isExported && !idRequired) { 707 classDefinition->SetAsExportDefault(); 708 } 709 710 if (!decorators.empty()) { 711 classDefinition->SetClassDecoratorPresent(); 712 } 713 714 auto location = classDefinition->Ident() ? classDefinition->Ident()->Start() : startLoc; 715 auto className = classDefinition->GetName(); 716 ASSERT(!className.Empty()); 717 718 binder::DeclarationFlags flag = isExported ? binder::DeclarationFlags::EXPORT : binder::DeclarationFlags::NONE; 719 auto *decl = Binder()->AddDecl<binder::ClassDecl>(location, flag, classDefinition->Declare(), className); 720 721 decl->BindNode(classDefinition); 722 723 lexer::SourcePosition endLoc = classDefinition->End(); 724 auto *classDecl = AllocNode<ir::ClassDeclaration>(classDefinition, std::move(decorators), std::move(annotations), 725 isAnnotation); 726 classDecl->SetRange({startLoc, endLoc}); 727 return classDecl; 728} 729 730ir::TSTypeAliasDeclaration *ParserImpl::ParseTsTypeAliasDeclaration(bool isDeclare) 731{ 732 ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE); 733 lexer::SourcePosition typeStart = lexer_->GetToken().Start(); 734 lexer_->NextToken(); // eat type keyword 735 736 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT && 737 !(lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT && isDeclare)) { 738 ThrowSyntaxError("Identifier expected"); 739 } 740 741 if (lexer_->GetToken().IsReservedTypeName()) { 742 std::string errMsg("Type alias name cannot be '"); 743 errMsg.append(TokenToString(lexer_->GetToken().KeywordType())); 744 errMsg.append("'"); 745 ThrowSyntaxError(errMsg.c_str()); 746 } 747 748 const util::StringView &ident = lexer_->GetToken().Ident(); 749 binder::TSBinding tsBinding(Allocator(), ident); 750 auto *decl = Binder()->AddTsDecl<binder::TypeAliasDecl>(lexer_->GetToken().Start(), isDeclare, tsBinding.View()); 751 752 auto *id = AllocNode<ir::Identifier>(ident); 753 id->SetRange(lexer_->GetToken().Loc()); 754 lexer_->NextToken(); 755 756 ir::TSTypeParameterDeclaration *typeParamDecl = nullptr; 757 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) { 758 typeParamDecl = ParseTsTypeParameterDeclaration(true, true); 759 } 760 761 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { 762 ThrowSyntaxError("'=' expected"); 763 } 764 765 lexer_->NextToken(); // eat '=' 766 767 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; 768 ir::Expression *typeAnnotation = ParseTsTypeAnnotation(&options); 769 770 auto *typeAliasDecl = AllocNode<ir::TSTypeAliasDeclaration>(id, typeParamDecl, typeAnnotation, isDeclare); 771 typeAliasDecl->SetRange({typeStart, lexer_->GetToken().End()}); 772 decl->BindNode(typeAliasDecl); 773 ConsumeSemicolon(typeAliasDecl); 774 775 return typeAliasDecl; 776} 777 778ir::TSInterfaceDeclaration *ParserImpl::ParseTsInterfaceDeclaration(bool isDeclare) 779{ 780 ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_INTERFACE); 781 context_.Status() |= ParserStatus::ALLOW_THIS_TYPE; 782 lexer::SourcePosition interfaceStart = lexer_->GetToken().Start(); 783 lexer_->NextToken(); // eat interface keyword 784 785 ValidateTsInterfaceName(isDeclare); 786 787 const util::StringView &ident = lexer_->GetToken().Ident(); 788 binder::TSBinding tsBinding(Allocator(), ident); 789 790 const auto &bindings = Binder()->GetScope()->Bindings(); 791 auto res = bindings.find(tsBinding.View()); 792 binder::InterfaceDecl *decl {}; 793 794 if (res == bindings.end()) { 795 decl = Binder()->AddTsDecl<binder::InterfaceDecl>(lexer_->GetToken().Start(), isDeclare, 796 Allocator(), tsBinding.View()); 797 } else if (!res->second->Declaration()->IsInterfaceDecl()) { 798 Binder()->ThrowRedeclaration(lexer_->GetToken().Start(), ident); 799 } else { 800 decl = res->second->Declaration()->AsInterfaceDecl(); 801 } 802 803 auto *id = AllocNode<ir::Identifier>(lexer_->GetToken().Ident()); 804 id->SetRange(lexer_->GetToken().Loc()); 805 id->SetReference(); 806 lexer_->NextToken(); 807 808 binder::LexicalScope<binder::LocalScope> localScope(Binder()); 809 810 ir::TSTypeParameterDeclaration *typeParamDecl = nullptr; 811 if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) { 812 typeParamDecl = ParseTsTypeParameterDeclaration(true, true); 813 } 814 815 ArenaVector<ir::TSInterfaceHeritage *> extends = ParseTsInterfaceExtends(); 816 817 lexer::SourcePosition bodyStart = lexer_->GetToken().Start(); 818 auto members = ParseTsTypeLiteralOrInterface(); 819 820 auto *body = AllocNode<ir::TSInterfaceBody>(std::move(members)); 821 body->SetRange({bodyStart, lexer_->GetToken().End()}); 822 823 auto *interfaceDecl = 824 AllocNode<ir::TSInterfaceDeclaration>(localScope.GetScope(), id, typeParamDecl, body, std::move(extends)); 825 interfaceDecl->SetRange({interfaceStart, lexer_->GetToken().End()}); 826 827 ASSERT(decl); 828 829 if (res == bindings.end()) { 830 decl->BindNode(interfaceDecl); 831 } 832 decl->AsInterfaceDecl()->Add(interfaceDecl); 833 834 lexer_->NextToken(); 835 context_.Status() &= ~ParserStatus::ALLOW_THIS_TYPE; 836 837 return interfaceDecl; 838} 839 840void ParserImpl::ValidateTsInterfaceName(bool isDeclare) 841{ 842 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT && 843 !(lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT && isDeclare)) { 844 ThrowSyntaxError("Identifier expected"); 845 } 846 847 if (lexer_->GetToken().IsReservedTypeName()) { 848 std::string errMsg("Interface name cannot be '"); 849 errMsg.append(TokenToString(lexer_->GetToken().KeywordType())); 850 errMsg.append("'"); 851 ThrowSyntaxError(errMsg.c_str()); 852 } 853} 854 855ArenaVector<ir::TSInterfaceHeritage *> ParserImpl::ParseTsInterfaceExtends() 856{ 857 ArenaVector<ir::TSInterfaceHeritage *> extends(Allocator()->Adapter()); 858 859 if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_EXTENDS) { 860 return extends; 861 } 862 863 lexer_->NextToken(); // eat extends keyword 864 while (true) { 865 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 866 ThrowSyntaxError("Identifier expected"); 867 } 868 const lexer::SourcePosition &heritageStart = lexer_->GetToken().Start(); 869 lexer::SourcePosition heritageEnd = lexer_->GetToken().End(); 870 ir::Expression *expr = AllocNode<ir::Identifier>(lexer_->GetToken().Ident()); 871 expr->AsIdentifier()->SetReference(); 872 expr->SetRange(lexer_->GetToken().Loc()); 873 if (lexer_->Lookahead() == LEX_CHAR_LESS_THAN) { 874 lexer_->ForwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1); 875 } else { 876 lexer_->NextToken(); 877 } 878 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) { 879 expr = ParseTsQualifiedReference(expr); 880 } 881 ir::TSTypeParameterInstantiation *typeParamInst = nullptr; 882 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) { 883 typeParamInst = ParseTsTypeParameterInstantiation(); 884 heritageEnd = typeParamInst->End(); 885 } 886 auto *typeReference = AllocNode<ir::TSTypeReference>(expr, typeParamInst); 887 typeReference->SetRange({heritageStart, heritageEnd}); 888 auto *heritage = AllocNode<ir::TSInterfaceHeritage>(typeReference); 889 heritage->SetRange(typeReference->Range()); 890 extends.push_back(heritage); 891 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 892 break; 893 } 894 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) { 895 ThrowSyntaxError("',' expected"); 896 } 897 lexer_->NextToken(); 898 } 899 900 return extends; 901} 902 903void ParserImpl::CheckFunctionDeclaration(StatementParsingFlags flags) 904{ 905 if (flags & StatementParsingFlags::ALLOW_LEXICAL) { 906 return; 907 } 908 909 if (lexer_->Lookahead() == LEX_CHAR_ASTERISK) { 910 ThrowSyntaxError("Generators can only be declared at the top level or inside a block."); 911 } 912 913 ThrowSyntaxError( 914 "In strict mode code, functions can only be " 915 "declared at top level, inside a block, " 916 "or " 917 "as the body of an if statement"); 918} 919 920void ParserImpl::ConsumeSemicolon(ir::Statement *statement) 921{ 922 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 923 statement->SetEnd(lexer_->GetToken().End()); 924 lexer_->NextToken(); 925 return; 926 } 927 928 if (!lexer_->GetToken().NewLine()) { 929 if (lexer_->GetToken().Type() != lexer::TokenType::EOS && 930 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 931 ThrowSyntaxError("Unexpected token"); 932 } 933 } 934} 935 936ArenaVector<ir::Statement *> ParserImpl::ParseStatementList(StatementParsingFlags flags) 937{ 938 ArenaVector<ir::Statement *> statements(Allocator()->Adapter()); 939 ParseDirectivePrologue(&statements); 940 941 auto endType = 942 (flags & StatementParsingFlags::GLOBAL) ? lexer::TokenType::EOS : lexer::TokenType::PUNCTUATOR_RIGHT_BRACE; 943 944 while (lexer_->GetToken().Type() != endType) { 945 statements.push_back(ParseStatement(flags)); 946 } 947 948 return statements; 949} 950 951bool ParserImpl::ParseDirective(ArenaVector<ir::Statement *> *statements) 952{ 953 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING); 954 955 const util::StringView &str = lexer_->GetToken().String(); 956 957 const auto status = static_cast<ParserStatus>( 958 context_.Status() & (ParserStatus::CONSTRUCTOR_FUNCTION | ParserStatus::HAS_COMPLEX_PARAM)); 959 if (status == ParserStatus::HAS_COMPLEX_PARAM && str.Is("use strict")) { 960 ThrowSyntaxError( 961 "Illegal 'use strict' directive in function with " 962 "non-simple parameter list"); 963 } 964 965 ir::Expression *exprNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 966 bool isDirective = exprNode->IsStringLiteral(); 967 968 auto *exprStatement = AllocNode<ir::ExpressionStatement>(exprNode); 969 exprStatement->SetRange(exprNode->Range()); 970 971 ConsumeSemicolon(exprStatement); 972 statements->push_back(exprStatement); 973 974 return isDirective; 975} 976 977void ParserImpl::ParseDirectivePrologue(ArenaVector<ir::Statement *> *statements) 978{ 979 while (true) { 980 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING || !ParseDirective(statements)) { 981 break; 982 } 983 } 984} 985 986ir::BlockStatement *ParserImpl::ParseBlockStatement(binder::Scope *scope) 987{ 988 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE); 989 990 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 991 lexer_->NextToken(); 992 auto statements = ParseStatementList(); 993 994 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 995 ThrowSyntaxError("Expected a '}'"); 996 } 997 998 auto *blockNode = AllocNode<ir::BlockStatement>(scope, std::move(statements)); 999 blockNode->SetRange({startLoc, lexer_->GetToken().End()}); 1000 scope->BindNode(blockNode); 1001 1002 return blockNode; 1003} 1004 1005ir::BlockStatement *ParserImpl::ParseBlockStatement() 1006{ 1007 auto localCtx = binder::LexicalScope<binder::LocalScope>(Binder()); 1008 auto *blockNode = ParseBlockStatement(localCtx.GetScope()); 1009 lexer_->NextToken(); 1010 return blockNode; 1011} 1012 1013ir::BreakStatement *ParserImpl::ParseBreakStatement() 1014{ 1015 bool allowBreak = (context_.Status() & (ParserStatus::IN_ITERATION | ParserStatus::IN_SWITCH)); 1016 1017 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 1018 lexer_->NextToken(); 1019 1020 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON || 1021 lexer_->GetToken().Type() == lexer::TokenType::EOS || lexer_->GetToken().NewLine() || 1022 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 1023 1024 if (!allowBreak && Extension() == ScriptExtension::JS) { 1025 ThrowSyntaxError("Illegal break statement"); 1026 } 1027 1028 if (!allowBreak && Extension() == ScriptExtension::TS) { 1029 if (context_.Status() & ParserStatus::FUNCTION) { 1030 ThrowSyntaxError("Jump target cannot cross function boundary"); 1031 } else { 1032 ThrowSyntaxError( 1033 "A 'break' statement can only be used within an " 1034 "enclosing iteration or switch statement"); 1035 } 1036 } 1037 1038 auto *breakStatement = AllocNode<ir::BreakStatement>(); 1039 breakStatement->SetRange({startLoc, lexer_->GetToken().End()}); 1040 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 1041 lexer_->NextToken(); 1042 } 1043 1044 return breakStatement; 1045 } 1046 1047 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 1048 ThrowSyntaxError("Unexpected token."); 1049 } 1050 1051 const auto &label = lexer_->GetToken().Ident(); 1052 1053 if (!context_.FindLabel(label)) { 1054 ThrowSyntaxError("Undefined label"); 1055 } 1056 1057 auto *identNode = AllocNode<ir::Identifier>(label); 1058 identNode->SetRange(lexer_->GetToken().Loc()); 1059 1060 auto *breakStatement = AllocNode<ir::BreakStatement>(identNode); 1061 breakStatement->SetRange({startLoc, lexer_->GetToken().End()}); 1062 1063 lexer_->NextToken(); 1064 ConsumeSemicolon(breakStatement); 1065 1066 return breakStatement; 1067} 1068 1069ir::ContinueStatement *ParserImpl::ParseContinueStatement() 1070{ 1071 if (Extension() == ScriptExtension::TS && 1072 (static_cast<ParserStatus>(context_.Status() & (ParserStatus::FUNCTION | ParserStatus::IN_ITERATION | 1073 ParserStatus::IN_SWITCH)) == ParserStatus::FUNCTION)) { 1074 ThrowSyntaxError("Jump target cannot cross function boundary"); 1075 } 1076 1077 if (!(context_.Status() & ParserStatus::IN_ITERATION)) { 1078 if (Extension() == ScriptExtension::JS) { 1079 ThrowSyntaxError("Illegal continue statement"); 1080 } 1081 if (Extension() == ScriptExtension::TS) { 1082 ThrowSyntaxError( 1083 "A 'continue' statement can only be used within an " 1084 "enclosing iteration statement"); 1085 } 1086 } 1087 1088 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 1089 lexer::SourcePosition endLoc = lexer_->GetToken().End(); 1090 lexer_->NextToken(); 1091 1092 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 1093 auto *continueStatement = AllocNode<ir::ContinueStatement>(); 1094 continueStatement->SetRange({startLoc, lexer_->GetToken().End()}); 1095 lexer_->NextToken(); 1096 return continueStatement; 1097 } 1098 1099 if (lexer_->GetToken().NewLine() || lexer_->GetToken().Type() == lexer::TokenType::EOS || 1100 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 1101 auto *continueStatement = AllocNode<ir::ContinueStatement>(); 1102 continueStatement->SetRange({startLoc, endLoc}); 1103 return continueStatement; 1104 } 1105 1106 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 1107 ThrowSyntaxError("Unexpected token."); 1108 } 1109 1110 const auto &label = lexer_->GetToken().Ident(); 1111 const ParserContext *labelCtx = context_.FindLabel(label); 1112 1113 if (!labelCtx || !(labelCtx->Status() & (ParserStatus::IN_ITERATION | ParserStatus::IN_LABELED)) || 1114 (labelCtx->Status() & ParserStatus::DISALLOW_CONTINUE)) { 1115 ThrowSyntaxError("Undefined label"); 1116 } 1117 1118 auto *identNode = AllocNode<ir::Identifier>(label); 1119 identNode->SetRange(lexer_->GetToken().Loc()); 1120 1121 auto *continueStatement = AllocNode<ir::ContinueStatement>(identNode); 1122 continueStatement->SetRange({startLoc, lexer_->GetToken().End()}); 1123 1124 lexer_->NextToken(); 1125 ConsumeSemicolon(continueStatement); 1126 1127 return continueStatement; 1128} 1129 1130ir::DoWhileStatement *ParserImpl::ParseDoWhileStatement() 1131{ 1132 auto *savedScope = Binder()->GetScope(); 1133 IterationContext<binder::LoopScope> iterCtx(&context_, Binder()); 1134 1135 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 1136 lexer_->NextToken(); 1137 ir::Statement *body = ParseStatement(); 1138 1139 if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_WHILE) { 1140 ThrowSyntaxError("Missing 'while' keyword in a 'DoWhileStatement'"); 1141 } 1142 1143 lexer_->NextToken(); 1144 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { 1145 ThrowSyntaxError("Missing left parenthesis in a 'DoWhileStatement'"); 1146 } 1147 1148 lexer_->NextToken(); 1149 ir::Expression *test = nullptr; 1150 1151 // The while expression should be included in the outer scope 1152 { 1153 auto outerScope = binder::LexicalScope<binder::Scope>::Enter(Binder(), savedScope); 1154 test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 1155 } 1156 1157 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 1158 ThrowSyntaxError("Missing right parenthesis in a 'DoWhileStatement'"); 1159 } 1160 1161 auto *doWhileStatement = AllocNode<ir::DoWhileStatement>(iterCtx.LexicalScope().GetScope(), body, test); 1162 doWhileStatement->SetRange({startLoc, lexer_->GetToken().End()}); 1163 iterCtx.LexicalScope().GetScope()->BindNode(doWhileStatement); 1164 1165 lexer_->NextToken(); 1166 1167 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 1168 doWhileStatement->SetEnd(lexer_->GetToken().End()); 1169 lexer_->NextToken(); 1170 } 1171 1172 return doWhileStatement; 1173} 1174 1175ir::FunctionDeclaration *ParserImpl::ParseFunctionDeclaration(bool canBeAnonymous, ParserStatus newStatus, 1176 bool isDeclare) 1177{ 1178 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 1179 1180 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION); 1181 ParserStatus savedStatus = context_.Status(); 1182 1183 lexer_->NextToken(); 1184 1185 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) { 1186 newStatus |= ParserStatus::GENERATOR_FUNCTION; 1187 lexer_->NextToken(); 1188 } 1189 1190 context_.Status() = savedStatus; 1191 1192 // e.g. export default function () {} 1193 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT && 1194 lexer_->GetToken().Type() != lexer::TokenType::KEYW_AWAIT) { 1195 if (canBeAnonymous) { 1196 ir::ScriptFunction *func = ParseFunction(newStatus, isDeclare); 1197 if (func->Body() != nullptr) { 1198 lexer_->NextToken(); 1199 } 1200 func->SetStart(startLoc); 1201 func->SetAsExportDefault(); 1202 1203 auto *funcDecl = AllocNode<ir::FunctionDeclaration>(func); 1204 funcDecl->SetRange(func->Range()); 1205 1206 binder::DeclarationFlags declflag = (newStatus & ParserStatus::EXPORT_REACHED) ? 1207 binder::DeclarationFlags::EXPORT : binder::DeclarationFlags::NONE; 1208 Binder()->AddDecl<binder::FunctionDecl>(startLoc, declflag, isDeclare, Allocator(), 1209 parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME, func); 1210 1211 return funcDecl; 1212 } 1213 1214 ThrowSyntaxError("Unexpected token, expected identifier after 'function' keyword"); 1215 } 1216 1217 if (!isDeclare) { 1218 CheckStrictReservedWord(); 1219 } 1220 1221 util::StringView ident = lexer_->GetToken().Ident(); 1222 1223 auto *identNode = AllocNode<ir::Identifier>(ident); 1224 identNode->SetRange(lexer_->GetToken().Loc()); 1225 lexer_->NextToken(); 1226 1227 newStatus |= ParserStatus::FUNCTION_DECLARATION; 1228 ir::ScriptFunction *func = ParseFunction(newStatus, isDeclare); 1229 if (func->Body() != nullptr) { 1230 lexer_->NextToken(); 1231 } 1232 1233 func->SetIdent(identNode); 1234 func->SetStart(startLoc); 1235 auto *funcDecl = AllocNode<ir::FunctionDeclaration>(func); 1236 funcDecl->SetRange(func->Range()); 1237 1238 AddFunctionToBinder(func, newStatus); 1239 1240 if (func->IsOverload() && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 1241 lexer_->NextToken(); 1242 } 1243 1244 CheckOptionalBindingPatternParameter(func); 1245 1246 return funcDecl; 1247} 1248 1249void ParserImpl::AddFunctionToBinder(ir::ScriptFunction *func, ParserStatus newStatus) 1250{ 1251 binder::DeclarationFlags declflag = (newStatus & ParserStatus::EXPORT_REACHED) ? 1252 binder::DeclarationFlags::EXPORT : binder::DeclarationFlags::NONE; 1253 const ir::Identifier *identNode = func->Id(); 1254 const lexer::SourcePosition &startLoc = func->Start(); 1255 const util::StringView ident = identNode->Name(); 1256 if (Extension() == ScriptExtension::TS) { 1257 const auto &bindings = Binder()->GetScope()->Bindings(); 1258 auto res = bindings.find(ident); 1259 binder::Decl *currentDecl = res == bindings.end() ? nullptr : res->second->Declaration(); 1260 binder::FunctionDecl *decl {}; 1261 1262 if (res == bindings.end() || 1263 (currentDecl->IsClassDecl() && currentDecl->AsClassDecl()->IsDeclare())) { 1264 decl = Binder()->AddDecl<binder::FunctionDecl>(identNode->Start(), declflag, func->Declare(), 1265 Allocator(), ident, func); 1266 } else { 1267 if (!currentDecl->IsFunctionDecl()) { 1268 Binder()->ThrowRedeclaration(startLoc, currentDecl->Name()); 1269 } 1270 1271 decl = currentDecl->AsFunctionDecl(); 1272 1273 if (!decl->Node()->AsScriptFunction()->IsOverload()) { 1274 Binder()->ThrowRedeclaration(startLoc, currentDecl->Name()); 1275 } 1276 if (!func->IsOverload()) { 1277 decl->BindNode(func); 1278 } 1279 } 1280 1281 decl->Add(func); 1282 } else { 1283 Binder()->AddDecl<binder::FunctionDecl>(identNode->Start(), declflag, func->Declare(), 1284 Allocator(), ident, func); 1285 } 1286} 1287 1288void ParserImpl::CheckOptionalBindingPatternParameter(ir::ScriptFunction *func) const 1289{ 1290 if (func->Declare() || func->IsOverload()) { 1291 return; 1292 } 1293 for (auto *it : func->Params()) { 1294 if ((it->IsObjectPattern() && it->AsObjectPattern()->Optional()) || 1295 (it->IsArrayPattern() && it->AsArrayPattern()->Optional())) { 1296 ThrowSyntaxError( 1297 "A binding pattern parameter cannot be optional in an " 1298 "implementation signature", it->Start()); 1299 } 1300 } 1301} 1302 1303ir::Statement *ParserImpl::ParseExpressionStatement(StatementParsingFlags flags) 1304{ 1305 const auto startPos = lexer_->Save(); 1306 ParserStatus savedStatus = context_.Status(); 1307 1308 if (lexer_->GetToken().IsAsyncModifier()) { 1309 context_.Status() |= ParserStatus::ASYNC_FUNCTION; 1310 lexer_->NextToken(); 1311 1312 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION && !lexer_->GetToken().NewLine()) { 1313 if (!(flags & StatementParsingFlags::ALLOW_LEXICAL)) { 1314 ThrowSyntaxError("Async functions can only be declared at the top level or inside a block."); 1315 } 1316 1317 ir::FunctionDeclaration *functionDecl = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION); 1318 functionDecl->SetStart(startPos.token.Start()); 1319 1320 return functionDecl; 1321 } 1322 1323 lexer_->Rewind(startPos); 1324 } 1325 1326 ir::Expression *exprNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 1327 context_.Status() = savedStatus; 1328 lexer::SourcePosition endPos = exprNode->End(); 1329 1330 auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(exprNode); 1331 exprStatementNode->SetRange({startPos.token.Start(), endPos}); 1332 ConsumeSemicolon(exprStatementNode); 1333 1334 return exprStatementNode; 1335} 1336 1337std::tuple<ForStatementKind, ir::Expression *, ir::Expression *> ParserImpl::ParseForInOf( 1338 ir::AstNode *initNode, ExpressionParseFlags exprFlags, bool isAwait) 1339{ 1340 ForStatementKind forKind = ForStatementKind::UPDATE; 1341 ir::Expression *updateNode = nullptr; 1342 ir::Expression *rightNode = nullptr; 1343 1344 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN || 1345 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OF) { 1346 const ir::VariableDeclarator *varDecl = initNode->AsVariableDeclaration()->Declarators().front(); 1347 1348 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN) { 1349 if (varDecl->Init()) { 1350 ThrowSyntaxError("for-in loop variable declaration may not have an initializer"); 1351 } 1352 forKind = ForStatementKind::IN; 1353 exprFlags = ExpressionParseFlags::ACCEPT_COMMA; 1354 } else { 1355 if (varDecl->Init()) { 1356 ThrowSyntaxError("for-of loop variable declaration may not have an initializer"); 1357 } 1358 1359 forKind = ForStatementKind::OF; 1360 } 1361 1362 lexer_->NextToken(); 1363 rightNode = ParseExpression(exprFlags); 1364 } else { 1365 if (isAwait) { 1366 ThrowSyntaxError("Unexpected token"); 1367 } 1368 1369 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 1370 ThrowSyntaxError("Invalid left-hand side in 'For[In/Of]Statement'"); 1371 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 1372 lexer_->NextToken(); 1373 } else { 1374 rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 1375 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 1376 ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'."); 1377 } 1378 lexer_->NextToken(); 1379 } 1380 1381 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 1382 updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 1383 } 1384 } 1385 1386 return {forKind, rightNode, updateNode}; 1387} 1388 1389std::tuple<ForStatementKind, ir::AstNode *, ir::Expression *, ir::Expression *> ParserImpl::ParseForInOf( 1390 ir::Expression *leftNode, ExpressionParseFlags exprFlags, bool isAwait) 1391{ 1392 ForStatementKind forKind = ForStatementKind::UPDATE; 1393 ir::AstNode *initNode = nullptr; 1394 ir::Expression *updateNode = nullptr; 1395 ir::Expression *rightNode = nullptr; 1396 1397 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN || 1398 (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OF)) { 1399 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN) { 1400 forKind = ForStatementKind::IN; 1401 exprFlags = ExpressionParseFlags::ACCEPT_COMMA; 1402 } else { 1403 forKind = ForStatementKind::OF; 1404 } 1405 1406 bool isValid = true; 1407 switch (leftNode->Type()) { 1408 case ir::AstNodeType::IDENTIFIER: { 1409 constexpr std::string_view ASYNC = "async"; 1410 if (isAwait || !(forKind == ForStatementKind::OF && leftNode->AsIdentifier()->Name().Is(ASYNC) && 1411 leftNode->End().index - leftNode->Start().index == ASYNC.length())) { 1412 break; 1413 } 1414 ThrowSyntaxError(" The left-hand side of a for-of loop may not be 'async'", leftNode->Start()); 1415 } 1416 case ir::AstNodeType::MEMBER_EXPRESSION: { 1417 break; 1418 } 1419 case ir::AstNodeType::ARRAY_EXPRESSION: { 1420 isValid = leftNode->AsArrayExpression()->ConvertibleToArrayPattern(); 1421 break; 1422 } 1423 case ir::AstNodeType::OBJECT_EXPRESSION: { 1424 isValid = leftNode->AsObjectExpression()->ConvertibleToObjectPattern(); 1425 break; 1426 } 1427 default: { 1428 isValid = false; 1429 } 1430 } 1431 1432 if (!isValid) { 1433 ValidateLvalueAssignmentTarget(leftNode); 1434 } 1435 1436 initNode = leftNode; 1437 lexer_->NextToken(); 1438 rightNode = ParseExpression(exprFlags); 1439 1440 return {forKind, initNode, rightNode, updateNode}; 1441 } 1442 1443 if (isAwait) { 1444 ThrowSyntaxError("Unexpected token"); 1445 } 1446 1447 exprFlags &= ExpressionParseFlags::POTENTIALLY_IN_PATTERN; 1448 ir::Expression *expr = ParseAssignmentExpression(leftNode, exprFlags); 1449 1450 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) { 1451 initNode = ParseSequenceExpression(expr); 1452 } else { 1453 initNode = expr; 1454 } 1455 1456 if (initNode->IsConditionalExpression()) { 1457 ir::ConditionalExpression *condExpr = initNode->AsConditionalExpression(); 1458 if (condExpr->Alternate()->IsBinaryExpression()) { 1459 const auto *binaryExpr = condExpr->Alternate()->AsBinaryExpression(); 1460 if (binaryExpr->OperatorType() == lexer::TokenType::KEYW_IN) { 1461 ThrowSyntaxError("Invalid left-hand side in for-in statement"); 1462 } 1463 } 1464 } 1465 1466 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 1467 ThrowSyntaxError("Invalid left-hand side in 'For[In/Of]Statement'"); 1468 } 1469 1470 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 1471 ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'."); 1472 } 1473 1474 lexer_->NextToken(); 1475 1476 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 1477 lexer_->NextToken(); 1478 } else { 1479 rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 1480 1481 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 1482 ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'."); 1483 } 1484 lexer_->NextToken(); 1485 } 1486 1487 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 1488 updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 1489 } 1490 1491 return {forKind, initNode, rightNode, updateNode}; 1492} 1493 1494std::tuple<ir::Expression *, ir::Expression *> ParserImpl::ParseForUpdate(bool isAwait) 1495{ 1496 if (isAwait) { 1497 ThrowSyntaxError("Unexpected token"); 1498 } 1499 1500 ir::Expression *updateNode = nullptr; 1501 ir::Expression *rightNode = nullptr; 1502 1503 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 1504 lexer_->NextToken(); 1505 } else { 1506 rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 1507 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 1508 ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'."); 1509 } 1510 lexer_->NextToken(); 1511 } 1512 1513 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 1514 updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 1515 } 1516 1517 return {rightNode, updateNode}; 1518} 1519 1520ir::Statement *ParserImpl::ParseForStatement() 1521{ 1522 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 1523 ForStatementKind forKind = ForStatementKind::UPDATE; 1524 ir::AstNode *initNode = nullptr; 1525 ir::Expression *updateNode = nullptr; 1526 ir::Expression *leftNode = nullptr; 1527 ir::Expression *rightNode = nullptr; 1528 bool canBeForInOf = true; 1529 bool isAwait = false; 1530 lexer_->NextToken(); 1531 VariableParsingFlags varFlags = VariableParsingFlags::STOP_AT_IN | VariableParsingFlags::IN_FOR; 1532 ExpressionParseFlags exprFlags = ExpressionParseFlags::NO_OPTS; 1533 1534 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) { 1535 isAwait = true; 1536 varFlags |= VariableParsingFlags::DISALLOW_INIT; 1537 lexer_->NextToken(); 1538 } 1539 1540 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { 1541 ThrowSyntaxError("Missing left parenthesis in a 'ForStatement'"); 1542 } 1543 lexer_->NextToken(); 1544 1545 IterationContext<binder::LoopScope> iterCtx(&context_, Binder()); 1546 1547 switch (lexer_->GetToken().Type()) { 1548 case lexer::TokenType::KEYW_VAR: { 1549 initNode = ParseVariableDeclaration(varFlags | VariableParsingFlags::VAR); 1550 break; 1551 } 1552 case lexer::TokenType::KEYW_LET: { 1553 initNode = ParseVariableDeclaration(varFlags | VariableParsingFlags::LET); 1554 break; 1555 } 1556 case lexer::TokenType::KEYW_CONST: { 1557 initNode = ParseVariableDeclaration(varFlags | VariableParsingFlags::CONST | 1558 VariableParsingFlags::ACCEPT_CONST_NO_INIT); 1559 break; 1560 } 1561 case lexer::TokenType::PUNCTUATOR_SEMI_COLON: { 1562 if (isAwait) { 1563 ThrowSyntaxError("Unexpected token"); 1564 } 1565 1566 canBeForInOf = false; 1567 lexer_->NextToken(); 1568 break; 1569 } 1570 default: { 1571 leftNode = ParseUnaryOrPrefixUpdateExpression(ExpressionParseFlags::POTENTIALLY_IN_PATTERN); 1572 1573 break; 1574 } 1575 } 1576 1577 if (initNode != nullptr) { 1578 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 1579 lexer_->NextToken(); 1580 canBeForInOf = false; 1581 } else { 1582 canBeForInOf = initNode->AsVariableDeclaration()->Declarators().size() == 1; 1583 } 1584 } 1585 1586 // VariableDeclaration->DeclarationSize > 1 or seen semi_colon 1587 if (!canBeForInOf) { 1588 std::tie(rightNode, updateNode) = ParseForUpdate(isAwait); 1589 } else if (leftNode) { 1590 // initNode was parsed as LHS 1591 if (leftNode->IsArrayExpression() || leftNode->IsObjectExpression()) { 1592 exprFlags |= ExpressionParseFlags::POTENTIALLY_IN_PATTERN; 1593 } 1594 std::tie(forKind, initNode, rightNode, updateNode) = ParseForInOf(leftNode, exprFlags, isAwait); 1595 } else if (initNode) { 1596 // initNode was parsed as VariableDeclaration and declaration size = 1 1597 std::tie(forKind, rightNode, updateNode) = ParseForInOf(initNode, exprFlags, isAwait); 1598 } 1599 1600 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 1601 ThrowSyntaxError("Unexpected token, expected ')' in 'ForStatement'."); 1602 } 1603 lexer_->NextToken(); 1604 1605 ir::Statement *bodyNode = ParseStatement(); 1606 lexer::SourcePosition endLoc = bodyNode->End(); 1607 1608 ir::Statement *forStatement = nullptr; 1609 auto *loopScope = iterCtx.LexicalScope().GetScope(); 1610 1611 if (forKind == ForStatementKind::UPDATE) { 1612 forStatement = AllocNode<ir::ForUpdateStatement>(loopScope, initNode, rightNode, updateNode, bodyNode); 1613 } else if (forKind == ForStatementKind::IN) { 1614 forStatement = AllocNode<ir::ForInStatement>(loopScope, initNode, rightNode, bodyNode); 1615 } else { 1616 forStatement = AllocNode<ir::ForOfStatement>(loopScope, initNode, rightNode, bodyNode, isAwait); 1617 } 1618 1619 forStatement->SetRange({startLoc, endLoc}); 1620 loopScope->BindNode(forStatement); 1621 1622 return forStatement; 1623} 1624 1625ir::IfStatement *ParserImpl::ParseIfStatement() 1626{ 1627 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 1628 lexer::SourcePosition endLoc = lexer_->GetToken().End(); 1629 lexer_->NextToken(); 1630 1631 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { 1632 ThrowSyntaxError("Missing left parenthesis in an 'IfStatement'"); 1633 } 1634 1635 lexer_->NextToken(); 1636 ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 1637 1638 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 1639 ThrowSyntaxError("Missing right parenthesis in an 'IfStatement'"); 1640 } 1641 1642 lexer_->NextToken(); 1643 ir::Statement *consequent = ParseStatement(StatementParsingFlags::IF_ELSE); 1644 1645 if (Extension() == ScriptExtension::TS && consequent->IsEmptyStatement()) { 1646 ThrowSyntaxError("The body of an if statement cannot be the empty statement"); 1647 } 1648 1649 endLoc = consequent->End(); 1650 ir::Statement *alternate = nullptr; 1651 1652 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_ELSE) { 1653 lexer_->NextToken(); // eat ELSE keyword 1654 alternate = ParseStatement(StatementParsingFlags::IF_ELSE); 1655 endLoc = alternate->End(); 1656 } 1657 1658 auto *ifStatement = AllocNode<ir::IfStatement>(test, consequent, alternate); 1659 ifStatement->SetRange({startLoc, endLoc}); 1660 return ifStatement; 1661} 1662 1663ir::LabelledStatement *ParserImpl::ParseLabelledStatement(const lexer::LexerPosition &pos) 1664{ 1665 const auto savedPos = lexer_->Save(); 1666 bool isLabelFollowedByIterationStatement = IsLabelFollowedByIterationStatement(); 1667 lexer_->Rewind(savedPos); 1668 1669 const util::StringView &actualLabel = pos.token.Ident(); 1670 1671 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AWAIT && context_.IsModule()) { 1672 ThrowSyntaxError("'await' is a reserved identifier in module code", pos.token.Start()); 1673 } 1674 1675 if (context_.FindLabel(actualLabel)) { 1676 ThrowSyntaxError("Label already declared", pos.token.Start()); 1677 } 1678 1679 SavedParserContext newCtx(this, ParserStatus::IN_LABELED | context_.Status(), actualLabel); 1680 if (isLabelFollowedByIterationStatement) { 1681 context_.Status() &= ~ParserStatus::DISALLOW_CONTINUE; 1682 } else { 1683 context_.Status() |= ParserStatus::DISALLOW_CONTINUE; 1684 } 1685 1686 auto *identNode = AllocNode<ir::Identifier>(actualLabel); 1687 identNode->SetRange(pos.token.Loc()); 1688 1689 lexer_->NextToken(); 1690 1691 ir::Statement *body = ParseStatement(StatementParsingFlags::LABELLED); 1692 1693 auto *labeledStatement = AllocNode<ir::LabelledStatement>(identNode, body); 1694 labeledStatement->SetRange({pos.token.Start(), body->End()}); 1695 1696 return labeledStatement; 1697} 1698 1699ir::ReturnStatement *ParserImpl::ParseReturnStatement() 1700{ 1701 if (!(context_.Status() & ParserStatus::FUNCTION)) { 1702 ThrowSyntaxError("return keyword should be used in function body"); 1703 } 1704 1705 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 1706 lexer::SourcePosition endLoc = lexer_->GetToken().End(); 1707 lexer_->NextToken(); 1708 1709 bool hasArgument = (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON && 1710 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE && 1711 lexer_->GetToken().Type() != lexer::TokenType::EOS && !lexer_->GetToken().NewLine()); 1712 1713 ir::ReturnStatement *returnStatement = nullptr; 1714 1715 if (hasArgument) { 1716 ir::Expression *expression = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 1717 endLoc = expression->End(); 1718 returnStatement = AllocNode<ir::ReturnStatement>(expression); 1719 } else { 1720 returnStatement = AllocNode<ir::ReturnStatement>(); 1721 } 1722 1723 returnStatement->SetRange({startLoc, endLoc}); 1724 ConsumeSemicolon(returnStatement); 1725 1726 return returnStatement; 1727} 1728 1729ir::SwitchCaseStatement *ParserImpl::ParseSwitchCaseStatement(bool *seenDefault) 1730{ 1731 lexer::SourcePosition caseStartLoc = lexer_->GetToken().Start(); 1732 ir::Expression *testExpr = nullptr; 1733 1734 switch (lexer_->GetToken().Type()) { 1735 case lexer::TokenType::KEYW_CASE: { 1736 lexer_->NextToken(); 1737 testExpr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 1738 break; 1739 } 1740 case lexer::TokenType::KEYW_DEFAULT: { 1741 if (*seenDefault) { 1742 if (Extension() == ScriptExtension::TS) { 1743 ThrowSyntaxError( 1744 "A 'default' clause cannot appear more than once in a " 1745 "'switch' statement"); 1746 } else { 1747 ThrowSyntaxError("Multiple default clauses."); 1748 } 1749 } 1750 *seenDefault = true; 1751 lexer_->NextToken(); 1752 break; 1753 } 1754 default: { 1755 ThrowSyntaxError("Unexpected token, expected 'case' or 'default'."); 1756 } 1757 } 1758 1759 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) { 1760 ThrowSyntaxError("Unexpected token, expected ':'"); 1761 } 1762 1763 ArenaVector<ir::Statement *> consequents(Allocator()->Adapter()); 1764 lexer::SourcePosition caseEndLoc = lexer_->GetToken().End(); 1765 1766 lexer_->NextToken(); 1767 1768 while (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CASE && 1769 lexer_->GetToken().Type() != lexer::TokenType::KEYW_DEFAULT && 1770 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 1771 ir::Statement *consequent = ParseStatement(StatementParsingFlags::ALLOW_LEXICAL); 1772 caseEndLoc = consequent->End(); 1773 consequents.push_back(consequent); 1774 } 1775 1776 auto *caseNode = AllocNode<ir::SwitchCaseStatement>(testExpr, std::move(consequents)); 1777 caseNode->SetRange({caseStartLoc, caseEndLoc}); 1778 return caseNode; 1779} 1780 1781ir::SwitchStatement *ParserImpl::ParseSwitchStatement() 1782{ 1783 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 1784 lexer_->NextToken(); 1785 if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS)) { 1786 ThrowSyntaxError("Unexpected token, expected '('"); 1787 } 1788 1789 lexer_->NextToken(); 1790 ir::Expression *discriminant = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 1791 1792 if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS)) { 1793 ThrowSyntaxError("Unexpected token, expected ')'"); 1794 } 1795 1796 lexer_->NextToken(); 1797 SwitchContext switchContext(&context_); 1798 1799 if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE)) { 1800 ThrowSyntaxError("Unexpected token, expected '{'"); 1801 } 1802 1803 lexer_->NextToken(); 1804 bool seenDefault = false; 1805 auto localCtx = binder::LexicalScope<binder::LocalScope>(Binder()); 1806 ArenaVector<ir::SwitchCaseStatement *> cases(Allocator()->Adapter()); 1807 1808 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 1809 cases.push_back(ParseSwitchCaseStatement(&seenDefault)); 1810 } 1811 1812 auto *switchStatement = AllocNode<ir::SwitchStatement>(localCtx.GetScope(), discriminant, std::move(cases)); 1813 switchStatement->SetRange({startLoc, lexer_->GetToken().End()}); 1814 localCtx.GetScope()->BindNode(switchStatement); 1815 1816 lexer_->NextToken(); 1817 1818 return switchStatement; 1819} 1820 1821ir::ThrowStatement *ParserImpl::ParseThrowStatement() 1822{ 1823 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 1824 lexer_->NextToken(); 1825 1826 if (lexer_->GetToken().NewLine()) { 1827 if (Extension() == ScriptExtension::JS) { 1828 ThrowSyntaxError("Illegal newline after throw"); 1829 } 1830 1831 if (Extension() == ScriptExtension::TS) { 1832 ThrowSyntaxError("Line break not permitted here"); 1833 } 1834 } 1835 1836 ir::Expression *expression = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 1837 lexer::SourcePosition endLoc = expression->End(); 1838 1839 auto *throwStatement = AllocNode<ir::ThrowStatement>(expression); 1840 throwStatement->SetRange({startLoc, endLoc}); 1841 ConsumeSemicolon(throwStatement); 1842 1843 return throwStatement; 1844} 1845 1846ir::Expression *ParserImpl::ParseCatchParam() 1847{ 1848 ir::Expression *param = nullptr; 1849 1850 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { 1851 return param; 1852 } 1853 1854 lexer_->NextToken(); // eat left paren 1855 1856 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) { 1857 switch (lexer_->GetToken().KeywordType()) { 1858 case lexer::TokenType::KEYW_EVAL: { 1859 ThrowSyntaxError("Binding 'eval' in strict mode is invalid"); 1860 } 1861 case lexer::TokenType::KEYW_ARGUMENTS: { 1862 ThrowSyntaxError("Binding 'arguments' in strict mode is invalid"); 1863 } 1864 default: { 1865 break; 1866 } 1867 } 1868 1869 param = AllocNode<ir::Identifier>(lexer_->GetToken().Ident()); 1870 param->SetRange(lexer_->GetToken().Loc()); 1871 1872 lexer_->NextToken(); 1873 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) { 1874 param = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN); 1875 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 1876 param = ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN); 1877 } else { 1878 ThrowSyntaxError("Unexpected token in catch parameter"); 1879 } 1880 1881 Binder()->AddParamDecl(param); 1882 1883 if (Extension() == ScriptExtension::TS) { 1884 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { 1885 lexer_->NextToken(); // eat ':' 1886 1887 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; 1888 param->SetTsTypeAnnotation(ParseTsTypeAnnotation(&options)); 1889 } 1890 1891 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { 1892 ThrowSyntaxError("Catch clause variable cannot have an initializer"); 1893 } 1894 } 1895 1896 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 1897 ThrowSyntaxError("Unexpected token, expected ')'"); 1898 } 1899 1900 lexer_->NextToken(); 1901 1902 return param; 1903} 1904 1905ir::CatchClause *ParserImpl::ParseCatchClause() 1906{ 1907 lexer::SourcePosition catchStartLoc = lexer_->GetToken().Start(); 1908 lexer_->NextToken(); // eat 'catch' keyword 1909 1910 auto catchParamCtx = binder::LexicalScope<binder::CatchParamScope>(Binder()); 1911 auto *catchParamScope = catchParamCtx.GetScope(); 1912 1913 ir::Expression *param = ParseCatchParam(); 1914 catchParamScope->BindNode(param); 1915 1916 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 1917 ThrowSyntaxError("Unexpected token, expected '{'"); 1918 } 1919 1920 auto catchCtx = binder::LexicalScope<binder::CatchScope>(Binder()); 1921 auto *catchScope = catchCtx.GetScope(); 1922 catchScope->AssignParamScope(catchParamScope); 1923 1924 ir::BlockStatement *catchBlock = ParseBlockStatement(catchScope); 1925 lexer_->NextToken(); 1926 lexer::SourcePosition endLoc = catchBlock->End(); 1927 1928 auto *catchClause = AllocNode<ir::CatchClause>(catchScope, param, catchBlock); 1929 catchClause->SetRange({catchStartLoc, endLoc}); 1930 catchScope->BindNode(catchClause); 1931 1932 return catchClause; 1933} 1934 1935ir::TryStatement *ParserImpl::ParseTryStatement() 1936{ 1937 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 1938 lexer::SourcePosition endLoc = lexer_->GetToken().End(); 1939 1940 lexer_->NextToken(); 1941 1942 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 1943 ThrowSyntaxError("Unexpected token, expected '{'"); 1944 } 1945 1946 ir::BlockStatement *body = ParseBlockStatement(); 1947 1948 if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CATCH && 1949 lexer_->GetToken().Type() != lexer::TokenType::KEYW_FINALLY) { 1950 ThrowSyntaxError("Missing catch or finally clause"); 1951 } 1952 1953 ir::CatchClause *catchClause = nullptr; 1954 ir::BlockStatement *finnalyClause = nullptr; 1955 1956 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_CATCH) { 1957 catchClause = ParseCatchClause(); 1958 endLoc = catchClause->End(); 1959 } 1960 1961 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FINALLY) { 1962 lexer_->NextToken(); // eat 'finally' keyword 1963 1964 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 1965 ThrowSyntaxError("Unexpected token, expected '{'"); 1966 } 1967 1968 finnalyClause = ParseBlockStatement(); 1969 endLoc = finnalyClause->End(); 1970 } 1971 1972 auto *tryStatement = AllocNode<ir::TryStatement>(body, catchClause, finnalyClause); 1973 tryStatement->SetRange({startLoc, endLoc}); 1974 return tryStatement; 1975} 1976 1977void ParserImpl::ValidateDeclaratorId(bool isDeclare) 1978{ 1979 if (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT) { 1980 return; 1981 } 1982 1983 switch (lexer_->GetToken().KeywordType()) { 1984 case lexer::TokenType::KEYW_AWAIT: { 1985 if (context_.IsModule() && !program_.IsDtsFile() && !context_.IsTsModule() && !isDeclare) { 1986 ThrowSyntaxError("'await' is not permitted as an identifier in module code"); 1987 } 1988 break; 1989 } 1990 case lexer::TokenType::KEYW_EVAL: { 1991 ThrowSyntaxError("Binding 'eval' in strict mode is invalid"); 1992 } 1993 case lexer::TokenType::KEYW_ARGUMENTS: { 1994 ThrowSyntaxError("Binding 'arguments' in strict mode is invalid"); 1995 } 1996 case lexer::TokenType::KEYW_LET: { 1997 ThrowSyntaxError("let is disallowed as a lexically bound name"); 1998 break; 1999 } 2000 case lexer::TokenType::KEYW_STATIC: 2001 case lexer::TokenType::KEYW_IMPLEMENTS: 2002 case lexer::TokenType::KEYW_INTERFACE: 2003 case lexer::TokenType::KEYW_PACKAGE: 2004 case lexer::TokenType::KEYW_PRIVATE: 2005 case lexer::TokenType::KEYW_PROTECTED: 2006 case lexer::TokenType::KEYW_PUBLIC: 2007 case lexer::TokenType::KEYW_YIELD: { 2008 ThrowSyntaxError("Unexpected reserved word"); 2009 } 2010 default: { 2011 break; 2012 } 2013 } 2014} 2015 2016ir::VariableDeclarator *ParserImpl::ParseVariableDeclaratorInitializer(ir::Expression *init, VariableParsingFlags flags, 2017 const lexer::SourcePosition &startLoc, 2018 bool isDeclare) 2019{ 2020 if (flags & VariableParsingFlags::DISALLOW_INIT) { 2021 ThrowSyntaxError("for-await-of loop variable declaration may not have an initializer"); 2022 } 2023 2024 lexer_->NextToken(); 2025 2026 if (isDeclare && !(flags & VariableParsingFlags::CONST)) { 2027 ThrowSyntaxError("Initializers are not allowed in ambient contexts."); 2028 } 2029 2030 auto exprFlags = 2031 ((flags & VariableParsingFlags::STOP_AT_IN) ? ExpressionParseFlags::STOP_AT_IN : ExpressionParseFlags::NO_OPTS); 2032 2033 ir::Expression *initializer = ParseExpression(exprFlags); 2034 lexer::SourcePosition endLoc = initializer->End(); 2035 2036 auto *declarator = AllocNode<ir::VariableDeclarator>(init, initializer); 2037 declarator->SetRange({startLoc, endLoc}); 2038 2039 return declarator; 2040} 2041 2042ir::VariableDeclarator *ParserImpl::ParseVariableDeclarator(VariableParsingFlags flags, bool isDeclare) 2043{ 2044 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 2045 2046 bool isDefinite = false; 2047 ir::Expression *init = ParseVariableDeclaratorKey(flags, isDeclare, &isDefinite); 2048 2049 ir::VariableDeclarator *declarator {}; 2050 2051 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { 2052 declarator = ParseVariableDeclaratorInitializer(init, flags, startLoc, isDeclare); 2053 } else { 2054 if (!isDeclare && (flags & VariableParsingFlags::CONST) && 2055 !(flags & VariableParsingFlags::ACCEPT_CONST_NO_INIT) && 2056 !(context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT)) { 2057 ThrowSyntaxError("Missing initializer in const declaration"); 2058 } 2059 2060 if (!isDeclare && !(flags & VariableParsingFlags::IN_FOR) && 2061 (init->IsArrayPattern() || init->IsObjectPattern())) { 2062 ThrowSyntaxError("Missing initializer in destructuring declaration"); 2063 } 2064 2065 lexer::SourcePosition endLoc = init->End(); 2066 declarator = AllocNode<ir::VariableDeclarator>(init); 2067 declarator->SetRange({startLoc, endLoc}); 2068 } 2069 2070 declarator->SetDefinite(isDefinite); 2071 2072 std::vector<const ir::Identifier *> bindings = util::Helpers::CollectBindingNames(init); 2073 2074 for (const auto *binding : bindings) { 2075 binder::Decl *decl = nullptr; 2076 binder::DeclarationFlags declflag = (flags & VariableParsingFlags::EXPORTED) ? 2077 binder::DeclarationFlags::EXPORT : binder::DeclarationFlags::NONE; 2078 if (flags & VariableParsingFlags::EXPORTED_IN_TSMODULE) { 2079 declflag |= binder::DeclarationFlags::EXPORT_IN_TSMODULE; 2080 } 2081 2082 if (flags & VariableParsingFlags::VAR) { 2083 decl = Binder()->AddDecl<binder::VarDecl>(startLoc, declflag, isDeclare, binding->Name()); 2084 } else if (flags & VariableParsingFlags::LET) { 2085 decl = Binder()->AddDecl<binder::LetDecl>(startLoc, declflag, isDeclare, binding->Name()); 2086 } else { 2087 decl = Binder()->AddDecl<binder::ConstDecl>(startLoc, declflag, isDeclare, binding->Name()); 2088 } 2089 2090 decl->BindNode(init); 2091 } 2092 2093 return declarator; 2094} 2095 2096ir::Expression *ParserImpl::ParseVariableDeclaratorKey(VariableParsingFlags flags, bool isDeclare, bool *isDefinite) 2097{ 2098 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT && isDeclare) { 2099 lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT); 2100 } 2101 2102 ir::Expression *init = nullptr; 2103 switch (lexer_->GetToken().Type()) { 2104 case lexer::TokenType::LITERAL_IDENT: { 2105 ValidateDeclaratorId(isDeclare); 2106 2107 if (!(flags & VariableParsingFlags::VAR) && 2108 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_LET) { 2109 ThrowSyntaxError("let is disallowed as a lexically bound name"); 2110 } 2111 2112 const util::StringView &identStr = lexer_->GetToken().Ident(); 2113 init = AllocNode<ir::Identifier>(identStr); 2114 init->SetRange(lexer_->GetToken().Loc()); 2115 2116 if (Extension() == ScriptExtension::TS) { 2117 init->AsIdentifier()->SetReference(); 2118 } 2119 2120 lexer_->NextToken(); 2121 break; 2122 } 2123 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: { 2124 init = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN); 2125 break; 2126 } 2127 case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { 2128 init = ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN); 2129 break; 2130 } 2131 default: { 2132 ThrowSyntaxError("Unexpected token in variable declaration"); 2133 } 2134 } 2135 2136 if (Extension() == ScriptExtension::TS) { 2137 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) { 2138 lexer_->NextToken(); // eat '!' 2139 *isDefinite = true; 2140 } 2141 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { 2142 lexer_->NextToken(); // eat ':' 2143 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; 2144 init->SetTsTypeAnnotation(ParseTsTypeAnnotation(&options)); 2145 } 2146 } 2147 2148 return init; 2149} 2150 2151ir::Statement *ParserImpl::ParseVariableDeclaration(VariableParsingFlags flags, bool isDeclare, bool isExport) 2152{ 2153 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 2154 if (!(flags & VariableParsingFlags::NO_SKIP_VAR_KIND)) { 2155 lexer_->NextToken(); 2156 } 2157 2158 if ((flags & VariableParsingFlags::LET) && util::Helpers::IsGlobalIdentifier(lexer_->GetToken().Ident())) { 2159 ThrowSyntaxError("Declaration name conflicts with built-in global identifier '" 2160 + lexer_->GetToken().Ident().Mutf8() + "'."); 2161 } 2162 2163 if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ENUM) { 2164 if (!(flags & VariableParsingFlags::CONST)) { 2165 ThrowSyntaxError("Variable declaration expected."); 2166 } 2167 return ParseEnumDeclaration(isExport, isDeclare, true); 2168 } 2169 2170 ArenaVector<ir::VariableDeclarator *> declarators(Allocator()->Adapter()); 2171 2172 while (true) { 2173 ir::VariableDeclarator *declarator = ParseVariableDeclarator(flags, isDeclare); 2174 2175 declarators.push_back(declarator); 2176 2177 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) { 2178 break; 2179 } 2180 lexer_->NextToken(); 2181 } 2182 2183 auto varKind = ir::VariableDeclaration::VariableDeclarationKind::VAR; 2184 2185 if (flags & VariableParsingFlags::LET) { 2186 varKind = ir::VariableDeclaration::VariableDeclarationKind::LET; 2187 } else if (flags & VariableParsingFlags::CONST) { 2188 varKind = ir::VariableDeclaration::VariableDeclarationKind::CONST; 2189 } 2190 2191 lexer::SourcePosition endLoc = declarators.back()->End(); 2192 auto *declaration = AllocNode<ir::VariableDeclaration>(varKind, std::move(declarators), isDeclare); 2193 declaration->SetRange({startLoc, endLoc}); 2194 2195 return declaration; 2196} 2197 2198ir::WhileStatement *ParserImpl::ParseWhileStatement() 2199{ 2200 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 2201 lexer_->NextToken(); 2202 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { 2203 ThrowSyntaxError("Unexpected token, expected '('"); 2204 } 2205 2206 lexer_->NextToken(); 2207 ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 2208 2209 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 2210 ThrowSyntaxError("Unexpected token, expected ')'"); 2211 } 2212 2213 lexer_->NextToken(); 2214 IterationContext<binder::LoopScope> iterCtx(&context_, Binder()); 2215 ir::Statement *body = ParseStatement(); 2216 2217 lexer::SourcePosition endLoc = body->End(); 2218 auto *whileStatement = AllocNode<ir::WhileStatement>(iterCtx.LexicalScope().GetScope(), test, body); 2219 whileStatement->SetRange({startLoc, endLoc}); 2220 iterCtx.LexicalScope().GetScope()->BindNode(whileStatement); 2221 2222 return whileStatement; 2223} 2224 2225void ParserImpl::AddImportEntryItem(const ir::StringLiteral *source, 2226 const ArenaVector<ir::AstNode *> *specifiers, bool isType, bool isLazy) 2227{ 2228 if (context_.IsTsModule()) { 2229 return; 2230 } 2231 2232 ASSERT(source != nullptr); 2233 2234 if (specifiers == nullptr) { 2235 if (isType) { 2236 ThrowSyntaxError("Unexpected import type syntax", source->Start()); 2237 } 2238 auto *moduleRecord = GetSourceTextModuleRecord(); 2239 ASSERT(moduleRecord != nullptr); 2240 moduleRecord->AddModuleRequest(source->Str()); 2241 return; 2242 } 2243 2244 for (auto *it : *specifiers) { 2245 if (!it->IsImportDefaultSpecifier() && !it->IsImportNamespaceSpecifier() && !it->IsImportSpecifier()) { 2246 ThrowSyntaxError("Unexpected astNode type", it->Start()); 2247 } 2248 if (it->IsImportSpecifier()) { 2249 AddImportEntryItemForImportSpecifier(source, it, isLazy); 2250 } else { 2251 AddImportEntryItemForImportDefaultOrNamespaceSpecifier(source, it, isType); 2252 } 2253 } 2254} 2255 2256void ParserImpl::AddImportEntryItemForImportSpecifier(const ir::StringLiteral *source, const ir::AstNode *specifier, 2257 bool isLazy) 2258{ 2259 auto *moduleRecord = specifier->AsImportSpecifier()->IsType() ? 2260 GetSourceTextTypeModuleRecord() : GetSourceTextModuleRecord(); 2261 ASSERT(moduleRecord != nullptr); 2262 int moduleRequestIdx = moduleRecord->AddModuleRequest(source->Str(), isLazy); 2263 2264 auto localName = specifier->AsImportSpecifier()->Local()->Name(); 2265 auto importName = specifier->AsImportSpecifier()->Imported()->Name(); 2266 auto localId = specifier->AsImportSpecifier()->Local(); 2267 auto importId = specifier->AsImportSpecifier()->Imported(); 2268 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ImportEntry>( 2269 localName, importName, moduleRequestIdx, localId, importId); 2270 moduleRecord->AddImportEntry(entry); 2271} 2272 2273void ParserImpl::AddImportEntryItemForImportDefaultOrNamespaceSpecifier(const ir::StringLiteral *source, 2274 const ir::AstNode *specifier, bool isType) 2275{ 2276 auto *moduleRecord = isType ? GetSourceTextTypeModuleRecord() : GetSourceTextModuleRecord(); 2277 ASSERT(moduleRecord != nullptr); 2278 auto moduleRequestIdx = moduleRecord->AddModuleRequest(source->Str()); 2279 2280 if (specifier->IsImportDefaultSpecifier()) { 2281 auto localName = specifier->AsImportDefaultSpecifier()->Local()->Name(); 2282 auto importName = parser::SourceTextModuleRecord::DEFAULT_EXTERNAL_NAME; 2283 auto localId = specifier->AsImportDefaultSpecifier()->Local(); 2284 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ImportEntry>( 2285 localName, importName, moduleRequestIdx, localId, nullptr); 2286 moduleRecord->AddImportEntry(entry); 2287 } else if (specifier->IsImportNamespaceSpecifier()) { 2288 auto localName = specifier->AsImportNamespaceSpecifier()->Local()->Name(); 2289 auto localId = specifier->AsImportNamespaceSpecifier()->Local(); 2290 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ImportEntry>( 2291 localName, moduleRequestIdx, localId); 2292 moduleRecord->AddStarImportEntry(entry); 2293 } 2294} 2295 2296void ParserImpl::AddExportNamedEntryItem(const ArenaVector<ir::ExportSpecifier *> &specifiers, 2297 const ir::StringLiteral *source, bool isType) 2298{ 2299 // The exported objects in the TSModuleScope do not need to be allocated index. 2300 if (context_.IsTsModule()) { 2301 ASSERT(Binder()->GetScope()->IsTSModuleScope()); 2302 return; 2303 } 2304 2305 if (source) { 2306 for (auto *it : specifiers) { 2307 auto exportSpecifier = it->AsExportSpecifier(); 2308 auto moduleRecord = 2309 exportSpecifier->IsType() ? GetSourceTextTypeModuleRecord() : GetSourceTextModuleRecord(); 2310 ASSERT(moduleRecord != nullptr); 2311 auto moduleRequestIdx = moduleRecord->AddModuleRequest(source->Str()); 2312 2313 auto importName = exportSpecifier->Local()->Name(); 2314 auto exportName = exportSpecifier->Exported()->Name(); 2315 auto importId = exportSpecifier->Local(); 2316 auto exportId = exportSpecifier->Exported(); 2317 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>( 2318 exportName, importName, moduleRequestIdx, exportId, importId); 2319 if (!moduleRecord->AddIndirectExportEntry(entry)) { 2320 ThrowSyntaxError("Duplicate export name of '" + exportName.Mutf8() + "'", 2321 exportSpecifier->Start()); 2322 } 2323 } 2324 } else { 2325 for (auto *it : specifiers) { 2326 auto exportSpecifier = it->AsExportSpecifier(); 2327 auto moduleRecord = 2328 exportSpecifier->IsType() ? GetSourceTextTypeModuleRecord() : GetSourceTextModuleRecord(); 2329 ASSERT(moduleRecord != nullptr); 2330 2331 auto exportName = exportSpecifier->Exported()->Name(); 2332 auto localName = exportSpecifier->Local()->Name(); 2333 auto exportId = exportSpecifier->Exported(); 2334 auto localId = exportSpecifier->Local(); 2335 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>( 2336 exportName, localName, exportId, localId); 2337 if (!moduleRecord->AddLocalExportEntry(entry)) { 2338 ThrowSyntaxError("Duplicate export name of '" + exportName.Mutf8() + "'", 2339 exportSpecifier->Start()); 2340 } 2341 } 2342 } 2343} 2344 2345void ParserImpl::AddExportStarEntryItem(const lexer::SourcePosition &startLoc, const ir::StringLiteral *source, 2346 const ir::Identifier *exported) 2347{ 2348 auto moduleRecord = GetSourceTextModuleRecord(); 2349 ASSERT(moduleRecord != nullptr); 2350 ASSERT(source != nullptr); 2351 auto moduleRequestIdx = moduleRecord->AddModuleRequest(source->Str()); 2352 2353 if (exported != nullptr) { 2354 /* Transform [NamespaceExport] into [NamespaceImport] & [LocalExport] 2355 * e.g. export * as ns from 'test.js' 2356 * ---> 2357 * import * as [internalName] from 'test.js' 2358 * export { [internalName] as ns } 2359 */ 2360 auto namespaceExportInternalName = GetNamespaceExportInternalName(); 2361 auto *decl = Binder()->AddDecl<binder::ConstDecl>(startLoc, binder::DeclarationFlags::EXPORT, 2362 false, namespaceExportInternalName); 2363 decl->BindNode(exported); 2364 2365 auto *importEntry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ImportEntry>( 2366 namespaceExportInternalName, moduleRequestIdx, nullptr); 2367 auto *exportEntry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>( 2368 exported->Name(), namespaceExportInternalName, exported, nullptr); 2369 moduleRecord->AddStarImportEntry(importEntry); 2370 if (!moduleRecord->AddLocalExportEntry(exportEntry)) { 2371 ThrowSyntaxError("Duplicate export name of '" + exported->Name().Mutf8() + "'", exported->Start()); 2372 } 2373 return; 2374 } 2375 2376 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(moduleRequestIdx); 2377 moduleRecord->AddStarExportEntry(entry); 2378} 2379 2380void ParserImpl::AddExportDefaultEntryItem(const ir::AstNode *declNode) 2381{ 2382 if (context_.IsTsModule()) { 2383 return; 2384 } 2385 2386 ASSERT(declNode != nullptr); 2387 if (declNode->IsTSInterfaceDeclaration() || 2388 (declNode->IsFunctionDeclaration() && declNode->AsFunctionDeclaration()->Function()->IsOverload())) { 2389 return; 2390 } 2391 2392 auto moduleRecord = GetSourceTextModuleRecord(); 2393 ASSERT(moduleRecord != nullptr); 2394 util::StringView exportName = parser::SourceTextModuleRecord::DEFAULT_EXTERNAL_NAME; 2395 util::StringView localName = parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME; 2396 if (declNode->IsFunctionDeclaration() || declNode->IsClassDeclaration()) { 2397 localName = declNode->IsFunctionDeclaration() ? declNode->AsFunctionDeclaration()->Function()->GetName() : 2398 declNode->AsClassDeclaration()->Definition()->GetName(); 2399 } 2400 2401 ASSERT(!localName.Empty()); 2402 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>( 2403 exportName, localName, nullptr, nullptr); 2404 if (!moduleRecord->AddLocalExportEntry(entry)) { 2405 ThrowSyntaxError("Duplicate export name of '" + exportName.Mutf8() + "'", declNode->Start()); 2406 } 2407} 2408 2409void ParserImpl::AddExportLocalEntryItem(const ir::Statement *declNode, bool isTsModule) 2410{ 2411 ASSERT(declNode != nullptr); 2412 auto moduleRecord = GetSourceTextModuleRecord(); 2413 ASSERT(isTsModule || moduleRecord != nullptr); 2414 binder::TSModuleScope *tsModuleScope = nullptr; 2415 if (isTsModule) { 2416 ASSERT(Binder()->GetScope()->IsTSModuleScope()); 2417 tsModuleScope = Binder()->GetScope()->AsTSModuleScope(); 2418 } 2419 if (declNode->IsVariableDeclaration()) { 2420 auto declarators = declNode->AsVariableDeclaration()->Declarators(); 2421 for (auto *decl : declarators) { 2422 std::vector<const ir::Identifier *> bindings = util::Helpers::CollectBindingNames(decl->Id()); 2423 for (const auto *binding : bindings) { 2424 if (isTsModule) { 2425 tsModuleScope->AddExportVariable(binding->Name()); 2426 } else { 2427 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>( 2428 binding->Name(), binding->Name(), binding, binding); 2429 if (!moduleRecord->AddLocalExportEntry(entry)) { 2430 ThrowSyntaxError("Duplicate export name of '" + binding->Name().Mutf8() 2431 + "'", binding->Start()); 2432 } 2433 } 2434 } 2435 } 2436 } 2437 if (declNode->IsFunctionDeclaration() || declNode->IsClassDeclaration()) { 2438 auto name = declNode->IsFunctionDeclaration() ? 2439 declNode->AsFunctionDeclaration()->Function()->Id() : 2440 declNode->AsClassDeclaration()->Definition()->Ident(); 2441 if (name == nullptr) { 2442 ThrowSyntaxError("A class or function declaration without the default modifier must have a name.", 2443 declNode->Start()); 2444 } 2445 if (declNode->IsFunctionDeclaration() && declNode->AsFunctionDeclaration()->Function()->IsOverload()) { 2446 return; 2447 } 2448 if (isTsModule) { 2449 tsModuleScope->AddExportVariable(name->Name()); 2450 } else { 2451 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>( 2452 name->Name(), name->Name(), name, name); 2453 if (!moduleRecord->AddLocalExportEntry(entry)) { 2454 ThrowSyntaxError("Duplicate export name of '" + name->Name().Mutf8() + "'", name->Start()); 2455 } 2456 } 2457 } 2458 AddTsTypeExportLocalEntryItem(declNode, isTsModule, tsModuleScope); 2459} 2460 2461void ParserImpl::AddTsTypeExportLocalEntryItem(const ir::Statement *declNode, bool isTsModule, 2462 binder::TSModuleScope *tsModuleScope) 2463{ 2464 if (!declNode->IsTSInterfaceDeclaration() && !declNode->IsTSTypeAliasDeclaration()) { 2465 return; 2466 } 2467 auto name = declNode->IsTSInterfaceDeclaration() ? 2468 declNode->AsTSInterfaceDeclaration()->Id() : declNode->AsTSTypeAliasDeclaration()->Id(); 2469 if (name == nullptr) { 2470 ThrowSyntaxError("An interface or type alias declaration must have a name."); 2471 } 2472 if (isTsModule) { 2473 binder::TSBinding tsBinding(Allocator(), name->Name()); 2474 tsModuleScope->AddExportVariable(tsBinding.View()); 2475 } 2476} 2477 2478ir::ExportDefaultDeclaration *ParserImpl::ParseExportDefaultDeclaration(const lexer::SourcePosition &startLoc, 2479 ArenaVector<ir::Decorator *> decorators, 2480 ArenaVector<ir::Annotation *> annotations, 2481 bool isExportEquals) 2482{ 2483 lexer_->NextToken(); // eat `default` keyword or `=` 2484 2485 ir::AstNode *declNode = nullptr; 2486 bool eatSemicolon = false; 2487 2488 if (!decorators.empty() && lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS && 2489 (context_.Status() & ParserStatus::IN_CLASS_BODY) == 0) { 2490 ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start()); 2491 } 2492 2493 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION) { 2494 declNode = ParseFunctionDeclaration(true, ParserStatus::EXPORT_REACHED); 2495 } else if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_CLASS) { 2496 declNode = ParseClassDeclaration(false, std::move(decorators), std::move(annotations), false, false, true); 2497 } else if (lexer_->GetToken().IsAsyncModifier()) { 2498 lexer_->NextToken(); // eat `async` keyword 2499 declNode = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION | ParserStatus::EXPORT_REACHED); 2500 } else if (Extension() == ScriptExtension::TS && 2501 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_INTERFACE) { 2502 declNode = ParseTsInterfaceDeclaration(false); 2503 } else if (Extension() == ScriptExtension::TS && 2504 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT) { 2505 lexer_->NextToken(); 2506 if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS) { 2507 ThrowSyntaxError("Unexpected token, expected 'class'."); 2508 } 2509 2510 if (!annotations.empty()) { 2511 ThrowSyntaxError("Annotations can not be used with abstract classes", annotations.front()->Start()); 2512 } 2513 2514 declNode = ParseClassDeclaration(false, std::move(decorators), std::move(annotations), false, true, true); 2515 } else { 2516 declNode = ParseExpression(); 2517 Binder()->AddDecl<binder::LetDecl>(declNode->Start(), binder::DeclarationFlags::EXPORT, 2518 false, parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME); 2519 eatSemicolon = true; 2520 } 2521 2522 // record default export entry 2523 if (!isExportEquals) { 2524 AddExportDefaultEntryItem(declNode); 2525 } 2526 2527 lexer::SourcePosition endLoc = declNode->End(); 2528 auto *exportDeclaration = AllocNode<ir::ExportDefaultDeclaration>(declNode, isExportEquals); 2529 exportDeclaration->SetRange({startLoc, endLoc}); 2530 2531 if (eatSemicolon) { 2532 ConsumeSemicolon(exportDeclaration); 2533 } 2534 2535 return exportDeclaration; 2536} 2537 2538ir::Identifier *ParserImpl::ParseNamedExport(const lexer::Token &exportedToken) 2539{ 2540 if (exportedToken.Type() != lexer::TokenType::LITERAL_IDENT) { 2541 ThrowSyntaxError("Unexpected token, expected an identifier."); 2542 } 2543 2544 const util::StringView &exportedString = exportedToken.Ident(); 2545 2546 auto *exported = AllocNode<ir::Identifier>(exportedString); 2547 exported->SetRange(exportedToken.Loc()); 2548 2549 return exported; 2550} 2551 2552ir::ExportAllDeclaration *ParserImpl::ParseExportAllDeclaration(const lexer::SourcePosition &startLoc) 2553{ 2554 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat `*` character 2555 2556 ir::Identifier *exported = nullptr; 2557 2558 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) { 2559 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); 2560 exported = ParseNamedExport(lexer_->GetToken()); 2561 lexer_->NextToken(); // eat exported name 2562 } 2563 2564 ir::StringLiteral *source = ParseFromClause(); 2565 lexer::SourcePosition endLoc = source->End(); 2566 2567 // record export star entry 2568 AddExportStarEntryItem(startLoc, source, exported); 2569 2570 ir::AssertClause *assertClause = nullptr; 2571 if (Extension() == ScriptExtension::TS && !lexer_->GetToken().NewLine() && 2572 lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && 2573 lexer_->GetToken().Ident().Is("assert")) { 2574 assertClause = ParseAssertClause(); 2575 } 2576 2577 auto *exportDeclaration = AllocNode<ir::ExportAllDeclaration>(source, exported, assertClause); 2578 exportDeclaration->SetRange({startLoc, endLoc}); 2579 2580 ConsumeSemicolon(exportDeclaration); 2581 2582 return exportDeclaration; 2583} 2584 2585ir::ExportNamedDeclaration *ParserImpl::ParseExportNamedSpecifiers(const lexer::SourcePosition &startLoc, 2586 bool isType) 2587{ 2588 if (Extension() == ScriptExtension::TS && context_.IsTsModule() && 2589 !(context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT)) { 2590 ThrowSyntaxError("Export declarations are not permitted in a namespace."); 2591 } 2592 2593 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat `{` character 2594 2595 ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter()); 2596 2597 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 2598 bool isTypeOfExportSpecifier = isType; 2599 if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE) { 2600 auto isTypeUsedAsKeyword = HandleTypeImportOrExportSpecifier(); 2601 if (isTypeUsedAsKeyword) { 2602 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat type 2603 if (isType) { 2604 ThrowSyntaxError("The type modifier cannot be used on a named export " 2605 "when 'export type' is used on its export statement."); 2606 } 2607 isTypeOfExportSpecifier = true; 2608 } 2609 } 2610 2611 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 2612 ThrowSyntaxError("Unexpected token"); 2613 } 2614 2615 lexer::Token localToken = lexer_->GetToken(); 2616 auto *local = AllocNode<ir::Identifier>(lexer_->GetToken().Ident()); 2617 local->SetRange(lexer_->GetToken().Loc()); 2618 2619 if (Extension() == ScriptExtension::TS) { 2620 local->SetReference(); 2621 } 2622 2623 lexer_->NextToken(); // eat local name 2624 2625 ir::Identifier *exported = nullptr; 2626 2627 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) { 2628 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat `as` literal 2629 exported = ParseNamedExport(lexer_->GetToken()); 2630 lexer_->NextToken(); // eat exported name 2631 } else { 2632 exported = ParseNamedExport(localToken); 2633 } 2634 2635 auto *specifier = AllocNode<ir::ExportSpecifier>(local, exported, isTypeOfExportSpecifier); 2636 specifier->SetRange({local->Start(), exported->End()}); 2637 2638 specifiers.push_back(specifier); 2639 2640 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) { 2641 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat comma 2642 } 2643 } 2644 2645 lexer::SourcePosition endPos = lexer_->GetToken().End(); 2646 lexer_->NextToken(); // eat right brace 2647 2648 ir::StringLiteral *source = nullptr; 2649 2650 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_FROM) { 2651 source = ParseFromClause(); 2652 } 2653 2654 // record ExportEntry 2655 AddExportNamedEntryItem(specifiers, source, isType); 2656 2657 ir::AssertClause *assertClause = nullptr; 2658 if (Extension() == ScriptExtension::TS && !lexer_->GetToken().NewLine() && 2659 lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && 2660 lexer_->GetToken().Ident().Is("assert")) { 2661 if (source == nullptr) { 2662 ThrowSyntaxError("';' expected."); 2663 } 2664 if (isType) { 2665 ThrowSyntaxError("Import assertions cannot be used with type-only imports or exports."); 2666 } 2667 assertClause = ParseAssertClause(); 2668 } 2669 2670 auto *exportDeclaration = AllocNode<ir::ExportNamedDeclaration>(source, std::move(specifiers), 2671 assertClause, isType); 2672 exportDeclaration->SetRange({startLoc, endPos}); 2673 ConsumeSemicolon(exportDeclaration); 2674 2675 return exportDeclaration; 2676} 2677 2678ir::ExportNamedDeclaration *ParserImpl::ParseNamedExportDeclaration(const lexer::SourcePosition &startLoc, 2679 ArenaVector<ir::Decorator *> &&decorators, 2680 ArenaVector<ir::Annotation *> &&annotations) 2681{ 2682 ir::Statement *decl = nullptr; 2683 2684 bool isDeclare = false; 2685 bool isTsModule = context_.IsTsModule(); 2686 2687 if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) { 2688 isDeclare = CheckDeclare(); 2689 } 2690 2691 if (!decorators.empty() && lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS && 2692 (context_.Status() & ParserStatus::IN_CLASS_BODY) == 0 && 2693 !(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && 2694 (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT))) { 2695 ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start()); 2696 } 2697 2698 if (!annotations.empty() && lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS && 2699 (context_.Status() & ParserStatus::IN_CLASS_BODY) == 0) { 2700 ThrowSyntaxError("Annotations can be used only with classes and class methods", annotations.front()->Start()); 2701 } 2702 2703 VariableParsingFlags flag = isTsModule ? 2704 VariableParsingFlags::EXPORTED_IN_TSMODULE : VariableParsingFlags::EXPORTED; 2705 ParserStatus status = isTsModule ? ParserStatus::NO_OPTS : ParserStatus::EXPORT_REACHED; 2706 2707 switch (lexer_->GetToken().Type()) { 2708 case lexer::TokenType::KEYW_VAR: { 2709 decl = ParseVariableDeclaration(flag | VariableParsingFlags::VAR, isDeclare, true); 2710 break; 2711 } 2712 case lexer::TokenType::KEYW_CONST: { 2713 decl = ParseVariableDeclaration(flag | VariableParsingFlags::CONST, isDeclare, true); 2714 break; 2715 } 2716 case lexer::TokenType::KEYW_LET: { 2717 decl = ParseVariableDeclaration(flag | VariableParsingFlags::LET, isDeclare, true); 2718 break; 2719 } 2720 case lexer::TokenType::KEYW_FUNCTION: { 2721 decl = ParseFunctionDeclaration(false, status, isDeclare); 2722 break; 2723 } 2724 case lexer::TokenType::KEYW_CLASS: { 2725 decl = ParseClassDeclaration(true, std::move(decorators), std::move(annotations), isDeclare || IsDtsFile(), 2726 false, !isTsModule); 2727 break; 2728 } 2729 case lexer::TokenType::PUNCTUATOR_AT: { 2730 lexer_->NextToken(); // eat @ symbol 2731 if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_INTERFACE) { 2732 ThrowSyntaxError("'interface' keyword expected."); 2733 } 2734 2735 if (!decorators.empty()) { 2736 ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start()); 2737 } 2738 2739 if (!annotations.empty()) { 2740 ThrowSyntaxError("Annotations can not be used with annotation declaration", 2741 annotations.front()->Start()); 2742 } 2743 decl = ParseClassDeclaration(true, std::move(decorators), std::move(annotations), isDeclare || IsDtsFile(), 2744 false, !isTsModule, true); 2745 break; 2746 } 2747 case lexer::TokenType::LITERAL_IDENT: { 2748 if (Extension() == ScriptExtension::TS) { 2749 switch (lexer_->GetToken().KeywordType()) { 2750 case lexer::TokenType::KEYW_LET: { 2751 decl = ParseVariableDeclaration(VariableParsingFlags::LET, isDeclare); 2752 break; 2753 } 2754 case lexer::TokenType::KEYW_ENUM: { 2755 decl = ParseEnumDeclaration(true, isDeclare, false); 2756 break; 2757 } 2758 case lexer::TokenType::KEYW_INTERFACE: { 2759 decl = ParseTsInterfaceDeclaration(isDeclare); 2760 break; 2761 } 2762 case lexer::TokenType::KEYW_TYPE: { 2763 decl = ParseTsTypeAliasDeclaration(isDeclare); 2764 break; 2765 } 2766 case lexer::TokenType::KEYW_GLOBAL: 2767 case lexer::TokenType::KEYW_MODULE: 2768 case lexer::TokenType::KEYW_NAMESPACE: { 2769 auto savedStatus = context_.Status(); 2770 if (isDeclare) { 2771 context_.Status() |= ParserStatus::IN_AMBIENT_CONTEXT; 2772 } 2773 decl = ParseTsModuleDeclaration(isDeclare, true); 2774 context_.Status() = savedStatus; 2775 break; 2776 } 2777 case lexer::TokenType::KEYW_ABSTRACT: { 2778 lexer_->NextToken(); // eat abstract keyword 2779 2780 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) { 2781 if (isDeclare) { 2782 ThrowSyntaxError("'declare' modifier already seen."); 2783 } 2784 lexer_->NextToken(); 2785 isDeclare = true; 2786 } 2787 2788 if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS) { 2789 ThrowSyntaxError("Unexpected token, expected 'class'."); 2790 } 2791 if (!annotations.empty()) { 2792 ThrowSyntaxError("Annotations can not be used with abstract classes", 2793 annotations.front()->Start()); 2794 } 2795 decl = ParseClassDeclaration(true, std::move(decorators), std::move(annotations), 2796 isDeclare || IsDtsFile(), true, !isTsModule); 2797 break; 2798 } 2799 default: { 2800 break; 2801 } 2802 } 2803 2804 if (decl) { 2805 break; 2806 } 2807 } 2808 2809 [[fallthrough]]; 2810 } 2811 default: { 2812 if (!lexer_->GetToken().IsAsyncModifier()) { 2813 ThrowSyntaxError("Unexpected token"); 2814 } 2815 2816 lexer_->NextToken(); // eat `async` keyword 2817 decl = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION | status); 2818 } 2819 } 2820 2821 if (decl->IsVariableDeclaration()) { 2822 ConsumeSemicolon(decl); 2823 } 2824 2825 AddExportLocalEntryItem(decl, isTsModule); 2826 2827 lexer::SourcePosition endLoc = decl->End(); 2828 ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter()); 2829 auto *exportDeclaration = AllocNode<ir::ExportNamedDeclaration>(decl, std::move(specifiers)); 2830 exportDeclaration->SetRange({startLoc, endLoc}); 2831 2832 return exportDeclaration; 2833} 2834 2835ir::Statement *ParserImpl::ParseExportDeclaration(StatementParsingFlags flags, 2836 ArenaVector<ir::Decorator *> &&decorators, 2837 ArenaVector<ir::Annotation *> &&annotations) 2838{ 2839 if (Extension() == ScriptExtension::JS || !context_.IsTsModule()) { 2840 if (!(flags & StatementParsingFlags::GLOBAL)) { 2841 ThrowSyntaxError("'import' and 'export' may only appear at the top level"); 2842 } 2843 2844 if (!context_.IsModule()) { 2845 ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'"); 2846 } 2847 } 2848 2849 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 2850 lexer_->NextToken(); // eat `export` keyword 2851 2852 // won't set `isType` for type alias 2853 bool isType = false; 2854 if (Extension() == ScriptExtension::TS && 2855 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE) { 2856 const auto savedPos = lexer_->Save(); 2857 lexer_->NextToken(); // eat type 2858 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 2859 isType = true; 2860 } else { 2861 lexer_->Rewind(savedPos); 2862 } 2863 } 2864 2865 switch (lexer_->GetToken().Type()) { 2866 case lexer::TokenType::KEYW_DEFAULT: { // export default Id 2867 return ParseExportDefaultDeclaration(startLoc, std::move(decorators), std::move(annotations)); 2868 } 2869 case lexer::TokenType::PUNCTUATOR_MULTIPLY: { // export * ... 2870 return ParseExportAllDeclaration(startLoc); 2871 } 2872 case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { // export { ... } ... 2873 return ParseExportNamedSpecifiers(startLoc, isType); 2874 } 2875 case lexer::TokenType::KEYW_IMPORT: { 2876 return ParseTsImportEqualsDeclaration(startLoc, true); 2877 } 2878 case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: { 2879 if (!annotations.empty()) { 2880 ThrowSyntaxError("Annotations can not be used with assignment expression", 2881 annotations.front()->Start()); 2882 } 2883 2884 if (Extension() == ScriptExtension::TS) { 2885 return ParseExportDefaultDeclaration(startLoc, std::move(decorators), std::move(annotations), true); 2886 } 2887 2888 [[fallthrough]]; 2889 } 2890 case lexer::TokenType::LITERAL_IDENT: { 2891 if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) { 2892 return ParseTsNamespaceExportDeclaration(startLoc); 2893 } 2894 2895 [[fallthrough]]; 2896 } 2897 default: { // export [var] id 2898 ir::ExportNamedDeclaration *exportDecl = ParseNamedExportDeclaration(startLoc, std::move(decorators), 2899 std::move(annotations)); 2900 2901 if (Extension() == ScriptExtension::TS && exportDecl->Decl()->IsVariableDeclaration() && 2902 !(flags & StatementParsingFlags::GLOBAL) && exportDecl->Parent() && 2903 !exportDecl->Parent()->IsTSModuleBlock() && !context_.IsModule()) { 2904 ThrowSyntaxError("Modifiers cannot appear here'"); 2905 } 2906 2907 return exportDecl; 2908 } 2909 } 2910} 2911 2912void ParserImpl::ParseNameSpaceImport(ArenaVector<ir::AstNode *> *specifiers, bool isType) 2913{ 2914 lexer::SourcePosition namespaceStart = lexer_->GetToken().Start(); 2915 lexer_->NextToken(); // eat `*` character 2916 2917 if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_AS) { 2918 ThrowSyntaxError("Unexpected token."); 2919 } 2920 2921 lexer_->NextToken(); // eat `as` literal 2922 2923 ir::Identifier *local = ParseNamedImport(lexer_->GetToken()); 2924 2925 auto *specifier = AllocNode<ir::ImportNamespaceSpecifier>(local); 2926 specifier->SetRange({namespaceStart, lexer_->GetToken().End()}); 2927 specifiers->push_back(specifier); 2928 2929 binder::Decl *decl = AddImportDecl(isType, local->Name(), namespaceStart, 2930 binder::DeclarationFlags::NAMESPACE_IMPORT); 2931 decl->BindNode(specifier); 2932 2933 lexer_->NextToken(); // eat local name 2934} 2935 2936binder::Decl *ParserImpl::AddImportDecl(bool isType, 2937 util::StringView name, 2938 lexer::SourcePosition startPos, 2939 binder::DeclarationFlags flag) 2940{ 2941 if (isType) { 2942 binder::TSBinding tsBinding(Allocator(), name); 2943 return Binder()->AddTsDecl<binder::TypeAliasDecl>(startPos, flag, false, tsBinding.View()); 2944 } 2945 return Binder()->AddDecl<binder::ConstDecl>(startPos, flag, false, name); 2946} 2947 2948ir::Identifier *ParserImpl::ParseNamedImport(const lexer::Token &importedToken) 2949{ 2950 if (importedToken.Type() != lexer::TokenType::LITERAL_IDENT) { 2951 ThrowSyntaxError("Unexpected token"); 2952 } 2953 2954 switch (importedToken.KeywordType()) { 2955 case lexer::TokenType::KEYW_EVAL: { 2956 ThrowSyntaxError("Binding 'eval' in strict mode is invalid"); 2957 } 2958 case lexer::TokenType::KEYW_ARGUMENTS: { 2959 ThrowSyntaxError("Binding 'arguments' in strict mode is invalid"); 2960 } 2961 default: { 2962 break; 2963 } 2964 } 2965 2966 auto *local = AllocNode<ir::Identifier>(importedToken.Ident()); 2967 local->SetRange(importedToken.Loc()); 2968 2969 return local; 2970} 2971 2972void ParserImpl::ParseNamedImportSpecifiers(ArenaVector<ir::AstNode *> *specifiers, bool isType, bool isLazy) 2973{ 2974 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat `{` character 2975 2976 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 2977 bool isTypeOfImportSpecifier = isType; 2978 if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE) { 2979 auto isTypeUsedAsKeyword = HandleTypeImportOrExportSpecifier(); 2980 if (isTypeUsedAsKeyword) { 2981 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat type 2982 isTypeOfImportSpecifier = true; 2983 } 2984 if (isTypeUsedAsKeyword && isType) { 2985 ThrowSyntaxError("The type modifier cannot be used on a named import " 2986 "when 'import type' is used on its import statement."); 2987 } 2988 } 2989 2990 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT || 2991 (Extension() == ScriptExtension::TS && lexer_->GetToken().Ident().Is("await"))) { 2992 ThrowSyntaxError("Unexpected token"); 2993 } 2994 2995 lexer::Token importedToken = lexer_->GetToken(); 2996 auto *imported = AllocNode<ir::Identifier>(importedToken.Ident()); 2997 ir::Identifier *local = nullptr; 2998 imported->SetRange(lexer_->GetToken().Loc()); 2999 3000 lexer_->NextToken(); // eat import name 3001 3002 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) { 3003 lexer_->NextToken(); // eat `as` literal 3004 local = ParseNamedImport(lexer_->GetToken()); 3005 lexer_->NextToken(); // eat local name 3006 } else { 3007 local = ParseNamedImport(importedToken); 3008 } 3009 3010 auto *specifier = AllocNode<ir::ImportSpecifier>(imported, local, isTypeOfImportSpecifier, isLazy); 3011 specifier->SetRange({imported->Start(), local->End()}); 3012 specifiers->push_back(specifier); 3013 3014 binder::Decl *decl = AddImportDecl(isTypeOfImportSpecifier, local->Name(), local->Start(), 3015 binder::DeclarationFlags::IMPORT); 3016 decl->BindNode(specifier); 3017 3018 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) { 3019 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat comma 3020 } else if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 3021 ThrowSyntaxError("Unexpected token"); 3022 } 3023 } 3024 3025 lexer_->NextToken(); // eat right brace 3026} 3027 3028bool ParserImpl::HandleTypeImportOrExportSpecifier() 3029{ 3030 bool isTypeUsedAsKeyword = false; 3031 const auto savedPos = lexer_->Save(); 3032 3033 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat type 3034 3035 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) { 3036 // {type as ...? } 3037 lexer_->NextToken(); // eat first as 3038 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) { 3039 // { type as as ...? } 3040 lexer_->NextToken(); // eat second as 3041 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) { 3042 // { type as as something } 3043 isTypeUsedAsKeyword = true; 3044 } else { 3045 // { type as as } 3046 isTypeUsedAsKeyword = false; 3047 } 3048 } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) { 3049 // { type as something } 3050 isTypeUsedAsKeyword = false; 3051 } else { 3052 // { type as } 3053 isTypeUsedAsKeyword = true; 3054 } 3055 } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) { 3056 // { type something ...? } 3057 isTypeUsedAsKeyword = true; 3058 } else { 3059 // { type } 3060 isTypeUsedAsKeyword = false; 3061 } 3062 3063 lexer_->Rewind(savedPos); 3064 return isTypeUsedAsKeyword; 3065} 3066 3067ir::Expression *ParserImpl::ParseModuleReference() 3068{ 3069 ir::Expression *result = nullptr; 3070 3071 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && 3072 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_REQUIRE && 3073 lexer_->Lookahead() == LEX_CHAR_LEFT_PAREN) { 3074 lexer::SourcePosition start = lexer_->GetToken().Start(); 3075 lexer_->NextToken(); // eat 'require' 3076 lexer_->NextToken(); // eat '(' 3077 3078 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) { 3079 ThrowSyntaxError("String literal expected."); 3080 } 3081 3082 result = AllocNode<ir::StringLiteral>(lexer_->GetToken().String()); 3083 result->SetRange(lexer_->GetToken().Loc()); 3084 lexer_->NextToken(); 3085 3086 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 3087 ThrowSyntaxError("')' expected."); 3088 } 3089 3090 result = AllocNode<ir::TSExternalModuleReference>(result); 3091 result->SetRange({start, lexer_->GetToken().End()}); 3092 lexer_->NextToken(); // eat ')' 3093 } else { 3094 result = AllocNode<ir::Identifier>(lexer_->GetToken().Ident()); 3095 result->SetRange(lexer_->GetToken().Loc()); 3096 lexer_->NextToken(); 3097 3098 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) { 3099 result = ParseTsQualifiedReference(result); 3100 } 3101 } 3102 3103 return result; 3104} 3105 3106ir::AstNode *ParserImpl::ParseImportDefaultSpecifier(ArenaVector<ir::AstNode *> *specifiers, bool isType) 3107{ 3108 ir::Identifier *local = ParseNamedImport(lexer_->GetToken()); 3109 lexer_->NextToken(); // eat local name 3110 3111 if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { 3112 lexer_->NextToken(); // eat substitution 3113 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 3114 ThrowSyntaxError("identifier expected"); 3115 } 3116 if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_REQUIRE || 3117 lexer_->Lookahead() != LEX_CHAR_LEFT_PAREN) { 3118 auto *decl = Binder()->AddDecl<binder::ImportEqualsDecl>(local->Start(), binder::DeclarationFlags::NONE, 3119 false, local->Name()); 3120 decl->BindNode(local); 3121 auto *scope = Binder()->GetScope(); 3122 auto *var = scope->FindLocalTSVariable<binder::TSBindingType::IMPORT_EQUALS>(local->Name()); 3123 CHECK_NOT_NULL(var); 3124 var->AsImportEqualsVariable()->SetScope(scope); 3125 } 3126 3127 auto *importEqualsDecl = AllocNode<ir::TSImportEqualsDeclaration>(local, ParseModuleReference(), false); 3128 3129 return importEqualsDecl; 3130 } 3131 3132 auto *specifier = AllocNode<ir::ImportDefaultSpecifier>(local); 3133 specifier->SetRange(specifier->Local()->Range()); 3134 specifiers->push_back(specifier); 3135 3136 binder::Decl *decl = AddImportDecl(isType, local->Name(), local->Start(), binder::DeclarationFlags::IMPORT); 3137 decl->BindNode(specifier); 3138 3139 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) { 3140 lexer_->NextToken(); // eat comma 3141 } else if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) { 3142 ThrowSyntaxError("Unexpected token."); 3143 } 3144 3145 return nullptr; 3146} 3147 3148ir::StringLiteral *ParserImpl::ParseFromClause(bool requireFrom) 3149{ 3150 if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) { 3151 if (requireFrom) { 3152 ThrowSyntaxError("Unexpected token."); 3153 } 3154 } else { 3155 lexer_->NextToken(); // eat `from` literal 3156 } 3157 3158 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) { 3159 ThrowSyntaxError("Unexpected token."); 3160 } 3161 3162 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING); 3163 3164 auto *source = AllocNode<ir::StringLiteral>(lexer_->GetToken().String()); 3165 source->SetRange(lexer_->GetToken().Loc()); 3166 3167 lexer_->NextToken(); 3168 3169 return source; 3170} 3171 3172ir::AstNode *ParserImpl::ParseImportSpecifiers(ArenaVector<ir::AstNode *> *specifiers, bool isType, bool isLazy) 3173{ 3174 ASSERT(specifiers->empty()); 3175 3176 // import [default] from 'source' 3177 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) { 3178 ir::AstNode *astNode = ParseImportDefaultSpecifier(specifiers, isType); 3179 if (astNode != nullptr) { 3180 return astNode; 3181 } 3182 } 3183 3184 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) { 3185 ParseNameSpaceImport(specifiers, isType); 3186 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 3187 ParseNamedImportSpecifiers(specifiers, isType, isLazy); 3188 } 3189 return nullptr; 3190} 3191 3192void ParserImpl::VerifySupportLazyImportVersion() 3193{ 3194 if (!util::Helpers::IsSupportLazyImportVersion(program_.TargetApiVersion(), program_.GetTargetApiSubVersion())) { 3195 std::string errMessage = "Current configuration does not support using lazy import. Lazy import can be " 3196 "used in the beta3 version of API 12 or higher versions.\n" 3197 "Solutions: > Check the compatibleSdkVersion and compatibleSdkVersionStage in build-profile.json5." 3198 "> If compatibleSdkVersion is set to API 12, then compatibleSdkVersionStage needs to be configured " 3199 "as beta3." 3200 "> If you're running es2abc in commandline without IDE, please check whether target-api-version and " 3201 "target-api-sub-version options are correctly configured."; 3202 ThrowSyntaxError(errMessage); 3203 } 3204} 3205 3206ir::Statement *ParserImpl::ParseImportDeclaration(StatementParsingFlags flags) 3207{ 3208 char32_t nextChar = lexer_->Lookahead(); 3209 // dynamic import || import.meta 3210 if (nextChar == LEX_CHAR_LEFT_PAREN || nextChar == LEX_CHAR_DOT) { 3211 return ParseExpressionStatement(); 3212 } 3213 3214 if (Extension() == ScriptExtension::JS) { 3215 if (!(flags & StatementParsingFlags::GLOBAL)) { 3216 ThrowSyntaxError("'import' and 'export' may only appear at the top level"); 3217 } 3218 3219 if (!context_.IsModule()) { 3220 ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'"); 3221 } 3222 } 3223 3224 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 3225 lexer_->NextToken(); // eat import 3226 3227 bool isLazy = false; 3228 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_LAZY) { 3229 const auto savedPos = lexer_->Save(); 3230 lexer_->NextToken(); // eat lazy 3231 // only support import lazy {xxx} from '...' 3232 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 3233 VerifySupportLazyImportVersion(); 3234 isLazy = true; 3235 } else { 3236 lexer_->Rewind(savedPos); 3237 } 3238 } 3239 3240 bool isType = false; 3241 if (Extension() == ScriptExtension::TS && 3242 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE) { 3243 const auto savedPos = lexer_->Save(); 3244 lexer_->NextToken(); // eat type 3245 if ((lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && 3246 lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) || 3247 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE || 3248 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) { 3249 isType = true; 3250 } else { 3251 lexer_->Rewind(savedPos); 3252 } 3253 } 3254 3255 ArenaVector<ir::AstNode *> specifiers(Allocator()->Adapter()); 3256 3257 ir::StringLiteral *source = nullptr; 3258 3259 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) { 3260 ir::AstNode *astNode = ParseImportSpecifiers(&specifiers, isType, isLazy); 3261 if (astNode != nullptr) { 3262 ASSERT(astNode->IsTSImportEqualsDeclaration()); 3263 astNode->SetRange({startLoc, lexer_->GetToken().End()}); 3264 ConsumeSemicolon(astNode->AsTSImportEqualsDeclaration()); 3265 return astNode->AsTSImportEqualsDeclaration(); 3266 } 3267 if (Extension() == ScriptExtension::TS && !context_.IsModule()) { 3268 ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'"); 3269 } 3270 source = ParseFromClause(true); 3271 AddImportEntryItem(source, &specifiers, isType, isLazy); 3272 } else { 3273 if (Extension() == ScriptExtension::TS && !context_.IsModule()) { 3274 ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'"); 3275 } 3276 // import 'source' 3277 source = ParseFromClause(false); 3278 AddImportEntryItem(source, nullptr, isType, isLazy); 3279 } 3280 3281 ir::AssertClause *assertClause = nullptr; 3282 if (Extension() == ScriptExtension::TS && !lexer_->GetToken().NewLine() && 3283 lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && 3284 lexer_->GetToken().Ident().Is("assert")) { 3285 if (isType) { 3286 ThrowSyntaxError("Import assertions cannot be used with type-only imports or exports."); 3287 } 3288 assertClause = ParseAssertClause(); 3289 } 3290 3291 lexer::SourcePosition endLoc = source->End(); 3292 auto *importDeclaration = AllocNode<ir::ImportDeclaration>(source, std::move(specifiers), 3293 assertClause, isType, isLazy); 3294 if (importDeclaration->Specifiers().empty() && program_.IsShared()) { 3295 ThrowSyntaxError("Arkts-no-side-effects-import is not allowed in shared module."); 3296 } 3297 importDeclaration->SetRange({startLoc, endLoc}); 3298 3299 ConsumeSemicolon(importDeclaration); 3300 3301 return importDeclaration; 3302} 3303 3304ir::AssertClause *ParserImpl::ParseAssertClause() 3305{ 3306 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 3307 lexer_->NextToken(); // eat assert 3308 3309 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 3310 ThrowSyntaxError("expected left brace."); 3311 } 3312 lexer_->NextToken(); // eat '{' 3313 3314 ArenaVector<ir::AssertEntry *> elements(Allocator()->Adapter()); 3315 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 3316 elements.push_back(ParseAssertEntry()); 3317 } 3318 3319 lexer_->NextToken(); // eat '}' 3320 3321 auto *assertClause = AllocNode<ir::AssertClause>(std::move(elements)); 3322 assertClause->SetRange({startLoc, lexer_->GetToken().End()}); 3323 3324 return assertClause; 3325} 3326 3327ir::AssertEntry *ParserImpl::ParseAssertEntry() 3328{ 3329 ir::Expression *key = nullptr; 3330 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) { 3331 key = AllocNode<ir::Identifier>(lexer_->GetToken().Ident()); 3332 key->SetRange(lexer_->GetToken().Loc()); 3333 } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) { 3334 key = AllocNode<ir::StringLiteral>(lexer_->GetToken().String()); 3335 key->SetRange(lexer_->GetToken().Loc()); 3336 } else { 3337 ThrowSyntaxError("Identifier or string literal expected."); 3338 } 3339 3340 lexer_->NextToken(); 3341 3342 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) { 3343 ThrowSyntaxError("':' expected."); 3344 } 3345 lexer_->NextToken(); // eat : 3346 3347 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) { 3348 ThrowSyntaxError("Import assertion values must be string literal expressions."); 3349 } 3350 3351 ir::StringLiteral *value = AllocNode<ir::StringLiteral>(lexer_->GetToken().String()); 3352 value->SetRange(lexer_->GetToken().Loc()); 3353 lexer_->NextToken(); 3354 3355 ASSERT(key); 3356 ASSERT(value); 3357 3358 auto *assertEntry = AllocNode<ir::AssertEntry>(key, value); 3359 assertEntry->SetRange({key->Start(), value->End()}); 3360 3361 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) { 3362 lexer_->NextToken(); // eat comma 3363 } 3364 3365 return assertEntry; 3366} 3367 3368} // namespace panda::es2panda::parser 3369