13af6ab5fSopenharmony_ci/** 23af6ab5fSopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License. 53af6ab5fSopenharmony_ci * You may obtain a copy of the License at 63af6ab5fSopenharmony_ci * 73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83af6ab5fSopenharmony_ci * 93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and 133af6ab5fSopenharmony_ci * limitations under the License. 143af6ab5fSopenharmony_ci */ 153af6ab5fSopenharmony_ci 163af6ab5fSopenharmony_ci#include "ETSparser.h" 173af6ab5fSopenharmony_ci#include "ETSNolintParser.h" 183af6ab5fSopenharmony_ci#include <utility> 193af6ab5fSopenharmony_ci 203af6ab5fSopenharmony_ci#include "macros.h" 213af6ab5fSopenharmony_ci#include "parser/parserFlags.h" 223af6ab5fSopenharmony_ci#include "parser/parserStatusContext.h" 233af6ab5fSopenharmony_ci#include "util/helpers.h" 243af6ab5fSopenharmony_ci#include "util/language.h" 253af6ab5fSopenharmony_ci#include "utils/arena_containers.h" 263af6ab5fSopenharmony_ci#include "varbinder/varbinder.h" 273af6ab5fSopenharmony_ci#include "varbinder/ETSBinder.h" 283af6ab5fSopenharmony_ci#include "lexer/lexer.h" 293af6ab5fSopenharmony_ci#include "lexer/ETSLexer.h" 303af6ab5fSopenharmony_ci#include "ir/astNode.h" 313af6ab5fSopenharmony_ci#include "ir/base/decorator.h" 323af6ab5fSopenharmony_ci#include "ir/base/catchClause.h" 333af6ab5fSopenharmony_ci#include "ir/base/scriptFunction.h" 343af6ab5fSopenharmony_ci#include "ir/base/methodDefinition.h" 353af6ab5fSopenharmony_ci#include "ir/base/spreadElement.h" 363af6ab5fSopenharmony_ci#include "ir/statements/namespaceDeclaration.h" 373af6ab5fSopenharmony_ci#include "ir/expressions/identifier.h" 383af6ab5fSopenharmony_ci#include "ir/expressions/functionExpression.h" 393af6ab5fSopenharmony_ci#include "ir/expressions/dummyNode.h" 403af6ab5fSopenharmony_ci#include "ir/module/importDeclaration.h" 413af6ab5fSopenharmony_ci#include "ir/module/importDefaultSpecifier.h" 423af6ab5fSopenharmony_ci#include "ir/module/importSpecifier.h" 433af6ab5fSopenharmony_ci#include "ir/module/exportSpecifier.h" 443af6ab5fSopenharmony_ci#include "ir/module/exportNamedDeclaration.h" 453af6ab5fSopenharmony_ci#include "ir/ets/etsPrimitiveType.h" 463af6ab5fSopenharmony_ci#include "ir/ets/etsPackageDeclaration.h" 473af6ab5fSopenharmony_ci#include "ir/ets/etsReExportDeclaration.h" 483af6ab5fSopenharmony_ci#include "ir/ets/etsWildcardType.h" 493af6ab5fSopenharmony_ci#include "ir/ets/etsTuple.h" 503af6ab5fSopenharmony_ci#include "ir/ets/etsFunctionType.h" 513af6ab5fSopenharmony_ci#include "ir/ets/etsScript.h" 523af6ab5fSopenharmony_ci#include "ir/ets/etsTypeReference.h" 533af6ab5fSopenharmony_ci#include "ir/ets/etsTypeReferencePart.h" 543af6ab5fSopenharmony_ci#include "ir/ets/etsNullishTypes.h" 553af6ab5fSopenharmony_ci#include "ir/ets/etsUnionType.h" 563af6ab5fSopenharmony_ci#include "ir/ets/etsImportSource.h" 573af6ab5fSopenharmony_ci#include "ir/ets/etsImportDeclaration.h" 583af6ab5fSopenharmony_ci#include "ir/ets/etsStructDeclaration.h" 593af6ab5fSopenharmony_ci#include "ir/module/importNamespaceSpecifier.h" 603af6ab5fSopenharmony_ci#include "ir/ts/tsInterfaceDeclaration.h" 613af6ab5fSopenharmony_ci#include "ir/ts/tsTypeParameterInstantiation.h" 623af6ab5fSopenharmony_ci#include "ir/ts/tsInterfaceBody.h" 633af6ab5fSopenharmony_ci#include "ir/ts/tsImportEqualsDeclaration.h" 643af6ab5fSopenharmony_ci#include "ir/ts/tsArrayType.h" 653af6ab5fSopenharmony_ci#include "ir/ts/tsQualifiedName.h" 663af6ab5fSopenharmony_ci#include "ir/ts/tsTypeReference.h" 673af6ab5fSopenharmony_ci#include "ir/ts/tsTypeParameter.h" 683af6ab5fSopenharmony_ci#include "ir/ts/tsInterfaceHeritage.h" 693af6ab5fSopenharmony_ci#include "ir/ts/tsFunctionType.h" 703af6ab5fSopenharmony_ci#include "ir/ts/tsTypeAliasDeclaration.h" 713af6ab5fSopenharmony_ci#include "ir/ts/tsTypeParameterDeclaration.h" 723af6ab5fSopenharmony_ci#include "ir/ts/tsThisType.h" 733af6ab5fSopenharmony_ci#include "generated/signatures.h" 743af6ab5fSopenharmony_ci 753af6ab5fSopenharmony_cinamespace ark::es2panda::parser { 763af6ab5fSopenharmony_ciclass FunctionContext; 773af6ab5fSopenharmony_ci 783af6ab5fSopenharmony_ciusing namespace std::literals::string_literals; 793af6ab5fSopenharmony_ci 803af6ab5fSopenharmony_ciETSParser::ETSParser(Program *program, const CompilerOptions &options, ParserStatus status) 813af6ab5fSopenharmony_ci : TypedParser(program, options, status), globalProgram_(GetProgram()) 823af6ab5fSopenharmony_ci{ 833af6ab5fSopenharmony_ci importPathManager_ = std::make_unique<util::ImportPathManager>(Allocator(), ArkTSConfig(), GetOptions().stdLib); 843af6ab5fSopenharmony_ci} 853af6ab5fSopenharmony_ci 863af6ab5fSopenharmony_cibool ETSParser::IsETSParser() const noexcept 873af6ab5fSopenharmony_ci{ 883af6ab5fSopenharmony_ci return true; 893af6ab5fSopenharmony_ci} 903af6ab5fSopenharmony_ci 913af6ab5fSopenharmony_cistd::unique_ptr<lexer::Lexer> ETSParser::InitLexer(const SourceFile &sourceFile) 923af6ab5fSopenharmony_ci{ 933af6ab5fSopenharmony_ci GetProgram()->SetSource(sourceFile); 943af6ab5fSopenharmony_ci auto lexer = std::make_unique<lexer::ETSLexer>(&GetContext()); 953af6ab5fSopenharmony_ci SetLexer(lexer.get()); 963af6ab5fSopenharmony_ci return lexer; 973af6ab5fSopenharmony_ci} 983af6ab5fSopenharmony_ci 993af6ab5fSopenharmony_civoid ETSParser::ParseProgram(ScriptKind kind) 1003af6ab5fSopenharmony_ci{ 1013af6ab5fSopenharmony_ci lexer::SourcePosition startLoc = Lexer()->GetToken().Start(); 1023af6ab5fSopenharmony_ci Lexer()->NextToken(); 1033af6ab5fSopenharmony_ci GetProgram()->SetKind(kind); 1043af6ab5fSopenharmony_ci 1053af6ab5fSopenharmony_ci if (GetProgram()->SourceFilePath().Utf8()[0] == '@') { 1063af6ab5fSopenharmony_ci // NOTE(user): handle multiple sourceFiles 1073af6ab5fSopenharmony_ci } 1083af6ab5fSopenharmony_ci 1093af6ab5fSopenharmony_ci ArenaVector<ir::Statement *> statements(Allocator()->Adapter()); 1103af6ab5fSopenharmony_ci auto decl = ParsePackageDeclaration(); 1113af6ab5fSopenharmony_ci if (decl != nullptr) { 1123af6ab5fSopenharmony_ci statements.emplace_back(decl); 1133af6ab5fSopenharmony_ci // If we found a package declaration, then add all files with the same package to the package parse list 1143af6ab5fSopenharmony_ci AddPackageSourcesToParseList(); 1153af6ab5fSopenharmony_ci } 1163af6ab5fSopenharmony_ci 1173af6ab5fSopenharmony_ci auto script = ParseETSGlobalScript(startLoc, statements); 1183af6ab5fSopenharmony_ci 1193af6ab5fSopenharmony_ci AddExternalSource(ParseSources(true)); 1203af6ab5fSopenharmony_ci GetProgram()->SetAst(script); 1213af6ab5fSopenharmony_ci GetProgram()->SetDeclarationModuleInfo(); 1223af6ab5fSopenharmony_ci} 1233af6ab5fSopenharmony_ci 1243af6ab5fSopenharmony_ciir::ETSScript *ETSParser::ParseETSGlobalScript(lexer::SourcePosition startLoc, ArenaVector<ir::Statement *> &statements) 1253af6ab5fSopenharmony_ci{ 1263af6ab5fSopenharmony_ci ETSNolintParser etsnolintParser(this); 1273af6ab5fSopenharmony_ci etsnolintParser.CollectETSNolints(); 1283af6ab5fSopenharmony_ci 1293af6ab5fSopenharmony_ci auto imports = ParseImportDeclarations(); 1303af6ab5fSopenharmony_ci statements.insert(statements.end(), imports.begin(), imports.end()); 1313af6ab5fSopenharmony_ci 1323af6ab5fSopenharmony_ci auto topLevelStatements = ParseTopLevelDeclaration(); 1333af6ab5fSopenharmony_ci statements.insert(statements.end(), topLevelStatements.begin(), topLevelStatements.end()); 1343af6ab5fSopenharmony_ci 1353af6ab5fSopenharmony_ci etsnolintParser.ApplyETSNolintsToStatements(statements); 1363af6ab5fSopenharmony_ci 1373af6ab5fSopenharmony_ci auto *etsScript = AllocNode<ir::ETSScript>(Allocator(), std::move(statements), GetProgram()); 1383af6ab5fSopenharmony_ci etsScript->SetRange({startLoc, Lexer()->GetToken().End()}); 1393af6ab5fSopenharmony_ci return etsScript; 1403af6ab5fSopenharmony_ci} 1413af6ab5fSopenharmony_ci 1423af6ab5fSopenharmony_civoid ETSParser::AddExternalSource(const std::vector<Program *> &programs) 1433af6ab5fSopenharmony_ci{ 1443af6ab5fSopenharmony_ci auto &extSources = globalProgram_->ExternalSources(); 1453af6ab5fSopenharmony_ci 1463af6ab5fSopenharmony_ci for (auto *newProg : programs) { 1473af6ab5fSopenharmony_ci const util::StringView moduleName = newProg->ModuleName(); 1483af6ab5fSopenharmony_ci if (extSources.count(moduleName) == 0) { 1493af6ab5fSopenharmony_ci extSources.try_emplace(moduleName, Allocator()->Adapter()); 1503af6ab5fSopenharmony_ci } 1513af6ab5fSopenharmony_ci 1523af6ab5fSopenharmony_ci extSources.at(moduleName).emplace_back(newProg); 1533af6ab5fSopenharmony_ci } 1543af6ab5fSopenharmony_ci} 1553af6ab5fSopenharmony_ci 1563af6ab5fSopenharmony_ciArenaVector<ir::ETSImportDeclaration *> ETSParser::ParseDefaultSources(std::string_view srcFile, 1573af6ab5fSopenharmony_ci std::string_view importSrc) 1583af6ab5fSopenharmony_ci{ 1593af6ab5fSopenharmony_ci auto isp = InnerSourceParser(this); 1603af6ab5fSopenharmony_ci SourceFile source(srcFile, importSrc); 1613af6ab5fSopenharmony_ci auto lexer = InitLexer(source); 1623af6ab5fSopenharmony_ci 1633af6ab5fSopenharmony_ci Lexer()->NextToken(); 1643af6ab5fSopenharmony_ci 1653af6ab5fSopenharmony_ci GetContext().Status() |= ParserStatus::IN_DEFAULT_IMPORTS; 1663af6ab5fSopenharmony_ci auto statements = ParseImportDeclarations(); 1673af6ab5fSopenharmony_ci GetContext().Status() &= ~ParserStatus::IN_DEFAULT_IMPORTS; 1683af6ab5fSopenharmony_ci 1693af6ab5fSopenharmony_ci AddExternalSource(ParseSources()); 1703af6ab5fSopenharmony_ci return statements; 1713af6ab5fSopenharmony_ci} 1723af6ab5fSopenharmony_ci 1733af6ab5fSopenharmony_civoid ETSParser::AddDirectImportsToDirectExternalSources( 1743af6ab5fSopenharmony_ci const ArenaVector<util::StringView> &directImportsFromMainSource, parser::Program *const newProg) const 1753af6ab5fSopenharmony_ci{ 1763af6ab5fSopenharmony_ci if (std::find_if(directImportsFromMainSource.begin(), directImportsFromMainSource.end(), 1773af6ab5fSopenharmony_ci [newProg](const util::StringView &sv) { return sv == newProg->AbsoluteName(); }) == 1783af6ab5fSopenharmony_ci directImportsFromMainSource.end()) { 1793af6ab5fSopenharmony_ci return; 1803af6ab5fSopenharmony_ci } 1813af6ab5fSopenharmony_ci 1823af6ab5fSopenharmony_ci const util::StringView name = newProg->Ast()->Statements().empty() ? newProg->FileName() : newProg->ModuleName(); 1833af6ab5fSopenharmony_ci if (GetProgram()->DirectExternalSources().count(name) == 0) { 1843af6ab5fSopenharmony_ci GetProgram()->DirectExternalSources().try_emplace(name, Allocator()->Adapter()); 1853af6ab5fSopenharmony_ci } 1863af6ab5fSopenharmony_ci GetProgram()->DirectExternalSources().at(name).emplace_back(newProg); 1873af6ab5fSopenharmony_ci} 1883af6ab5fSopenharmony_ci 1893af6ab5fSopenharmony_civoid ETSParser::TryParseSource(const util::ImportPathManager::ParseInfo &parseListIdx, util::UString *extSrc, 1903af6ab5fSopenharmony_ci const ArenaVector<util::StringView> &directImportsFromMainSource, 1913af6ab5fSopenharmony_ci std::vector<Program *> &programs) 1923af6ab5fSopenharmony_ci{ 1933af6ab5fSopenharmony_ci try { 1943af6ab5fSopenharmony_ci parser::Program *newProg = 1953af6ab5fSopenharmony_ci ParseSource({parseListIdx.sourcePath.Utf8(), extSrc->View().Utf8(), parseListIdx.sourcePath.Utf8(), false}); 1963af6ab5fSopenharmony_ci 1973af6ab5fSopenharmony_ci if (!parseListIdx.isImplicitPackageImported || newProg->IsPackageModule()) { 1983af6ab5fSopenharmony_ci AddDirectImportsToDirectExternalSources(directImportsFromMainSource, newProg); 1993af6ab5fSopenharmony_ci // don't insert the separate modules into the programs, when we collect implicit package imports 2003af6ab5fSopenharmony_ci programs.emplace_back(newProg); 2013af6ab5fSopenharmony_ci } 2023af6ab5fSopenharmony_ci } catch (const Error &) { 2033af6ab5fSopenharmony_ci // Here file is not a valid STS source. Ignore and continue if it's implicit package import, else throw 2043af6ab5fSopenharmony_ci // the syntax error as usual 2053af6ab5fSopenharmony_ci 2063af6ab5fSopenharmony_ci if (!parseListIdx.isImplicitPackageImported) { 2073af6ab5fSopenharmony_ci throw; 2083af6ab5fSopenharmony_ci } 2093af6ab5fSopenharmony_ci 2103af6ab5fSopenharmony_ci util::Helpers::LogWarning("Error during parse of file '", parseListIdx.sourcePath, 2113af6ab5fSopenharmony_ci "' in compiled package. File will be omitted."); 2123af6ab5fSopenharmony_ci } 2133af6ab5fSopenharmony_ci} 2143af6ab5fSopenharmony_ci 2153af6ab5fSopenharmony_cistd::vector<Program *> ETSParser::ParseSources(bool firstSource) 2163af6ab5fSopenharmony_ci{ 2173af6ab5fSopenharmony_ci std::vector<Program *> programs; 2183af6ab5fSopenharmony_ci 2193af6ab5fSopenharmony_ci auto &parseList = importPathManager_->ParseList(); 2203af6ab5fSopenharmony_ci 2213af6ab5fSopenharmony_ci ArenaVector<util::StringView> directImportsFromMainSource(Allocator()->Adapter()); 2223af6ab5fSopenharmony_ci 2233af6ab5fSopenharmony_ci if (firstSource) { 2243af6ab5fSopenharmony_ci for (auto pl : parseList) { 2253af6ab5fSopenharmony_ci if (pl.isParsed) { 2263af6ab5fSopenharmony_ci // Handle excluded files, which are already set to be parsed before parsing them 2273af6ab5fSopenharmony_ci continue; 2283af6ab5fSopenharmony_ci } 2293af6ab5fSopenharmony_ci directImportsFromMainSource.emplace_back(pl.sourcePath); 2303af6ab5fSopenharmony_ci } 2313af6ab5fSopenharmony_ci } 2323af6ab5fSopenharmony_ci 2333af6ab5fSopenharmony_ci auto notParsedElement = 2343af6ab5fSopenharmony_ci std::find_if(parseList.begin(), parseList.end(), [](const auto &parseInfo) { return !parseInfo.isParsed; }); 2353af6ab5fSopenharmony_ci 2363af6ab5fSopenharmony_ci // NOTE (mmartin): Need a more optimal solution here 2373af6ab5fSopenharmony_ci // This is needed, as during a parsing of a file, programs can be re-added to the parseList, which needs to be 2383af6ab5fSopenharmony_ci // re-parsed. This won't change the size of the list, so with only the 'for loop', there can be unparsed files 2393af6ab5fSopenharmony_ci // remained. 2403af6ab5fSopenharmony_ci // An example for this, is when a file is added as an implicit package import, but it's erroneous, so we just ignore 2413af6ab5fSopenharmony_ci // the file. But when the same file is also added with an explicit import declaration, then we need to re-parse it, 2423af6ab5fSopenharmony_ci // and throw the syntax error. 2433af6ab5fSopenharmony_ci while (notParsedElement != parseList.end()) { 2443af6ab5fSopenharmony_ci // This parse list `paths` can grow in the meantime, so keep this index-based iteration 2453af6ab5fSopenharmony_ci // NOLINTNEXTLINE(modernize-loop-convert) 2463af6ab5fSopenharmony_ci for (size_t idx = 0; idx < parseList.size(); idx++) { 2473af6ab5fSopenharmony_ci // check if already parsed 2483af6ab5fSopenharmony_ci if (parseList[idx].isParsed) { 2493af6ab5fSopenharmony_ci continue; 2503af6ab5fSopenharmony_ci } 2513af6ab5fSopenharmony_ci std::ifstream inputStream(parseList[idx].sourcePath.Mutf8()); 2523af6ab5fSopenharmony_ci const auto data = importPathManager_->GetImportData(parseList[idx].sourcePath, Extension()); 2533af6ab5fSopenharmony_ci if (!data.hasDecl) { 2543af6ab5fSopenharmony_ci importPathManager_->MarkAsParsed(parseList[idx].sourcePath); 2553af6ab5fSopenharmony_ci continue; 2563af6ab5fSopenharmony_ci } 2573af6ab5fSopenharmony_ci 2583af6ab5fSopenharmony_ci if (GetProgram()->SourceFilePath().Is(parseList[idx].sourcePath.Mutf8())) { 2593af6ab5fSopenharmony_ci return programs; 2603af6ab5fSopenharmony_ci } 2613af6ab5fSopenharmony_ci 2623af6ab5fSopenharmony_ci if (inputStream.fail()) { 2633af6ab5fSopenharmony_ci ThrowSyntaxError({"Failed to open file: ", parseList[idx].sourcePath.Mutf8()}); 2643af6ab5fSopenharmony_ci } 2653af6ab5fSopenharmony_ci 2663af6ab5fSopenharmony_ci std::stringstream ss; 2673af6ab5fSopenharmony_ci ss << inputStream.rdbuf(); 2683af6ab5fSopenharmony_ci auto externalSource = ss.str(); 2693af6ab5fSopenharmony_ci 2703af6ab5fSopenharmony_ci auto currentLang = GetContext().SetLanguage(data.lang); 2713af6ab5fSopenharmony_ci auto extSrc = Allocator()->New<util::UString>(externalSource, Allocator()); 2723af6ab5fSopenharmony_ci importPathManager_->MarkAsParsed(parseList[idx].sourcePath); 2733af6ab5fSopenharmony_ci 2743af6ab5fSopenharmony_ci // In case of implicit package import, if we find a malformed STS file in the package's directory, instead 2753af6ab5fSopenharmony_ci // of aborting compilation we just ignore the file 2763af6ab5fSopenharmony_ci 2773af6ab5fSopenharmony_ci // NOTE (mmartin): after the multiple syntax error handling in the parser is implemented, this try-catch 2783af6ab5fSopenharmony_ci // must be changed, as exception throwing will be removed 2793af6ab5fSopenharmony_ci 2803af6ab5fSopenharmony_ci TryParseSource(parseList[idx], extSrc, directImportsFromMainSource, programs); 2813af6ab5fSopenharmony_ci 2823af6ab5fSopenharmony_ci GetContext().SetLanguage(currentLang); 2833af6ab5fSopenharmony_ci } 2843af6ab5fSopenharmony_ci 2853af6ab5fSopenharmony_ci notParsedElement = 2863af6ab5fSopenharmony_ci std::find_if(parseList.begin(), parseList.end(), [](const auto &parseInfo) { return !parseInfo.isParsed; }); 2873af6ab5fSopenharmony_ci } 2883af6ab5fSopenharmony_ci 2893af6ab5fSopenharmony_ci return programs; 2903af6ab5fSopenharmony_ci} 2913af6ab5fSopenharmony_ci 2923af6ab5fSopenharmony_ciparser::Program *ETSParser::ParseSource(const SourceFile &sourceFile) 2933af6ab5fSopenharmony_ci{ 2943af6ab5fSopenharmony_ci importPathManager_->MarkAsParsed(sourceFile.filePath); 2953af6ab5fSopenharmony_ci auto *program = Allocator()->New<parser::Program>(Allocator(), GetProgram()->VarBinder()); 2963af6ab5fSopenharmony_ci auto esp = ExternalSourceParser(this, program); 2973af6ab5fSopenharmony_ci auto lexer = InitLexer(sourceFile); 2983af6ab5fSopenharmony_ci 2993af6ab5fSopenharmony_ci lexer::SourcePosition startLoc = Lexer()->GetToken().Start(); 3003af6ab5fSopenharmony_ci Lexer()->NextToken(); 3013af6ab5fSopenharmony_ci 3023af6ab5fSopenharmony_ci ArenaVector<ir::Statement *> statements(Allocator()->Adapter()); 3033af6ab5fSopenharmony_ci auto decl = ParsePackageDeclaration(); 3043af6ab5fSopenharmony_ci if (decl != nullptr) { 3053af6ab5fSopenharmony_ci statements.emplace_back(decl); 3063af6ab5fSopenharmony_ci } 3073af6ab5fSopenharmony_ci auto script = ParseETSGlobalScript(startLoc, statements); 3083af6ab5fSopenharmony_ci program->SetAst(script); 3093af6ab5fSopenharmony_ci GetProgram()->SetDeclarationModuleInfo(); 3103af6ab5fSopenharmony_ci return program; 3113af6ab5fSopenharmony_ci} 3123af6ab5fSopenharmony_ci 3133af6ab5fSopenharmony_ciir::Statement *ETSParser::ParseIdentKeyword() 3143af6ab5fSopenharmony_ci{ 3153af6ab5fSopenharmony_ci const auto token = Lexer()->GetToken(); 3163af6ab5fSopenharmony_ci ASSERT(token.Type() == lexer::TokenType::LITERAL_IDENT); 3173af6ab5fSopenharmony_ci switch (token.KeywordType()) { 3183af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_STRUCT: { 3193af6ab5fSopenharmony_ci // Remove this ThrowSyntaxError when struct is implemented in #12726 3203af6ab5fSopenharmony_ci ThrowSyntaxError("Struct types are not supported yet!"); 3213af6ab5fSopenharmony_ci } 3223af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_TYPE: { 3233af6ab5fSopenharmony_ci return ParseTypeAliasDeclaration(); 3243af6ab5fSopenharmony_ci } 3253af6ab5fSopenharmony_ci default: { 3263af6ab5fSopenharmony_ci break; 3273af6ab5fSopenharmony_ci } 3283af6ab5fSopenharmony_ci } 3293af6ab5fSopenharmony_ci return nullptr; 3303af6ab5fSopenharmony_ci} 3313af6ab5fSopenharmony_ci 3323af6ab5fSopenharmony_ciir::ScriptFunction *ETSParser::ParseFunction(ParserStatus newStatus, ir::Identifier *className) 3333af6ab5fSopenharmony_ci{ 3343af6ab5fSopenharmony_ci FunctionContext functionContext(this, newStatus | ParserStatus::FUNCTION); 3353af6ab5fSopenharmony_ci lexer::SourcePosition startLoc = Lexer()->GetToken().Start(); 3363af6ab5fSopenharmony_ci auto [signature, throwMarker] = ParseFunctionSignature(newStatus, className); 3373af6ab5fSopenharmony_ci 3383af6ab5fSopenharmony_ci ir::AstNode *body = nullptr; 3393af6ab5fSopenharmony_ci lexer::SourcePosition endLoc = startLoc; 3403af6ab5fSopenharmony_ci bool isOverload = false; 3413af6ab5fSopenharmony_ci bool isArrow = (newStatus & ParserStatus::ARROW_FUNCTION) != 0; 3423af6ab5fSopenharmony_ci 3433af6ab5fSopenharmony_ci if ((newStatus & ParserStatus::ASYNC_FUNCTION) != 0) { 3443af6ab5fSopenharmony_ci functionContext.AddFlag(ir::ScriptFunctionFlags::ASYNC); 3453af6ab5fSopenharmony_ci } 3463af6ab5fSopenharmony_ci 3473af6ab5fSopenharmony_ci if (isArrow) { 3483af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { 3493af6ab5fSopenharmony_ci ThrowSyntaxError("'=>' expected"); 3503af6ab5fSopenharmony_ci } 3513af6ab5fSopenharmony_ci 3523af6ab5fSopenharmony_ci functionContext.AddFlag(ir::ScriptFunctionFlags::ARROW); 3533af6ab5fSopenharmony_ci Lexer()->NextToken(); 3543af6ab5fSopenharmony_ci } 3553af6ab5fSopenharmony_ci 3563af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 3573af6ab5fSopenharmony_ci std::tie(std::ignore, body, endLoc, isOverload) = 3583af6ab5fSopenharmony_ci ParseFunctionBody(signature.Params(), newStatus, GetContext().Status()); 3593af6ab5fSopenharmony_ci } else if (isArrow) { 3603af6ab5fSopenharmony_ci body = ParseExpression(); 3613af6ab5fSopenharmony_ci endLoc = body->AsExpression()->End(); 3623af6ab5fSopenharmony_ci functionContext.AddFlag(ir::ScriptFunctionFlags::EXPRESSION); 3633af6ab5fSopenharmony_ci } 3643af6ab5fSopenharmony_ci 3653af6ab5fSopenharmony_ci if ((GetContext().Status() & ParserStatus::FUNCTION_HAS_RETURN_STATEMENT) != 0) { 3663af6ab5fSopenharmony_ci functionContext.AddFlag(ir::ScriptFunctionFlags::HAS_RETURN); 3673af6ab5fSopenharmony_ci GetContext().Status() ^= ParserStatus::FUNCTION_HAS_RETURN_STATEMENT; 3683af6ab5fSopenharmony_ci } 3693af6ab5fSopenharmony_ci functionContext.AddFlag(throwMarker); 3703af6ab5fSopenharmony_ci 3713af6ab5fSopenharmony_ci bool isDeclare = InAmbientContext(); 3723af6ab5fSopenharmony_ci if (functionContext.IsAsync() && isDeclare) { 3733af6ab5fSopenharmony_ci ThrowSyntaxError("The modifier async cannot be used in an ambient context."); 3743af6ab5fSopenharmony_ci } 3753af6ab5fSopenharmony_ci 3763af6ab5fSopenharmony_ci // clang-format off 3773af6ab5fSopenharmony_ci ir::ModifierFlags mFlags = isDeclare ? ir::ModifierFlags::DECLARE : ir::ModifierFlags::NONE; 3783af6ab5fSopenharmony_ci ir::ScriptFunctionFlags funcFlags = 3793af6ab5fSopenharmony_ci isDeclare ? (functionContext.Flags() | ir::ScriptFunctionFlags::EXTERNAL) : functionContext.Flags(); 3803af6ab5fSopenharmony_ci auto *funcNode = AllocNode<ir::ScriptFunction>( 3813af6ab5fSopenharmony_ci Allocator(), ir::ScriptFunction::ScriptFunctionData {body, std::move(signature), funcFlags, mFlags, isDeclare, 3823af6ab5fSopenharmony_ci GetContext().GetLanguage()}); 3833af6ab5fSopenharmony_ci funcNode->SetRange({startLoc, endLoc}); 3843af6ab5fSopenharmony_ci // clang-format on 3853af6ab5fSopenharmony_ci 3863af6ab5fSopenharmony_ci return funcNode; 3873af6ab5fSopenharmony_ci} 3883af6ab5fSopenharmony_ci 3893af6ab5fSopenharmony_cistd::tuple<bool, ir::BlockStatement *, lexer::SourcePosition, bool> ETSParser::ParseFunctionBody( 3903af6ab5fSopenharmony_ci [[maybe_unused]] const ArenaVector<ir::Expression *> ¶ms, [[maybe_unused]] ParserStatus newStatus, 3913af6ab5fSopenharmony_ci [[maybe_unused]] ParserStatus contextStatus) 3923af6ab5fSopenharmony_ci{ 3933af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 3943af6ab5fSopenharmony_ci LogSyntaxError({"Expected token '{', got '", TokenToString(Lexer()->GetToken().Type()), "'"}); 3953af6ab5fSopenharmony_ci return {false, nullptr, Lexer()->GetToken().End(), false}; 3963af6ab5fSopenharmony_ci } 3973af6ab5fSopenharmony_ci 3983af6ab5fSopenharmony_ci ir::BlockStatement *body = ParseBlockStatement(); 3993af6ab5fSopenharmony_ci 4003af6ab5fSopenharmony_ci return {true, body, body->End(), false}; 4013af6ab5fSopenharmony_ci} 4023af6ab5fSopenharmony_ci 4033af6ab5fSopenharmony_ciir::ScriptFunctionFlags ETSParser::ParseFunctionThrowMarker(bool isRethrowsAllowed) 4043af6ab5fSopenharmony_ci{ 4053af6ab5fSopenharmony_ci ir::ScriptFunctionFlags throwMarker = ir::ScriptFunctionFlags::NONE; 4063af6ab5fSopenharmony_ci 4073af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) { 4083af6ab5fSopenharmony_ci if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_THROWS) { 4093af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat 'throws' 4103af6ab5fSopenharmony_ci throwMarker = ir::ScriptFunctionFlags::THROWS; 4113af6ab5fSopenharmony_ci } else if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_RETHROWS) { 4123af6ab5fSopenharmony_ci if (isRethrowsAllowed) { 4133af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat 'rethrows' 4143af6ab5fSopenharmony_ci throwMarker = ir::ScriptFunctionFlags::RETHROWS; 4153af6ab5fSopenharmony_ci } else { 4163af6ab5fSopenharmony_ci ThrowSyntaxError("Only 'throws' can be used with function types"); 4173af6ab5fSopenharmony_ci } 4183af6ab5fSopenharmony_ci } 4193af6ab5fSopenharmony_ci } 4203af6ab5fSopenharmony_ci 4213af6ab5fSopenharmony_ci return throwMarker; 4223af6ab5fSopenharmony_ci} 4233af6ab5fSopenharmony_ci 4243af6ab5fSopenharmony_ciir::AstNode *ETSParser::ParseInnerTypeDeclaration(ir::ModifierFlags memberModifiers, lexer::LexerPosition savedPos, 4253af6ab5fSopenharmony_ci bool isStepToken, bool seenStatic) 4263af6ab5fSopenharmony_ci{ 4273af6ab5fSopenharmony_ci if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) == 0) { 4283af6ab5fSopenharmony_ci ThrowSyntaxError("Local type declaration (class, struct, interface and enum) support is not yet implemented."); 4293af6ab5fSopenharmony_ci } 4303af6ab5fSopenharmony_ci 4313af6ab5fSopenharmony_ci // remove saved_pos nolint 4323af6ab5fSopenharmony_ci Lexer()->Rewind(savedPos); 4333af6ab5fSopenharmony_ci if (isStepToken) { 4343af6ab5fSopenharmony_ci Lexer()->NextToken(); 4353af6ab5fSopenharmony_ci } 4363af6ab5fSopenharmony_ci 4373af6ab5fSopenharmony_ci Lexer()->GetToken().SetTokenType(Lexer()->GetToken().KeywordType()); 4383af6ab5fSopenharmony_ci ir::AstNode *typeDecl = ParseTypeDeclaration(true); 4393af6ab5fSopenharmony_ci memberModifiers &= (ir::ModifierFlags::PUBLIC | ir::ModifierFlags::PROTECTED | ir::ModifierFlags::PRIVATE | 4403af6ab5fSopenharmony_ci ir::ModifierFlags::INTERNAL); 4413af6ab5fSopenharmony_ci typeDecl->AddModifier(memberModifiers); 4423af6ab5fSopenharmony_ci 4433af6ab5fSopenharmony_ci if (!seenStatic) { 4443af6ab5fSopenharmony_ci if (typeDecl->IsClassDeclaration()) { 4453af6ab5fSopenharmony_ci typeDecl->AsClassDeclaration()->Definition()->AsClassDefinition()->SetInnerModifier(); 4463af6ab5fSopenharmony_ci } else if (typeDecl->IsETSStructDeclaration()) { 4473af6ab5fSopenharmony_ci typeDecl->AsETSStructDeclaration()->Definition()->AsClassDefinition()->SetInnerModifier(); 4483af6ab5fSopenharmony_ci } 4493af6ab5fSopenharmony_ci } 4503af6ab5fSopenharmony_ci 4513af6ab5fSopenharmony_ci return typeDecl; 4523af6ab5fSopenharmony_ci} 4533af6ab5fSopenharmony_ci 4543af6ab5fSopenharmony_ciir::AstNode *ETSParser::ParseInnerConstructorDeclaration(ir::ModifierFlags memberModifiers, 4553af6ab5fSopenharmony_ci const lexer::SourcePosition &startLoc) 4563af6ab5fSopenharmony_ci{ 4573af6ab5fSopenharmony_ci if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) != 0) { 4583af6ab5fSopenharmony_ci ThrowSyntaxError({"Namespaces should not have a constructor"}); 4593af6ab5fSopenharmony_ci } 4603af6ab5fSopenharmony_ci if ((memberModifiers & (~(ir::ModifierFlags::ACCESS | ir::ModifierFlags::DECLARE))) != 0) { 4613af6ab5fSopenharmony_ci ThrowSyntaxError( 4623af6ab5fSopenharmony_ci {"The modifier for a constructor should be limited to access modifiers(private, internal, protected, " 4633af6ab5fSopenharmony_ci "public)."}); 4643af6ab5fSopenharmony_ci } 4653af6ab5fSopenharmony_ci auto *memberName = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator()); 4663af6ab5fSopenharmony_ci memberModifiers |= ir::ModifierFlags::CONSTRUCTOR; 4673af6ab5fSopenharmony_ci Lexer()->NextToken(); 4683af6ab5fSopenharmony_ci auto *classMethod = ParseClassMethodDefinition(memberName, memberModifiers); 4693af6ab5fSopenharmony_ci classMethod->SetStart(startLoc); 4703af6ab5fSopenharmony_ci 4713af6ab5fSopenharmony_ci return classMethod; 4723af6ab5fSopenharmony_ci} 4733af6ab5fSopenharmony_ci 4743af6ab5fSopenharmony_ciir::Identifier *ETSParser::CreateInvokeIdentifier() 4753af6ab5fSopenharmony_ci{ 4763af6ab5fSopenharmony_ci util::StringView tokenName = util::StringView {compiler::Signatures::STATIC_INVOKE_METHOD}; 4773af6ab5fSopenharmony_ci auto ident = AllocNode<ir::Identifier>(tokenName, Allocator()); 4783af6ab5fSopenharmony_ci ident->SetReference(false); 4793af6ab5fSopenharmony_ci ident->SetRange({Lexer()->GetToken().Start(), Lexer()->GetToken().End()}); 4803af6ab5fSopenharmony_ci return ident; 4813af6ab5fSopenharmony_ci} 4823af6ab5fSopenharmony_ci 4833af6ab5fSopenharmony_civoid ETSParser::CheckAccessorDeclaration(ir::ModifierFlags memberModifiers) 4843af6ab5fSopenharmony_ci{ 4853af6ab5fSopenharmony_ci ir::ModifierFlags methodModifiersNotAccessorModifiers = ir::ModifierFlags::NATIVE | ir::ModifierFlags::ASYNC; 4863af6ab5fSopenharmony_ci if ((memberModifiers & methodModifiersNotAccessorModifiers) != 0) { 4873af6ab5fSopenharmony_ci ThrowSyntaxError("Modifiers of getter and setter are limited to ('abstract', 'static', 'final', 'override')."); 4883af6ab5fSopenharmony_ci } 4893af6ab5fSopenharmony_ci} 4903af6ab5fSopenharmony_ci 4913af6ab5fSopenharmony_ciir::AstNode *ETSParser::ParseInnerRest(const ArenaVector<ir::AstNode *> &properties, 4923af6ab5fSopenharmony_ci ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags memberModifiers, 4933af6ab5fSopenharmony_ci const lexer::SourcePosition &startLoc) 4943af6ab5fSopenharmony_ci{ 4953af6ab5fSopenharmony_ci if (Lexer()->Lookahead() != lexer::LEX_CHAR_LEFT_PAREN && Lexer()->Lookahead() != lexer::LEX_CHAR_LESS_THAN && 4963af6ab5fSopenharmony_ci (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_GET || 4973af6ab5fSopenharmony_ci Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_SET)) { 4983af6ab5fSopenharmony_ci CheckAccessorDeclaration(memberModifiers); 4993af6ab5fSopenharmony_ci return ParseClassGetterSetterMethod(properties, modifiers, memberModifiers); 5003af6ab5fSopenharmony_ci } 5013af6ab5fSopenharmony_ci 5023af6ab5fSopenharmony_ci if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) != 0) { 5033af6ab5fSopenharmony_ci auto type = Lexer()->GetToken().Type(); 5043af6ab5fSopenharmony_ci if (type == lexer::TokenType::KEYW_FUNCTION || type == lexer::TokenType::KEYW_LET || 5053af6ab5fSopenharmony_ci type == lexer::TokenType::KEYW_CONST) { 5063af6ab5fSopenharmony_ci Lexer()->NextToken(); 5073af6ab5fSopenharmony_ci } 5083af6ab5fSopenharmony_ci } 5093af6ab5fSopenharmony_ci 5103af6ab5fSopenharmony_ci auto parseClassMethod = [&memberModifiers, &startLoc, this](ir::Identifier *methodName) { 5113af6ab5fSopenharmony_ci auto *classMethod = ParseClassMethodDefinition(methodName, memberModifiers, nullptr); 5123af6ab5fSopenharmony_ci classMethod->SetStart(startLoc); 5133af6ab5fSopenharmony_ci return classMethod; 5143af6ab5fSopenharmony_ci }; 5153af6ab5fSopenharmony_ci 5163af6ab5fSopenharmony_ci if (InAmbientContext()) { 5173af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS && 5183af6ab5fSopenharmony_ci (GetContext().Status() & ParserStatus::IN_CLASS_BODY) != 0U) { 5193af6ab5fSopenharmony_ci // Special case for processing of special '(param: type): returnType` identifier using in ambient context 5203af6ab5fSopenharmony_ci auto ident = CreateInvokeIdentifier(); 5213af6ab5fSopenharmony_ci memberModifiers |= ir::ModifierFlags::STATIC; 5223af6ab5fSopenharmony_ci return parseClassMethod(ident); 5233af6ab5fSopenharmony_ci } 5243af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) { 5253af6ab5fSopenharmony_ci auto const savePos = Lexer()->Save(); 5263af6ab5fSopenharmony_ci Lexer()->NextToken(); 5273af6ab5fSopenharmony_ci if (Lexer()->GetToken().Ident().Is("Symbol")) { 5283af6ab5fSopenharmony_ci Lexer()->Rewind(savePos); 5293af6ab5fSopenharmony_ci } else { 5303af6ab5fSopenharmony_ci return ParseAmbientSignature(); 5313af6ab5fSopenharmony_ci } 5323af6ab5fSopenharmony_ci } 5333af6ab5fSopenharmony_ci } 5343af6ab5fSopenharmony_ci 5353af6ab5fSopenharmony_ci auto *memberName = ExpectIdentifier(); 5363af6ab5fSopenharmony_ci if (memberName == nullptr) { // Error processing. 5373af6ab5fSopenharmony_ci return nullptr; 5383af6ab5fSopenharmony_ci } 5393af6ab5fSopenharmony_ci 5403af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS || 5413af6ab5fSopenharmony_ci Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) { 5423af6ab5fSopenharmony_ci return parseClassMethod(memberName); 5433af6ab5fSopenharmony_ci } 5443af6ab5fSopenharmony_ci 5453af6ab5fSopenharmony_ci ArenaVector<ir::AstNode *> fieldDeclarations(Allocator()->Adapter()); 5463af6ab5fSopenharmony_ci auto *placeholder = AllocNode<ir::TSInterfaceBody>(std::move(fieldDeclarations)); 5473af6ab5fSopenharmony_ci ParseClassFieldDefinition(memberName, memberModifiers, placeholder->BodyPtr()); 5483af6ab5fSopenharmony_ci return placeholder; 5493af6ab5fSopenharmony_ci} 5503af6ab5fSopenharmony_ci 5513af6ab5fSopenharmony_ciir::Statement *ETSParser::ParseTypeDeclarationAbstractFinal(bool allowStatic, ir::ClassDefinitionModifiers modifiers) 5523af6ab5fSopenharmony_ci{ 5533af6ab5fSopenharmony_ci auto flags = ParseClassModifiers(); 5543af6ab5fSopenharmony_ci if (allowStatic && (flags & ir::ModifierFlags::STATIC) == 0U) { 5553af6ab5fSopenharmony_ci modifiers |= ir::ClassDefinitionModifiers::INNER; 5563af6ab5fSopenharmony_ci } 5573af6ab5fSopenharmony_ci 5583af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS) { 5593af6ab5fSopenharmony_ci return ParseClassDeclaration(modifiers, flags); 5603af6ab5fSopenharmony_ci } 5613af6ab5fSopenharmony_ci 5623af6ab5fSopenharmony_ci if (IsStructKeyword()) { 5633af6ab5fSopenharmony_ci return ParseStructDeclaration(modifiers, flags); 5643af6ab5fSopenharmony_ci } 5653af6ab5fSopenharmony_ci 5663af6ab5fSopenharmony_ci ThrowUnexpectedToken(Lexer()->GetToken().Type()); 5673af6ab5fSopenharmony_ci} 5683af6ab5fSopenharmony_ci 5693af6ab5fSopenharmony_ciir::Statement *ETSParser::ParseTypeDeclaration(bool allowStatic) 5703af6ab5fSopenharmony_ci{ 5713af6ab5fSopenharmony_ci auto savedPos = Lexer()->Save(); 5723af6ab5fSopenharmony_ci 5733af6ab5fSopenharmony_ci auto modifiers = ir::ClassDefinitionModifiers::ID_REQUIRED | ir::ClassDefinitionModifiers::CLASS_DECL; 5743af6ab5fSopenharmony_ci 5753af6ab5fSopenharmony_ci auto tokenType = Lexer()->GetToken().Type(); 5763af6ab5fSopenharmony_ci switch (tokenType) { 5773af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_STATIC: { 5783af6ab5fSopenharmony_ci if (!allowStatic) { 5793af6ab5fSopenharmony_ci ThrowUnexpectedToken(Lexer()->GetToken().Type()); 5803af6ab5fSopenharmony_ci } 5813af6ab5fSopenharmony_ci 5823af6ab5fSopenharmony_ci Lexer()->NextToken(); 5833af6ab5fSopenharmony_ci 5843af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_INTERFACE) { 5853af6ab5fSopenharmony_ci return ParseInterfaceDeclaration(true); 5863af6ab5fSopenharmony_ci } 5873af6ab5fSopenharmony_ci 5883af6ab5fSopenharmony_ci Lexer()->Rewind(savedPos); 5893af6ab5fSopenharmony_ci [[fallthrough]]; 5903af6ab5fSopenharmony_ci } 5913af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_ABSTRACT: 5923af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_FINAL: { 5933af6ab5fSopenharmony_ci return ParseTypeDeclarationAbstractFinal(allowStatic, modifiers); 5943af6ab5fSopenharmony_ci } 5953af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_ENUM: { 5963af6ab5fSopenharmony_ci return ParseEnumDeclaration(false); 5973af6ab5fSopenharmony_ci } 5983af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_INTERFACE: { 5993af6ab5fSopenharmony_ci return ParseInterfaceDeclaration(false); 6003af6ab5fSopenharmony_ci } 6013af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_NAMESPACE: { 6023af6ab5fSopenharmony_ci if (!InAmbientContext()) { 6033af6ab5fSopenharmony_ci ThrowSyntaxError("Namespaces are declare only"); 6043af6ab5fSopenharmony_ci } 6053af6ab5fSopenharmony_ci GetContext().Status() |= ParserStatus::IN_NAMESPACE; 6063af6ab5fSopenharmony_ci auto *ns = ParseNamespaceDeclaration(ir::ModifierFlags::DECLARE | ir::ModifierFlags::EXPORT); 6073af6ab5fSopenharmony_ci GetContext().Status() &= ~ParserStatus::IN_NAMESPACE; 6083af6ab5fSopenharmony_ci return ns; 6093af6ab5fSopenharmony_ci } 6103af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_CLASS: { 6113af6ab5fSopenharmony_ci return ParseClassDeclaration(modifiers); 6123af6ab5fSopenharmony_ci } 6133af6ab5fSopenharmony_ci case lexer::TokenType::LITERAL_IDENT: { 6143af6ab5fSopenharmony_ci if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STRUCT) { 6153af6ab5fSopenharmony_ci return ParseStructDeclaration(modifiers); 6163af6ab5fSopenharmony_ci } 6173af6ab5fSopenharmony_ci [[fallthrough]]; 6183af6ab5fSopenharmony_ci } 6193af6ab5fSopenharmony_ci default: { 6203af6ab5fSopenharmony_ci ThrowUnexpectedToken(Lexer()->GetToken().Type()); 6213af6ab5fSopenharmony_ci } 6223af6ab5fSopenharmony_ci } 6233af6ab5fSopenharmony_ci} 6243af6ab5fSopenharmony_ci 6253af6ab5fSopenharmony_ciir::TSTypeAliasDeclaration *ETSParser::ParseTypeAliasDeclaration() 6263af6ab5fSopenharmony_ci{ 6273af6ab5fSopenharmony_ci ASSERT(Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE); 6283af6ab5fSopenharmony_ci 6293af6ab5fSopenharmony_ci lexer::SourcePosition typeStart = Lexer()->GetToken().Start(); 6303af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat type keyword 6313af6ab5fSopenharmony_ci 6323af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 6333af6ab5fSopenharmony_ci ThrowSyntaxError("Identifier expected"); 6343af6ab5fSopenharmony_ci } 6353af6ab5fSopenharmony_ci 6363af6ab5fSopenharmony_ci if (Lexer()->GetToken().IsReservedTypeName()) { 6373af6ab5fSopenharmony_ci std::string errMsg("Type alias name cannot be '"); 6383af6ab5fSopenharmony_ci errMsg.append(TokenToString(Lexer()->GetToken().KeywordType())); 6393af6ab5fSopenharmony_ci errMsg.append("'"); 6403af6ab5fSopenharmony_ci ThrowSyntaxError(errMsg.c_str()); 6413af6ab5fSopenharmony_ci } 6423af6ab5fSopenharmony_ci 6433af6ab5fSopenharmony_ci const util::StringView ident = Lexer()->GetToken().Ident(); 6443af6ab5fSopenharmony_ci auto *id = AllocNode<ir::Identifier>(ident, Allocator()); 6453af6ab5fSopenharmony_ci id->SetRange(Lexer()->GetToken().Loc()); 6463af6ab5fSopenharmony_ci 6473af6ab5fSopenharmony_ci auto *typeAliasDecl = AllocNode<ir::TSTypeAliasDeclaration>(Allocator(), id); 6483af6ab5fSopenharmony_ci 6493af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat alias name 6503af6ab5fSopenharmony_ci 6513af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) { 6523af6ab5fSopenharmony_ci auto options = 6533af6ab5fSopenharmony_ci TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::ALLOW_DECLARATION_SITE_VARIANCE; 6543af6ab5fSopenharmony_ci ir::TSTypeParameterDeclaration *params = ParseTypeParameterDeclaration(&options); 6553af6ab5fSopenharmony_ci typeAliasDecl->SetTypeParameters(params); 6563af6ab5fSopenharmony_ci params->SetParent(typeAliasDecl); 6573af6ab5fSopenharmony_ci } 6583af6ab5fSopenharmony_ci 6593af6ab5fSopenharmony_ci if (!Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_SUBSTITUTION)) { 6603af6ab5fSopenharmony_ci ThrowSyntaxError("'=' expected"); 6613af6ab5fSopenharmony_ci } 6623af6ab5fSopenharmony_ci 6633af6ab5fSopenharmony_ci TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR; 6643af6ab5fSopenharmony_ci ir::TypeNode *typeAnnotation = ParseTypeAnnotation(&options); 6653af6ab5fSopenharmony_ci if (typeAnnotation != nullptr) { // Error processing. 6663af6ab5fSopenharmony_ci typeAliasDecl->SetTsTypeAnnotation(typeAnnotation); 6673af6ab5fSopenharmony_ci typeAnnotation->SetParent(typeAliasDecl); 6683af6ab5fSopenharmony_ci } 6693af6ab5fSopenharmony_ci 6703af6ab5fSopenharmony_ci typeAliasDecl->SetRange({typeStart, Lexer()->GetToken().End()}); 6713af6ab5fSopenharmony_ci return typeAliasDecl; 6723af6ab5fSopenharmony_ci} 6733af6ab5fSopenharmony_ci 6743af6ab5fSopenharmony_cistd::pair<bool, std::size_t> ETSParser::CheckDefaultParameters(const ir::ScriptFunction *const function) const 6753af6ab5fSopenharmony_ci{ 6763af6ab5fSopenharmony_ci bool hasDefaultParameter = false; 6773af6ab5fSopenharmony_ci bool hasRestParameter = false; 6783af6ab5fSopenharmony_ci std::size_t requiredParametersNumber = 0U; 6793af6ab5fSopenharmony_ci 6803af6ab5fSopenharmony_ci for (auto *const it : function->Params()) { 6813af6ab5fSopenharmony_ci auto const *const param = it->AsETSParameterExpression(); 6823af6ab5fSopenharmony_ci 6833af6ab5fSopenharmony_ci if (param->IsRestParameter()) { 6843af6ab5fSopenharmony_ci hasRestParameter = true; 6853af6ab5fSopenharmony_ci continue; 6863af6ab5fSopenharmony_ci } 6873af6ab5fSopenharmony_ci 6883af6ab5fSopenharmony_ci if (hasRestParameter) { 6893af6ab5fSopenharmony_ci ThrowSyntaxError("Rest parameter should be the last one.", param->Start()); 6903af6ab5fSopenharmony_ci } 6913af6ab5fSopenharmony_ci 6923af6ab5fSopenharmony_ci if (param->IsDefault()) { 6933af6ab5fSopenharmony_ci hasDefaultParameter = true; 6943af6ab5fSopenharmony_ci continue; 6953af6ab5fSopenharmony_ci } 6963af6ab5fSopenharmony_ci 6973af6ab5fSopenharmony_ci if (hasDefaultParameter) { 6983af6ab5fSopenharmony_ci ThrowSyntaxError("Required parameter follows default parameter(s).", param->Start()); 6993af6ab5fSopenharmony_ci } 7003af6ab5fSopenharmony_ci 7013af6ab5fSopenharmony_ci ++requiredParametersNumber; 7023af6ab5fSopenharmony_ci } 7033af6ab5fSopenharmony_ci 7043af6ab5fSopenharmony_ci if (hasDefaultParameter && hasRestParameter) { 7053af6ab5fSopenharmony_ci ThrowSyntaxError("Both optional and rest parameters are not allowed in function's parameter list.", 7063af6ab5fSopenharmony_ci function->Start()); 7073af6ab5fSopenharmony_ci } 7083af6ab5fSopenharmony_ci 7093af6ab5fSopenharmony_ci return std::make_pair(hasDefaultParameter, requiredParametersNumber); 7103af6ab5fSopenharmony_ci} 7113af6ab5fSopenharmony_ci 7123af6ab5fSopenharmony_cistd::string ETSParser::PrimitiveTypeToName(ir::PrimitiveType type) 7133af6ab5fSopenharmony_ci{ 7143af6ab5fSopenharmony_ci switch (type) { 7153af6ab5fSopenharmony_ci case ir::PrimitiveType::BYTE: 7163af6ab5fSopenharmony_ci return "byte"; 7173af6ab5fSopenharmony_ci case ir::PrimitiveType::INT: 7183af6ab5fSopenharmony_ci return "int"; 7193af6ab5fSopenharmony_ci case ir::PrimitiveType::LONG: 7203af6ab5fSopenharmony_ci return "long"; 7213af6ab5fSopenharmony_ci case ir::PrimitiveType::SHORT: 7223af6ab5fSopenharmony_ci return "short"; 7233af6ab5fSopenharmony_ci case ir::PrimitiveType::FLOAT: 7243af6ab5fSopenharmony_ci return "float"; 7253af6ab5fSopenharmony_ci case ir::PrimitiveType::DOUBLE: 7263af6ab5fSopenharmony_ci return "double"; 7273af6ab5fSopenharmony_ci case ir::PrimitiveType::BOOLEAN: 7283af6ab5fSopenharmony_ci return "boolean"; 7293af6ab5fSopenharmony_ci case ir::PrimitiveType::CHAR: 7303af6ab5fSopenharmony_ci return "char"; 7313af6ab5fSopenharmony_ci case ir::PrimitiveType::VOID: 7323af6ab5fSopenharmony_ci return "void"; 7333af6ab5fSopenharmony_ci default: 7343af6ab5fSopenharmony_ci UNREACHABLE(); 7353af6ab5fSopenharmony_ci } 7363af6ab5fSopenharmony_ci} 7373af6ab5fSopenharmony_ci 7383af6ab5fSopenharmony_cistd::string ETSParser::GetNameForETSUnionType(const ir::TypeNode *typeAnnotation) const 7393af6ab5fSopenharmony_ci{ 7403af6ab5fSopenharmony_ci ASSERT(typeAnnotation->IsETSUnionType()); 7413af6ab5fSopenharmony_ci std::string newstr; 7423af6ab5fSopenharmony_ci for (size_t i = 0; i < typeAnnotation->AsETSUnionType()->Types().size(); i++) { 7433af6ab5fSopenharmony_ci auto type = typeAnnotation->AsETSUnionType()->Types()[i]; 7443af6ab5fSopenharmony_ci std::string str = GetNameForTypeNode(type); 7453af6ab5fSopenharmony_ci newstr += str; 7463af6ab5fSopenharmony_ci if (i != typeAnnotation->AsETSUnionType()->Types().size() - 1) { 7473af6ab5fSopenharmony_ci newstr += "|"; 7483af6ab5fSopenharmony_ci } 7493af6ab5fSopenharmony_ci } 7503af6ab5fSopenharmony_ci return newstr; 7513af6ab5fSopenharmony_ci} 7523af6ab5fSopenharmony_ci 7533af6ab5fSopenharmony_cistd::string ETSParser::GetNameForTypeNode(const ir::TypeNode *typeAnnotation) const 7543af6ab5fSopenharmony_ci{ 7553af6ab5fSopenharmony_ci if (typeAnnotation->IsETSUnionType()) { 7563af6ab5fSopenharmony_ci return GetNameForETSUnionType(typeAnnotation); 7573af6ab5fSopenharmony_ci } 7583af6ab5fSopenharmony_ci if (typeAnnotation->IsETSPrimitiveType()) { 7593af6ab5fSopenharmony_ci return PrimitiveTypeToName(typeAnnotation->AsETSPrimitiveType()->GetPrimitiveType()); 7603af6ab5fSopenharmony_ci } 7613af6ab5fSopenharmony_ci 7623af6ab5fSopenharmony_ci if (typeAnnotation->IsETSTypeReference()) { 7633af6ab5fSopenharmony_ci std::string typeParamNames; 7643af6ab5fSopenharmony_ci auto typeParam = typeAnnotation->AsETSTypeReference()->Part()->TypeParams(); 7653af6ab5fSopenharmony_ci if (typeParam != nullptr && typeParam->IsTSTypeParameterInstantiation()) { 7663af6ab5fSopenharmony_ci typeParamNames = "<"; 7673af6ab5fSopenharmony_ci auto paramList = typeParam->Params(); 7683af6ab5fSopenharmony_ci for (auto param : paramList) { 7693af6ab5fSopenharmony_ci std::string typeParamName = GetNameForTypeNode(param); 7703af6ab5fSopenharmony_ci typeParamNames += typeParamName + ","; 7713af6ab5fSopenharmony_ci } 7723af6ab5fSopenharmony_ci typeParamNames.pop_back(); 7733af6ab5fSopenharmony_ci typeParamNames += ">"; 7743af6ab5fSopenharmony_ci } 7753af6ab5fSopenharmony_ci return typeAnnotation->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Name().Mutf8() + typeParamNames; 7763af6ab5fSopenharmony_ci } 7773af6ab5fSopenharmony_ci 7783af6ab5fSopenharmony_ci if (typeAnnotation->IsETSFunctionType()) { 7793af6ab5fSopenharmony_ci std::string lambdaParams = " "; 7803af6ab5fSopenharmony_ci 7813af6ab5fSopenharmony_ci for (const auto *const param : typeAnnotation->AsETSFunctionType()->Params()) { 7823af6ab5fSopenharmony_ci lambdaParams += param->AsETSParameterExpression()->Ident()->Name().Mutf8(); 7833af6ab5fSopenharmony_ci lambdaParams += ":"; 7843af6ab5fSopenharmony_ci lambdaParams += GetNameForTypeNode(param->AsETSParameterExpression()->Ident()->TypeAnnotation()); 7853af6ab5fSopenharmony_ci lambdaParams += ","; 7863af6ab5fSopenharmony_ci } 7873af6ab5fSopenharmony_ci 7883af6ab5fSopenharmony_ci lambdaParams.pop_back(); 7893af6ab5fSopenharmony_ci const std::string returnTypeName = GetNameForTypeNode(typeAnnotation->AsETSFunctionType()->ReturnType()); 7903af6ab5fSopenharmony_ci 7913af6ab5fSopenharmony_ci return "((" + lambdaParams + ") => " + returnTypeName + ")"; 7923af6ab5fSopenharmony_ci } 7933af6ab5fSopenharmony_ci 7943af6ab5fSopenharmony_ci if (typeAnnotation->IsTSArrayType()) { 7953af6ab5fSopenharmony_ci // Note! array is required for the rest parameter. 7963af6ab5fSopenharmony_ci return GetNameForTypeNode(typeAnnotation->AsTSArrayType()->ElementType()) + "[]"; 7973af6ab5fSopenharmony_ci } 7983af6ab5fSopenharmony_ci 7993af6ab5fSopenharmony_ci if (typeAnnotation->IsETSNullType()) { 8003af6ab5fSopenharmony_ci return "null"; 8013af6ab5fSopenharmony_ci } 8023af6ab5fSopenharmony_ci 8033af6ab5fSopenharmony_ci if (typeAnnotation->IsETSUndefinedType()) { 8043af6ab5fSopenharmony_ci return "undefined"; 8053af6ab5fSopenharmony_ci } 8063af6ab5fSopenharmony_ci 8073af6ab5fSopenharmony_ci UNREACHABLE(); 8083af6ab5fSopenharmony_ci} 8093af6ab5fSopenharmony_ci 8103af6ab5fSopenharmony_civoid ETSParser::ValidateRestParameter(ir::Expression *param) 8113af6ab5fSopenharmony_ci{ 8123af6ab5fSopenharmony_ci if (param->IsETSParameterExpression()) { 8133af6ab5fSopenharmony_ci if (param->AsETSParameterExpression()->IsRestParameter()) { 8143af6ab5fSopenharmony_ci GetContext().Status() |= ParserStatus::HAS_COMPLEX_PARAM; 8153af6ab5fSopenharmony_ci 8163af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 8173af6ab5fSopenharmony_ci ThrowSyntaxError("Rest parameter must be the last formal parameter."); 8183af6ab5fSopenharmony_ci } 8193af6ab5fSopenharmony_ci } 8203af6ab5fSopenharmony_ci } 8213af6ab5fSopenharmony_ci} 8223af6ab5fSopenharmony_ci 8233af6ab5fSopenharmony_cibool ETSParser::ValidateBreakLabel([[maybe_unused]] util::StringView label) 8243af6ab5fSopenharmony_ci{ 8253af6ab5fSopenharmony_ci // For ETS validate labels in checker via variables 8263af6ab5fSopenharmony_ci return true; 8273af6ab5fSopenharmony_ci} 8283af6ab5fSopenharmony_ci 8293af6ab5fSopenharmony_cibool ETSParser::ValidateContinueLabel([[maybe_unused]] util::StringView label) 8303af6ab5fSopenharmony_ci{ 8313af6ab5fSopenharmony_ci // For ETS validate labels in checker via variables 8323af6ab5fSopenharmony_ci return true; 8333af6ab5fSopenharmony_ci} 8343af6ab5fSopenharmony_ci 8353af6ab5fSopenharmony_cistd::tuple<ir::Expression *, ir::TSTypeParameterInstantiation *> ETSParser::ParseTypeReferencePart( 8363af6ab5fSopenharmony_ci TypeAnnotationParsingOptions *options) 8373af6ab5fSopenharmony_ci{ 8383af6ab5fSopenharmony_ci ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS; 8393af6ab5fSopenharmony_ci 8403af6ab5fSopenharmony_ci if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL) != 0) { 8413af6ab5fSopenharmony_ci flags |= ExpressionParseFlags::POTENTIAL_CLASS_LITERAL; 8423af6ab5fSopenharmony_ci } 8433af6ab5fSopenharmony_ci 8443af6ab5fSopenharmony_ci if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_NEW_ARRAY) != 0) { 8453af6ab5fSopenharmony_ci flags |= ExpressionParseFlags::POTENTIAL_NEW_ARRAY; 8463af6ab5fSopenharmony_ci } 8473af6ab5fSopenharmony_ci 8483af6ab5fSopenharmony_ci auto *typeName = ParseQualifiedName(flags); 8493af6ab5fSopenharmony_ci if (typeName == nullptr) { 8503af6ab5fSopenharmony_ci return {nullptr, nullptr}; 8513af6ab5fSopenharmony_ci } 8523af6ab5fSopenharmony_ci 8533af6ab5fSopenharmony_ci if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL) != 0 && 8543af6ab5fSopenharmony_ci (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS || IsStructKeyword())) { 8553af6ab5fSopenharmony_ci return {typeName, nullptr}; 8563af6ab5fSopenharmony_ci } 8573af6ab5fSopenharmony_ci 8583af6ab5fSopenharmony_ci ir::TSTypeParameterInstantiation *typeParamInst = nullptr; 8593af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT || 8603af6ab5fSopenharmony_ci Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) { 8613af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) { 8623af6ab5fSopenharmony_ci Lexer()->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1); 8633af6ab5fSopenharmony_ci } 8643af6ab5fSopenharmony_ci *options |= TypeAnnotationParsingOptions::ALLOW_WILDCARD; 8653af6ab5fSopenharmony_ci typeParamInst = ParseTypeParameterInstantiation(options); 8663af6ab5fSopenharmony_ci *options &= ~TypeAnnotationParsingOptions::ALLOW_WILDCARD; 8673af6ab5fSopenharmony_ci } 8683af6ab5fSopenharmony_ci 8693af6ab5fSopenharmony_ci return {typeName, typeParamInst}; 8703af6ab5fSopenharmony_ci} 8713af6ab5fSopenharmony_ci 8723af6ab5fSopenharmony_ciir::TypeNode *ETSParser::ParseTypeReference(TypeAnnotationParsingOptions *options) 8733af6ab5fSopenharmony_ci{ 8743af6ab5fSopenharmony_ci auto startPos = Lexer()->GetToken().Start(); 8753af6ab5fSopenharmony_ci ir::ETSTypeReferencePart *typeRefPart = nullptr; 8763af6ab5fSopenharmony_ci 8773af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT) { 8783af6ab5fSopenharmony_ci return ParseTypeFormatPlaceholder(); 8793af6ab5fSopenharmony_ci } 8803af6ab5fSopenharmony_ci 8813af6ab5fSopenharmony_ci while (true) { 8823af6ab5fSopenharmony_ci auto partPos = Lexer()->GetToken().Start(); 8833af6ab5fSopenharmony_ci auto [typeName, typeParams] = ParseTypeReferencePart(options); 8843af6ab5fSopenharmony_ci if (typeName == nullptr) { 8853af6ab5fSopenharmony_ci return nullptr; 8863af6ab5fSopenharmony_ci } 8873af6ab5fSopenharmony_ci 8883af6ab5fSopenharmony_ci typeRefPart = AllocNode<ir::ETSTypeReferencePart>(typeName, typeParams, typeRefPart); 8893af6ab5fSopenharmony_ci typeRefPart->SetRange({partPos, Lexer()->GetToken().End()}); 8903af6ab5fSopenharmony_ci 8913af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_PERIOD) { 8923af6ab5fSopenharmony_ci break; 8933af6ab5fSopenharmony_ci } 8943af6ab5fSopenharmony_ci 8953af6ab5fSopenharmony_ci Lexer()->NextToken(); 8963af6ab5fSopenharmony_ci 8973af6ab5fSopenharmony_ci if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL) != 0 && 8983af6ab5fSopenharmony_ci (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS || IsStructKeyword())) { 8993af6ab5fSopenharmony_ci break; 9003af6ab5fSopenharmony_ci } 9013af6ab5fSopenharmony_ci } 9023af6ab5fSopenharmony_ci 9033af6ab5fSopenharmony_ci auto *typeReference = AllocNode<ir::ETSTypeReference>(typeRefPart); 9043af6ab5fSopenharmony_ci typeReference->SetRange({startPos, Lexer()->GetToken().End()}); 9053af6ab5fSopenharmony_ci return typeReference; 9063af6ab5fSopenharmony_ci} 9073af6ab5fSopenharmony_ci 9083af6ab5fSopenharmony_ciir::TypeNode *ETSParser::ParseBaseTypeReference(TypeAnnotationParsingOptions *options) 9093af6ab5fSopenharmony_ci{ 9103af6ab5fSopenharmony_ci ir::TypeNode *typeAnnotation = nullptr; 9113af6ab5fSopenharmony_ci 9123af6ab5fSopenharmony_ci switch (Lexer()->GetToken().KeywordType()) { 9133af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_BOOLEAN: { 9143af6ab5fSopenharmony_ci typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::BOOLEAN); 9153af6ab5fSopenharmony_ci break; 9163af6ab5fSopenharmony_ci } 9173af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_BYTE: { 9183af6ab5fSopenharmony_ci typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::BYTE); 9193af6ab5fSopenharmony_ci break; 9203af6ab5fSopenharmony_ci } 9213af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_CHAR: { 9223af6ab5fSopenharmony_ci typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::CHAR); 9233af6ab5fSopenharmony_ci break; 9243af6ab5fSopenharmony_ci } 9253af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_DOUBLE: { 9263af6ab5fSopenharmony_ci typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::DOUBLE); 9273af6ab5fSopenharmony_ci break; 9283af6ab5fSopenharmony_ci } 9293af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_FLOAT: { 9303af6ab5fSopenharmony_ci typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::FLOAT); 9313af6ab5fSopenharmony_ci break; 9323af6ab5fSopenharmony_ci } 9333af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_INT: { 9343af6ab5fSopenharmony_ci typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::INT); 9353af6ab5fSopenharmony_ci break; 9363af6ab5fSopenharmony_ci } 9373af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_LONG: { 9383af6ab5fSopenharmony_ci typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::LONG); 9393af6ab5fSopenharmony_ci break; 9403af6ab5fSopenharmony_ci } 9413af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_SHORT: { 9423af6ab5fSopenharmony_ci typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::SHORT); 9433af6ab5fSopenharmony_ci break; 9443af6ab5fSopenharmony_ci } 9453af6ab5fSopenharmony_ci 9463af6ab5fSopenharmony_ci default: { 9473af6ab5fSopenharmony_ci break; 9483af6ab5fSopenharmony_ci } 9493af6ab5fSopenharmony_ci } 9503af6ab5fSopenharmony_ci 9513af6ab5fSopenharmony_ci return typeAnnotation; 9523af6ab5fSopenharmony_ci} 9533af6ab5fSopenharmony_ci 9543af6ab5fSopenharmony_cistd::optional<lexer::SourcePosition> ETSParser::GetDefaultParamPosition(ArenaVector<ir::Expression *> params) 9553af6ab5fSopenharmony_ci{ 9563af6ab5fSopenharmony_ci for (auto ¶m : params) { 9573af6ab5fSopenharmony_ci if (param->IsETSParameterExpression() && param->AsETSParameterExpression()->IsDefault()) { 9583af6ab5fSopenharmony_ci return param->AsETSParameterExpression()->Initializer()->Start(); 9593af6ab5fSopenharmony_ci } 9603af6ab5fSopenharmony_ci } 9613af6ab5fSopenharmony_ci return {}; 9623af6ab5fSopenharmony_ci} 9633af6ab5fSopenharmony_ci 9643af6ab5fSopenharmony_ciir::TypeNode *ETSParser::ParseLiteralIdent(TypeAnnotationParsingOptions *options) 9653af6ab5fSopenharmony_ci{ 9663af6ab5fSopenharmony_ci if (const auto keyword = Lexer()->GetToken().KeywordType(); 9673af6ab5fSopenharmony_ci keyword == lexer::TokenType::KEYW_IN || keyword == lexer::TokenType::KEYW_OUT) { 9683af6ab5fSopenharmony_ci return ParseWildcardType(options); 9693af6ab5fSopenharmony_ci } 9703af6ab5fSopenharmony_ci 9713af6ab5fSopenharmony_ci if (Lexer()->GetToken().IsDefinableTypeName()) { 9723af6ab5fSopenharmony_ci return GetTypeAnnotationOfPrimitiveType(Lexer()->GetToken().KeywordType(), options); 9733af6ab5fSopenharmony_ci } 9743af6ab5fSopenharmony_ci 9753af6ab5fSopenharmony_ci return ParseTypeReference(options); 9763af6ab5fSopenharmony_ci} 9773af6ab5fSopenharmony_ci 9783af6ab5fSopenharmony_civoid ETSParser::ParseRightParenthesis(TypeAnnotationParsingOptions *options, ir::TypeNode *&typeAnnotation, 9793af6ab5fSopenharmony_ci lexer::LexerPosition savedPos) 9803af6ab5fSopenharmony_ci{ 9813af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 9823af6ab5fSopenharmony_ci if (((*options) & TypeAnnotationParsingOptions::REPORT_ERROR) != 0) { 9833af6ab5fSopenharmony_ci ThrowExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS); 9843af6ab5fSopenharmony_ci } 9853af6ab5fSopenharmony_ci 9863af6ab5fSopenharmony_ci Lexer()->Rewind(savedPos); 9873af6ab5fSopenharmony_ci typeAnnotation = nullptr; 9883af6ab5fSopenharmony_ci } else { 9893af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat ')' 9903af6ab5fSopenharmony_ci } 9913af6ab5fSopenharmony_ci} 9923af6ab5fSopenharmony_ci 9933af6ab5fSopenharmony_civoid ETSParser::ThrowIfVarDeclaration(VariableParsingFlags flags) 9943af6ab5fSopenharmony_ci{ 9953af6ab5fSopenharmony_ci if ((flags & VariableParsingFlags::VAR) != 0) { 9963af6ab5fSopenharmony_ci ThrowUnexpectedToken(lexer::TokenType::KEYW_VAR); 9973af6ab5fSopenharmony_ci } 9983af6ab5fSopenharmony_ci} 9993af6ab5fSopenharmony_ci 10003af6ab5fSopenharmony_ciir::Statement *ETSParser::ParseExport(lexer::SourcePosition startLoc, ir::ModifierFlags modifiers) 10013af6ab5fSopenharmony_ci{ 10023af6ab5fSopenharmony_ci ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY || 10033af6ab5fSopenharmony_ci Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE || 10043af6ab5fSopenharmony_ci Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT); 10053af6ab5fSopenharmony_ci ArenaVector<ir::AstNode *> specifiers(Allocator()->Adapter()); 10063af6ab5fSopenharmony_ci 10073af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) { 10083af6ab5fSopenharmony_ci ParseNameSpaceSpecifier(&specifiers, true); 10093af6ab5fSopenharmony_ci } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 10103af6ab5fSopenharmony_ci auto specs = ParseNamedSpecifiers(); 10113af6ab5fSopenharmony_ci 10123af6ab5fSopenharmony_ci if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_FROM) { 10133af6ab5fSopenharmony_ci specifiers = util::Helpers::ConvertVector<ir::AstNode>(specs.first); 10143af6ab5fSopenharmony_ci } else { 10153af6ab5fSopenharmony_ci ArenaVector<ir::ExportSpecifier *> exports(Allocator()->Adapter()); 10163af6ab5fSopenharmony_ci for (auto spec : specs.first) { 10173af6ab5fSopenharmony_ci exports.emplace_back(AllocNode<ir::ExportSpecifier>(spec->Local(), spec->Imported())); 10183af6ab5fSopenharmony_ci } 10193af6ab5fSopenharmony_ci auto result = AllocNode<ir::ExportNamedDeclaration>(Allocator(), static_cast<ir::StringLiteral *>(nullptr), 10203af6ab5fSopenharmony_ci std::move(exports)); 10213af6ab5fSopenharmony_ci result->AddModifier(modifiers); 10223af6ab5fSopenharmony_ci return result; 10233af6ab5fSopenharmony_ci } 10243af6ab5fSopenharmony_ci } else { 10253af6ab5fSopenharmony_ci return ParseSingleExport(modifiers); 10263af6ab5fSopenharmony_ci } 10273af6ab5fSopenharmony_ci 10283af6ab5fSopenharmony_ci // re-export directive 10293af6ab5fSopenharmony_ci ir::ImportSource *reExportSource = ParseSourceFromClause(true); 10303af6ab5fSopenharmony_ci 10313af6ab5fSopenharmony_ci lexer::SourcePosition endLoc = reExportSource->Source()->End(); 10323af6ab5fSopenharmony_ci auto *reExportDeclaration = AllocNode<ir::ETSImportDeclaration>(reExportSource, std::move(specifiers)); 10333af6ab5fSopenharmony_ci reExportDeclaration->SetRange({startLoc, endLoc}); 10343af6ab5fSopenharmony_ci 10353af6ab5fSopenharmony_ci ConsumeSemicolon(reExportDeclaration); 10363af6ab5fSopenharmony_ci 10373af6ab5fSopenharmony_ci auto reExport = AllocNode<ir::ETSReExportDeclaration>(reExportDeclaration, std::vector<std::string>(), 10383af6ab5fSopenharmony_ci GetProgram()->SourceFilePath(), Allocator()); 10393af6ab5fSopenharmony_ci reExport->AddModifier(modifiers); 10403af6ab5fSopenharmony_ci return reExport; 10413af6ab5fSopenharmony_ci} 10423af6ab5fSopenharmony_ci 10433af6ab5fSopenharmony_ciir::ETSPackageDeclaration *ETSParser::ParsePackageDeclaration() 10443af6ab5fSopenharmony_ci{ 10453af6ab5fSopenharmony_ci auto startLoc = Lexer()->GetToken().Start(); 10463af6ab5fSopenharmony_ci 10473af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_PACKAGE) { 10483af6ab5fSopenharmony_ci // NOTE(rsipka): Unclear behavior/code. Currently, all entry programs omit the module name if it is not a 10493af6ab5fSopenharmony_ci // package module and the '--ets-module' option is not specified during compilation 10503af6ab5fSopenharmony_ci GetProgram()->SetModuleInfo(GetProgram()->FileName(), false, GetProgram()->IsEntryPoint() && !IsETSModule()); 10513af6ab5fSopenharmony_ci return nullptr; 10523af6ab5fSopenharmony_ci } 10533af6ab5fSopenharmony_ci 10543af6ab5fSopenharmony_ci Lexer()->NextToken(); 10553af6ab5fSopenharmony_ci 10563af6ab5fSopenharmony_ci ir::Expression *name = ParseQualifiedName(); 10573af6ab5fSopenharmony_ci 10583af6ab5fSopenharmony_ci auto *packageDeclaration = AllocNode<ir::ETSPackageDeclaration>(name); 10593af6ab5fSopenharmony_ci packageDeclaration->SetRange({startLoc, Lexer()->GetToken().End()}); 10603af6ab5fSopenharmony_ci 10613af6ab5fSopenharmony_ci ConsumeSemicolon(packageDeclaration); 10623af6ab5fSopenharmony_ci 10633af6ab5fSopenharmony_ci auto packageName = 10643af6ab5fSopenharmony_ci name->IsIdentifier() ? name->AsIdentifier()->Name() : name->AsTSQualifiedName()->ToString(Allocator()); 10653af6ab5fSopenharmony_ci 10663af6ab5fSopenharmony_ci GetProgram()->SetModuleInfo(packageName, true); 10673af6ab5fSopenharmony_ci 10683af6ab5fSopenharmony_ci return packageDeclaration; 10693af6ab5fSopenharmony_ci} 10703af6ab5fSopenharmony_ci 10713af6ab5fSopenharmony_ciir::ImportSource *ETSParser::ParseSourceFromClause(bool requireFrom) 10723af6ab5fSopenharmony_ci{ 10733af6ab5fSopenharmony_ci if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) { 10743af6ab5fSopenharmony_ci if (requireFrom) { 10753af6ab5fSopenharmony_ci ThrowSyntaxError("Unexpected token."); 10763af6ab5fSopenharmony_ci } 10773af6ab5fSopenharmony_ci } else { 10783af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat `from` 10793af6ab5fSopenharmony_ci } 10803af6ab5fSopenharmony_ci 10813af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_STRING) { 10823af6ab5fSopenharmony_ci ThrowSyntaxError("Unexpected token."); 10833af6ab5fSopenharmony_ci } 10843af6ab5fSopenharmony_ci 10853af6ab5fSopenharmony_ci ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_STRING); 10863af6ab5fSopenharmony_ci auto importPath = Lexer()->GetToken().Ident(); 10873af6ab5fSopenharmony_ci 10883af6ab5fSopenharmony_ci auto resolvedImportPath = importPathManager_->ResolvePath(GetProgram()->AbsoluteName(), importPath); 10893af6ab5fSopenharmony_ci if (globalProgram_->AbsoluteName() != resolvedImportPath) { 10903af6ab5fSopenharmony_ci importPathManager_->AddToParseList(resolvedImportPath, 10913af6ab5fSopenharmony_ci (GetContext().Status() & ParserStatus::IN_DEFAULT_IMPORTS) != 0U 10923af6ab5fSopenharmony_ci ? util::ImportFlags::DEFAULT_IMPORT 10933af6ab5fSopenharmony_ci : util::ImportFlags::NONE); 10943af6ab5fSopenharmony_ci } else if (!IsETSModule()) { 10953af6ab5fSopenharmony_ci ThrowSyntaxError("Please compile `" + globalProgram_->FileName().Mutf8() + "." + 10963af6ab5fSopenharmony_ci globalProgram_->SourceFile().GetExtension().Mutf8() + 10973af6ab5fSopenharmony_ci "` with `--ets-module` option. It is being imported by another file."); 10983af6ab5fSopenharmony_ci } 10993af6ab5fSopenharmony_ci 11003af6ab5fSopenharmony_ci auto *resolvedSource = AllocNode<ir::StringLiteral>(resolvedImportPath); 11013af6ab5fSopenharmony_ci auto importData = importPathManager_->GetImportData(resolvedImportPath, Extension()); 11023af6ab5fSopenharmony_ci auto *source = AllocNode<ir::StringLiteral>(importPath); 11033af6ab5fSopenharmony_ci source->SetRange(Lexer()->GetToken().Loc()); 11043af6ab5fSopenharmony_ci 11053af6ab5fSopenharmony_ci Lexer()->NextToken(); 11063af6ab5fSopenharmony_ci 11073af6ab5fSopenharmony_ci return Allocator()->New<ir::ImportSource>(source, resolvedSource, importData.lang, importData.hasDecl); 11083af6ab5fSopenharmony_ci} 11093af6ab5fSopenharmony_ci 11103af6ab5fSopenharmony_ciArenaVector<ir::ETSImportDeclaration *> ETSParser::ParseImportDeclarations() 11113af6ab5fSopenharmony_ci{ 11123af6ab5fSopenharmony_ci std::vector<std::string> userPaths; 11133af6ab5fSopenharmony_ci ArenaVector<ir::ETSImportDeclaration *> statements(Allocator()->Adapter()); 11143af6ab5fSopenharmony_ci 11153af6ab5fSopenharmony_ci while (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_IMPORT) { 11163af6ab5fSopenharmony_ci auto startLoc = Lexer()->GetToken().Start(); 11173af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat import 11183af6ab5fSopenharmony_ci 11193af6ab5fSopenharmony_ci ir::ImportKinds importKind = 11203af6ab5fSopenharmony_ci Lexer()->TryEatTokenKeyword(lexer::TokenType::KEYW_TYPE) ? ir::ImportKinds::TYPE : ir::ImportKinds::VALUE; 11213af6ab5fSopenharmony_ci 11223af6ab5fSopenharmony_ci ArenaVector<ir::AstNode *> specifiers(Allocator()->Adapter()); 11233af6ab5fSopenharmony_ci ArenaVector<ir::AstNode *> defaultSpecifiers(Allocator()->Adapter()); 11243af6ab5fSopenharmony_ci 11253af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) { 11263af6ab5fSopenharmony_ci if (importKind == ir::ImportKinds::TYPE) { 11273af6ab5fSopenharmony_ci ThrowSyntaxError("Type import requires selective binding to define the required imported elements."); 11283af6ab5fSopenharmony_ci } 11293af6ab5fSopenharmony_ci ParseNameSpaceSpecifier(&specifiers); 11303af6ab5fSopenharmony_ci } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 11313af6ab5fSopenharmony_ci auto specs = ParseNamedSpecifiers(); 11323af6ab5fSopenharmony_ci specifiers = util::Helpers::ConvertVector<ir::AstNode>(specs.first); 11333af6ab5fSopenharmony_ci defaultSpecifiers = util::Helpers::ConvertVector<ir::AstNode>(specs.second); 11343af6ab5fSopenharmony_ci } else { 11353af6ab5fSopenharmony_ci ParseImportDefaultSpecifier(&specifiers); 11363af6ab5fSopenharmony_ci } 11373af6ab5fSopenharmony_ci auto pos = Lexer()->Save(); 11383af6ab5fSopenharmony_ci if (!specifiers.empty()) { 11393af6ab5fSopenharmony_ci ir::ImportSource *importSource = ParseSourceFromClause(true); 11403af6ab5fSopenharmony_ci 11413af6ab5fSopenharmony_ci lexer::SourcePosition endLoc = importSource->Source()->End(); 11423af6ab5fSopenharmony_ci auto *importDeclaration = 11433af6ab5fSopenharmony_ci AllocNode<ir::ETSImportDeclaration>(importSource, std::move(specifiers), importKind); 11443af6ab5fSopenharmony_ci importDeclaration->SetRange({startLoc, endLoc}); 11453af6ab5fSopenharmony_ci 11463af6ab5fSopenharmony_ci ConsumeSemicolon(importDeclaration); 11473af6ab5fSopenharmony_ci statements.push_back(importDeclaration); 11483af6ab5fSopenharmony_ci } 11493af6ab5fSopenharmony_ci 11503af6ab5fSopenharmony_ci if (!defaultSpecifiers.empty()) { 11513af6ab5fSopenharmony_ci Lexer()->Rewind(pos); 11523af6ab5fSopenharmony_ci ir::ImportSource *importSourceDefault = ParseSourceFromClause(true); 11533af6ab5fSopenharmony_ci 11543af6ab5fSopenharmony_ci lexer::SourcePosition endLocDef = importSourceDefault->Source()->End(); 11553af6ab5fSopenharmony_ci auto *importDeclarationDefault = 11563af6ab5fSopenharmony_ci AllocNode<ir::ETSImportDeclaration>(importSourceDefault, std::move(defaultSpecifiers), importKind); 11573af6ab5fSopenharmony_ci importDeclarationDefault->SetRange({startLoc, endLocDef}); 11583af6ab5fSopenharmony_ci 11593af6ab5fSopenharmony_ci ConsumeSemicolon(importDeclarationDefault); 11603af6ab5fSopenharmony_ci util::Helpers::CheckDefaultImport(statements); 11613af6ab5fSopenharmony_ci statements.push_back(importDeclarationDefault); 11623af6ab5fSopenharmony_ci } 11633af6ab5fSopenharmony_ci } 11643af6ab5fSopenharmony_ci 11653af6ab5fSopenharmony_ci std::sort(statements.begin(), statements.end(), [](const auto *s1, const auto *s2) -> bool { 11663af6ab5fSopenharmony_ci return s1->Specifiers()[0]->IsImportNamespaceSpecifier() && !s2->Specifiers()[0]->IsImportNamespaceSpecifier(); 11673af6ab5fSopenharmony_ci }); 11683af6ab5fSopenharmony_ci return statements; 11693af6ab5fSopenharmony_ci} 11703af6ab5fSopenharmony_ci 11713af6ab5fSopenharmony_ciir::ExportNamedDeclaration *ETSParser::ParseSingleExport(ir::ModifierFlags modifiers) 11723af6ab5fSopenharmony_ci{ 11733af6ab5fSopenharmony_ci lexer::Token token = Lexer()->GetToken(); 11743af6ab5fSopenharmony_ci auto *exported = AllocNode<ir::Identifier>(token.Ident(), Allocator()); 11753af6ab5fSopenharmony_ci exported->SetReference(); 11763af6ab5fSopenharmony_ci exported->SetRange(Lexer()->GetToken().Loc()); 11773af6ab5fSopenharmony_ci 11783af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat exported variable name 11793af6ab5fSopenharmony_ci 11803af6ab5fSopenharmony_ci ArenaVector<ir::ExportSpecifier *> exports(Allocator()->Adapter()); 11813af6ab5fSopenharmony_ci 11823af6ab5fSopenharmony_ci exports.emplace_back(AllocNode<ir::ExportSpecifier>(exported, ParseNamedExport(token))); 11833af6ab5fSopenharmony_ci auto result = AllocNode<ir::ExportNamedDeclaration>(Allocator(), static_cast<ir::StringLiteral *>(nullptr), 11843af6ab5fSopenharmony_ci std::move(exports)); 11853af6ab5fSopenharmony_ci result->AddModifier(modifiers); 11863af6ab5fSopenharmony_ci ConsumeSemicolon(result); 11873af6ab5fSopenharmony_ci 11883af6ab5fSopenharmony_ci return result; 11893af6ab5fSopenharmony_ci} 11903af6ab5fSopenharmony_ci 11913af6ab5fSopenharmony_cibool ETSParser::IsDefaultImport() 11923af6ab5fSopenharmony_ci{ 11933af6ab5fSopenharmony_ci if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_DEFAULT) { 11943af6ab5fSopenharmony_ci Lexer()->NextToken(); 11953af6ab5fSopenharmony_ci if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) { 11963af6ab5fSopenharmony_ci Lexer()->NextToken(); 11973af6ab5fSopenharmony_ci return true; 11983af6ab5fSopenharmony_ci } 11993af6ab5fSopenharmony_ci ThrowSyntaxError("Unexpected token. 'as' keyword is expected."); 12003af6ab5fSopenharmony_ci } 12013af6ab5fSopenharmony_ci return false; 12023af6ab5fSopenharmony_ci} 12033af6ab5fSopenharmony_ci 12043af6ab5fSopenharmony_ciusing ImportSpecifierVector = ArenaVector<ir::ImportSpecifier *>; 12053af6ab5fSopenharmony_ciusing ImportDefaultSpecifierVector = ArenaVector<ir::ImportDefaultSpecifier *>; 12063af6ab5fSopenharmony_cistd::pair<ImportSpecifierVector, ImportDefaultSpecifierVector> ETSParser::ParseNamedSpecifiers() 12073af6ab5fSopenharmony_ci{ 12083af6ab5fSopenharmony_ci // NOTE(user): handle qualifiedName in file bindings: qualifiedName '.' '*' 12093af6ab5fSopenharmony_ci if (!Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_LEFT_BRACE)) { 12103af6ab5fSopenharmony_ci ThrowExpectedToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE); 12113af6ab5fSopenharmony_ci } 12123af6ab5fSopenharmony_ci 12133af6ab5fSopenharmony_ci auto fileName = GetProgram()->SourceFilePath().Mutf8(); 12143af6ab5fSopenharmony_ci 12153af6ab5fSopenharmony_ci ArenaVector<ir::ImportSpecifier *> result(Allocator()->Adapter()); 12163af6ab5fSopenharmony_ci ArenaVector<ir::ImportDefaultSpecifier *> resultDefault(Allocator()->Adapter()); 12173af6ab5fSopenharmony_ci 12183af6ab5fSopenharmony_ci while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 12193af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) { 12203af6ab5fSopenharmony_ci ThrowSyntaxError("The '*' token is not allowed as a selective binding (between braces)"); 12213af6ab5fSopenharmony_ci } 12223af6ab5fSopenharmony_ci 12233af6ab5fSopenharmony_ci if (!IsDefaultImport()) { 12243af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 12253af6ab5fSopenharmony_ci ThrowSyntaxError("Unexpected token"); 12263af6ab5fSopenharmony_ci } 12273af6ab5fSopenharmony_ci 12283af6ab5fSopenharmony_ci lexer::Token importedToken = Lexer()->GetToken(); 12293af6ab5fSopenharmony_ci auto *imported = AllocNode<ir::Identifier>(importedToken.Ident(), Allocator()); 12303af6ab5fSopenharmony_ci ir::Identifier *local = nullptr; 12313af6ab5fSopenharmony_ci imported->SetReference(); 12323af6ab5fSopenharmony_ci imported->SetRange(Lexer()->GetToken().Loc()); 12333af6ab5fSopenharmony_ci 12343af6ab5fSopenharmony_ci Lexer()->NextToken(); 12353af6ab5fSopenharmony_ci 12363af6ab5fSopenharmony_ci if (CheckModuleAsModifier() && Lexer()->TryEatTokenType(lexer::TokenType::KEYW_AS)) { 12373af6ab5fSopenharmony_ci local = ParseNamedImport(Lexer()->GetToken()); 12383af6ab5fSopenharmony_ci Lexer()->NextToken(); 12393af6ab5fSopenharmony_ci } else { 12403af6ab5fSopenharmony_ci local = ParseNamedImport(importedToken); 12413af6ab5fSopenharmony_ci } 12423af6ab5fSopenharmony_ci 12433af6ab5fSopenharmony_ci auto *specifier = AllocNode<ir::ImportSpecifier>(imported, local); 12443af6ab5fSopenharmony_ci specifier->SetRange({imported->Start(), local->End()}); 12453af6ab5fSopenharmony_ci 12463af6ab5fSopenharmony_ci util::Helpers::CheckImportedName(result, specifier, fileName); 12473af6ab5fSopenharmony_ci 12483af6ab5fSopenharmony_ci result.emplace_back(specifier); 12493af6ab5fSopenharmony_ci } else { 12503af6ab5fSopenharmony_ci auto *imported = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator()); 12513af6ab5fSopenharmony_ci imported->SetReference(); 12523af6ab5fSopenharmony_ci imported->SetRange(Lexer()->GetToken().Loc()); 12533af6ab5fSopenharmony_ci Lexer()->NextToken(); 12543af6ab5fSopenharmony_ci auto *specifier = AllocNode<ir::ImportDefaultSpecifier>(imported); 12553af6ab5fSopenharmony_ci specifier->SetRange({imported->Start(), imported->End()}); 12563af6ab5fSopenharmony_ci 12573af6ab5fSopenharmony_ci util::Helpers::CheckDefaultImportedName(resultDefault, specifier, fileName); 12583af6ab5fSopenharmony_ci 12593af6ab5fSopenharmony_ci resultDefault.emplace_back(specifier); 12603af6ab5fSopenharmony_ci } 12613af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) { 12623af6ab5fSopenharmony_ci Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); // eat comma 12633af6ab5fSopenharmony_ci } 12643af6ab5fSopenharmony_ci } 12653af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat '}' 12663af6ab5fSopenharmony_ci std::pair<ArenaVector<ir::ImportSpecifier *>, ArenaVector<ir::ImportDefaultSpecifier *>> resultSpecifiers( 12673af6ab5fSopenharmony_ci result, resultDefault); 12683af6ab5fSopenharmony_ci 12693af6ab5fSopenharmony_ci return resultSpecifiers; 12703af6ab5fSopenharmony_ci} 12713af6ab5fSopenharmony_ci 12723af6ab5fSopenharmony_civoid ETSParser::ParseNameSpaceSpecifier(ArenaVector<ir::AstNode *> *specifiers, bool isReExport) 12733af6ab5fSopenharmony_ci{ 12743af6ab5fSopenharmony_ci lexer::SourcePosition namespaceStart = Lexer()->GetToken().Start(); 12753af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat `*` character 12763af6ab5fSopenharmony_ci 12773af6ab5fSopenharmony_ci if (!CheckModuleAsModifier()) { 12783af6ab5fSopenharmony_ci ThrowSyntaxError("Unexpected token."); 12793af6ab5fSopenharmony_ci } 12803af6ab5fSopenharmony_ci 12813af6ab5fSopenharmony_ci // Note (oeotvos) As a temporary solution we allow the stdlib to use namespace import without an alias, but this 12823af6ab5fSopenharmony_ci // should be handled at some point. 12833af6ab5fSopenharmony_ci if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_FROM && !isReExport && 12843af6ab5fSopenharmony_ci (GetContext().Status() & ParserStatus::IN_DEFAULT_IMPORTS) == 0) { 12853af6ab5fSopenharmony_ci ThrowSyntaxError("Unexpected token, expected 'as' but found 'from'"); 12863af6ab5fSopenharmony_ci } 12873af6ab5fSopenharmony_ci 12883af6ab5fSopenharmony_ci auto *local = AllocNode<ir::Identifier>(util::StringView(""), Allocator()); 12893af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA || 12903af6ab5fSopenharmony_ci Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_FROM || isReExport) { 12913af6ab5fSopenharmony_ci local->SetReference(); 12923af6ab5fSopenharmony_ci auto *specifier = AllocNode<ir::ImportNamespaceSpecifier>(local); 12933af6ab5fSopenharmony_ci specifier->SetRange({namespaceStart, Lexer()->GetToken().End()}); 12943af6ab5fSopenharmony_ci specifiers->push_back(specifier); 12953af6ab5fSopenharmony_ci return; 12963af6ab5fSopenharmony_ci } 12973af6ab5fSopenharmony_ci 12983af6ab5fSopenharmony_ci ExpectToken(lexer::TokenType::KEYW_AS, true); // eat `as` literal 12993af6ab5fSopenharmony_ci local = ParseNamedImport(Lexer()->GetToken()); 13003af6ab5fSopenharmony_ci 13013af6ab5fSopenharmony_ci auto *specifier = AllocNode<ir::ImportNamespaceSpecifier>(local); 13023af6ab5fSopenharmony_ci specifier->SetRange({namespaceStart, Lexer()->GetToken().End()}); 13033af6ab5fSopenharmony_ci specifiers->push_back(specifier); 13043af6ab5fSopenharmony_ci 13053af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat local name 13063af6ab5fSopenharmony_ci} 13073af6ab5fSopenharmony_ci 13083af6ab5fSopenharmony_ciir::AstNode *ETSParser::ParseImportDefaultSpecifier(ArenaVector<ir::AstNode *> *specifiers) 13093af6ab5fSopenharmony_ci{ 13103af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 13113af6ab5fSopenharmony_ci ThrowSyntaxError("Unexpected token, expected an identifier"); 13123af6ab5fSopenharmony_ci } 13133af6ab5fSopenharmony_ci 13143af6ab5fSopenharmony_ci auto *imported = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator()); 13153af6ab5fSopenharmony_ci imported->SetReference(); 13163af6ab5fSopenharmony_ci imported->SetRange(Lexer()->GetToken().Loc()); 13173af6ab5fSopenharmony_ci Lexer()->NextToken(); // Eat import specifier. 13183af6ab5fSopenharmony_ci 13193af6ab5fSopenharmony_ci if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) { 13203af6ab5fSopenharmony_ci ThrowSyntaxError("Unexpected token, expected 'from'"); 13213af6ab5fSopenharmony_ci } 13223af6ab5fSopenharmony_ci 13233af6ab5fSopenharmony_ci auto *specifier = AllocNode<ir::ImportDefaultSpecifier>(imported); 13243af6ab5fSopenharmony_ci specifier->SetRange({imported->Start(), imported->End()}); 13253af6ab5fSopenharmony_ci specifiers->push_back(specifier); 13263af6ab5fSopenharmony_ci 13273af6ab5fSopenharmony_ci return nullptr; 13283af6ab5fSopenharmony_ci} 13293af6ab5fSopenharmony_ci 13303af6ab5fSopenharmony_cibool ETSParser::CheckModuleAsModifier() 13313af6ab5fSopenharmony_ci{ 13323af6ab5fSopenharmony_ci if ((Lexer()->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0U) { 13333af6ab5fSopenharmony_ci ThrowSyntaxError("Escape sequences are not allowed in 'as' keyword"); 13343af6ab5fSopenharmony_ci } 13353af6ab5fSopenharmony_ci 13363af6ab5fSopenharmony_ci return true; 13373af6ab5fSopenharmony_ci} 13383af6ab5fSopenharmony_ci 13393af6ab5fSopenharmony_ciir::AnnotatedExpression *ETSParser::GetAnnotatedExpressionFromParam() 13403af6ab5fSopenharmony_ci{ 13413af6ab5fSopenharmony_ci ir::AnnotatedExpression *parameter; 13423af6ab5fSopenharmony_ci 13433af6ab5fSopenharmony_ci switch (Lexer()->GetToken().Type()) { 13443af6ab5fSopenharmony_ci case lexer::TokenType::LITERAL_IDENT: { 13453af6ab5fSopenharmony_ci parameter = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator()); 13463af6ab5fSopenharmony_ci if (parameter->AsIdentifier()->Decorators().empty()) { 13473af6ab5fSopenharmony_ci parameter->SetRange(Lexer()->GetToken().Loc()); 13483af6ab5fSopenharmony_ci } else { 13493af6ab5fSopenharmony_ci parameter->SetRange( 13503af6ab5fSopenharmony_ci {parameter->AsIdentifier()->Decorators().front()->Start(), Lexer()->GetToken().End()}); 13513af6ab5fSopenharmony_ci } 13523af6ab5fSopenharmony_ci break; 13533af6ab5fSopenharmony_ci } 13543af6ab5fSopenharmony_ci 13553af6ab5fSopenharmony_ci case lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD: { 13563af6ab5fSopenharmony_ci const auto startLoc = Lexer()->GetToken().Start(); 13573af6ab5fSopenharmony_ci Lexer()->NextToken(); 13583af6ab5fSopenharmony_ci 13593af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 13603af6ab5fSopenharmony_ci ThrowSyntaxError("Unexpected token, expected an identifier."); 13613af6ab5fSopenharmony_ci } 13623af6ab5fSopenharmony_ci 13633af6ab5fSopenharmony_ci auto *const restIdent = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator()); 13643af6ab5fSopenharmony_ci restIdent->SetRange(Lexer()->GetToken().Loc()); 13653af6ab5fSopenharmony_ci 13663af6ab5fSopenharmony_ci parameter = AllocNode<ir::SpreadElement>(ir::AstNodeType::REST_ELEMENT, Allocator(), restIdent); 13673af6ab5fSopenharmony_ci parameter->SetRange({startLoc, Lexer()->GetToken().End()}); 13683af6ab5fSopenharmony_ci break; 13693af6ab5fSopenharmony_ci } 13703af6ab5fSopenharmony_ci 13713af6ab5fSopenharmony_ci default: { 13723af6ab5fSopenharmony_ci ThrowSyntaxError("Unexpected token, expected an identifier."); 13733af6ab5fSopenharmony_ci } 13743af6ab5fSopenharmony_ci } 13753af6ab5fSopenharmony_ci 13763af6ab5fSopenharmony_ci Lexer()->NextToken(); 13773af6ab5fSopenharmony_ci return parameter; 13783af6ab5fSopenharmony_ci} 13793af6ab5fSopenharmony_ci 13803af6ab5fSopenharmony_ci// NOLINTBEGIN(modernize-avoid-c-arrays) 13813af6ab5fSopenharmony_cistatic constexpr char const NO_DEFAULT_FOR_REST[] = "Rest parameter cannot have the default value."; 13823af6ab5fSopenharmony_cistatic constexpr char const ONLY_ARRAY_FOR_REST[] = "Rest parameter should be of an array type."; 13833af6ab5fSopenharmony_cistatic constexpr char const EXPLICIT_PARAM_TYPE[] = "Parameter declaration should have an explicit type annotation."; 13843af6ab5fSopenharmony_ci// NOLINTEND(modernize-avoid-c-arrays) 13853af6ab5fSopenharmony_ci 13863af6ab5fSopenharmony_ciir::ETSUnionType *ETSParser::CreateOptionalParameterTypeNode(ir::TypeNode *typeAnnotation, 13873af6ab5fSopenharmony_ci ir::ETSUndefinedType *defaultUndef) 13883af6ab5fSopenharmony_ci{ 13893af6ab5fSopenharmony_ci ArenaVector<ir::TypeNode *> types(Allocator()->Adapter()); 13903af6ab5fSopenharmony_ci if (typeAnnotation->IsETSUnionType()) { 13913af6ab5fSopenharmony_ci for (auto const &type : typeAnnotation->AsETSUnionType()->Types()) { 13923af6ab5fSopenharmony_ci types.push_back(type); 13933af6ab5fSopenharmony_ci } 13943af6ab5fSopenharmony_ci } else { 13953af6ab5fSopenharmony_ci types.push_back(typeAnnotation); 13963af6ab5fSopenharmony_ci } 13973af6ab5fSopenharmony_ci types.push_back(defaultUndef); 13983af6ab5fSopenharmony_ci 13993af6ab5fSopenharmony_ci auto *const unionType = AllocNode<ir::ETSUnionType>(std::move(types)); 14003af6ab5fSopenharmony_ci unionType->SetRange({typeAnnotation->Start(), typeAnnotation->End()}); 14013af6ab5fSopenharmony_ci return unionType; 14023af6ab5fSopenharmony_ci} 14033af6ab5fSopenharmony_ci 14043af6ab5fSopenharmony_ciir::Expression *ETSParser::ParseFunctionParameter() 14053af6ab5fSopenharmony_ci{ 14063af6ab5fSopenharmony_ci auto *const paramIdent = GetAnnotatedExpressionFromParam(); 14073af6ab5fSopenharmony_ci 14083af6ab5fSopenharmony_ci ir::ETSUndefinedType *defaultUndef = nullptr; 14093af6ab5fSopenharmony_ci 14103af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) { 14113af6ab5fSopenharmony_ci if (paramIdent->IsRestElement()) { 14123af6ab5fSopenharmony_ci ThrowSyntaxError(NO_DEFAULT_FOR_REST); 14133af6ab5fSopenharmony_ci } 14143af6ab5fSopenharmony_ci defaultUndef = AllocNode<ir::ETSUndefinedType>(); 14153af6ab5fSopenharmony_ci defaultUndef->SetRange({Lexer()->GetToken().Start(), Lexer()->GetToken().End()}); 14163af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat '?' 14173af6ab5fSopenharmony_ci } 14183af6ab5fSopenharmony_ci 14193af6ab5fSopenharmony_ci const bool isArrow = (GetContext().Status() & ParserStatus::ARROW_FUNCTION) != 0; 14203af6ab5fSopenharmony_ci 14213af6ab5fSopenharmony_ci if (Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_COLON)) { 14223af6ab5fSopenharmony_ci TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR; 14233af6ab5fSopenharmony_ci ir::TypeNode *typeAnnotation = ParseTypeAnnotation(&options); 14243af6ab5fSopenharmony_ci if (typeAnnotation == nullptr) { // Error processing. 14253af6ab5fSopenharmony_ci return nullptr; 14263af6ab5fSopenharmony_ci } 14273af6ab5fSopenharmony_ci 14283af6ab5fSopenharmony_ci if (defaultUndef != nullptr) { 14293af6ab5fSopenharmony_ci typeAnnotation = CreateOptionalParameterTypeNode(typeAnnotation, defaultUndef); 14303af6ab5fSopenharmony_ci } 14313af6ab5fSopenharmony_ci 14323af6ab5fSopenharmony_ci if (paramIdent->IsRestElement() && !typeAnnotation->IsTSArrayType()) { 14333af6ab5fSopenharmony_ci ThrowSyntaxError(ONLY_ARRAY_FOR_REST); 14343af6ab5fSopenharmony_ci } 14353af6ab5fSopenharmony_ci 14363af6ab5fSopenharmony_ci typeAnnotation->SetParent(paramIdent); 14373af6ab5fSopenharmony_ci paramIdent->SetTsTypeAnnotation(typeAnnotation); 14383af6ab5fSopenharmony_ci paramIdent->SetEnd(typeAnnotation->End()); 14393af6ab5fSopenharmony_ci } else if (!isArrow && defaultUndef == nullptr) { 14403af6ab5fSopenharmony_ci ThrowSyntaxError(EXPLICIT_PARAM_TYPE); 14413af6ab5fSopenharmony_ci } 14423af6ab5fSopenharmony_ci 14433af6ab5fSopenharmony_ci return ParseFunctionParameterExpression(paramIdent, defaultUndef); 14443af6ab5fSopenharmony_ci} 14453af6ab5fSopenharmony_ci 14463af6ab5fSopenharmony_ciir::Expression *ETSParser::CreateParameterThis(const util::StringView className) 14473af6ab5fSopenharmony_ci{ 14483af6ab5fSopenharmony_ci auto *paramIdent = AllocNode<ir::Identifier>(varbinder::TypedBinder::MANDATORY_PARAM_THIS, Allocator()); 14493af6ab5fSopenharmony_ci paramIdent->SetRange(Lexer()->GetToken().Loc()); 14503af6ab5fSopenharmony_ci 14513af6ab5fSopenharmony_ci ir::Expression *classTypeName = AllocNode<ir::Identifier>(className, Allocator()); 14523af6ab5fSopenharmony_ci classTypeName->AsIdentifier()->SetReference(); 14533af6ab5fSopenharmony_ci classTypeName->SetRange(Lexer()->GetToken().Loc()); 14543af6ab5fSopenharmony_ci 14553af6ab5fSopenharmony_ci auto typeRefPart = AllocNode<ir::ETSTypeReferencePart>(classTypeName, nullptr, nullptr); 14563af6ab5fSopenharmony_ci ir::TypeNode *typeAnnotation = AllocNode<ir::ETSTypeReference>(typeRefPart); 14573af6ab5fSopenharmony_ci 14583af6ab5fSopenharmony_ci typeAnnotation->SetParent(paramIdent); 14593af6ab5fSopenharmony_ci paramIdent->SetTsTypeAnnotation(typeAnnotation); 14603af6ab5fSopenharmony_ci 14613af6ab5fSopenharmony_ci auto *paramExpression = AllocNode<ir::ETSParameterExpression>(paramIdent, nullptr); 14623af6ab5fSopenharmony_ci paramExpression->SetRange({paramIdent->Start(), paramIdent->End()}); 14633af6ab5fSopenharmony_ci 14643af6ab5fSopenharmony_ci return paramExpression; 14653af6ab5fSopenharmony_ci} 14663af6ab5fSopenharmony_ci 14673af6ab5fSopenharmony_ciir::AnnotatedExpression *ETSParser::ParseVariableDeclaratorKey([[maybe_unused]] VariableParsingFlags flags) 14683af6ab5fSopenharmony_ci{ 14693af6ab5fSopenharmony_ci ir::Identifier *init = ExpectIdentifier(); 14703af6ab5fSopenharmony_ci ir::TypeNode *typeAnnotation = nullptr; 14713af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) { 14723af6ab5fSopenharmony_ci if ((flags & VariableParsingFlags::FOR_OF) != 0U) { 14733af6ab5fSopenharmony_ci ThrowSyntaxError("Optional variable is not allowed in for of statements"); 14743af6ab5fSopenharmony_ci } 14753af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat '?' 14763af6ab5fSopenharmony_ci init->AddModifier(ir::ModifierFlags::OPTIONAL); 14773af6ab5fSopenharmony_ci } 14783af6ab5fSopenharmony_ci 14793af6ab5fSopenharmony_ci if (auto const tokenType = Lexer()->GetToken().Type(); tokenType == lexer::TokenType::PUNCTUATOR_COLON) { 14803af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat ':' 14813af6ab5fSopenharmony_ci TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR; 14823af6ab5fSopenharmony_ci typeAnnotation = ParseTypeAnnotation(&options); 14833af6ab5fSopenharmony_ci } else if (tokenType != lexer::TokenType::PUNCTUATOR_SUBSTITUTION && (flags & VariableParsingFlags::FOR_OF) == 0U) { 14843af6ab5fSopenharmony_ci ThrowSyntaxError("Variable must be initialized or it's type must be declared"); 14853af6ab5fSopenharmony_ci } 14863af6ab5fSopenharmony_ci 14873af6ab5fSopenharmony_ci if (typeAnnotation != nullptr) { 14883af6ab5fSopenharmony_ci init->SetTsTypeAnnotation(typeAnnotation); 14893af6ab5fSopenharmony_ci typeAnnotation->SetParent(init); 14903af6ab5fSopenharmony_ci } 14913af6ab5fSopenharmony_ci 14923af6ab5fSopenharmony_ci return init; 14933af6ab5fSopenharmony_ci} 14943af6ab5fSopenharmony_ci 14953af6ab5fSopenharmony_ciir::VariableDeclarator *ETSParser::ParseVariableDeclaratorInitializer(ir::Expression *init, VariableParsingFlags flags, 14963af6ab5fSopenharmony_ci const lexer::SourcePosition &startLoc) 14973af6ab5fSopenharmony_ci{ 14983af6ab5fSopenharmony_ci if ((flags & VariableParsingFlags::DISALLOW_INIT) != 0) { 14993af6ab5fSopenharmony_ci ThrowSyntaxError("for-await-of loop variable declaration may not have an initializer"); 15003af6ab5fSopenharmony_ci } 15013af6ab5fSopenharmony_ci 15023af6ab5fSopenharmony_ci Lexer()->NextToken(); 15033af6ab5fSopenharmony_ci 15043af6ab5fSopenharmony_ci ir::Expression *initializer = ParseExpression(); 15053af6ab5fSopenharmony_ci 15063af6ab5fSopenharmony_ci lexer::SourcePosition endLoc = initializer->End(); 15073af6ab5fSopenharmony_ci 15083af6ab5fSopenharmony_ci auto *declarator = AllocNode<ir::VariableDeclarator>(GetFlag(flags), init, initializer); 15093af6ab5fSopenharmony_ci declarator->SetRange({startLoc, endLoc}); 15103af6ab5fSopenharmony_ci 15113af6ab5fSopenharmony_ci return declarator; 15123af6ab5fSopenharmony_ci} 15133af6ab5fSopenharmony_ci 15143af6ab5fSopenharmony_ciir::VariableDeclarator *ETSParser::ParseVariableDeclarator(ir::Expression *init, lexer::SourcePosition startLoc, 15153af6ab5fSopenharmony_ci VariableParsingFlags flags) 15163af6ab5fSopenharmony_ci{ 15173af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { 15183af6ab5fSopenharmony_ci return ParseVariableDeclaratorInitializer(init, flags, startLoc); 15193af6ab5fSopenharmony_ci } 15203af6ab5fSopenharmony_ci 15213af6ab5fSopenharmony_ci if ((flags & VariableParsingFlags::CONST) != 0 && 15223af6ab5fSopenharmony_ci static_cast<uint32_t>(flags & VariableParsingFlags::ACCEPT_CONST_NO_INIT) == 0U && !InAmbientContext()) { 15233af6ab5fSopenharmony_ci ThrowSyntaxError("Missing initializer in const declaration"); 15243af6ab5fSopenharmony_ci } 15253af6ab5fSopenharmony_ci 15263af6ab5fSopenharmony_ci if (init->AsIdentifier()->TypeAnnotation() == nullptr && (flags & VariableParsingFlags::FOR_OF) == 0U) { 15273af6ab5fSopenharmony_ci ThrowSyntaxError("Variable must be initialized or it's type must be declared"); 15283af6ab5fSopenharmony_ci } 15293af6ab5fSopenharmony_ci 15303af6ab5fSopenharmony_ci lexer::SourcePosition endLoc = init->End(); 15313af6ab5fSopenharmony_ci auto declarator = AllocNode<ir::VariableDeclarator>(GetFlag(flags), init); 15323af6ab5fSopenharmony_ci declarator->SetRange({startLoc, endLoc}); 15333af6ab5fSopenharmony_ci 15343af6ab5fSopenharmony_ci // NOTE (psiket) Transfer the OPTIONAL flag from the init to the declarator? 15353af6ab5fSopenharmony_ci return declarator; 15363af6ab5fSopenharmony_ci} 15373af6ab5fSopenharmony_ci 15383af6ab5fSopenharmony_ciir::Expression *ETSParser::ParseCatchParam() 15393af6ab5fSopenharmony_ci{ 15403af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { 15413af6ab5fSopenharmony_ci ThrowSyntaxError("Unexpected token, expected '('"); 15423af6ab5fSopenharmony_ci } 15433af6ab5fSopenharmony_ci 15443af6ab5fSopenharmony_ci ir::AnnotatedExpression *param = nullptr; 15453af6ab5fSopenharmony_ci 15463af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat left paren 15473af6ab5fSopenharmony_ci 15483af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) { 15493af6ab5fSopenharmony_ci CheckRestrictedBinding(); 15503af6ab5fSopenharmony_ci param = ExpectIdentifier(); 15513af6ab5fSopenharmony_ci } else { 15523af6ab5fSopenharmony_ci ThrowSyntaxError("Unexpected token in catch parameter, expected an identifier"); 15533af6ab5fSopenharmony_ci } 15543af6ab5fSopenharmony_ci 15553af6ab5fSopenharmony_ci ParseCatchParamTypeAnnotation(param); 15563af6ab5fSopenharmony_ci 15573af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 15583af6ab5fSopenharmony_ci ThrowSyntaxError("Unexpected token, expected ')'"); 15593af6ab5fSopenharmony_ci } 15603af6ab5fSopenharmony_ci 15613af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat right paren 15623af6ab5fSopenharmony_ci 15633af6ab5fSopenharmony_ci return param; 15643af6ab5fSopenharmony_ci} 15653af6ab5fSopenharmony_ci 15663af6ab5fSopenharmony_civoid ETSParser::ParseCatchParamTypeAnnotation([[maybe_unused]] ir::AnnotatedExpression *param) 15673af6ab5fSopenharmony_ci{ 15683af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { 15693af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat ':' 15703af6ab5fSopenharmony_ci 15713af6ab5fSopenharmony_ci TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR; 15723af6ab5fSopenharmony_ci if (auto *typeAnnotation = ParseTypeAnnotation(&options); typeAnnotation != nullptr) { 15733af6ab5fSopenharmony_ci typeAnnotation->SetParent(param); 15743af6ab5fSopenharmony_ci param->SetTsTypeAnnotation(typeAnnotation); 15753af6ab5fSopenharmony_ci } 15763af6ab5fSopenharmony_ci } 15773af6ab5fSopenharmony_ci 15783af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { 15793af6ab5fSopenharmony_ci ThrowSyntaxError("Catch clause variable cannot have an initializer"); 15803af6ab5fSopenharmony_ci } 15813af6ab5fSopenharmony_ci} 15823af6ab5fSopenharmony_ci 15833af6ab5fSopenharmony_ciir::Statement *ETSParser::ParseImportDeclaration([[maybe_unused]] StatementParsingFlags flags) 15843af6ab5fSopenharmony_ci{ 15853af6ab5fSopenharmony_ci char32_t nextChar = Lexer()->Lookahead(); 15863af6ab5fSopenharmony_ci if (nextChar == lexer::LEX_CHAR_LEFT_PAREN || nextChar == lexer::LEX_CHAR_DOT) { 15873af6ab5fSopenharmony_ci return ParseExpressionStatement(); 15883af6ab5fSopenharmony_ci } 15893af6ab5fSopenharmony_ci 15903af6ab5fSopenharmony_ci lexer::SourcePosition startLoc = Lexer()->GetToken().Start(); 15913af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat import 15923af6ab5fSopenharmony_ci 15933af6ab5fSopenharmony_ci ArenaVector<ir::AstNode *> specifiers(Allocator()->Adapter()); 15943af6ab5fSopenharmony_ci 15953af6ab5fSopenharmony_ci ir::ImportSource *importSource = nullptr; 15963af6ab5fSopenharmony_ci 15973af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_STRING) { 15983af6ab5fSopenharmony_ci ir::AstNode *astNode = ParseImportSpecifiers(&specifiers); 15993af6ab5fSopenharmony_ci if (astNode != nullptr) { 16003af6ab5fSopenharmony_ci ASSERT(astNode->IsTSImportEqualsDeclaration()); 16013af6ab5fSopenharmony_ci astNode->SetRange({startLoc, Lexer()->GetToken().End()}); 16023af6ab5fSopenharmony_ci ConsumeSemicolon(astNode->AsTSImportEqualsDeclaration()); 16033af6ab5fSopenharmony_ci return astNode->AsTSImportEqualsDeclaration(); 16043af6ab5fSopenharmony_ci } 16053af6ab5fSopenharmony_ci importSource = ParseSourceFromClause(true); 16063af6ab5fSopenharmony_ci } else { 16073af6ab5fSopenharmony_ci importSource = ParseSourceFromClause(false); 16083af6ab5fSopenharmony_ci } 16093af6ab5fSopenharmony_ci 16103af6ab5fSopenharmony_ci lexer::SourcePosition endLoc = importSource->Source()->End(); 16113af6ab5fSopenharmony_ci auto *importDeclaration = AllocNode<ir::ETSImportDeclaration>(importSource, std::move(specifiers)); 16123af6ab5fSopenharmony_ci importDeclaration->SetRange({startLoc, endLoc}); 16133af6ab5fSopenharmony_ci 16143af6ab5fSopenharmony_ci ConsumeSemicolon(importDeclaration); 16153af6ab5fSopenharmony_ci 16163af6ab5fSopenharmony_ci return importDeclaration; 16173af6ab5fSopenharmony_ci} 16183af6ab5fSopenharmony_ci 16193af6ab5fSopenharmony_ciir::Statement *ETSParser::ParseExportDeclaration([[maybe_unused]] StatementParsingFlags flags) 16203af6ab5fSopenharmony_ci{ 16213af6ab5fSopenharmony_ci ThrowUnexpectedToken(lexer::TokenType::KEYW_EXPORT); 16223af6ab5fSopenharmony_ci} 16233af6ab5fSopenharmony_ci 16243af6ab5fSopenharmony_ciir::Expression *ETSParser::ParseExpressionOrTypeAnnotation(lexer::TokenType type, 16253af6ab5fSopenharmony_ci [[maybe_unused]] ExpressionParseFlags flags) 16263af6ab5fSopenharmony_ci{ 16273af6ab5fSopenharmony_ci if (type == lexer::TokenType::KEYW_INSTANCEOF) { 16283af6ab5fSopenharmony_ci TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR; 16293af6ab5fSopenharmony_ci 16303af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_NULL) { 16313af6ab5fSopenharmony_ci auto *typeAnnotation = AllocNode<ir::NullLiteral>(); 16323af6ab5fSopenharmony_ci typeAnnotation->SetRange(Lexer()->GetToken().Loc()); 16333af6ab5fSopenharmony_ci Lexer()->NextToken(); 16343af6ab5fSopenharmony_ci 16353af6ab5fSopenharmony_ci return typeAnnotation; 16363af6ab5fSopenharmony_ci } 16373af6ab5fSopenharmony_ci 16383af6ab5fSopenharmony_ci return ParseTypeAnnotation(&options); 16393af6ab5fSopenharmony_ci } 16403af6ab5fSopenharmony_ci 16413af6ab5fSopenharmony_ci return ParseExpression(ExpressionParseFlags::DISALLOW_YIELD); 16423af6ab5fSopenharmony_ci} 16433af6ab5fSopenharmony_ci 16443af6ab5fSopenharmony_cibool ETSParser::ParsePotentialGenericFunctionCall(ir::Expression *primaryExpr, ir::Expression **returnExpression, 16453af6ab5fSopenharmony_ci [[maybe_unused]] const lexer::SourcePosition &startLoc, 16463af6ab5fSopenharmony_ci bool ignoreCallExpression) 16473af6ab5fSopenharmony_ci{ 16483af6ab5fSopenharmony_ci if (Lexer()->Lookahead() == lexer::LEX_CHAR_LESS_THAN || 16493af6ab5fSopenharmony_ci (!primaryExpr->IsIdentifier() && !primaryExpr->IsMemberExpression())) { 16503af6ab5fSopenharmony_ci return true; 16513af6ab5fSopenharmony_ci } 16523af6ab5fSopenharmony_ci 16533af6ab5fSopenharmony_ci const auto savedPos = Lexer()->Save(); 16543af6ab5fSopenharmony_ci 16553af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) { 16563af6ab5fSopenharmony_ci Lexer()->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1); 16573af6ab5fSopenharmony_ci } 16583af6ab5fSopenharmony_ci 16593af6ab5fSopenharmony_ci TypeAnnotationParsingOptions options = 16603af6ab5fSopenharmony_ci TypeAnnotationParsingOptions::ALLOW_WILDCARD | TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE; 16613af6ab5fSopenharmony_ci ir::TSTypeParameterInstantiation *typeParams = ParseTypeParameterInstantiation(&options); 16623af6ab5fSopenharmony_ci 16633af6ab5fSopenharmony_ci if (typeParams == nullptr) { 16643af6ab5fSopenharmony_ci Lexer()->Rewind(savedPos); 16653af6ab5fSopenharmony_ci return true; 16663af6ab5fSopenharmony_ci } 16673af6ab5fSopenharmony_ci 16683af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::EOS) { 16693af6ab5fSopenharmony_ci ThrowSyntaxError("'(' expected"); 16703af6ab5fSopenharmony_ci } 16713af6ab5fSopenharmony_ci 16723af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { 16733af6ab5fSopenharmony_ci if (!ignoreCallExpression) { 16743af6ab5fSopenharmony_ci *returnExpression = ParseCallExpression(*returnExpression, false, false); 16753af6ab5fSopenharmony_ci (*returnExpression)->AsCallExpression()->SetTypeParams(typeParams); 16763af6ab5fSopenharmony_ci return false; 16773af6ab5fSopenharmony_ci } 16783af6ab5fSopenharmony_ci 16793af6ab5fSopenharmony_ci return true; 16803af6ab5fSopenharmony_ci } 16813af6ab5fSopenharmony_ci 16823af6ab5fSopenharmony_ci Lexer()->Rewind(savedPos); 16833af6ab5fSopenharmony_ci return true; 16843af6ab5fSopenharmony_ci} 16853af6ab5fSopenharmony_ci 16863af6ab5fSopenharmony_ciir::ModifierFlags ETSParser::ParseTypeVarianceModifier(TypeAnnotationParsingOptions *const options) 16873af6ab5fSopenharmony_ci{ 16883af6ab5fSopenharmony_ci if ((*options & TypeAnnotationParsingOptions::ALLOW_WILDCARD) == 0 && 16893af6ab5fSopenharmony_ci (*options & TypeAnnotationParsingOptions::ALLOW_DECLARATION_SITE_VARIANCE) == 0) { 16903af6ab5fSopenharmony_ci ThrowSyntaxError("Variance modifier is not allowed here."); 16913af6ab5fSopenharmony_ci } 16923af6ab5fSopenharmony_ci 16933af6ab5fSopenharmony_ci switch (Lexer()->GetToken().KeywordType()) { 16943af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_IN: { 16953af6ab5fSopenharmony_ci Lexer()->NextToken(); 16963af6ab5fSopenharmony_ci return ir::ModifierFlags::IN; 16973af6ab5fSopenharmony_ci } 16983af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_OUT: { 16993af6ab5fSopenharmony_ci Lexer()->NextToken(); 17003af6ab5fSopenharmony_ci return ir::ModifierFlags::OUT; 17013af6ab5fSopenharmony_ci } 17023af6ab5fSopenharmony_ci default: { 17033af6ab5fSopenharmony_ci return ir::ModifierFlags::NONE; 17043af6ab5fSopenharmony_ci } 17053af6ab5fSopenharmony_ci } 17063af6ab5fSopenharmony_ci} 17073af6ab5fSopenharmony_ci 17083af6ab5fSopenharmony_ciir::AstNode *ETSParser::ParseAmbientSignature() 17093af6ab5fSopenharmony_ci{ 17103af6ab5fSopenharmony_ci auto const startPos = Lexer()->GetToken().Start(); 17113af6ab5fSopenharmony_ci 17123af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 17133af6ab5fSopenharmony_ci ThrowSyntaxError("Unexpected token at", Lexer()->GetToken().Start()); 17143af6ab5fSopenharmony_ci } 17153af6ab5fSopenharmony_ci auto const indexName = Lexer()->GetToken().Ident(); 17163af6ab5fSopenharmony_ci 17173af6ab5fSopenharmony_ci Lexer()->NextToken(); 17183af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) { 17193af6ab5fSopenharmony_ci ThrowSyntaxError("Index type expected in index signature", Lexer()->GetToken().Start()); 17203af6ab5fSopenharmony_ci } 17213af6ab5fSopenharmony_ci 17223af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat ":" 17233af6ab5fSopenharmony_ci if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_NUMBER) { 17243af6ab5fSopenharmony_ci ThrowSyntaxError("Index type must be number in index signature", Lexer()->GetToken().Start()); 17253af6ab5fSopenharmony_ci } 17263af6ab5fSopenharmony_ci 17273af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat indexType 17283af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) { 17293af6ab5fSopenharmony_ci ThrowSyntaxError("] expected in index signature", Lexer()->GetToken().Start()); 17303af6ab5fSopenharmony_ci } 17313af6ab5fSopenharmony_ci 17323af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat "]" 17333af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) { 17343af6ab5fSopenharmony_ci ThrowSyntaxError("An index signature must have a type annotation.", Lexer()->GetToken().Start()); 17353af6ab5fSopenharmony_ci } 17363af6ab5fSopenharmony_ci 17373af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat ":" 17383af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 17393af6ab5fSopenharmony_ci ThrowSyntaxError("Return type of index signature from exported class or interface need to be identifier", 17403af6ab5fSopenharmony_ci Lexer()->GetToken().Start()); 17413af6ab5fSopenharmony_ci } 17423af6ab5fSopenharmony_ci auto const returnType = 17433af6ab5fSopenharmony_ci AllocNode<ir::ETSTypeReferencePart>(AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator())); 17443af6ab5fSopenharmony_ci 17453af6ab5fSopenharmony_ci auto dummyNode = AllocNode<ir::DummyNode>(compiler::Signatures::AMBIENT_INDEXER, indexName, returnType, 17463af6ab5fSopenharmony_ci ir::DummyNodeFlag::INDEXER); 17473af6ab5fSopenharmony_ci dummyNode->SetRange({startPos, Lexer()->GetToken().End()}); 17483af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat return type 17493af6ab5fSopenharmony_ci return dummyNode; 17503af6ab5fSopenharmony_ci} 17513af6ab5fSopenharmony_ci 17523af6ab5fSopenharmony_ciir::TSTypeParameter *ETSParser::ParseTypeParameter([[maybe_unused]] TypeAnnotationParsingOptions *options) 17533af6ab5fSopenharmony_ci{ 17543af6ab5fSopenharmony_ci lexer::SourcePosition startLoc = Lexer()->GetToken().Start(); 17553af6ab5fSopenharmony_ci 17563af6ab5fSopenharmony_ci const auto varianceModifier = [this, options] { 17573af6ab5fSopenharmony_ci switch (Lexer()->GetToken().KeywordType()) { 17583af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_IN: 17593af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_OUT: 17603af6ab5fSopenharmony_ci return ParseTypeVarianceModifier(options); 17613af6ab5fSopenharmony_ci default: 17623af6ab5fSopenharmony_ci return ir::ModifierFlags::NONE; 17633af6ab5fSopenharmony_ci } 17643af6ab5fSopenharmony_ci }(); 17653af6ab5fSopenharmony_ci 17663af6ab5fSopenharmony_ci auto *paramIdent = ExpectIdentifier(); 17673af6ab5fSopenharmony_ci 17683af6ab5fSopenharmony_ci ir::TypeNode *constraint = nullptr; 17693af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) { 17703af6ab5fSopenharmony_ci Lexer()->NextToken(); 17713af6ab5fSopenharmony_ci TypeAnnotationParsingOptions newOptions = 17723af6ab5fSopenharmony_ci TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE; 17733af6ab5fSopenharmony_ci constraint = ParseTypeAnnotation(&newOptions); 17743af6ab5fSopenharmony_ci } 17753af6ab5fSopenharmony_ci 17763af6ab5fSopenharmony_ci ir::TypeNode *defaultType = nullptr; 17773af6ab5fSopenharmony_ci 17783af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { 17793af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat '=' 17803af6ab5fSopenharmony_ci defaultType = ParseTypeAnnotation(options); 17813af6ab5fSopenharmony_ci } 17823af6ab5fSopenharmony_ci 17833af6ab5fSopenharmony_ci auto *typeParam = AllocNode<ir::TSTypeParameter>(paramIdent, constraint, defaultType, varianceModifier); 17843af6ab5fSopenharmony_ci 17853af6ab5fSopenharmony_ci typeParam->SetRange({startLoc, Lexer()->GetToken().End()}); 17863af6ab5fSopenharmony_ci return typeParam; 17873af6ab5fSopenharmony_ci} 17883af6ab5fSopenharmony_ci 17893af6ab5fSopenharmony_ciir::Identifier *ETSParser::ParseClassIdent([[maybe_unused]] ir::ClassDefinitionModifiers modifiers) 17903af6ab5fSopenharmony_ci{ 17913af6ab5fSopenharmony_ci return ExpectIdentifier(false, true); 17923af6ab5fSopenharmony_ci} 17933af6ab5fSopenharmony_ci 17943af6ab5fSopenharmony_cibool ETSParser::IsStructKeyword() const 17953af6ab5fSopenharmony_ci{ 17963af6ab5fSopenharmony_ci return (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && 17973af6ab5fSopenharmony_ci Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STRUCT); 17983af6ab5fSopenharmony_ci} 17993af6ab5fSopenharmony_ci 18003af6ab5fSopenharmony_civoid ETSParser::ParseTrailingBlock(ir::CallExpression *callExpr) 18013af6ab5fSopenharmony_ci{ 18023af6ab5fSopenharmony_ci if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 18033af6ab5fSopenharmony_ci callExpr->SetIsTrailingBlockInNewLine(Lexer()->GetToken().NewLine()); 18043af6ab5fSopenharmony_ci callExpr->SetTrailingBlock(ParseBlockStatement()); 18053af6ab5fSopenharmony_ci } 18063af6ab5fSopenharmony_ci} 18073af6ab5fSopenharmony_ci 18083af6ab5fSopenharmony_ciir::Expression *ETSParser::ParseCoercedNumberLiteral() 18093af6ab5fSopenharmony_ci{ 18103af6ab5fSopenharmony_ci if ((Lexer()->GetToken().Flags() & lexer::TokenFlags::NUMBER_FLOAT) != 0U) { 18113af6ab5fSopenharmony_ci auto *number = AllocNode<ir::NumberLiteral>(Lexer()->GetToken().GetNumber()); 18123af6ab5fSopenharmony_ci number->SetRange(Lexer()->GetToken().Loc()); 18133af6ab5fSopenharmony_ci auto *floatType = AllocNode<ir::ETSPrimitiveType>(ir::PrimitiveType::FLOAT); 18143af6ab5fSopenharmony_ci floatType->SetRange(Lexer()->GetToken().Loc()); 18153af6ab5fSopenharmony_ci auto *asExpression = AllocNode<ir::TSAsExpression>(number, floatType, true); 18163af6ab5fSopenharmony_ci asExpression->SetRange(Lexer()->GetToken().Loc()); 18173af6ab5fSopenharmony_ci 18183af6ab5fSopenharmony_ci Lexer()->NextToken(); 18193af6ab5fSopenharmony_ci return asExpression; 18203af6ab5fSopenharmony_ci } 18213af6ab5fSopenharmony_ci return ParseNumberLiteral(); 18223af6ab5fSopenharmony_ci} 18233af6ab5fSopenharmony_ci 18243af6ab5fSopenharmony_civoid ETSParser::CheckDeclare() 18253af6ab5fSopenharmony_ci{ 18263af6ab5fSopenharmony_ci ASSERT(Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE); 18273af6ab5fSopenharmony_ci 18283af6ab5fSopenharmony_ci if (InAmbientContext()) { 18293af6ab5fSopenharmony_ci ThrowSyntaxError("A 'declare' modifier cannot be used in an already ambient context."); 18303af6ab5fSopenharmony_ci } 18313af6ab5fSopenharmony_ci 18323af6ab5fSopenharmony_ci GetContext().Status() |= ParserStatus::IN_AMBIENT_CONTEXT; 18333af6ab5fSopenharmony_ci 18343af6ab5fSopenharmony_ci Lexer()->NextToken(); // eat 'declare' 18353af6ab5fSopenharmony_ci 18363af6ab5fSopenharmony_ci switch (Lexer()->GetToken().KeywordType()) { 18373af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_LET: 18383af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_CONST: 18393af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_FUNCTION: 18403af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_CLASS: 18413af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_NAMESPACE: 18423af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_ENUM: 18433af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_TYPE: 18443af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_ABSTRACT: 18453af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_FINAL: 18463af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_INTERFACE: 18473af6ab5fSopenharmony_ci case lexer::TokenType::KEYW_ASYNC: { 18483af6ab5fSopenharmony_ci return; 18493af6ab5fSopenharmony_ci } 18503af6ab5fSopenharmony_ci default: { 18513af6ab5fSopenharmony_ci ThrowSyntaxError("Unexpected token."); 18523af6ab5fSopenharmony_ci } 18533af6ab5fSopenharmony_ci } 18543af6ab5fSopenharmony_ci} 18553af6ab5fSopenharmony_ci 18563af6ab5fSopenharmony_ciir::FunctionDeclaration *ETSParser::ParseFunctionDeclaration(bool canBeAnonymous, ir::ModifierFlags modifiers) 18573af6ab5fSopenharmony_ci{ 18583af6ab5fSopenharmony_ci lexer::SourcePosition startLoc = Lexer()->GetToken().Start(); 18593af6ab5fSopenharmony_ci 18603af6ab5fSopenharmony_ci ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION); 18613af6ab5fSopenharmony_ci Lexer()->NextToken(); 18623af6ab5fSopenharmony_ci auto newStatus = ParserStatus::NEED_RETURN_TYPE | ParserStatus::ALLOW_SUPER; 18633af6ab5fSopenharmony_ci 18643af6ab5fSopenharmony_ci if ((modifiers & ir::ModifierFlags::ASYNC) != 0) { 18653af6ab5fSopenharmony_ci newStatus |= ParserStatus::ASYNC_FUNCTION; 18663af6ab5fSopenharmony_ci } 18673af6ab5fSopenharmony_ci if (Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_MULTIPLY)) { 18683af6ab5fSopenharmony_ci newStatus |= ParserStatus::GENERATOR_FUNCTION; 18693af6ab5fSopenharmony_ci } 18703af6ab5fSopenharmony_ci 18713af6ab5fSopenharmony_ci ir::Identifier *className = nullptr; 18723af6ab5fSopenharmony_ci ir::Identifier *identNode = nullptr; 18733af6ab5fSopenharmony_ci if (Lexer()->Lookahead() == lexer::LEX_CHAR_DOT) { 18743af6ab5fSopenharmony_ci className = ExpectIdentifier(); 18753af6ab5fSopenharmony_ci if (className != nullptr) { 18763af6ab5fSopenharmony_ci newStatus |= ParserStatus::IN_EXTENSION_FUNCTION; 18773af6ab5fSopenharmony_ci } 18783af6ab5fSopenharmony_ci Lexer()->NextToken(); 18793af6ab5fSopenharmony_ci identNode = ExpectIdentifier(); 18803af6ab5fSopenharmony_ci } else if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) { 18813af6ab5fSopenharmony_ci identNode = ExpectIdentifier(); 18823af6ab5fSopenharmony_ci } else if (!canBeAnonymous) { 18833af6ab5fSopenharmony_ci LogSyntaxError("Unexpected token, expected identifier after 'function' keyword"); 18843af6ab5fSopenharmony_ci } 18853af6ab5fSopenharmony_ci newStatus |= ParserStatus::FUNCTION_DECLARATION; 18863af6ab5fSopenharmony_ci if (identNode != nullptr) { 18873af6ab5fSopenharmony_ci CheckRestrictedBinding(identNode->Name(), identNode->Start()); 18883af6ab5fSopenharmony_ci } 18893af6ab5fSopenharmony_ci 18903af6ab5fSopenharmony_ci ir::ScriptFunction *func = ParseFunction(newStatus, className); 18913af6ab5fSopenharmony_ci if (identNode != nullptr) { // Error processing. 18923af6ab5fSopenharmony_ci func->SetIdent(identNode); 18933af6ab5fSopenharmony_ci } 18943af6ab5fSopenharmony_ci 18953af6ab5fSopenharmony_ci auto *funcDecl = AllocNode<ir::FunctionDeclaration>(Allocator(), func); 18963af6ab5fSopenharmony_ci if (func->IsOverload() && Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 18973af6ab5fSopenharmony_ci Lexer()->NextToken(); 18983af6ab5fSopenharmony_ci } 18993af6ab5fSopenharmony_ci funcDecl->SetRange(func->Range()); 19003af6ab5fSopenharmony_ci func->AddModifier(modifiers); 19013af6ab5fSopenharmony_ci func->SetStart(startLoc); 19023af6ab5fSopenharmony_ci 19033af6ab5fSopenharmony_ci if (className != nullptr) { 19043af6ab5fSopenharmony_ci func->AddFlag(ir::ScriptFunctionFlags::INSTANCE_EXTENSION_METHOD); 19053af6ab5fSopenharmony_ci } 19063af6ab5fSopenharmony_ci 19073af6ab5fSopenharmony_ci return funcDecl; 19083af6ab5fSopenharmony_ci} 19093af6ab5fSopenharmony_ci 19103af6ab5fSopenharmony_civoid ETSParser::AddPackageSourcesToParseList() 19113af6ab5fSopenharmony_ci{ 19123af6ab5fSopenharmony_ci importPathManager_->AddToParseList(GetProgram()->SourceFileFolder(), util::ImportFlags::IMPLICIT_PACKAGE_IMPORT); 19133af6ab5fSopenharmony_ci 19143af6ab5fSopenharmony_ci // Global program file is always in the same folder that we scanned, but we don't need to parse it twice 19153af6ab5fSopenharmony_ci importPathManager_->MarkAsParsed(globalProgram_->SourceFilePath()); 19163af6ab5fSopenharmony_ci} 19173af6ab5fSopenharmony_ci 19183af6ab5fSopenharmony_ci//================================================================================================// 19193af6ab5fSopenharmony_ci// ExternalSourceParser class 19203af6ab5fSopenharmony_ci//================================================================================================// 19213af6ab5fSopenharmony_ci 19223af6ab5fSopenharmony_ciExternalSourceParser::ExternalSourceParser(ETSParser *parser, Program *newProgram) 19233af6ab5fSopenharmony_ci : parser_(parser), 19243af6ab5fSopenharmony_ci savedProgram_(parser_->GetProgram()), 19253af6ab5fSopenharmony_ci savedLexer_(parser_->Lexer()), 19263af6ab5fSopenharmony_ci savedTopScope_(parser_->GetProgram()->VarBinder()->TopScope()) 19273af6ab5fSopenharmony_ci{ 19283af6ab5fSopenharmony_ci parser_->SetProgram(newProgram); 19293af6ab5fSopenharmony_ci parser_->GetContext().SetProgram(newProgram); 19303af6ab5fSopenharmony_ci} 19313af6ab5fSopenharmony_ci 19323af6ab5fSopenharmony_ciExternalSourceParser::~ExternalSourceParser() 19333af6ab5fSopenharmony_ci{ 19343af6ab5fSopenharmony_ci parser_->SetLexer(savedLexer_); 19353af6ab5fSopenharmony_ci parser_->SetProgram(savedProgram_); 19363af6ab5fSopenharmony_ci parser_->GetContext().SetProgram(savedProgram_); 19373af6ab5fSopenharmony_ci parser_->GetProgram()->VarBinder()->ResetTopScope(savedTopScope_); 19383af6ab5fSopenharmony_ci} 19393af6ab5fSopenharmony_ci 19403af6ab5fSopenharmony_ci//================================================================================================// 19413af6ab5fSopenharmony_ci// InnerSourceParser class 19423af6ab5fSopenharmony_ci//================================================================================================// 19433af6ab5fSopenharmony_ci 19443af6ab5fSopenharmony_ciInnerSourceParser::InnerSourceParser(ETSParser *parser) 19453af6ab5fSopenharmony_ci : parser_(parser), 19463af6ab5fSopenharmony_ci savedLexer_(parser_->Lexer()), 19473af6ab5fSopenharmony_ci savedSourceCode_(parser_->GetProgram()->SourceCode()), 19483af6ab5fSopenharmony_ci savedSourceFile_(parser_->GetProgram()->SourceFilePath()), 19493af6ab5fSopenharmony_ci savedSourceFilePath_(parser_->GetProgram()->SourceFileFolder()) 19503af6ab5fSopenharmony_ci{ 19513af6ab5fSopenharmony_ci} 19523af6ab5fSopenharmony_ci 19533af6ab5fSopenharmony_ciInnerSourceParser::~InnerSourceParser() 19543af6ab5fSopenharmony_ci{ 19553af6ab5fSopenharmony_ci parser_->SetLexer(savedLexer_); 19563af6ab5fSopenharmony_ci parser_->GetProgram()->SetSource(savedSourceCode_, savedSourceFile_, savedSourceFilePath_); 19573af6ab5fSopenharmony_ci} 19583af6ab5fSopenharmony_ci} // namespace ark::es2panda::parser 1959