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