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 *> &params, [[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 &param : 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