1/** 2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "ETSparser.h" 17#include "ETSNolintParser.h" 18#include <utility> 19 20#include "macros.h" 21#include "parser/parserFlags.h" 22#include "parser/parserStatusContext.h" 23#include "util/helpers.h" 24#include "util/language.h" 25#include "utils/arena_containers.h" 26#include "varbinder/varbinder.h" 27#include "varbinder/ETSBinder.h" 28#include "lexer/lexer.h" 29#include "lexer/ETSLexer.h" 30#include "ir/astNode.h" 31#include "ir/base/decorator.h" 32#include "ir/base/catchClause.h" 33#include "ir/base/scriptFunction.h" 34#include "ir/base/methodDefinition.h" 35#include "ir/base/spreadElement.h" 36#include "ir/statements/namespaceDeclaration.h" 37#include "ir/expressions/identifier.h" 38#include "ir/expressions/functionExpression.h" 39#include "ir/expressions/dummyNode.h" 40#include "ir/module/importDeclaration.h" 41#include "ir/module/importDefaultSpecifier.h" 42#include "ir/module/importSpecifier.h" 43#include "ir/module/exportSpecifier.h" 44#include "ir/module/exportNamedDeclaration.h" 45#include "ir/ets/etsPrimitiveType.h" 46#include "ir/ets/etsPackageDeclaration.h" 47#include "ir/ets/etsReExportDeclaration.h" 48#include "ir/ets/etsWildcardType.h" 49#include "ir/ets/etsTuple.h" 50#include "ir/ets/etsFunctionType.h" 51#include "ir/ets/etsScript.h" 52#include "ir/ets/etsTypeReference.h" 53#include "ir/ets/etsTypeReferencePart.h" 54#include "ir/ets/etsNullishTypes.h" 55#include "ir/ets/etsUnionType.h" 56#include "ir/ets/etsImportSource.h" 57#include "ir/ets/etsImportDeclaration.h" 58#include "ir/ets/etsStructDeclaration.h" 59#include "ir/module/importNamespaceSpecifier.h" 60#include "ir/ts/tsInterfaceDeclaration.h" 61#include "ir/ts/tsTypeParameterInstantiation.h" 62#include "ir/ts/tsInterfaceBody.h" 63#include "ir/ts/tsImportEqualsDeclaration.h" 64#include "ir/ts/tsArrayType.h" 65#include "ir/ts/tsQualifiedName.h" 66#include "ir/ts/tsTypeReference.h" 67#include "ir/ts/tsTypeParameter.h" 68#include "ir/ts/tsInterfaceHeritage.h" 69#include "ir/ts/tsFunctionType.h" 70#include "ir/ts/tsTypeAliasDeclaration.h" 71#include "ir/ts/tsTypeParameterDeclaration.h" 72#include "ir/ts/tsThisType.h" 73#include "generated/signatures.h" 74 75namespace ark::es2panda::parser { 76class FunctionContext; 77 78using namespace std::literals::string_literals; 79 80ETSParser::ETSParser(Program *program, const CompilerOptions &options, ParserStatus status) 81 : TypedParser(program, options, status), globalProgram_(GetProgram()) 82{ 83 importPathManager_ = std::make_unique<util::ImportPathManager>(Allocator(), ArkTSConfig(), GetOptions().stdLib); 84} 85 86bool ETSParser::IsETSParser() const noexcept 87{ 88 return true; 89} 90 91std::unique_ptr<lexer::Lexer> ETSParser::InitLexer(const SourceFile &sourceFile) 92{ 93 GetProgram()->SetSource(sourceFile); 94 auto lexer = std::make_unique<lexer::ETSLexer>(&GetContext()); 95 SetLexer(lexer.get()); 96 return lexer; 97} 98 99void ETSParser::ParseProgram(ScriptKind kind) 100{ 101 lexer::SourcePosition startLoc = Lexer()->GetToken().Start(); 102 Lexer()->NextToken(); 103 GetProgram()->SetKind(kind); 104 105 if (GetProgram()->SourceFilePath().Utf8()[0] == '@') { 106 // NOTE(user): handle multiple sourceFiles 107 } 108 109 ArenaVector<ir::Statement *> statements(Allocator()->Adapter()); 110 auto decl = ParsePackageDeclaration(); 111 if (decl != nullptr) { 112 statements.emplace_back(decl); 113 // If we found a package declaration, then add all files with the same package to the package parse list 114 AddPackageSourcesToParseList(); 115 } 116 117 auto script = ParseETSGlobalScript(startLoc, statements); 118 119 AddExternalSource(ParseSources(true)); 120 GetProgram()->SetAst(script); 121 GetProgram()->SetDeclarationModuleInfo(); 122} 123 124ir::ETSScript *ETSParser::ParseETSGlobalScript(lexer::SourcePosition startLoc, ArenaVector<ir::Statement *> &statements) 125{ 126 ETSNolintParser etsnolintParser(this); 127 etsnolintParser.CollectETSNolints(); 128 129 auto imports = ParseImportDeclarations(); 130 statements.insert(statements.end(), imports.begin(), imports.end()); 131 132 auto topLevelStatements = ParseTopLevelDeclaration(); 133 statements.insert(statements.end(), topLevelStatements.begin(), topLevelStatements.end()); 134 135 etsnolintParser.ApplyETSNolintsToStatements(statements); 136 137 auto *etsScript = AllocNode<ir::ETSScript>(Allocator(), std::move(statements), GetProgram()); 138 etsScript->SetRange({startLoc, Lexer()->GetToken().End()}); 139 return etsScript; 140} 141 142void ETSParser::AddExternalSource(const std::vector<Program *> &programs) 143{ 144 auto &extSources = globalProgram_->ExternalSources(); 145 146 for (auto *newProg : programs) { 147 const util::StringView moduleName = newProg->ModuleName(); 148 if (extSources.count(moduleName) == 0) { 149 extSources.try_emplace(moduleName, Allocator()->Adapter()); 150 } 151 152 extSources.at(moduleName).emplace_back(newProg); 153 } 154} 155 156ArenaVector<ir::ETSImportDeclaration *> ETSParser::ParseDefaultSources(std::string_view srcFile, 157 std::string_view importSrc) 158{ 159 auto isp = InnerSourceParser(this); 160 SourceFile source(srcFile, importSrc); 161 auto lexer = InitLexer(source); 162 163 Lexer()->NextToken(); 164 165 GetContext().Status() |= ParserStatus::IN_DEFAULT_IMPORTS; 166 auto statements = ParseImportDeclarations(); 167 GetContext().Status() &= ~ParserStatus::IN_DEFAULT_IMPORTS; 168 169 AddExternalSource(ParseSources()); 170 return statements; 171} 172 173void ETSParser::AddDirectImportsToDirectExternalSources( 174 const ArenaVector<util::StringView> &directImportsFromMainSource, parser::Program *const newProg) const 175{ 176 if (std::find_if(directImportsFromMainSource.begin(), directImportsFromMainSource.end(), 177 [newProg](const util::StringView &sv) { return sv == newProg->AbsoluteName(); }) == 178 directImportsFromMainSource.end()) { 179 return; 180 } 181 182 const util::StringView name = newProg->Ast()->Statements().empty() ? newProg->FileName() : newProg->ModuleName(); 183 if (GetProgram()->DirectExternalSources().count(name) == 0) { 184 GetProgram()->DirectExternalSources().try_emplace(name, Allocator()->Adapter()); 185 } 186 GetProgram()->DirectExternalSources().at(name).emplace_back(newProg); 187} 188 189void ETSParser::TryParseSource(const util::ImportPathManager::ParseInfo &parseListIdx, util::UString *extSrc, 190 const ArenaVector<util::StringView> &directImportsFromMainSource, 191 std::vector<Program *> &programs) 192{ 193 try { 194 parser::Program *newProg = 195 ParseSource({parseListIdx.sourcePath.Utf8(), extSrc->View().Utf8(), parseListIdx.sourcePath.Utf8(), false}); 196 197 if (!parseListIdx.isImplicitPackageImported || newProg->IsPackageModule()) { 198 AddDirectImportsToDirectExternalSources(directImportsFromMainSource, newProg); 199 // don't insert the separate modules into the programs, when we collect implicit package imports 200 programs.emplace_back(newProg); 201 } 202 } catch (const Error &) { 203 // Here file is not a valid STS source. Ignore and continue if it's implicit package import, else throw 204 // the syntax error as usual 205 206 if (!parseListIdx.isImplicitPackageImported) { 207 throw; 208 } 209 210 util::Helpers::LogWarning("Error during parse of file '", parseListIdx.sourcePath, 211 "' in compiled package. File will be omitted."); 212 } 213} 214 215std::vector<Program *> ETSParser::ParseSources(bool firstSource) 216{ 217 std::vector<Program *> programs; 218 219 auto &parseList = importPathManager_->ParseList(); 220 221 ArenaVector<util::StringView> directImportsFromMainSource(Allocator()->Adapter()); 222 223 if (firstSource) { 224 for (auto pl : parseList) { 225 if (pl.isParsed) { 226 // Handle excluded files, which are already set to be parsed before parsing them 227 continue; 228 } 229 directImportsFromMainSource.emplace_back(pl.sourcePath); 230 } 231 } 232 233 auto notParsedElement = 234 std::find_if(parseList.begin(), parseList.end(), [](const auto &parseInfo) { return !parseInfo.isParsed; }); 235 236 // NOTE (mmartin): Need a more optimal solution here 237 // This is needed, as during a parsing of a file, programs can be re-added to the parseList, which needs to be 238 // re-parsed. This won't change the size of the list, so with only the 'for loop', there can be unparsed files 239 // remained. 240 // An example for this, is when a file is added as an implicit package import, but it's erroneous, so we just ignore 241 // the file. But when the same file is also added with an explicit import declaration, then we need to re-parse it, 242 // and throw the syntax error. 243 while (notParsedElement != parseList.end()) { 244 // This parse list `paths` can grow in the meantime, so keep this index-based iteration 245 // NOLINTNEXTLINE(modernize-loop-convert) 246 for (size_t idx = 0; idx < parseList.size(); idx++) { 247 // check if already parsed 248 if (parseList[idx].isParsed) { 249 continue; 250 } 251 std::ifstream inputStream(parseList[idx].sourcePath.Mutf8()); 252 const auto data = importPathManager_->GetImportData(parseList[idx].sourcePath, Extension()); 253 if (!data.hasDecl) { 254 importPathManager_->MarkAsParsed(parseList[idx].sourcePath); 255 continue; 256 } 257 258 if (GetProgram()->SourceFilePath().Is(parseList[idx].sourcePath.Mutf8())) { 259 return programs; 260 } 261 262 if (inputStream.fail()) { 263 ThrowSyntaxError({"Failed to open file: ", parseList[idx].sourcePath.Mutf8()}); 264 } 265 266 std::stringstream ss; 267 ss << inputStream.rdbuf(); 268 auto externalSource = ss.str(); 269 270 auto currentLang = GetContext().SetLanguage(data.lang); 271 auto extSrc = Allocator()->New<util::UString>(externalSource, Allocator()); 272 importPathManager_->MarkAsParsed(parseList[idx].sourcePath); 273 274 // In case of implicit package import, if we find a malformed STS file in the package's directory, instead 275 // of aborting compilation we just ignore the file 276 277 // NOTE (mmartin): after the multiple syntax error handling in the parser is implemented, this try-catch 278 // must be changed, as exception throwing will be removed 279 280 TryParseSource(parseList[idx], extSrc, directImportsFromMainSource, programs); 281 282 GetContext().SetLanguage(currentLang); 283 } 284 285 notParsedElement = 286 std::find_if(parseList.begin(), parseList.end(), [](const auto &parseInfo) { return !parseInfo.isParsed; }); 287 } 288 289 return programs; 290} 291 292parser::Program *ETSParser::ParseSource(const SourceFile &sourceFile) 293{ 294 importPathManager_->MarkAsParsed(sourceFile.filePath); 295 auto *program = Allocator()->New<parser::Program>(Allocator(), GetProgram()->VarBinder()); 296 auto esp = ExternalSourceParser(this, program); 297 auto lexer = InitLexer(sourceFile); 298 299 lexer::SourcePosition startLoc = Lexer()->GetToken().Start(); 300 Lexer()->NextToken(); 301 302 ArenaVector<ir::Statement *> statements(Allocator()->Adapter()); 303 auto decl = ParsePackageDeclaration(); 304 if (decl != nullptr) { 305 statements.emplace_back(decl); 306 } 307 auto script = ParseETSGlobalScript(startLoc, statements); 308 program->SetAst(script); 309 GetProgram()->SetDeclarationModuleInfo(); 310 return program; 311} 312 313ir::Statement *ETSParser::ParseIdentKeyword() 314{ 315 const auto token = Lexer()->GetToken(); 316 ASSERT(token.Type() == lexer::TokenType::LITERAL_IDENT); 317 switch (token.KeywordType()) { 318 case lexer::TokenType::KEYW_STRUCT: { 319 // Remove this ThrowSyntaxError when struct is implemented in #12726 320 ThrowSyntaxError("Struct types are not supported yet!"); 321 } 322 case lexer::TokenType::KEYW_TYPE: { 323 return ParseTypeAliasDeclaration(); 324 } 325 default: { 326 break; 327 } 328 } 329 return nullptr; 330} 331 332ir::ScriptFunction *ETSParser::ParseFunction(ParserStatus newStatus, ir::Identifier *className) 333{ 334 FunctionContext functionContext(this, newStatus | ParserStatus::FUNCTION); 335 lexer::SourcePosition startLoc = Lexer()->GetToken().Start(); 336 auto [signature, throwMarker] = ParseFunctionSignature(newStatus, className); 337 338 ir::AstNode *body = nullptr; 339 lexer::SourcePosition endLoc = startLoc; 340 bool isOverload = false; 341 bool isArrow = (newStatus & ParserStatus::ARROW_FUNCTION) != 0; 342 343 if ((newStatus & ParserStatus::ASYNC_FUNCTION) != 0) { 344 functionContext.AddFlag(ir::ScriptFunctionFlags::ASYNC); 345 } 346 347 if (isArrow) { 348 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { 349 ThrowSyntaxError("'=>' expected"); 350 } 351 352 functionContext.AddFlag(ir::ScriptFunctionFlags::ARROW); 353 Lexer()->NextToken(); 354 } 355 356 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 357 std::tie(std::ignore, body, endLoc, isOverload) = 358 ParseFunctionBody(signature.Params(), newStatus, GetContext().Status()); 359 } else if (isArrow) { 360 body = ParseExpression(); 361 endLoc = body->AsExpression()->End(); 362 functionContext.AddFlag(ir::ScriptFunctionFlags::EXPRESSION); 363 } 364 365 if ((GetContext().Status() & ParserStatus::FUNCTION_HAS_RETURN_STATEMENT) != 0) { 366 functionContext.AddFlag(ir::ScriptFunctionFlags::HAS_RETURN); 367 GetContext().Status() ^= ParserStatus::FUNCTION_HAS_RETURN_STATEMENT; 368 } 369 functionContext.AddFlag(throwMarker); 370 371 bool isDeclare = InAmbientContext(); 372 if (functionContext.IsAsync() && isDeclare) { 373 ThrowSyntaxError("The modifier async cannot be used in an ambient context."); 374 } 375 376 // clang-format off 377 ir::ModifierFlags mFlags = isDeclare ? ir::ModifierFlags::DECLARE : ir::ModifierFlags::NONE; 378 ir::ScriptFunctionFlags funcFlags = 379 isDeclare ? (functionContext.Flags() | ir::ScriptFunctionFlags::EXTERNAL) : functionContext.Flags(); 380 auto *funcNode = AllocNode<ir::ScriptFunction>( 381 Allocator(), ir::ScriptFunction::ScriptFunctionData {body, std::move(signature), funcFlags, mFlags, isDeclare, 382 GetContext().GetLanguage()}); 383 funcNode->SetRange({startLoc, endLoc}); 384 // clang-format on 385 386 return funcNode; 387} 388 389std::tuple<bool, ir::BlockStatement *, lexer::SourcePosition, bool> ETSParser::ParseFunctionBody( 390 [[maybe_unused]] const ArenaVector<ir::Expression *> ¶ms, [[maybe_unused]] ParserStatus newStatus, 391 [[maybe_unused]] ParserStatus contextStatus) 392{ 393 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 394 LogSyntaxError({"Expected token '{', got '", TokenToString(Lexer()->GetToken().Type()), "'"}); 395 return {false, nullptr, Lexer()->GetToken().End(), false}; 396 } 397 398 ir::BlockStatement *body = ParseBlockStatement(); 399 400 return {true, body, body->End(), false}; 401} 402 403ir::ScriptFunctionFlags ETSParser::ParseFunctionThrowMarker(bool isRethrowsAllowed) 404{ 405 ir::ScriptFunctionFlags throwMarker = ir::ScriptFunctionFlags::NONE; 406 407 if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) { 408 if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_THROWS) { 409 Lexer()->NextToken(); // eat 'throws' 410 throwMarker = ir::ScriptFunctionFlags::THROWS; 411 } else if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_RETHROWS) { 412 if (isRethrowsAllowed) { 413 Lexer()->NextToken(); // eat 'rethrows' 414 throwMarker = ir::ScriptFunctionFlags::RETHROWS; 415 } else { 416 ThrowSyntaxError("Only 'throws' can be used with function types"); 417 } 418 } 419 } 420 421 return throwMarker; 422} 423 424ir::AstNode *ETSParser::ParseInnerTypeDeclaration(ir::ModifierFlags memberModifiers, lexer::LexerPosition savedPos, 425 bool isStepToken, bool seenStatic) 426{ 427 if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) == 0) { 428 ThrowSyntaxError("Local type declaration (class, struct, interface and enum) support is not yet implemented."); 429 } 430 431 // remove saved_pos nolint 432 Lexer()->Rewind(savedPos); 433 if (isStepToken) { 434 Lexer()->NextToken(); 435 } 436 437 Lexer()->GetToken().SetTokenType(Lexer()->GetToken().KeywordType()); 438 ir::AstNode *typeDecl = ParseTypeDeclaration(true); 439 memberModifiers &= (ir::ModifierFlags::PUBLIC | ir::ModifierFlags::PROTECTED | ir::ModifierFlags::PRIVATE | 440 ir::ModifierFlags::INTERNAL); 441 typeDecl->AddModifier(memberModifiers); 442 443 if (!seenStatic) { 444 if (typeDecl->IsClassDeclaration()) { 445 typeDecl->AsClassDeclaration()->Definition()->AsClassDefinition()->SetInnerModifier(); 446 } else if (typeDecl->IsETSStructDeclaration()) { 447 typeDecl->AsETSStructDeclaration()->Definition()->AsClassDefinition()->SetInnerModifier(); 448 } 449 } 450 451 return typeDecl; 452} 453 454ir::AstNode *ETSParser::ParseInnerConstructorDeclaration(ir::ModifierFlags memberModifiers, 455 const lexer::SourcePosition &startLoc) 456{ 457 if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) != 0) { 458 ThrowSyntaxError({"Namespaces should not have a constructor"}); 459 } 460 if ((memberModifiers & (~(ir::ModifierFlags::ACCESS | ir::ModifierFlags::DECLARE))) != 0) { 461 ThrowSyntaxError( 462 {"The modifier for a constructor should be limited to access modifiers(private, internal, protected, " 463 "public)."}); 464 } 465 auto *memberName = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator()); 466 memberModifiers |= ir::ModifierFlags::CONSTRUCTOR; 467 Lexer()->NextToken(); 468 auto *classMethod = ParseClassMethodDefinition(memberName, memberModifiers); 469 classMethod->SetStart(startLoc); 470 471 return classMethod; 472} 473 474ir::Identifier *ETSParser::CreateInvokeIdentifier() 475{ 476 util::StringView tokenName = util::StringView {compiler::Signatures::STATIC_INVOKE_METHOD}; 477 auto ident = AllocNode<ir::Identifier>(tokenName, Allocator()); 478 ident->SetReference(false); 479 ident->SetRange({Lexer()->GetToken().Start(), Lexer()->GetToken().End()}); 480 return ident; 481} 482 483void ETSParser::CheckAccessorDeclaration(ir::ModifierFlags memberModifiers) 484{ 485 ir::ModifierFlags methodModifiersNotAccessorModifiers = ir::ModifierFlags::NATIVE | ir::ModifierFlags::ASYNC; 486 if ((memberModifiers & methodModifiersNotAccessorModifiers) != 0) { 487 ThrowSyntaxError("Modifiers of getter and setter are limited to ('abstract', 'static', 'final', 'override')."); 488 } 489} 490 491ir::AstNode *ETSParser::ParseInnerRest(const ArenaVector<ir::AstNode *> &properties, 492 ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags memberModifiers, 493 const lexer::SourcePosition &startLoc) 494{ 495 if (Lexer()->Lookahead() != lexer::LEX_CHAR_LEFT_PAREN && Lexer()->Lookahead() != lexer::LEX_CHAR_LESS_THAN && 496 (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_GET || 497 Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_SET)) { 498 CheckAccessorDeclaration(memberModifiers); 499 return ParseClassGetterSetterMethod(properties, modifiers, memberModifiers); 500 } 501 502 if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) != 0) { 503 auto type = Lexer()->GetToken().Type(); 504 if (type == lexer::TokenType::KEYW_FUNCTION || type == lexer::TokenType::KEYW_LET || 505 type == lexer::TokenType::KEYW_CONST) { 506 Lexer()->NextToken(); 507 } 508 } 509 510 auto parseClassMethod = [&memberModifiers, &startLoc, this](ir::Identifier *methodName) { 511 auto *classMethod = ParseClassMethodDefinition(methodName, memberModifiers, nullptr); 512 classMethod->SetStart(startLoc); 513 return classMethod; 514 }; 515 516 if (InAmbientContext()) { 517 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS && 518 (GetContext().Status() & ParserStatus::IN_CLASS_BODY) != 0U) { 519 // Special case for processing of special '(param: type): returnType` identifier using in ambient context 520 auto ident = CreateInvokeIdentifier(); 521 memberModifiers |= ir::ModifierFlags::STATIC; 522 return parseClassMethod(ident); 523 } 524 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) { 525 auto const savePos = Lexer()->Save(); 526 Lexer()->NextToken(); 527 if (Lexer()->GetToken().Ident().Is("Symbol")) { 528 Lexer()->Rewind(savePos); 529 } else { 530 return ParseAmbientSignature(); 531 } 532 } 533 } 534 535 auto *memberName = ExpectIdentifier(); 536 if (memberName == nullptr) { // Error processing. 537 return nullptr; 538 } 539 540 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS || 541 Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) { 542 return parseClassMethod(memberName); 543 } 544 545 ArenaVector<ir::AstNode *> fieldDeclarations(Allocator()->Adapter()); 546 auto *placeholder = AllocNode<ir::TSInterfaceBody>(std::move(fieldDeclarations)); 547 ParseClassFieldDefinition(memberName, memberModifiers, placeholder->BodyPtr()); 548 return placeholder; 549} 550 551ir::Statement *ETSParser::ParseTypeDeclarationAbstractFinal(bool allowStatic, ir::ClassDefinitionModifiers modifiers) 552{ 553 auto flags = ParseClassModifiers(); 554 if (allowStatic && (flags & ir::ModifierFlags::STATIC) == 0U) { 555 modifiers |= ir::ClassDefinitionModifiers::INNER; 556 } 557 558 if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS) { 559 return ParseClassDeclaration(modifiers, flags); 560 } 561 562 if (IsStructKeyword()) { 563 return ParseStructDeclaration(modifiers, flags); 564 } 565 566 ThrowUnexpectedToken(Lexer()->GetToken().Type()); 567} 568 569ir::Statement *ETSParser::ParseTypeDeclaration(bool allowStatic) 570{ 571 auto savedPos = Lexer()->Save(); 572 573 auto modifiers = ir::ClassDefinitionModifiers::ID_REQUIRED | ir::ClassDefinitionModifiers::CLASS_DECL; 574 575 auto tokenType = Lexer()->GetToken().Type(); 576 switch (tokenType) { 577 case lexer::TokenType::KEYW_STATIC: { 578 if (!allowStatic) { 579 ThrowUnexpectedToken(Lexer()->GetToken().Type()); 580 } 581 582 Lexer()->NextToken(); 583 584 if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_INTERFACE) { 585 return ParseInterfaceDeclaration(true); 586 } 587 588 Lexer()->Rewind(savedPos); 589 [[fallthrough]]; 590 } 591 case lexer::TokenType::KEYW_ABSTRACT: 592 case lexer::TokenType::KEYW_FINAL: { 593 return ParseTypeDeclarationAbstractFinal(allowStatic, modifiers); 594 } 595 case lexer::TokenType::KEYW_ENUM: { 596 return ParseEnumDeclaration(false); 597 } 598 case lexer::TokenType::KEYW_INTERFACE: { 599 return ParseInterfaceDeclaration(false); 600 } 601 case lexer::TokenType::KEYW_NAMESPACE: { 602 if (!InAmbientContext()) { 603 ThrowSyntaxError("Namespaces are declare only"); 604 } 605 GetContext().Status() |= ParserStatus::IN_NAMESPACE; 606 auto *ns = ParseNamespaceDeclaration(ir::ModifierFlags::DECLARE | ir::ModifierFlags::EXPORT); 607 GetContext().Status() &= ~ParserStatus::IN_NAMESPACE; 608 return ns; 609 } 610 case lexer::TokenType::KEYW_CLASS: { 611 return ParseClassDeclaration(modifiers); 612 } 613 case lexer::TokenType::LITERAL_IDENT: { 614 if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STRUCT) { 615 return ParseStructDeclaration(modifiers); 616 } 617 [[fallthrough]]; 618 } 619 default: { 620 ThrowUnexpectedToken(Lexer()->GetToken().Type()); 621 } 622 } 623} 624 625ir::TSTypeAliasDeclaration *ETSParser::ParseTypeAliasDeclaration() 626{ 627 ASSERT(Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE); 628 629 lexer::SourcePosition typeStart = Lexer()->GetToken().Start(); 630 Lexer()->NextToken(); // eat type keyword 631 632 if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 633 ThrowSyntaxError("Identifier expected"); 634 } 635 636 if (Lexer()->GetToken().IsReservedTypeName()) { 637 std::string errMsg("Type alias name cannot be '"); 638 errMsg.append(TokenToString(Lexer()->GetToken().KeywordType())); 639 errMsg.append("'"); 640 ThrowSyntaxError(errMsg.c_str()); 641 } 642 643 const util::StringView ident = Lexer()->GetToken().Ident(); 644 auto *id = AllocNode<ir::Identifier>(ident, Allocator()); 645 id->SetRange(Lexer()->GetToken().Loc()); 646 647 auto *typeAliasDecl = AllocNode<ir::TSTypeAliasDeclaration>(Allocator(), id); 648 649 Lexer()->NextToken(); // eat alias name 650 651 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) { 652 auto options = 653 TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::ALLOW_DECLARATION_SITE_VARIANCE; 654 ir::TSTypeParameterDeclaration *params = ParseTypeParameterDeclaration(&options); 655 typeAliasDecl->SetTypeParameters(params); 656 params->SetParent(typeAliasDecl); 657 } 658 659 if (!Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_SUBSTITUTION)) { 660 ThrowSyntaxError("'=' expected"); 661 } 662 663 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR; 664 ir::TypeNode *typeAnnotation = ParseTypeAnnotation(&options); 665 if (typeAnnotation != nullptr) { // Error processing. 666 typeAliasDecl->SetTsTypeAnnotation(typeAnnotation); 667 typeAnnotation->SetParent(typeAliasDecl); 668 } 669 670 typeAliasDecl->SetRange({typeStart, Lexer()->GetToken().End()}); 671 return typeAliasDecl; 672} 673 674std::pair<bool, std::size_t> ETSParser::CheckDefaultParameters(const ir::ScriptFunction *const function) const 675{ 676 bool hasDefaultParameter = false; 677 bool hasRestParameter = false; 678 std::size_t requiredParametersNumber = 0U; 679 680 for (auto *const it : function->Params()) { 681 auto const *const param = it->AsETSParameterExpression(); 682 683 if (param->IsRestParameter()) { 684 hasRestParameter = true; 685 continue; 686 } 687 688 if (hasRestParameter) { 689 ThrowSyntaxError("Rest parameter should be the last one.", param->Start()); 690 } 691 692 if (param->IsDefault()) { 693 hasDefaultParameter = true; 694 continue; 695 } 696 697 if (hasDefaultParameter) { 698 ThrowSyntaxError("Required parameter follows default parameter(s).", param->Start()); 699 } 700 701 ++requiredParametersNumber; 702 } 703 704 if (hasDefaultParameter && hasRestParameter) { 705 ThrowSyntaxError("Both optional and rest parameters are not allowed in function's parameter list.", 706 function->Start()); 707 } 708 709 return std::make_pair(hasDefaultParameter, requiredParametersNumber); 710} 711 712std::string ETSParser::PrimitiveTypeToName(ir::PrimitiveType type) 713{ 714 switch (type) { 715 case ir::PrimitiveType::BYTE: 716 return "byte"; 717 case ir::PrimitiveType::INT: 718 return "int"; 719 case ir::PrimitiveType::LONG: 720 return "long"; 721 case ir::PrimitiveType::SHORT: 722 return "short"; 723 case ir::PrimitiveType::FLOAT: 724 return "float"; 725 case ir::PrimitiveType::DOUBLE: 726 return "double"; 727 case ir::PrimitiveType::BOOLEAN: 728 return "boolean"; 729 case ir::PrimitiveType::CHAR: 730 return "char"; 731 case ir::PrimitiveType::VOID: 732 return "void"; 733 default: 734 UNREACHABLE(); 735 } 736} 737 738std::string ETSParser::GetNameForETSUnionType(const ir::TypeNode *typeAnnotation) const 739{ 740 ASSERT(typeAnnotation->IsETSUnionType()); 741 std::string newstr; 742 for (size_t i = 0; i < typeAnnotation->AsETSUnionType()->Types().size(); i++) { 743 auto type = typeAnnotation->AsETSUnionType()->Types()[i]; 744 std::string str = GetNameForTypeNode(type); 745 newstr += str; 746 if (i != typeAnnotation->AsETSUnionType()->Types().size() - 1) { 747 newstr += "|"; 748 } 749 } 750 return newstr; 751} 752 753std::string ETSParser::GetNameForTypeNode(const ir::TypeNode *typeAnnotation) const 754{ 755 if (typeAnnotation->IsETSUnionType()) { 756 return GetNameForETSUnionType(typeAnnotation); 757 } 758 if (typeAnnotation->IsETSPrimitiveType()) { 759 return PrimitiveTypeToName(typeAnnotation->AsETSPrimitiveType()->GetPrimitiveType()); 760 } 761 762 if (typeAnnotation->IsETSTypeReference()) { 763 std::string typeParamNames; 764 auto typeParam = typeAnnotation->AsETSTypeReference()->Part()->TypeParams(); 765 if (typeParam != nullptr && typeParam->IsTSTypeParameterInstantiation()) { 766 typeParamNames = "<"; 767 auto paramList = typeParam->Params(); 768 for (auto param : paramList) { 769 std::string typeParamName = GetNameForTypeNode(param); 770 typeParamNames += typeParamName + ","; 771 } 772 typeParamNames.pop_back(); 773 typeParamNames += ">"; 774 } 775 return typeAnnotation->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Name().Mutf8() + typeParamNames; 776 } 777 778 if (typeAnnotation->IsETSFunctionType()) { 779 std::string lambdaParams = " "; 780 781 for (const auto *const param : typeAnnotation->AsETSFunctionType()->Params()) { 782 lambdaParams += param->AsETSParameterExpression()->Ident()->Name().Mutf8(); 783 lambdaParams += ":"; 784 lambdaParams += GetNameForTypeNode(param->AsETSParameterExpression()->Ident()->TypeAnnotation()); 785 lambdaParams += ","; 786 } 787 788 lambdaParams.pop_back(); 789 const std::string returnTypeName = GetNameForTypeNode(typeAnnotation->AsETSFunctionType()->ReturnType()); 790 791 return "((" + lambdaParams + ") => " + returnTypeName + ")"; 792 } 793 794 if (typeAnnotation->IsTSArrayType()) { 795 // Note! array is required for the rest parameter. 796 return GetNameForTypeNode(typeAnnotation->AsTSArrayType()->ElementType()) + "[]"; 797 } 798 799 if (typeAnnotation->IsETSNullType()) { 800 return "null"; 801 } 802 803 if (typeAnnotation->IsETSUndefinedType()) { 804 return "undefined"; 805 } 806 807 UNREACHABLE(); 808} 809 810void ETSParser::ValidateRestParameter(ir::Expression *param) 811{ 812 if (param->IsETSParameterExpression()) { 813 if (param->AsETSParameterExpression()->IsRestParameter()) { 814 GetContext().Status() |= ParserStatus::HAS_COMPLEX_PARAM; 815 816 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 817 ThrowSyntaxError("Rest parameter must be the last formal parameter."); 818 } 819 } 820 } 821} 822 823bool ETSParser::ValidateBreakLabel([[maybe_unused]] util::StringView label) 824{ 825 // For ETS validate labels in checker via variables 826 return true; 827} 828 829bool ETSParser::ValidateContinueLabel([[maybe_unused]] util::StringView label) 830{ 831 // For ETS validate labels in checker via variables 832 return true; 833} 834 835std::tuple<ir::Expression *, ir::TSTypeParameterInstantiation *> ETSParser::ParseTypeReferencePart( 836 TypeAnnotationParsingOptions *options) 837{ 838 ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS; 839 840 if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL) != 0) { 841 flags |= ExpressionParseFlags::POTENTIAL_CLASS_LITERAL; 842 } 843 844 if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_NEW_ARRAY) != 0) { 845 flags |= ExpressionParseFlags::POTENTIAL_NEW_ARRAY; 846 } 847 848 auto *typeName = ParseQualifiedName(flags); 849 if (typeName == nullptr) { 850 return {nullptr, nullptr}; 851 } 852 853 if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL) != 0 && 854 (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS || IsStructKeyword())) { 855 return {typeName, nullptr}; 856 } 857 858 ir::TSTypeParameterInstantiation *typeParamInst = nullptr; 859 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT || 860 Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) { 861 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) { 862 Lexer()->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1); 863 } 864 *options |= TypeAnnotationParsingOptions::ALLOW_WILDCARD; 865 typeParamInst = ParseTypeParameterInstantiation(options); 866 *options &= ~TypeAnnotationParsingOptions::ALLOW_WILDCARD; 867 } 868 869 return {typeName, typeParamInst}; 870} 871 872ir::TypeNode *ETSParser::ParseTypeReference(TypeAnnotationParsingOptions *options) 873{ 874 auto startPos = Lexer()->GetToken().Start(); 875 ir::ETSTypeReferencePart *typeRefPart = nullptr; 876 877 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT) { 878 return ParseTypeFormatPlaceholder(); 879 } 880 881 while (true) { 882 auto partPos = Lexer()->GetToken().Start(); 883 auto [typeName, typeParams] = ParseTypeReferencePart(options); 884 if (typeName == nullptr) { 885 return nullptr; 886 } 887 888 typeRefPart = AllocNode<ir::ETSTypeReferencePart>(typeName, typeParams, typeRefPart); 889 typeRefPart->SetRange({partPos, Lexer()->GetToken().End()}); 890 891 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_PERIOD) { 892 break; 893 } 894 895 Lexer()->NextToken(); 896 897 if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL) != 0 && 898 (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS || IsStructKeyword())) { 899 break; 900 } 901 } 902 903 auto *typeReference = AllocNode<ir::ETSTypeReference>(typeRefPart); 904 typeReference->SetRange({startPos, Lexer()->GetToken().End()}); 905 return typeReference; 906} 907 908ir::TypeNode *ETSParser::ParseBaseTypeReference(TypeAnnotationParsingOptions *options) 909{ 910 ir::TypeNode *typeAnnotation = nullptr; 911 912 switch (Lexer()->GetToken().KeywordType()) { 913 case lexer::TokenType::KEYW_BOOLEAN: { 914 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::BOOLEAN); 915 break; 916 } 917 case lexer::TokenType::KEYW_BYTE: { 918 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::BYTE); 919 break; 920 } 921 case lexer::TokenType::KEYW_CHAR: { 922 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::CHAR); 923 break; 924 } 925 case lexer::TokenType::KEYW_DOUBLE: { 926 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::DOUBLE); 927 break; 928 } 929 case lexer::TokenType::KEYW_FLOAT: { 930 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::FLOAT); 931 break; 932 } 933 case lexer::TokenType::KEYW_INT: { 934 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::INT); 935 break; 936 } 937 case lexer::TokenType::KEYW_LONG: { 938 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::LONG); 939 break; 940 } 941 case lexer::TokenType::KEYW_SHORT: { 942 typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::SHORT); 943 break; 944 } 945 946 default: { 947 break; 948 } 949 } 950 951 return typeAnnotation; 952} 953 954std::optional<lexer::SourcePosition> ETSParser::GetDefaultParamPosition(ArenaVector<ir::Expression *> params) 955{ 956 for (auto ¶m : params) { 957 if (param->IsETSParameterExpression() && param->AsETSParameterExpression()->IsDefault()) { 958 return param->AsETSParameterExpression()->Initializer()->Start(); 959 } 960 } 961 return {}; 962} 963 964ir::TypeNode *ETSParser::ParseLiteralIdent(TypeAnnotationParsingOptions *options) 965{ 966 if (const auto keyword = Lexer()->GetToken().KeywordType(); 967 keyword == lexer::TokenType::KEYW_IN || keyword == lexer::TokenType::KEYW_OUT) { 968 return ParseWildcardType(options); 969 } 970 971 if (Lexer()->GetToken().IsDefinableTypeName()) { 972 return GetTypeAnnotationOfPrimitiveType(Lexer()->GetToken().KeywordType(), options); 973 } 974 975 return ParseTypeReference(options); 976} 977 978void ETSParser::ParseRightParenthesis(TypeAnnotationParsingOptions *options, ir::TypeNode *&typeAnnotation, 979 lexer::LexerPosition savedPos) 980{ 981 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 982 if (((*options) & TypeAnnotationParsingOptions::REPORT_ERROR) != 0) { 983 ThrowExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS); 984 } 985 986 Lexer()->Rewind(savedPos); 987 typeAnnotation = nullptr; 988 } else { 989 Lexer()->NextToken(); // eat ')' 990 } 991} 992 993void ETSParser::ThrowIfVarDeclaration(VariableParsingFlags flags) 994{ 995 if ((flags & VariableParsingFlags::VAR) != 0) { 996 ThrowUnexpectedToken(lexer::TokenType::KEYW_VAR); 997 } 998} 999 1000ir::Statement *ETSParser::ParseExport(lexer::SourcePosition startLoc, ir::ModifierFlags modifiers) 1001{ 1002 ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY || 1003 Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE || 1004 Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT); 1005 ArenaVector<ir::AstNode *> specifiers(Allocator()->Adapter()); 1006 1007 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) { 1008 ParseNameSpaceSpecifier(&specifiers, true); 1009 } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 1010 auto specs = ParseNamedSpecifiers(); 1011 1012 if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_FROM) { 1013 specifiers = util::Helpers::ConvertVector<ir::AstNode>(specs.first); 1014 } else { 1015 ArenaVector<ir::ExportSpecifier *> exports(Allocator()->Adapter()); 1016 for (auto spec : specs.first) { 1017 exports.emplace_back(AllocNode<ir::ExportSpecifier>(spec->Local(), spec->Imported())); 1018 } 1019 auto result = AllocNode<ir::ExportNamedDeclaration>(Allocator(), static_cast<ir::StringLiteral *>(nullptr), 1020 std::move(exports)); 1021 result->AddModifier(modifiers); 1022 return result; 1023 } 1024 } else { 1025 return ParseSingleExport(modifiers); 1026 } 1027 1028 // re-export directive 1029 ir::ImportSource *reExportSource = ParseSourceFromClause(true); 1030 1031 lexer::SourcePosition endLoc = reExportSource->Source()->End(); 1032 auto *reExportDeclaration = AllocNode<ir::ETSImportDeclaration>(reExportSource, std::move(specifiers)); 1033 reExportDeclaration->SetRange({startLoc, endLoc}); 1034 1035 ConsumeSemicolon(reExportDeclaration); 1036 1037 auto reExport = AllocNode<ir::ETSReExportDeclaration>(reExportDeclaration, std::vector<std::string>(), 1038 GetProgram()->SourceFilePath(), Allocator()); 1039 reExport->AddModifier(modifiers); 1040 return reExport; 1041} 1042 1043ir::ETSPackageDeclaration *ETSParser::ParsePackageDeclaration() 1044{ 1045 auto startLoc = Lexer()->GetToken().Start(); 1046 1047 if (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_PACKAGE) { 1048 // NOTE(rsipka): Unclear behavior/code. Currently, all entry programs omit the module name if it is not a 1049 // package module and the '--ets-module' option is not specified during compilation 1050 GetProgram()->SetModuleInfo(GetProgram()->FileName(), false, GetProgram()->IsEntryPoint() && !IsETSModule()); 1051 return nullptr; 1052 } 1053 1054 Lexer()->NextToken(); 1055 1056 ir::Expression *name = ParseQualifiedName(); 1057 1058 auto *packageDeclaration = AllocNode<ir::ETSPackageDeclaration>(name); 1059 packageDeclaration->SetRange({startLoc, Lexer()->GetToken().End()}); 1060 1061 ConsumeSemicolon(packageDeclaration); 1062 1063 auto packageName = 1064 name->IsIdentifier() ? name->AsIdentifier()->Name() : name->AsTSQualifiedName()->ToString(Allocator()); 1065 1066 GetProgram()->SetModuleInfo(packageName, true); 1067 1068 return packageDeclaration; 1069} 1070 1071ir::ImportSource *ETSParser::ParseSourceFromClause(bool requireFrom) 1072{ 1073 if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) { 1074 if (requireFrom) { 1075 ThrowSyntaxError("Unexpected token."); 1076 } 1077 } else { 1078 Lexer()->NextToken(); // eat `from` 1079 } 1080 1081 if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_STRING) { 1082 ThrowSyntaxError("Unexpected token."); 1083 } 1084 1085 ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_STRING); 1086 auto importPath = Lexer()->GetToken().Ident(); 1087 1088 auto resolvedImportPath = importPathManager_->ResolvePath(GetProgram()->AbsoluteName(), importPath); 1089 if (globalProgram_->AbsoluteName() != resolvedImportPath) { 1090 importPathManager_->AddToParseList(resolvedImportPath, 1091 (GetContext().Status() & ParserStatus::IN_DEFAULT_IMPORTS) != 0U 1092 ? util::ImportFlags::DEFAULT_IMPORT 1093 : util::ImportFlags::NONE); 1094 } else if (!IsETSModule()) { 1095 ThrowSyntaxError("Please compile `" + globalProgram_->FileName().Mutf8() + "." + 1096 globalProgram_->SourceFile().GetExtension().Mutf8() + 1097 "` with `--ets-module` option. It is being imported by another file."); 1098 } 1099 1100 auto *resolvedSource = AllocNode<ir::StringLiteral>(resolvedImportPath); 1101 auto importData = importPathManager_->GetImportData(resolvedImportPath, Extension()); 1102 auto *source = AllocNode<ir::StringLiteral>(importPath); 1103 source->SetRange(Lexer()->GetToken().Loc()); 1104 1105 Lexer()->NextToken(); 1106 1107 return Allocator()->New<ir::ImportSource>(source, resolvedSource, importData.lang, importData.hasDecl); 1108} 1109 1110ArenaVector<ir::ETSImportDeclaration *> ETSParser::ParseImportDeclarations() 1111{ 1112 std::vector<std::string> userPaths; 1113 ArenaVector<ir::ETSImportDeclaration *> statements(Allocator()->Adapter()); 1114 1115 while (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_IMPORT) { 1116 auto startLoc = Lexer()->GetToken().Start(); 1117 Lexer()->NextToken(); // eat import 1118 1119 ir::ImportKinds importKind = 1120 Lexer()->TryEatTokenKeyword(lexer::TokenType::KEYW_TYPE) ? ir::ImportKinds::TYPE : ir::ImportKinds::VALUE; 1121 1122 ArenaVector<ir::AstNode *> specifiers(Allocator()->Adapter()); 1123 ArenaVector<ir::AstNode *> defaultSpecifiers(Allocator()->Adapter()); 1124 1125 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) { 1126 if (importKind == ir::ImportKinds::TYPE) { 1127 ThrowSyntaxError("Type import requires selective binding to define the required imported elements."); 1128 } 1129 ParseNameSpaceSpecifier(&specifiers); 1130 } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 1131 auto specs = ParseNamedSpecifiers(); 1132 specifiers = util::Helpers::ConvertVector<ir::AstNode>(specs.first); 1133 defaultSpecifiers = util::Helpers::ConvertVector<ir::AstNode>(specs.second); 1134 } else { 1135 ParseImportDefaultSpecifier(&specifiers); 1136 } 1137 auto pos = Lexer()->Save(); 1138 if (!specifiers.empty()) { 1139 ir::ImportSource *importSource = ParseSourceFromClause(true); 1140 1141 lexer::SourcePosition endLoc = importSource->Source()->End(); 1142 auto *importDeclaration = 1143 AllocNode<ir::ETSImportDeclaration>(importSource, std::move(specifiers), importKind); 1144 importDeclaration->SetRange({startLoc, endLoc}); 1145 1146 ConsumeSemicolon(importDeclaration); 1147 statements.push_back(importDeclaration); 1148 } 1149 1150 if (!defaultSpecifiers.empty()) { 1151 Lexer()->Rewind(pos); 1152 ir::ImportSource *importSourceDefault = ParseSourceFromClause(true); 1153 1154 lexer::SourcePosition endLocDef = importSourceDefault->Source()->End(); 1155 auto *importDeclarationDefault = 1156 AllocNode<ir::ETSImportDeclaration>(importSourceDefault, std::move(defaultSpecifiers), importKind); 1157 importDeclarationDefault->SetRange({startLoc, endLocDef}); 1158 1159 ConsumeSemicolon(importDeclarationDefault); 1160 util::Helpers::CheckDefaultImport(statements); 1161 statements.push_back(importDeclarationDefault); 1162 } 1163 } 1164 1165 std::sort(statements.begin(), statements.end(), [](const auto *s1, const auto *s2) -> bool { 1166 return s1->Specifiers()[0]->IsImportNamespaceSpecifier() && !s2->Specifiers()[0]->IsImportNamespaceSpecifier(); 1167 }); 1168 return statements; 1169} 1170 1171ir::ExportNamedDeclaration *ETSParser::ParseSingleExport(ir::ModifierFlags modifiers) 1172{ 1173 lexer::Token token = Lexer()->GetToken(); 1174 auto *exported = AllocNode<ir::Identifier>(token.Ident(), Allocator()); 1175 exported->SetReference(); 1176 exported->SetRange(Lexer()->GetToken().Loc()); 1177 1178 Lexer()->NextToken(); // eat exported variable name 1179 1180 ArenaVector<ir::ExportSpecifier *> exports(Allocator()->Adapter()); 1181 1182 exports.emplace_back(AllocNode<ir::ExportSpecifier>(exported, ParseNamedExport(token))); 1183 auto result = AllocNode<ir::ExportNamedDeclaration>(Allocator(), static_cast<ir::StringLiteral *>(nullptr), 1184 std::move(exports)); 1185 result->AddModifier(modifiers); 1186 ConsumeSemicolon(result); 1187 1188 return result; 1189} 1190 1191bool ETSParser::IsDefaultImport() 1192{ 1193 if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_DEFAULT) { 1194 Lexer()->NextToken(); 1195 if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) { 1196 Lexer()->NextToken(); 1197 return true; 1198 } 1199 ThrowSyntaxError("Unexpected token. 'as' keyword is expected."); 1200 } 1201 return false; 1202} 1203 1204using ImportSpecifierVector = ArenaVector<ir::ImportSpecifier *>; 1205using ImportDefaultSpecifierVector = ArenaVector<ir::ImportDefaultSpecifier *>; 1206std::pair<ImportSpecifierVector, ImportDefaultSpecifierVector> ETSParser::ParseNamedSpecifiers() 1207{ 1208 // NOTE(user): handle qualifiedName in file bindings: qualifiedName '.' '*' 1209 if (!Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_LEFT_BRACE)) { 1210 ThrowExpectedToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE); 1211 } 1212 1213 auto fileName = GetProgram()->SourceFilePath().Mutf8(); 1214 1215 ArenaVector<ir::ImportSpecifier *> result(Allocator()->Adapter()); 1216 ArenaVector<ir::ImportDefaultSpecifier *> resultDefault(Allocator()->Adapter()); 1217 1218 while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 1219 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) { 1220 ThrowSyntaxError("The '*' token is not allowed as a selective binding (between braces)"); 1221 } 1222 1223 if (!IsDefaultImport()) { 1224 if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 1225 ThrowSyntaxError("Unexpected token"); 1226 } 1227 1228 lexer::Token importedToken = Lexer()->GetToken(); 1229 auto *imported = AllocNode<ir::Identifier>(importedToken.Ident(), Allocator()); 1230 ir::Identifier *local = nullptr; 1231 imported->SetReference(); 1232 imported->SetRange(Lexer()->GetToken().Loc()); 1233 1234 Lexer()->NextToken(); 1235 1236 if (CheckModuleAsModifier() && Lexer()->TryEatTokenType(lexer::TokenType::KEYW_AS)) { 1237 local = ParseNamedImport(Lexer()->GetToken()); 1238 Lexer()->NextToken(); 1239 } else { 1240 local = ParseNamedImport(importedToken); 1241 } 1242 1243 auto *specifier = AllocNode<ir::ImportSpecifier>(imported, local); 1244 specifier->SetRange({imported->Start(), local->End()}); 1245 1246 util::Helpers::CheckImportedName(result, specifier, fileName); 1247 1248 result.emplace_back(specifier); 1249 } else { 1250 auto *imported = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator()); 1251 imported->SetReference(); 1252 imported->SetRange(Lexer()->GetToken().Loc()); 1253 Lexer()->NextToken(); 1254 auto *specifier = AllocNode<ir::ImportDefaultSpecifier>(imported); 1255 specifier->SetRange({imported->Start(), imported->End()}); 1256 1257 util::Helpers::CheckDefaultImportedName(resultDefault, specifier, fileName); 1258 1259 resultDefault.emplace_back(specifier); 1260 } 1261 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) { 1262 Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); // eat comma 1263 } 1264 } 1265 Lexer()->NextToken(); // eat '}' 1266 std::pair<ArenaVector<ir::ImportSpecifier *>, ArenaVector<ir::ImportDefaultSpecifier *>> resultSpecifiers( 1267 result, resultDefault); 1268 1269 return resultSpecifiers; 1270} 1271 1272void ETSParser::ParseNameSpaceSpecifier(ArenaVector<ir::AstNode *> *specifiers, bool isReExport) 1273{ 1274 lexer::SourcePosition namespaceStart = Lexer()->GetToken().Start(); 1275 Lexer()->NextToken(); // eat `*` character 1276 1277 if (!CheckModuleAsModifier()) { 1278 ThrowSyntaxError("Unexpected token."); 1279 } 1280 1281 // Note (oeotvos) As a temporary solution we allow the stdlib to use namespace import without an alias, but this 1282 // should be handled at some point. 1283 if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_FROM && !isReExport && 1284 (GetContext().Status() & ParserStatus::IN_DEFAULT_IMPORTS) == 0) { 1285 ThrowSyntaxError("Unexpected token, expected 'as' but found 'from'"); 1286 } 1287 1288 auto *local = AllocNode<ir::Identifier>(util::StringView(""), Allocator()); 1289 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA || 1290 Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_FROM || isReExport) { 1291 local->SetReference(); 1292 auto *specifier = AllocNode<ir::ImportNamespaceSpecifier>(local); 1293 specifier->SetRange({namespaceStart, Lexer()->GetToken().End()}); 1294 specifiers->push_back(specifier); 1295 return; 1296 } 1297 1298 ExpectToken(lexer::TokenType::KEYW_AS, true); // eat `as` literal 1299 local = ParseNamedImport(Lexer()->GetToken()); 1300 1301 auto *specifier = AllocNode<ir::ImportNamespaceSpecifier>(local); 1302 specifier->SetRange({namespaceStart, Lexer()->GetToken().End()}); 1303 specifiers->push_back(specifier); 1304 1305 Lexer()->NextToken(); // eat local name 1306} 1307 1308ir::AstNode *ETSParser::ParseImportDefaultSpecifier(ArenaVector<ir::AstNode *> *specifiers) 1309{ 1310 if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 1311 ThrowSyntaxError("Unexpected token, expected an identifier"); 1312 } 1313 1314 auto *imported = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator()); 1315 imported->SetReference(); 1316 imported->SetRange(Lexer()->GetToken().Loc()); 1317 Lexer()->NextToken(); // Eat import specifier. 1318 1319 if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) { 1320 ThrowSyntaxError("Unexpected token, expected 'from'"); 1321 } 1322 1323 auto *specifier = AllocNode<ir::ImportDefaultSpecifier>(imported); 1324 specifier->SetRange({imported->Start(), imported->End()}); 1325 specifiers->push_back(specifier); 1326 1327 return nullptr; 1328} 1329 1330bool ETSParser::CheckModuleAsModifier() 1331{ 1332 if ((Lexer()->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0U) { 1333 ThrowSyntaxError("Escape sequences are not allowed in 'as' keyword"); 1334 } 1335 1336 return true; 1337} 1338 1339ir::AnnotatedExpression *ETSParser::GetAnnotatedExpressionFromParam() 1340{ 1341 ir::AnnotatedExpression *parameter; 1342 1343 switch (Lexer()->GetToken().Type()) { 1344 case lexer::TokenType::LITERAL_IDENT: { 1345 parameter = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator()); 1346 if (parameter->AsIdentifier()->Decorators().empty()) { 1347 parameter->SetRange(Lexer()->GetToken().Loc()); 1348 } else { 1349 parameter->SetRange( 1350 {parameter->AsIdentifier()->Decorators().front()->Start(), Lexer()->GetToken().End()}); 1351 } 1352 break; 1353 } 1354 1355 case lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD: { 1356 const auto startLoc = Lexer()->GetToken().Start(); 1357 Lexer()->NextToken(); 1358 1359 if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 1360 ThrowSyntaxError("Unexpected token, expected an identifier."); 1361 } 1362 1363 auto *const restIdent = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator()); 1364 restIdent->SetRange(Lexer()->GetToken().Loc()); 1365 1366 parameter = AllocNode<ir::SpreadElement>(ir::AstNodeType::REST_ELEMENT, Allocator(), restIdent); 1367 parameter->SetRange({startLoc, Lexer()->GetToken().End()}); 1368 break; 1369 } 1370 1371 default: { 1372 ThrowSyntaxError("Unexpected token, expected an identifier."); 1373 } 1374 } 1375 1376 Lexer()->NextToken(); 1377 return parameter; 1378} 1379 1380// NOLINTBEGIN(modernize-avoid-c-arrays) 1381static constexpr char const NO_DEFAULT_FOR_REST[] = "Rest parameter cannot have the default value."; 1382static constexpr char const ONLY_ARRAY_FOR_REST[] = "Rest parameter should be of an array type."; 1383static constexpr char const EXPLICIT_PARAM_TYPE[] = "Parameter declaration should have an explicit type annotation."; 1384// NOLINTEND(modernize-avoid-c-arrays) 1385 1386ir::ETSUnionType *ETSParser::CreateOptionalParameterTypeNode(ir::TypeNode *typeAnnotation, 1387 ir::ETSUndefinedType *defaultUndef) 1388{ 1389 ArenaVector<ir::TypeNode *> types(Allocator()->Adapter()); 1390 if (typeAnnotation->IsETSUnionType()) { 1391 for (auto const &type : typeAnnotation->AsETSUnionType()->Types()) { 1392 types.push_back(type); 1393 } 1394 } else { 1395 types.push_back(typeAnnotation); 1396 } 1397 types.push_back(defaultUndef); 1398 1399 auto *const unionType = AllocNode<ir::ETSUnionType>(std::move(types)); 1400 unionType->SetRange({typeAnnotation->Start(), typeAnnotation->End()}); 1401 return unionType; 1402} 1403 1404ir::Expression *ETSParser::ParseFunctionParameter() 1405{ 1406 auto *const paramIdent = GetAnnotatedExpressionFromParam(); 1407 1408 ir::ETSUndefinedType *defaultUndef = nullptr; 1409 1410 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) { 1411 if (paramIdent->IsRestElement()) { 1412 ThrowSyntaxError(NO_DEFAULT_FOR_REST); 1413 } 1414 defaultUndef = AllocNode<ir::ETSUndefinedType>(); 1415 defaultUndef->SetRange({Lexer()->GetToken().Start(), Lexer()->GetToken().End()}); 1416 Lexer()->NextToken(); // eat '?' 1417 } 1418 1419 const bool isArrow = (GetContext().Status() & ParserStatus::ARROW_FUNCTION) != 0; 1420 1421 if (Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_COLON)) { 1422 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR; 1423 ir::TypeNode *typeAnnotation = ParseTypeAnnotation(&options); 1424 if (typeAnnotation == nullptr) { // Error processing. 1425 return nullptr; 1426 } 1427 1428 if (defaultUndef != nullptr) { 1429 typeAnnotation = CreateOptionalParameterTypeNode(typeAnnotation, defaultUndef); 1430 } 1431 1432 if (paramIdent->IsRestElement() && !typeAnnotation->IsTSArrayType()) { 1433 ThrowSyntaxError(ONLY_ARRAY_FOR_REST); 1434 } 1435 1436 typeAnnotation->SetParent(paramIdent); 1437 paramIdent->SetTsTypeAnnotation(typeAnnotation); 1438 paramIdent->SetEnd(typeAnnotation->End()); 1439 } else if (!isArrow && defaultUndef == nullptr) { 1440 ThrowSyntaxError(EXPLICIT_PARAM_TYPE); 1441 } 1442 1443 return ParseFunctionParameterExpression(paramIdent, defaultUndef); 1444} 1445 1446ir::Expression *ETSParser::CreateParameterThis(const util::StringView className) 1447{ 1448 auto *paramIdent = AllocNode<ir::Identifier>(varbinder::TypedBinder::MANDATORY_PARAM_THIS, Allocator()); 1449 paramIdent->SetRange(Lexer()->GetToken().Loc()); 1450 1451 ir::Expression *classTypeName = AllocNode<ir::Identifier>(className, Allocator()); 1452 classTypeName->AsIdentifier()->SetReference(); 1453 classTypeName->SetRange(Lexer()->GetToken().Loc()); 1454 1455 auto typeRefPart = AllocNode<ir::ETSTypeReferencePart>(classTypeName, nullptr, nullptr); 1456 ir::TypeNode *typeAnnotation = AllocNode<ir::ETSTypeReference>(typeRefPart); 1457 1458 typeAnnotation->SetParent(paramIdent); 1459 paramIdent->SetTsTypeAnnotation(typeAnnotation); 1460 1461 auto *paramExpression = AllocNode<ir::ETSParameterExpression>(paramIdent, nullptr); 1462 paramExpression->SetRange({paramIdent->Start(), paramIdent->End()}); 1463 1464 return paramExpression; 1465} 1466 1467ir::AnnotatedExpression *ETSParser::ParseVariableDeclaratorKey([[maybe_unused]] VariableParsingFlags flags) 1468{ 1469 ir::Identifier *init = ExpectIdentifier(); 1470 ir::TypeNode *typeAnnotation = nullptr; 1471 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) { 1472 if ((flags & VariableParsingFlags::FOR_OF) != 0U) { 1473 ThrowSyntaxError("Optional variable is not allowed in for of statements"); 1474 } 1475 Lexer()->NextToken(); // eat '?' 1476 init->AddModifier(ir::ModifierFlags::OPTIONAL); 1477 } 1478 1479 if (auto const tokenType = Lexer()->GetToken().Type(); tokenType == lexer::TokenType::PUNCTUATOR_COLON) { 1480 Lexer()->NextToken(); // eat ':' 1481 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR; 1482 typeAnnotation = ParseTypeAnnotation(&options); 1483 } else if (tokenType != lexer::TokenType::PUNCTUATOR_SUBSTITUTION && (flags & VariableParsingFlags::FOR_OF) == 0U) { 1484 ThrowSyntaxError("Variable must be initialized or it's type must be declared"); 1485 } 1486 1487 if (typeAnnotation != nullptr) { 1488 init->SetTsTypeAnnotation(typeAnnotation); 1489 typeAnnotation->SetParent(init); 1490 } 1491 1492 return init; 1493} 1494 1495ir::VariableDeclarator *ETSParser::ParseVariableDeclaratorInitializer(ir::Expression *init, VariableParsingFlags flags, 1496 const lexer::SourcePosition &startLoc) 1497{ 1498 if ((flags & VariableParsingFlags::DISALLOW_INIT) != 0) { 1499 ThrowSyntaxError("for-await-of loop variable declaration may not have an initializer"); 1500 } 1501 1502 Lexer()->NextToken(); 1503 1504 ir::Expression *initializer = ParseExpression(); 1505 1506 lexer::SourcePosition endLoc = initializer->End(); 1507 1508 auto *declarator = AllocNode<ir::VariableDeclarator>(GetFlag(flags), init, initializer); 1509 declarator->SetRange({startLoc, endLoc}); 1510 1511 return declarator; 1512} 1513 1514ir::VariableDeclarator *ETSParser::ParseVariableDeclarator(ir::Expression *init, lexer::SourcePosition startLoc, 1515 VariableParsingFlags flags) 1516{ 1517 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { 1518 return ParseVariableDeclaratorInitializer(init, flags, startLoc); 1519 } 1520 1521 if ((flags & VariableParsingFlags::CONST) != 0 && 1522 static_cast<uint32_t>(flags & VariableParsingFlags::ACCEPT_CONST_NO_INIT) == 0U && !InAmbientContext()) { 1523 ThrowSyntaxError("Missing initializer in const declaration"); 1524 } 1525 1526 if (init->AsIdentifier()->TypeAnnotation() == nullptr && (flags & VariableParsingFlags::FOR_OF) == 0U) { 1527 ThrowSyntaxError("Variable must be initialized or it's type must be declared"); 1528 } 1529 1530 lexer::SourcePosition endLoc = init->End(); 1531 auto declarator = AllocNode<ir::VariableDeclarator>(GetFlag(flags), init); 1532 declarator->SetRange({startLoc, endLoc}); 1533 1534 // NOTE (psiket) Transfer the OPTIONAL flag from the init to the declarator? 1535 return declarator; 1536} 1537 1538ir::Expression *ETSParser::ParseCatchParam() 1539{ 1540 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { 1541 ThrowSyntaxError("Unexpected token, expected '('"); 1542 } 1543 1544 ir::AnnotatedExpression *param = nullptr; 1545 1546 Lexer()->NextToken(); // eat left paren 1547 1548 if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) { 1549 CheckRestrictedBinding(); 1550 param = ExpectIdentifier(); 1551 } else { 1552 ThrowSyntaxError("Unexpected token in catch parameter, expected an identifier"); 1553 } 1554 1555 ParseCatchParamTypeAnnotation(param); 1556 1557 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 1558 ThrowSyntaxError("Unexpected token, expected ')'"); 1559 } 1560 1561 Lexer()->NextToken(); // eat right paren 1562 1563 return param; 1564} 1565 1566void ETSParser::ParseCatchParamTypeAnnotation([[maybe_unused]] ir::AnnotatedExpression *param) 1567{ 1568 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { 1569 Lexer()->NextToken(); // eat ':' 1570 1571 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR; 1572 if (auto *typeAnnotation = ParseTypeAnnotation(&options); typeAnnotation != nullptr) { 1573 typeAnnotation->SetParent(param); 1574 param->SetTsTypeAnnotation(typeAnnotation); 1575 } 1576 } 1577 1578 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { 1579 ThrowSyntaxError("Catch clause variable cannot have an initializer"); 1580 } 1581} 1582 1583ir::Statement *ETSParser::ParseImportDeclaration([[maybe_unused]] StatementParsingFlags flags) 1584{ 1585 char32_t nextChar = Lexer()->Lookahead(); 1586 if (nextChar == lexer::LEX_CHAR_LEFT_PAREN || nextChar == lexer::LEX_CHAR_DOT) { 1587 return ParseExpressionStatement(); 1588 } 1589 1590 lexer::SourcePosition startLoc = Lexer()->GetToken().Start(); 1591 Lexer()->NextToken(); // eat import 1592 1593 ArenaVector<ir::AstNode *> specifiers(Allocator()->Adapter()); 1594 1595 ir::ImportSource *importSource = nullptr; 1596 1597 if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_STRING) { 1598 ir::AstNode *astNode = ParseImportSpecifiers(&specifiers); 1599 if (astNode != nullptr) { 1600 ASSERT(astNode->IsTSImportEqualsDeclaration()); 1601 astNode->SetRange({startLoc, Lexer()->GetToken().End()}); 1602 ConsumeSemicolon(astNode->AsTSImportEqualsDeclaration()); 1603 return astNode->AsTSImportEqualsDeclaration(); 1604 } 1605 importSource = ParseSourceFromClause(true); 1606 } else { 1607 importSource = ParseSourceFromClause(false); 1608 } 1609 1610 lexer::SourcePosition endLoc = importSource->Source()->End(); 1611 auto *importDeclaration = AllocNode<ir::ETSImportDeclaration>(importSource, std::move(specifiers)); 1612 importDeclaration->SetRange({startLoc, endLoc}); 1613 1614 ConsumeSemicolon(importDeclaration); 1615 1616 return importDeclaration; 1617} 1618 1619ir::Statement *ETSParser::ParseExportDeclaration([[maybe_unused]] StatementParsingFlags flags) 1620{ 1621 ThrowUnexpectedToken(lexer::TokenType::KEYW_EXPORT); 1622} 1623 1624ir::Expression *ETSParser::ParseExpressionOrTypeAnnotation(lexer::TokenType type, 1625 [[maybe_unused]] ExpressionParseFlags flags) 1626{ 1627 if (type == lexer::TokenType::KEYW_INSTANCEOF) { 1628 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR; 1629 1630 if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_NULL) { 1631 auto *typeAnnotation = AllocNode<ir::NullLiteral>(); 1632 typeAnnotation->SetRange(Lexer()->GetToken().Loc()); 1633 Lexer()->NextToken(); 1634 1635 return typeAnnotation; 1636 } 1637 1638 return ParseTypeAnnotation(&options); 1639 } 1640 1641 return ParseExpression(ExpressionParseFlags::DISALLOW_YIELD); 1642} 1643 1644bool ETSParser::ParsePotentialGenericFunctionCall(ir::Expression *primaryExpr, ir::Expression **returnExpression, 1645 [[maybe_unused]] const lexer::SourcePosition &startLoc, 1646 bool ignoreCallExpression) 1647{ 1648 if (Lexer()->Lookahead() == lexer::LEX_CHAR_LESS_THAN || 1649 (!primaryExpr->IsIdentifier() && !primaryExpr->IsMemberExpression())) { 1650 return true; 1651 } 1652 1653 const auto savedPos = Lexer()->Save(); 1654 1655 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) { 1656 Lexer()->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1); 1657 } 1658 1659 TypeAnnotationParsingOptions options = 1660 TypeAnnotationParsingOptions::ALLOW_WILDCARD | TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE; 1661 ir::TSTypeParameterInstantiation *typeParams = ParseTypeParameterInstantiation(&options); 1662 1663 if (typeParams == nullptr) { 1664 Lexer()->Rewind(savedPos); 1665 return true; 1666 } 1667 1668 if (Lexer()->GetToken().Type() == lexer::TokenType::EOS) { 1669 ThrowSyntaxError("'(' expected"); 1670 } 1671 1672 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { 1673 if (!ignoreCallExpression) { 1674 *returnExpression = ParseCallExpression(*returnExpression, false, false); 1675 (*returnExpression)->AsCallExpression()->SetTypeParams(typeParams); 1676 return false; 1677 } 1678 1679 return true; 1680 } 1681 1682 Lexer()->Rewind(savedPos); 1683 return true; 1684} 1685 1686ir::ModifierFlags ETSParser::ParseTypeVarianceModifier(TypeAnnotationParsingOptions *const options) 1687{ 1688 if ((*options & TypeAnnotationParsingOptions::ALLOW_WILDCARD) == 0 && 1689 (*options & TypeAnnotationParsingOptions::ALLOW_DECLARATION_SITE_VARIANCE) == 0) { 1690 ThrowSyntaxError("Variance modifier is not allowed here."); 1691 } 1692 1693 switch (Lexer()->GetToken().KeywordType()) { 1694 case lexer::TokenType::KEYW_IN: { 1695 Lexer()->NextToken(); 1696 return ir::ModifierFlags::IN; 1697 } 1698 case lexer::TokenType::KEYW_OUT: { 1699 Lexer()->NextToken(); 1700 return ir::ModifierFlags::OUT; 1701 } 1702 default: { 1703 return ir::ModifierFlags::NONE; 1704 } 1705 } 1706} 1707 1708ir::AstNode *ETSParser::ParseAmbientSignature() 1709{ 1710 auto const startPos = Lexer()->GetToken().Start(); 1711 1712 if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 1713 ThrowSyntaxError("Unexpected token at", Lexer()->GetToken().Start()); 1714 } 1715 auto const indexName = Lexer()->GetToken().Ident(); 1716 1717 Lexer()->NextToken(); 1718 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) { 1719 ThrowSyntaxError("Index type expected in index signature", Lexer()->GetToken().Start()); 1720 } 1721 1722 Lexer()->NextToken(); // eat ":" 1723 if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_NUMBER) { 1724 ThrowSyntaxError("Index type must be number in index signature", Lexer()->GetToken().Start()); 1725 } 1726 1727 Lexer()->NextToken(); // eat indexType 1728 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) { 1729 ThrowSyntaxError("] expected in index signature", Lexer()->GetToken().Start()); 1730 } 1731 1732 Lexer()->NextToken(); // eat "]" 1733 if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) { 1734 ThrowSyntaxError("An index signature must have a type annotation.", Lexer()->GetToken().Start()); 1735 } 1736 1737 Lexer()->NextToken(); // eat ":" 1738 if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 1739 ThrowSyntaxError("Return type of index signature from exported class or interface need to be identifier", 1740 Lexer()->GetToken().Start()); 1741 } 1742 auto const returnType = 1743 AllocNode<ir::ETSTypeReferencePart>(AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator())); 1744 1745 auto dummyNode = AllocNode<ir::DummyNode>(compiler::Signatures::AMBIENT_INDEXER, indexName, returnType, 1746 ir::DummyNodeFlag::INDEXER); 1747 dummyNode->SetRange({startPos, Lexer()->GetToken().End()}); 1748 Lexer()->NextToken(); // eat return type 1749 return dummyNode; 1750} 1751 1752ir::TSTypeParameter *ETSParser::ParseTypeParameter([[maybe_unused]] TypeAnnotationParsingOptions *options) 1753{ 1754 lexer::SourcePosition startLoc = Lexer()->GetToken().Start(); 1755 1756 const auto varianceModifier = [this, options] { 1757 switch (Lexer()->GetToken().KeywordType()) { 1758 case lexer::TokenType::KEYW_IN: 1759 case lexer::TokenType::KEYW_OUT: 1760 return ParseTypeVarianceModifier(options); 1761 default: 1762 return ir::ModifierFlags::NONE; 1763 } 1764 }(); 1765 1766 auto *paramIdent = ExpectIdentifier(); 1767 1768 ir::TypeNode *constraint = nullptr; 1769 if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) { 1770 Lexer()->NextToken(); 1771 TypeAnnotationParsingOptions newOptions = 1772 TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE; 1773 constraint = ParseTypeAnnotation(&newOptions); 1774 } 1775 1776 ir::TypeNode *defaultType = nullptr; 1777 1778 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { 1779 Lexer()->NextToken(); // eat '=' 1780 defaultType = ParseTypeAnnotation(options); 1781 } 1782 1783 auto *typeParam = AllocNode<ir::TSTypeParameter>(paramIdent, constraint, defaultType, varianceModifier); 1784 1785 typeParam->SetRange({startLoc, Lexer()->GetToken().End()}); 1786 return typeParam; 1787} 1788 1789ir::Identifier *ETSParser::ParseClassIdent([[maybe_unused]] ir::ClassDefinitionModifiers modifiers) 1790{ 1791 return ExpectIdentifier(false, true); 1792} 1793 1794bool ETSParser::IsStructKeyword() const 1795{ 1796 return (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && 1797 Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STRUCT); 1798} 1799 1800void ETSParser::ParseTrailingBlock(ir::CallExpression *callExpr) 1801{ 1802 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 1803 callExpr->SetIsTrailingBlockInNewLine(Lexer()->GetToken().NewLine()); 1804 callExpr->SetTrailingBlock(ParseBlockStatement()); 1805 } 1806} 1807 1808ir::Expression *ETSParser::ParseCoercedNumberLiteral() 1809{ 1810 if ((Lexer()->GetToken().Flags() & lexer::TokenFlags::NUMBER_FLOAT) != 0U) { 1811 auto *number = AllocNode<ir::NumberLiteral>(Lexer()->GetToken().GetNumber()); 1812 number->SetRange(Lexer()->GetToken().Loc()); 1813 auto *floatType = AllocNode<ir::ETSPrimitiveType>(ir::PrimitiveType::FLOAT); 1814 floatType->SetRange(Lexer()->GetToken().Loc()); 1815 auto *asExpression = AllocNode<ir::TSAsExpression>(number, floatType, true); 1816 asExpression->SetRange(Lexer()->GetToken().Loc()); 1817 1818 Lexer()->NextToken(); 1819 return asExpression; 1820 } 1821 return ParseNumberLiteral(); 1822} 1823 1824void ETSParser::CheckDeclare() 1825{ 1826 ASSERT(Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE); 1827 1828 if (InAmbientContext()) { 1829 ThrowSyntaxError("A 'declare' modifier cannot be used in an already ambient context."); 1830 } 1831 1832 GetContext().Status() |= ParserStatus::IN_AMBIENT_CONTEXT; 1833 1834 Lexer()->NextToken(); // eat 'declare' 1835 1836 switch (Lexer()->GetToken().KeywordType()) { 1837 case lexer::TokenType::KEYW_LET: 1838 case lexer::TokenType::KEYW_CONST: 1839 case lexer::TokenType::KEYW_FUNCTION: 1840 case lexer::TokenType::KEYW_CLASS: 1841 case lexer::TokenType::KEYW_NAMESPACE: 1842 case lexer::TokenType::KEYW_ENUM: 1843 case lexer::TokenType::KEYW_TYPE: 1844 case lexer::TokenType::KEYW_ABSTRACT: 1845 case lexer::TokenType::KEYW_FINAL: 1846 case lexer::TokenType::KEYW_INTERFACE: 1847 case lexer::TokenType::KEYW_ASYNC: { 1848 return; 1849 } 1850 default: { 1851 ThrowSyntaxError("Unexpected token."); 1852 } 1853 } 1854} 1855 1856ir::FunctionDeclaration *ETSParser::ParseFunctionDeclaration(bool canBeAnonymous, ir::ModifierFlags modifiers) 1857{ 1858 lexer::SourcePosition startLoc = Lexer()->GetToken().Start(); 1859 1860 ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION); 1861 Lexer()->NextToken(); 1862 auto newStatus = ParserStatus::NEED_RETURN_TYPE | ParserStatus::ALLOW_SUPER; 1863 1864 if ((modifiers & ir::ModifierFlags::ASYNC) != 0) { 1865 newStatus |= ParserStatus::ASYNC_FUNCTION; 1866 } 1867 if (Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_MULTIPLY)) { 1868 newStatus |= ParserStatus::GENERATOR_FUNCTION; 1869 } 1870 1871 ir::Identifier *className = nullptr; 1872 ir::Identifier *identNode = nullptr; 1873 if (Lexer()->Lookahead() == lexer::LEX_CHAR_DOT) { 1874 className = ExpectIdentifier(); 1875 if (className != nullptr) { 1876 newStatus |= ParserStatus::IN_EXTENSION_FUNCTION; 1877 } 1878 Lexer()->NextToken(); 1879 identNode = ExpectIdentifier(); 1880 } else if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) { 1881 identNode = ExpectIdentifier(); 1882 } else if (!canBeAnonymous) { 1883 LogSyntaxError("Unexpected token, expected identifier after 'function' keyword"); 1884 } 1885 newStatus |= ParserStatus::FUNCTION_DECLARATION; 1886 if (identNode != nullptr) { 1887 CheckRestrictedBinding(identNode->Name(), identNode->Start()); 1888 } 1889 1890 ir::ScriptFunction *func = ParseFunction(newStatus, className); 1891 if (identNode != nullptr) { // Error processing. 1892 func->SetIdent(identNode); 1893 } 1894 1895 auto *funcDecl = AllocNode<ir::FunctionDeclaration>(Allocator(), func); 1896 if (func->IsOverload() && Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 1897 Lexer()->NextToken(); 1898 } 1899 funcDecl->SetRange(func->Range()); 1900 func->AddModifier(modifiers); 1901 func->SetStart(startLoc); 1902 1903 if (className != nullptr) { 1904 func->AddFlag(ir::ScriptFunctionFlags::INSTANCE_EXTENSION_METHOD); 1905 } 1906 1907 return funcDecl; 1908} 1909 1910void ETSParser::AddPackageSourcesToParseList() 1911{ 1912 importPathManager_->AddToParseList(GetProgram()->SourceFileFolder(), util::ImportFlags::IMPLICIT_PACKAGE_IMPORT); 1913 1914 // Global program file is always in the same folder that we scanned, but we don't need to parse it twice 1915 importPathManager_->MarkAsParsed(globalProgram_->SourceFilePath()); 1916} 1917 1918//================================================================================================// 1919// ExternalSourceParser class 1920//================================================================================================// 1921 1922ExternalSourceParser::ExternalSourceParser(ETSParser *parser, Program *newProgram) 1923 : parser_(parser), 1924 savedProgram_(parser_->GetProgram()), 1925 savedLexer_(parser_->Lexer()), 1926 savedTopScope_(parser_->GetProgram()->VarBinder()->TopScope()) 1927{ 1928 parser_->SetProgram(newProgram); 1929 parser_->GetContext().SetProgram(newProgram); 1930} 1931 1932ExternalSourceParser::~ExternalSourceParser() 1933{ 1934 parser_->SetLexer(savedLexer_); 1935 parser_->SetProgram(savedProgram_); 1936 parser_->GetContext().SetProgram(savedProgram_); 1937 parser_->GetProgram()->VarBinder()->ResetTopScope(savedTopScope_); 1938} 1939 1940//================================================================================================// 1941// InnerSourceParser class 1942//================================================================================================// 1943 1944InnerSourceParser::InnerSourceParser(ETSParser *parser) 1945 : parser_(parser), 1946 savedLexer_(parser_->Lexer()), 1947 savedSourceCode_(parser_->GetProgram()->SourceCode()), 1948 savedSourceFile_(parser_->GetProgram()->SourceFilePath()), 1949 savedSourceFilePath_(parser_->GetProgram()->SourceFileFolder()) 1950{ 1951} 1952 1953InnerSourceParser::~InnerSourceParser() 1954{ 1955 parser_->SetLexer(savedLexer_); 1956 parser_->GetProgram()->SetSource(savedSourceCode_, savedSourceFile_, savedSourceFilePath_); 1957} 1958} // namespace ark::es2panda::parser 1959