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 "parserImpl.h"
173af6ab5fSopenharmony_ci#include "parserStatusContext.h"
183af6ab5fSopenharmony_ci
193af6ab5fSopenharmony_ci#include "varbinder/privateBinding.h"
203af6ab5fSopenharmony_ci#include "ir/astNode.h"
213af6ab5fSopenharmony_ci#include "ir/base/classDefinition.h"
223af6ab5fSopenharmony_ci#include "ir/base/classProperty.h"
233af6ab5fSopenharmony_ci#include "ir/base/classStaticBlock.h"
243af6ab5fSopenharmony_ci#include "ir/base/methodDefinition.h"
253af6ab5fSopenharmony_ci#include "ir/base/scriptFunction.h"
263af6ab5fSopenharmony_ci#include "ir/base/spreadElement.h"
273af6ab5fSopenharmony_ci#include "ir/expression.h"
283af6ab5fSopenharmony_ci#include "ir/expressions/arrayExpression.h"
293af6ab5fSopenharmony_ci#include "ir/expressions/assignmentExpression.h"
303af6ab5fSopenharmony_ci#include "ir/expressions/callExpression.h"
313af6ab5fSopenharmony_ci#include "ir/expressions/functionExpression.h"
323af6ab5fSopenharmony_ci#include "ir/expressions/identifier.h"
333af6ab5fSopenharmony_ci#include "ir/expressions/literals/bigIntLiteral.h"
343af6ab5fSopenharmony_ci#include "ir/expressions/literals/numberLiteral.h"
353af6ab5fSopenharmony_ci#include "ir/expressions/literals/stringLiteral.h"
363af6ab5fSopenharmony_ci#include "ir/expressions/objectExpression.h"
373af6ab5fSopenharmony_ci#include "ir/expressions/superExpression.h"
383af6ab5fSopenharmony_ci#include "ir/module/exportNamedDeclaration.h"
393af6ab5fSopenharmony_ci#include "ir/module/exportSpecifier.h"
403af6ab5fSopenharmony_ci#include "ir/statements/blockStatement.h"
413af6ab5fSopenharmony_ci#include "ir/statements/expressionStatement.h"
423af6ab5fSopenharmony_ci#include "ir/statements/functionDeclaration.h"
433af6ab5fSopenharmony_ci#include "lexer/lexer.h"
443af6ab5fSopenharmony_ci#include "lexer/token/letters.h"
453af6ab5fSopenharmony_ci#include "lexer/token/sourceLocation.h"
463af6ab5fSopenharmony_ci
473af6ab5fSopenharmony_ciusing namespace std::literals::string_literals;
483af6ab5fSopenharmony_ci
493af6ab5fSopenharmony_cinamespace ark::es2panda::parser {
503af6ab5fSopenharmony_ciParserImpl::ParserImpl(Program *program, const CompilerOptions &options, ParserStatus status)
513af6ab5fSopenharmony_ci    : program_(program), context_(program_, status), options_(options)
523af6ab5fSopenharmony_ci{
533af6ab5fSopenharmony_ci}
543af6ab5fSopenharmony_ci
553af6ab5fSopenharmony_cistd::unique_ptr<lexer::Lexer> ParserImpl::InitLexer(const SourceFile &sourceFile)
563af6ab5fSopenharmony_ci{
573af6ab5fSopenharmony_ci    program_->SetSource(sourceFile);
583af6ab5fSopenharmony_ci    std::unique_ptr<lexer::Lexer> lexer = std::make_unique<lexer::Lexer>(&context_);
593af6ab5fSopenharmony_ci    lexer_ = lexer.get();
603af6ab5fSopenharmony_ci    return lexer;
613af6ab5fSopenharmony_ci}
623af6ab5fSopenharmony_ci
633af6ab5fSopenharmony_civoid ParserImpl::ParseScript(const SourceFile &sourceFile, bool genStdLib)
643af6ab5fSopenharmony_ci{
653af6ab5fSopenharmony_ci    auto lexer = InitLexer(sourceFile);
663af6ab5fSopenharmony_ci
673af6ab5fSopenharmony_ci    if (sourceFile.isModule) {
683af6ab5fSopenharmony_ci        context_.Status() |= (ParserStatus::MODULE);
693af6ab5fSopenharmony_ci        ParseProgram(ScriptKind::MODULE);
703af6ab5fSopenharmony_ci    } else if (genStdLib) {
713af6ab5fSopenharmony_ci        ParseProgram(ScriptKind::STDLIB);
723af6ab5fSopenharmony_ci    } else {
733af6ab5fSopenharmony_ci        ParseProgram(ScriptKind::SCRIPT);
743af6ab5fSopenharmony_ci    }
753af6ab5fSopenharmony_ci}
763af6ab5fSopenharmony_ci
773af6ab5fSopenharmony_civoid ParserImpl::ParseProgram(ScriptKind kind)
783af6ab5fSopenharmony_ci{
793af6ab5fSopenharmony_ci    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
803af6ab5fSopenharmony_ci    lexer_->NextToken();
813af6ab5fSopenharmony_ci    program_->SetKind(kind);
823af6ab5fSopenharmony_ci
833af6ab5fSopenharmony_ci    auto statements = ParseStatementList(StatementParsingFlags::STMT_GLOBAL_LEXICAL);
843af6ab5fSopenharmony_ci
853af6ab5fSopenharmony_ci    auto *blockStmt = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
863af6ab5fSopenharmony_ci    blockStmt->SetRange({startLoc, lexer_->GetToken().End()});
873af6ab5fSopenharmony_ci
883af6ab5fSopenharmony_ci    program_->SetAst(blockStmt);
893af6ab5fSopenharmony_ci    program_->SetDeclarationModuleInfo();
903af6ab5fSopenharmony_ci}
913af6ab5fSopenharmony_ci
923af6ab5fSopenharmony_cibool ParserImpl::InAmbientContext()
933af6ab5fSopenharmony_ci{
943af6ab5fSopenharmony_ci    return (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT) != 0;
953af6ab5fSopenharmony_ci}
963af6ab5fSopenharmony_ci
973af6ab5fSopenharmony_ciExpressionParseFlags ParserImpl::CarryExpressionParserFlag(ExpressionParseFlags origin, ExpressionParseFlags carry)
983af6ab5fSopenharmony_ci{
993af6ab5fSopenharmony_ci    return static_cast<ExpressionParseFlags>(origin & carry);
1003af6ab5fSopenharmony_ci}
1013af6ab5fSopenharmony_ci
1023af6ab5fSopenharmony_ciExpressionParseFlags ParserImpl::CarryPatternFlags(ExpressionParseFlags flags)
1033af6ab5fSopenharmony_ci{
1043af6ab5fSopenharmony_ci    return CarryExpressionParserFlag(flags, ExpressionParseFlags::POTENTIALLY_IN_PATTERN |
1053af6ab5fSopenharmony_ci                                                ExpressionParseFlags::OBJECT_PATTERN);
1063af6ab5fSopenharmony_ci}
1073af6ab5fSopenharmony_ci
1083af6ab5fSopenharmony_ciir::ModifierFlags ParserImpl::GetAccessability(ir::ModifierFlags modifiers)
1093af6ab5fSopenharmony_ci{
1103af6ab5fSopenharmony_ci    if ((modifiers & ir::ModifierFlags::PUBLIC) != 0) {
1113af6ab5fSopenharmony_ci        return ir::ModifierFlags::PUBLIC;
1123af6ab5fSopenharmony_ci    }
1133af6ab5fSopenharmony_ci
1143af6ab5fSopenharmony_ci    if ((modifiers & ir::ModifierFlags::PRIVATE) != 0) {
1153af6ab5fSopenharmony_ci        return ir::ModifierFlags::PRIVATE;
1163af6ab5fSopenharmony_ci    }
1173af6ab5fSopenharmony_ci
1183af6ab5fSopenharmony_ci    if ((modifiers & ir::ModifierFlags::PROTECTED) != 0) {
1193af6ab5fSopenharmony_ci        return ir::ModifierFlags::PROTECTED;
1203af6ab5fSopenharmony_ci    }
1213af6ab5fSopenharmony_ci
1223af6ab5fSopenharmony_ci    if ((modifiers & ir::ModifierFlags::INTERNAL) != 0) {
1233af6ab5fSopenharmony_ci        return ir::ModifierFlags::INTERNAL;
1243af6ab5fSopenharmony_ci    }
1253af6ab5fSopenharmony_ci
1263af6ab5fSopenharmony_ci    return ir::ModifierFlags::NONE;
1273af6ab5fSopenharmony_ci}
1283af6ab5fSopenharmony_ci
1293af6ab5fSopenharmony_cibool ParserImpl::IsModifierKind(const lexer::Token &token)
1303af6ab5fSopenharmony_ci{
1313af6ab5fSopenharmony_ci    switch (token.KeywordType()) {
1323af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_STATIC:
1333af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_ASYNC:
1343af6ab5fSopenharmony_ci            return true;
1353af6ab5fSopenharmony_ci        default:
1363af6ab5fSopenharmony_ci            break;
1373af6ab5fSopenharmony_ci    }
1383af6ab5fSopenharmony_ci
1393af6ab5fSopenharmony_ci    return false;
1403af6ab5fSopenharmony_ci}
1413af6ab5fSopenharmony_ci
1423af6ab5fSopenharmony_ciir::ModifierFlags ParserImpl::ParseModifiers()
1433af6ab5fSopenharmony_ci{
1443af6ab5fSopenharmony_ci    ir::ModifierFlags resultStatus = ir::ModifierFlags::NONE;
1453af6ab5fSopenharmony_ci    ir::ModifierFlags prevStatus = ir::ModifierFlags::ALL;
1463af6ab5fSopenharmony_ci
1473af6ab5fSopenharmony_ci    while (IsModifierKind(lexer_->GetToken())) {
1483af6ab5fSopenharmony_ci        char32_t nextCp = lexer_->Lookahead();
1493af6ab5fSopenharmony_ci        if (nextCp == lexer::LEX_CHAR_LEFT_PAREN) {
1503af6ab5fSopenharmony_ci            return resultStatus;
1513af6ab5fSopenharmony_ci        }
1523af6ab5fSopenharmony_ci
1533af6ab5fSopenharmony_ci        lexer::TokenFlags tokenFlags = lexer_->GetToken().Flags();
1543af6ab5fSopenharmony_ci        if ((tokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) {
1553af6ab5fSopenharmony_ci            ThrowSyntaxError("Keyword must not contain escaped characters");
1563af6ab5fSopenharmony_ci        }
1573af6ab5fSopenharmony_ci
1583af6ab5fSopenharmony_ci        ir::ModifierFlags actualStatus = ir::ModifierFlags::NONE;
1593af6ab5fSopenharmony_ci        ir::ModifierFlags nextStatus = ir::ModifierFlags::NONE;
1603af6ab5fSopenharmony_ci
1613af6ab5fSopenharmony_ci        switch (lexer_->GetToken().KeywordType()) {
1623af6ab5fSopenharmony_ci            case lexer::TokenType::KEYW_STATIC: {
1633af6ab5fSopenharmony_ci                actualStatus = ir::ModifierFlags::STATIC;
1643af6ab5fSopenharmony_ci                nextStatus = ir::ModifierFlags::ASYNC;
1653af6ab5fSopenharmony_ci                break;
1663af6ab5fSopenharmony_ci            }
1673af6ab5fSopenharmony_ci            case lexer::TokenType::KEYW_ASYNC: {
1683af6ab5fSopenharmony_ci                actualStatus = ir::ModifierFlags::ASYNC;
1693af6ab5fSopenharmony_ci                nextStatus = ir::ModifierFlags::NONE;
1703af6ab5fSopenharmony_ci                break;
1713af6ab5fSopenharmony_ci            }
1723af6ab5fSopenharmony_ci            default: {
1733af6ab5fSopenharmony_ci                break;
1743af6ab5fSopenharmony_ci            }
1753af6ab5fSopenharmony_ci        }
1763af6ab5fSopenharmony_ci
1773af6ab5fSopenharmony_ci        if (lexer_->Lookahead() == lexer::LEX_CHAR_COLON || lexer_->Lookahead() == lexer::LEX_CHAR_COMMA ||
1783af6ab5fSopenharmony_ci            lexer_->Lookahead() == lexer::LEX_CHAR_RIGHT_PAREN || lexer_->Lookahead() == lexer::LEX_CHAR_QUESTION ||
1793af6ab5fSopenharmony_ci            lexer_->Lookahead() == lexer::LEX_CHAR_RIGHT_BRACE || lexer_->Lookahead() == lexer::LEX_CHAR_LESS_THAN) {
1803af6ab5fSopenharmony_ci            break;
1813af6ab5fSopenharmony_ci        }
1823af6ab5fSopenharmony_ci
1833af6ab5fSopenharmony_ci        auto pos = lexer_->Save();
1843af6ab5fSopenharmony_ci        lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
1853af6ab5fSopenharmony_ci
1863af6ab5fSopenharmony_ci        if ((prevStatus & actualStatus) == 0) {
1873af6ab5fSopenharmony_ci            lexer_->Rewind(pos);
1883af6ab5fSopenharmony_ci            ThrowSyntaxError("Unexpected modifier");
1893af6ab5fSopenharmony_ci        }
1903af6ab5fSopenharmony_ci
1913af6ab5fSopenharmony_ci        if ((resultStatus & actualStatus) != 0) {
1923af6ab5fSopenharmony_ci            lexer_->Rewind(pos);
1933af6ab5fSopenharmony_ci            ThrowSyntaxError("Duplicated modifier is not allowed");
1943af6ab5fSopenharmony_ci        }
1953af6ab5fSopenharmony_ci
1963af6ab5fSopenharmony_ci        resultStatus |= actualStatus;
1973af6ab5fSopenharmony_ci        prevStatus = nextStatus;
1983af6ab5fSopenharmony_ci    }
1993af6ab5fSopenharmony_ci
2003af6ab5fSopenharmony_ci    return resultStatus;
2013af6ab5fSopenharmony_ci}
2023af6ab5fSopenharmony_ci
2033af6ab5fSopenharmony_civoid ParserImpl::CheckAccessorPair(const ArenaVector<ir::AstNode *> &properties, const ir::Expression *propName,
2043af6ab5fSopenharmony_ci                                   ir::MethodDefinitionKind methodKind, ir::ModifierFlags access)
2053af6ab5fSopenharmony_ci{
2063af6ab5fSopenharmony_ci    for (const auto &it : properties) {
2073af6ab5fSopenharmony_ci        if (!it->IsMethodDefinition() || it->AsMethodDefinition()->Kind() != methodKind) {
2083af6ab5fSopenharmony_ci            continue;
2093af6ab5fSopenharmony_ci        }
2103af6ab5fSopenharmony_ci
2113af6ab5fSopenharmony_ci        const ir::Expression *key = it->AsMethodDefinition()->Key();
2123af6ab5fSopenharmony_ci
2133af6ab5fSopenharmony_ci        if (key->Type() != propName->Type()) {
2143af6ab5fSopenharmony_ci            continue;
2153af6ab5fSopenharmony_ci        }
2163af6ab5fSopenharmony_ci
2173af6ab5fSopenharmony_ci        bool keyIsSame = false;
2183af6ab5fSopenharmony_ci
2193af6ab5fSopenharmony_ci        if (key->IsIdentifier()) {
2203af6ab5fSopenharmony_ci            const util::StringView &strName = propName->AsIdentifier()->Name();
2213af6ab5fSopenharmony_ci            const util::StringView &compareName = (key->AsIdentifier()->Name());
2223af6ab5fSopenharmony_ci
2233af6ab5fSopenharmony_ci            keyIsSame = strName == compareName;
2243af6ab5fSopenharmony_ci        } else if (key->IsNumberLiteral()) {
2253af6ab5fSopenharmony_ci            keyIsSame =
2263af6ab5fSopenharmony_ci                key->AsNumberLiteral()->Number().GetDouble() == propName->AsNumberLiteral()->Number().GetDouble();
2273af6ab5fSopenharmony_ci        } else if (key->IsStringLiteral()) {
2283af6ab5fSopenharmony_ci            keyIsSame = *key->AsStringLiteral() == *propName->AsStringLiteral();
2293af6ab5fSopenharmony_ci        }
2303af6ab5fSopenharmony_ci
2313af6ab5fSopenharmony_ci        if (!keyIsSame) {
2323af6ab5fSopenharmony_ci            continue;
2333af6ab5fSopenharmony_ci        }
2343af6ab5fSopenharmony_ci
2353af6ab5fSopenharmony_ci        ir::ModifierFlags getAccess;
2363af6ab5fSopenharmony_ci        ir::ModifierFlags setAccess;
2373af6ab5fSopenharmony_ci
2383af6ab5fSopenharmony_ci        if (methodKind == ir::MethodDefinitionKind::GET) {
2393af6ab5fSopenharmony_ci            setAccess = access;
2403af6ab5fSopenharmony_ci            getAccess = GetAccessability(it->Modifiers());
2413af6ab5fSopenharmony_ci        } else {
2423af6ab5fSopenharmony_ci            getAccess = access;
2433af6ab5fSopenharmony_ci            setAccess = GetAccessability(it->Modifiers());
2443af6ab5fSopenharmony_ci        }
2453af6ab5fSopenharmony_ci
2463af6ab5fSopenharmony_ci        if ((setAccess == ir::ModifierFlags::NONE && getAccess > ir::ModifierFlags::PUBLIC) ||
2473af6ab5fSopenharmony_ci            (setAccess != ir::ModifierFlags::NONE && getAccess > setAccess)) {
2483af6ab5fSopenharmony_ci            ThrowSyntaxError("A get accessor must be at least as accessible as the setter", key->Start());
2493af6ab5fSopenharmony_ci        }
2503af6ab5fSopenharmony_ci    }
2513af6ab5fSopenharmony_ci}
2523af6ab5fSopenharmony_ci
2533af6ab5fSopenharmony_civoid ParserImpl::ParseClassAccessor(ClassElementDescriptor *desc, char32_t *nextCp)
2543af6ab5fSopenharmony_ci{
2553af6ab5fSopenharmony_ci    ConsumeClassPrivateIdentifier(desc, nextCp);
2563af6ab5fSopenharmony_ci
2573af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2583af6ab5fSopenharmony_ci        return;
2593af6ab5fSopenharmony_ci    }
2603af6ab5fSopenharmony_ci
2613af6ab5fSopenharmony_ci    auto keywordType = lexer_->GetToken().KeywordType();
2623af6ab5fSopenharmony_ci    if ((keywordType != lexer::TokenType::KEYW_GET && keywordType != lexer::TokenType::KEYW_SET) ||
2633af6ab5fSopenharmony_ci        (*nextCp == lexer::LEX_CHAR_EQUALS || *nextCp == lexer::LEX_CHAR_SEMICOLON ||
2643af6ab5fSopenharmony_ci         *nextCp == lexer::LEX_CHAR_LEFT_PAREN || *nextCp == lexer::LEX_CHAR_COLON ||
2653af6ab5fSopenharmony_ci         *nextCp == lexer::LEX_CHAR_LESS_THAN)) {
2663af6ab5fSopenharmony_ci        return;
2673af6ab5fSopenharmony_ci    }
2683af6ab5fSopenharmony_ci
2693af6ab5fSopenharmony_ci    ThrowIfPrivateIdent(desc, "Unexpected identifier");
2703af6ab5fSopenharmony_ci
2713af6ab5fSopenharmony_ci    if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0) {
2723af6ab5fSopenharmony_ci        ThrowSyntaxError("Keyword must not contain escaped characters");
2733af6ab5fSopenharmony_ci    }
2743af6ab5fSopenharmony_ci
2753af6ab5fSopenharmony_ci    desc->methodKind =
2763af6ab5fSopenharmony_ci        keywordType == lexer::TokenType::KEYW_GET ? ir::MethodDefinitionKind::GET : ir::MethodDefinitionKind::SET;
2773af6ab5fSopenharmony_ci    desc->methodStart = lexer_->GetToken().Start();
2783af6ab5fSopenharmony_ci
2793af6ab5fSopenharmony_ci    lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
2803af6ab5fSopenharmony_ci    ConsumeClassPrivateIdentifier(desc, nextCp);
2813af6ab5fSopenharmony_ci}
2823af6ab5fSopenharmony_ci
2833af6ab5fSopenharmony_civoid ParserImpl::ThrowIfPrivateIdent(ClassElementDescriptor *desc, const char *msg)
2843af6ab5fSopenharmony_ci{
2853af6ab5fSopenharmony_ci    if (desc->isPrivateIdent) {
2863af6ab5fSopenharmony_ci        ThrowSyntaxError(msg);
2873af6ab5fSopenharmony_ci    }
2883af6ab5fSopenharmony_ci}
2893af6ab5fSopenharmony_ci
2903af6ab5fSopenharmony_civoid ParserImpl::ThrowErrorIfStaticConstructor([[maybe_unused]] ir::ModifierFlags flags) {}
2913af6ab5fSopenharmony_ci
2923af6ab5fSopenharmony_civoid ParserImpl::ValidateClassKey(ClassElementDescriptor *desc)
2933af6ab5fSopenharmony_ci{
2943af6ab5fSopenharmony_ci    if (((desc->modifiers & ir::ModifierFlags::ASYNC) != 0 || desc->isGenerator) &&
2953af6ab5fSopenharmony_ci        (desc->methodKind == ir::MethodDefinitionKind::GET || desc->methodKind == ir::MethodDefinitionKind::SET)) {
2963af6ab5fSopenharmony_ci        ThrowSyntaxError("Invalid accessor");
2973af6ab5fSopenharmony_ci    }
2983af6ab5fSopenharmony_ci
2993af6ab5fSopenharmony_ci    const util::StringView &propNameStr = lexer_->GetToken().Ident();
3003af6ab5fSopenharmony_ci
3013af6ab5fSopenharmony_ci    if (propNameStr.Is("constructor")) {
3023af6ab5fSopenharmony_ci        if (lexer_->Lookahead() != lexer::LEX_CHAR_LEFT_PAREN) {
3033af6ab5fSopenharmony_ci            ThrowSyntaxError("Classes may not have a field named 'constructor'");
3043af6ab5fSopenharmony_ci        }
3053af6ab5fSopenharmony_ci
3063af6ab5fSopenharmony_ci        ThrowIfPrivateIdent(desc, "Private identifier can not be constructor");
3073af6ab5fSopenharmony_ci
3083af6ab5fSopenharmony_ci        if ((desc->modifiers & ir::ModifierFlags::STATIC) == 0) {
3093af6ab5fSopenharmony_ci            if ((desc->modifiers & ir::ModifierFlags::ASYNC) != 0 ||
3103af6ab5fSopenharmony_ci                desc->methodKind == ir::MethodDefinitionKind::GET ||
3113af6ab5fSopenharmony_ci                desc->methodKind == ir::MethodDefinitionKind::SET || desc->isGenerator) {
3123af6ab5fSopenharmony_ci                ThrowSyntaxError("Constructor can not be special method");
3133af6ab5fSopenharmony_ci            }
3143af6ab5fSopenharmony_ci
3153af6ab5fSopenharmony_ci            desc->methodKind = ir::MethodDefinitionKind::CONSTRUCTOR;
3163af6ab5fSopenharmony_ci            desc->methodStart = lexer_->GetToken().Start();
3173af6ab5fSopenharmony_ci            desc->newStatus |= ParserStatus::CONSTRUCTOR_FUNCTION;
3183af6ab5fSopenharmony_ci
3193af6ab5fSopenharmony_ci            if (desc->hasSuperClass) {
3203af6ab5fSopenharmony_ci                desc->newStatus |= ParserStatus::ALLOW_SUPER_CALL;
3213af6ab5fSopenharmony_ci            }
3223af6ab5fSopenharmony_ci        }
3233af6ab5fSopenharmony_ci
3243af6ab5fSopenharmony_ci        ThrowErrorIfStaticConstructor(desc->modifiers);
3253af6ab5fSopenharmony_ci    } else if (propNameStr.Is("prototype") && (desc->modifiers & ir::ModifierFlags::STATIC) != 0) {
3263af6ab5fSopenharmony_ci        ThrowSyntaxError("Classes may not have static property named prototype");
3273af6ab5fSopenharmony_ci    }
3283af6ab5fSopenharmony_ci}
3293af6ab5fSopenharmony_ci
3303af6ab5fSopenharmony_cistd::tuple<bool, bool, bool> ParserImpl::ParseComputedClassFieldOrIndexSignature(ir::Expression **propName)
3313af6ab5fSopenharmony_ci{
3323af6ab5fSopenharmony_ci    lexer_->NextToken();  // eat left square bracket
3333af6ab5fSopenharmony_ci
3343af6ab5fSopenharmony_ci    *propName = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
3353af6ab5fSopenharmony_ci
3363af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
3373af6ab5fSopenharmony_ci        ThrowSyntaxError("Unexpected token, expected ']'");
3383af6ab5fSopenharmony_ci    }
3393af6ab5fSopenharmony_ci
3403af6ab5fSopenharmony_ci    return {true, false, false};
3413af6ab5fSopenharmony_ci}
3423af6ab5fSopenharmony_ci
3433af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParseClassKey(ClassElementDescriptor *desc)
3443af6ab5fSopenharmony_ci{
3453af6ab5fSopenharmony_ci    ir::Expression *propName = nullptr;
3463af6ab5fSopenharmony_ci    if (lexer_->GetToken().IsKeyword()) {
3473af6ab5fSopenharmony_ci        lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
3483af6ab5fSopenharmony_ci    }
3493af6ab5fSopenharmony_ci
3503af6ab5fSopenharmony_ci    switch (lexer_->GetToken().Type()) {
3513af6ab5fSopenharmony_ci        case lexer::TokenType::LITERAL_IDENT: {
3523af6ab5fSopenharmony_ci            ValidateClassKey(desc);
3533af6ab5fSopenharmony_ci
3543af6ab5fSopenharmony_ci            propName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
3553af6ab5fSopenharmony_ci            propName->SetRange(lexer_->GetToken().Loc());
3563af6ab5fSopenharmony_ci            propName->AsIdentifier()->SetPrivate(desc->isPrivateIdent);
3573af6ab5fSopenharmony_ci            break;
3583af6ab5fSopenharmony_ci        }
3593af6ab5fSopenharmony_ci        case lexer::TokenType::LITERAL_STRING: {
3603af6ab5fSopenharmony_ci            ThrowIfPrivateIdent(desc, "Private identifier name can not be string");
3613af6ab5fSopenharmony_ci
3623af6ab5fSopenharmony_ci            if (lexer_->GetToken().Ident().Is("constructor")) {
3633af6ab5fSopenharmony_ci                ThrowSyntaxError("Classes may not have a field named 'constructor'");
3643af6ab5fSopenharmony_ci            }
3653af6ab5fSopenharmony_ci
3663af6ab5fSopenharmony_ci            if (lexer_->GetToken().Ident().Is("prototype") && (desc->modifiers & ir::ModifierFlags::STATIC) != 0) {
3673af6ab5fSopenharmony_ci                ThrowSyntaxError("Classes may not have a static property named 'prototype'");
3683af6ab5fSopenharmony_ci            }
3693af6ab5fSopenharmony_ci
3703af6ab5fSopenharmony_ci            propName = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
3713af6ab5fSopenharmony_ci            propName->SetRange(lexer_->GetToken().Loc());
3723af6ab5fSopenharmony_ci            break;
3733af6ab5fSopenharmony_ci        }
3743af6ab5fSopenharmony_ci        case lexer::TokenType::LITERAL_NUMBER: {
3753af6ab5fSopenharmony_ci            ThrowIfPrivateIdent(desc, "Private identifier name can not be number");
3763af6ab5fSopenharmony_ci
3773af6ab5fSopenharmony_ci            if ((lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) != 0) {
3783af6ab5fSopenharmony_ci                propName = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
3793af6ab5fSopenharmony_ci            } else {
3803af6ab5fSopenharmony_ci                propName = AllocNode<ir::NumberLiteral>(lexer_->GetToken().GetNumber());
3813af6ab5fSopenharmony_ci            }
3823af6ab5fSopenharmony_ci
3833af6ab5fSopenharmony_ci            propName->SetRange(lexer_->GetToken().Loc());
3843af6ab5fSopenharmony_ci            break;
3853af6ab5fSopenharmony_ci        }
3863af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
3873af6ab5fSopenharmony_ci            ThrowIfPrivateIdent(desc, "Unexpected character in private identifier");
3883af6ab5fSopenharmony_ci            std::tie(desc->isComputed, desc->invalidComputedProperty, desc->isIndexSignature) =
3893af6ab5fSopenharmony_ci                ParseComputedClassFieldOrIndexSignature(&propName);
3903af6ab5fSopenharmony_ci            break;
3913af6ab5fSopenharmony_ci        }
3923af6ab5fSopenharmony_ci        default: {
3933af6ab5fSopenharmony_ci            ThrowSyntaxError("Unexpected token in class property");
3943af6ab5fSopenharmony_ci        }
3953af6ab5fSopenharmony_ci    }
3963af6ab5fSopenharmony_ci
3973af6ab5fSopenharmony_ci    lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
3983af6ab5fSopenharmony_ci
3993af6ab5fSopenharmony_ci    return propName;
4003af6ab5fSopenharmony_ci}
4013af6ab5fSopenharmony_ci
4023af6ab5fSopenharmony_civoid ParserImpl::ValidateClassMethodStart(ClassElementDescriptor *desc, [[maybe_unused]] ir::TypeNode *typeAnnotation)
4033af6ab5fSopenharmony_ci{
4043af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
4053af6ab5fSopenharmony_ci        return;
4063af6ab5fSopenharmony_ci    }
4073af6ab5fSopenharmony_ci    desc->classMethod = true;
4083af6ab5fSopenharmony_ci
4093af6ab5fSopenharmony_ci    if ((desc->modifiers & ir::ModifierFlags::ASYNC) != 0) {
4103af6ab5fSopenharmony_ci        desc->newStatus |= ParserStatus::ASYNC_FUNCTION;
4113af6ab5fSopenharmony_ci    }
4123af6ab5fSopenharmony_ci
4133af6ab5fSopenharmony_ci    if (desc->isGenerator) {
4143af6ab5fSopenharmony_ci        desc->newStatus |= ParserStatus::GENERATOR_FUNCTION;
4153af6ab5fSopenharmony_ci    }
4163af6ab5fSopenharmony_ci}
4173af6ab5fSopenharmony_ci
4183af6ab5fSopenharmony_civoid ParserImpl::ValidateClassSetter([[maybe_unused]] ClassElementDescriptor *desc,
4193af6ab5fSopenharmony_ci                                     [[maybe_unused]] const ArenaVector<ir::AstNode *> &properties,
4203af6ab5fSopenharmony_ci                                     [[maybe_unused]] ir::Expression *propName, ir::ScriptFunction *func)
4213af6ab5fSopenharmony_ci{
4223af6ab5fSopenharmony_ci    if (func->Params().size() != 1) {
4233af6ab5fSopenharmony_ci        ThrowSyntaxError("Setter must have exactly one formal parameter");
4243af6ab5fSopenharmony_ci    }
4253af6ab5fSopenharmony_ci}
4263af6ab5fSopenharmony_ci
4273af6ab5fSopenharmony_civoid ParserImpl::ValidateClassGetter([[maybe_unused]] ClassElementDescriptor *desc,
4283af6ab5fSopenharmony_ci                                     [[maybe_unused]] const ArenaVector<ir::AstNode *> &properties,
4293af6ab5fSopenharmony_ci                                     [[maybe_unused]] ir::Expression *propName, ir::ScriptFunction *func)
4303af6ab5fSopenharmony_ci{
4313af6ab5fSopenharmony_ci    if (!func->Params().empty()) {
4323af6ab5fSopenharmony_ci        ThrowSyntaxError("Getter must not have formal parameters");
4333af6ab5fSopenharmony_ci    }
4343af6ab5fSopenharmony_ci}
4353af6ab5fSopenharmony_ci
4363af6ab5fSopenharmony_ciir::MethodDefinition *ParserImpl::ParseClassMethod(ClassElementDescriptor *desc,
4373af6ab5fSopenharmony_ci                                                   const ArenaVector<ir::AstNode *> &properties,
4383af6ab5fSopenharmony_ci                                                   ir::Expression *propName, lexer::SourcePosition *propEnd)
4393af6ab5fSopenharmony_ci{
4403af6ab5fSopenharmony_ci    if (desc->methodKind != ir::MethodDefinitionKind::SET &&
4413af6ab5fSopenharmony_ci        (desc->newStatus & ParserStatus::CONSTRUCTOR_FUNCTION) == 0) {
4423af6ab5fSopenharmony_ci        desc->newStatus |= ParserStatus::NEED_RETURN_TYPE;
4433af6ab5fSopenharmony_ci    }
4443af6ab5fSopenharmony_ci
4453af6ab5fSopenharmony_ci    ir::ScriptFunction *func = ParseFunction(desc->newStatus);
4463af6ab5fSopenharmony_ci
4473af6ab5fSopenharmony_ci    auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
4483af6ab5fSopenharmony_ci    funcExpr->SetRange(func->Range());
4493af6ab5fSopenharmony_ci
4503af6ab5fSopenharmony_ci    if (desc->methodKind == ir::MethodDefinitionKind::SET) {
4513af6ab5fSopenharmony_ci        ValidateClassSetter(desc, properties, propName, func);
4523af6ab5fSopenharmony_ci    } else if (desc->methodKind == ir::MethodDefinitionKind::GET) {
4533af6ab5fSopenharmony_ci        ValidateClassGetter(desc, properties, propName, func);
4543af6ab5fSopenharmony_ci    }
4553af6ab5fSopenharmony_ci
4563af6ab5fSopenharmony_ci    *propEnd = func->End();
4573af6ab5fSopenharmony_ci    func->AddFlag(ir::ScriptFunctionFlags::METHOD);
4583af6ab5fSopenharmony_ci
4593af6ab5fSopenharmony_ci    auto *ident = !propName->IsArrowFunctionExpression() && !propName->IsFunctionExpression()
4603af6ab5fSopenharmony_ci                      ? propName->Clone(Allocator(), nullptr)->AsExpression()
4613af6ab5fSopenharmony_ci                      : propName;
4623af6ab5fSopenharmony_ci    auto *method = AllocNode<ir::MethodDefinition>(desc->methodKind, ident, funcExpr, desc->modifiers, Allocator(),
4633af6ab5fSopenharmony_ci                                                   desc->isComputed);
4643af6ab5fSopenharmony_ci    method->SetRange(funcExpr->Range());
4653af6ab5fSopenharmony_ci
4663af6ab5fSopenharmony_ci    return method;
4673af6ab5fSopenharmony_ci}
4683af6ab5fSopenharmony_ci
4693af6ab5fSopenharmony_ciir::ClassElement *ParserImpl::ParseClassProperty(ClassElementDescriptor *desc,
4703af6ab5fSopenharmony_ci                                                 const ArenaVector<ir::AstNode *> &properties, ir::Expression *propName,
4713af6ab5fSopenharmony_ci                                                 ir::TypeNode *typeAnnotation)
4723af6ab5fSopenharmony_ci{
4733af6ab5fSopenharmony_ci    lexer::SourcePosition propEnd = propName->End();
4743af6ab5fSopenharmony_ci    ir::ClassElement *property = nullptr;
4753af6ab5fSopenharmony_ci
4763af6ab5fSopenharmony_ci    if (desc->classMethod) {
4773af6ab5fSopenharmony_ci        if ((desc->modifiers & ir::ModifierFlags::DECLARE) != 0) {
4783af6ab5fSopenharmony_ci            ThrowSyntaxError("'declare modifier cannot appear on class elements of this kind.");
4793af6ab5fSopenharmony_ci        }
4803af6ab5fSopenharmony_ci
4813af6ab5fSopenharmony_ci        property = ParseClassMethod(desc, properties, propName, &propEnd);
4823af6ab5fSopenharmony_ci        property->SetRange({desc->propStart, propEnd});
4833af6ab5fSopenharmony_ci        return property;
4843af6ab5fSopenharmony_ci    }
4853af6ab5fSopenharmony_ci
4863af6ab5fSopenharmony_ci    ir::Expression *value = nullptr;
4873af6ab5fSopenharmony_ci
4883af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
4893af6ab5fSopenharmony_ci        lexer_->NextToken();  // eat equals
4903af6ab5fSopenharmony_ci
4913af6ab5fSopenharmony_ci        if (InAmbientContext() || (desc->modifiers & ir::ModifierFlags::DECLARE) != 0) {
4923af6ab5fSopenharmony_ci            ThrowSyntaxError("Initializers are not allowed in ambient contexts.");
4933af6ab5fSopenharmony_ci        }
4943af6ab5fSopenharmony_ci
4953af6ab5fSopenharmony_ci        value = ParseExpression();
4963af6ab5fSopenharmony_ci        propEnd = value->End();
4973af6ab5fSopenharmony_ci    }
4983af6ab5fSopenharmony_ci
4993af6ab5fSopenharmony_ci    property =
5003af6ab5fSopenharmony_ci        AllocNode<ir::ClassProperty>(propName, value, typeAnnotation, desc->modifiers, Allocator(), desc->isComputed);
5013af6ab5fSopenharmony_ci
5023af6ab5fSopenharmony_ci    property->SetRange({desc->propStart, propEnd});
5033af6ab5fSopenharmony_ci
5043af6ab5fSopenharmony_ci    return property;
5053af6ab5fSopenharmony_ci}
5063af6ab5fSopenharmony_ci
5073af6ab5fSopenharmony_civoid ParserImpl::CheckClassGeneratorMethod(ClassElementDescriptor *desc, char32_t *nextCp)
5083af6ab5fSopenharmony_ci{
5093af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_MULTIPLY) {
5103af6ab5fSopenharmony_ci        return;
5113af6ab5fSopenharmony_ci    }
5123af6ab5fSopenharmony_ci
5133af6ab5fSopenharmony_ci    desc->isGenerator = true;
5143af6ab5fSopenharmony_ci    lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
5153af6ab5fSopenharmony_ci    *nextCp = lexer_->Lookahead();
5163af6ab5fSopenharmony_ci}
5173af6ab5fSopenharmony_ci
5183af6ab5fSopenharmony_civoid ParserImpl::ValidatePrivateIdentifier()
5193af6ab5fSopenharmony_ci{
5203af6ab5fSopenharmony_ci    size_t iterIdx = lexer_->GetToken().Start().index;
5213af6ab5fSopenharmony_ci    lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
5223af6ab5fSopenharmony_ci
5233af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT ||
5243af6ab5fSopenharmony_ci        (lexer_->GetToken().Start().index - iterIdx > 1)) {
5253af6ab5fSopenharmony_ci        ThrowSyntaxError("Unexpected token in private field");
5263af6ab5fSopenharmony_ci    }
5273af6ab5fSopenharmony_ci}
5283af6ab5fSopenharmony_ci
5293af6ab5fSopenharmony_civoid ParserImpl::ConsumeClassPrivateIdentifier(ClassElementDescriptor *desc, char32_t *nextCp)
5303af6ab5fSopenharmony_ci{
5313af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_HASH_MARK) {
5323af6ab5fSopenharmony_ci        return;
5333af6ab5fSopenharmony_ci    }
5343af6ab5fSopenharmony_ci
5353af6ab5fSopenharmony_ci    desc->isPrivateIdent = true;
5363af6ab5fSopenharmony_ci    ValidatePrivateIdentifier();
5373af6ab5fSopenharmony_ci    *nextCp = lexer_->Lookahead();
5383af6ab5fSopenharmony_ci}
5393af6ab5fSopenharmony_ci
5403af6ab5fSopenharmony_civoid ParserImpl::AddPrivateElement(const ir::ClassElement *elem)
5413af6ab5fSopenharmony_ci{
5423af6ab5fSopenharmony_ci    if (!classPrivateContext_.AddElement(elem)) {
5433af6ab5fSopenharmony_ci        ThrowSyntaxError("Private field has already been declared");
5443af6ab5fSopenharmony_ci    }
5453af6ab5fSopenharmony_ci}
5463af6ab5fSopenharmony_ci
5473af6ab5fSopenharmony_ciir::ClassElement *ParserImpl::ParseClassStaticBlock()
5483af6ab5fSopenharmony_ci{
5493af6ab5fSopenharmony_ci    const lexer::SourcePosition &startPos = lexer_->GetToken().Start();
5503af6ab5fSopenharmony_ci
5513af6ab5fSopenharmony_ci    lexer_->NextToken();  // eat 'static'
5523af6ab5fSopenharmony_ci
5533af6ab5fSopenharmony_ci    SavedParserContext context(this, ParserStatus::ALLOW_SUPER);
5543af6ab5fSopenharmony_ci    context_.Status() &= ~(ParserStatus::ASYNC_FUNCTION | ParserStatus::GENERATOR_FUNCTION);
5553af6ab5fSopenharmony_ci
5563af6ab5fSopenharmony_ci    lexer_->NextToken();  // eat '{'
5573af6ab5fSopenharmony_ci
5583af6ab5fSopenharmony_ci    ArenaVector<ir::Expression *> params(Allocator()->Adapter());
5593af6ab5fSopenharmony_ci
5603af6ab5fSopenharmony_ci    ArenaVector<ir::Statement *> statements = ParseStatementList();
5613af6ab5fSopenharmony_ci
5623af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
5633af6ab5fSopenharmony_ci        ThrowSyntaxError("Expected a '}'");
5643af6ab5fSopenharmony_ci    }
5653af6ab5fSopenharmony_ci
5663af6ab5fSopenharmony_ci    auto *body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
5673af6ab5fSopenharmony_ci    // clang-format off
5683af6ab5fSopenharmony_ci    auto *func = AllocNode<ir::ScriptFunction>(
5693af6ab5fSopenharmony_ci        Allocator(), ir::ScriptFunction::ScriptFunctionData {
5703af6ab5fSopenharmony_ci            body, ir::FunctionSignature(nullptr, std::move(params), nullptr),
5713af6ab5fSopenharmony_ci            ir::ScriptFunctionFlags::EXPRESSION | ir::ScriptFunctionFlags::STATIC_BLOCK,
5723af6ab5fSopenharmony_ci            ir::ModifierFlags::STATIC, false, context_.GetLanguage()});
5733af6ab5fSopenharmony_ci    // clang-format on
5743af6ab5fSopenharmony_ci
5753af6ab5fSopenharmony_ci    auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
5763af6ab5fSopenharmony_ci    auto *staticBlock = AllocNode<ir::ClassStaticBlock>(funcExpr, Allocator());
5773af6ab5fSopenharmony_ci    staticBlock->SetRange({startPos, lexer_->GetToken().End()});
5783af6ab5fSopenharmony_ci
5793af6ab5fSopenharmony_ci    lexer_->NextToken();  // eat '}'
5803af6ab5fSopenharmony_ci
5813af6ab5fSopenharmony_ci    return staticBlock;
5823af6ab5fSopenharmony_ci}
5833af6ab5fSopenharmony_ci
5843af6ab5fSopenharmony_ciir::AstNode *ParserImpl::ParseClassElement(const ArenaVector<ir::AstNode *> &properties,
5853af6ab5fSopenharmony_ci                                           ir::ClassDefinitionModifiers modifiers,
5863af6ab5fSopenharmony_ci                                           [[maybe_unused]] ir::ModifierFlags flags)
5873af6ab5fSopenharmony_ci{
5883af6ab5fSopenharmony_ci    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_STATIC &&
5893af6ab5fSopenharmony_ci        lexer_->Lookahead() == lexer::LEX_CHAR_LEFT_BRACE) {
5903af6ab5fSopenharmony_ci        return ParseClassStaticBlock();
5913af6ab5fSopenharmony_ci    }
5923af6ab5fSopenharmony_ci
5933af6ab5fSopenharmony_ci    ClassElementDescriptor desc(Allocator());
5943af6ab5fSopenharmony_ci
5953af6ab5fSopenharmony_ci    desc.methodKind = ir::MethodDefinitionKind::METHOD;
5963af6ab5fSopenharmony_ci    desc.newStatus = ParserStatus::ALLOW_SUPER;
5973af6ab5fSopenharmony_ci    desc.hasSuperClass = (modifiers & ir::ClassDefinitionModifiers::HAS_SUPER) != 0U;
5983af6ab5fSopenharmony_ci    desc.propStart = lexer_->GetToken().Start();
5993af6ab5fSopenharmony_ci    desc.modifiers = ParseModifiers();
6003af6ab5fSopenharmony_ci
6013af6ab5fSopenharmony_ci    char32_t nextCp = lexer_->Lookahead();
6023af6ab5fSopenharmony_ci    CheckClassGeneratorMethod(&desc, &nextCp);
6033af6ab5fSopenharmony_ci    ParseClassAccessor(&desc, &nextCp);
6043af6ab5fSopenharmony_ci
6053af6ab5fSopenharmony_ci    if ((desc.modifiers & ir::ModifierFlags::STATIC) == 0) {
6063af6ab5fSopenharmony_ci        context_.Status() |= ParserStatus::ALLOW_THIS_TYPE;
6073af6ab5fSopenharmony_ci    }
6083af6ab5fSopenharmony_ci
6093af6ab5fSopenharmony_ci    ir::Expression *propName = ParseClassKey(&desc);
6103af6ab5fSopenharmony_ci    ValidateClassMethodStart(&desc, nullptr);
6113af6ab5fSopenharmony_ci    ir::ClassElement *property = ParseClassProperty(&desc, properties, propName, nullptr);
6123af6ab5fSopenharmony_ci
6133af6ab5fSopenharmony_ci    if (property != nullptr && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
6143af6ab5fSopenharmony_ci        lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
6153af6ab5fSopenharmony_ci        (lexer_->GetToken().Flags() & lexer::TokenFlags::NEW_LINE) == 0 &&
6163af6ab5fSopenharmony_ci        !(property->IsMethodDefinition() &&
6173af6ab5fSopenharmony_ci          property->AsMethodDefinition()->Value()->AsFunctionExpression()->Function()->Body() != nullptr)) {
6183af6ab5fSopenharmony_ci        ThrowSyntaxError("';' expected.");
6193af6ab5fSopenharmony_ci    }
6203af6ab5fSopenharmony_ci
6213af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
6223af6ab5fSopenharmony_ci        lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
6233af6ab5fSopenharmony_ci    }
6243af6ab5fSopenharmony_ci
6253af6ab5fSopenharmony_ci    context_.Status() &= ~ParserStatus::ALLOW_THIS_TYPE;
6263af6ab5fSopenharmony_ci
6273af6ab5fSopenharmony_ci    if (desc.isPrivateIdent) {
6283af6ab5fSopenharmony_ci        AddPrivateElement(property);
6293af6ab5fSopenharmony_ci    }
6303af6ab5fSopenharmony_ci
6313af6ab5fSopenharmony_ci    return property;
6323af6ab5fSopenharmony_ci}
6333af6ab5fSopenharmony_ci
6343af6ab5fSopenharmony_ciir::MethodDefinition *ParserImpl::BuildImplicitConstructor(ir::ClassDefinitionModifiers modifiers,
6353af6ab5fSopenharmony_ci                                                           const lexer::SourcePosition &startLoc)
6363af6ab5fSopenharmony_ci{
6373af6ab5fSopenharmony_ci    ArenaVector<ir::Expression *> params(Allocator()->Adapter());
6383af6ab5fSopenharmony_ci    ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
6393af6ab5fSopenharmony_ci
6403af6ab5fSopenharmony_ci    if ((modifiers & ir::ClassDefinitionModifiers::HAS_SUPER) != 0U) {
6413af6ab5fSopenharmony_ci        util::StringView argsStr = "args";
6423af6ab5fSopenharmony_ci        params.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::REST_ELEMENT, Allocator(),
6433af6ab5fSopenharmony_ci                                                      AllocNode<ir::Identifier>(argsStr, Allocator())));
6443af6ab5fSopenharmony_ci        ArenaVector<ir::Expression *> callArgs(Allocator()->Adapter());
6453af6ab5fSopenharmony_ci        auto *superExpr = AllocNode<ir::SuperExpression>();
6463af6ab5fSopenharmony_ci        callArgs.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::SPREAD_ELEMENT, Allocator(),
6473af6ab5fSopenharmony_ci                                                        AllocNode<ir::Identifier>(argsStr, Allocator())));
6483af6ab5fSopenharmony_ci
6493af6ab5fSopenharmony_ci        auto *callExpr = AllocNode<ir::CallExpression>(superExpr, std::move(callArgs), nullptr, false);
6503af6ab5fSopenharmony_ci        statements.push_back(AllocNode<ir::ExpressionStatement>(callExpr));
6513af6ab5fSopenharmony_ci    }
6523af6ab5fSopenharmony_ci
6533af6ab5fSopenharmony_ci    auto *body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
6543af6ab5fSopenharmony_ci    auto *func = AllocNode<ir::ScriptFunction>(
6553af6ab5fSopenharmony_ci        Allocator(), ir::ScriptFunction::ScriptFunctionData {body,
6563af6ab5fSopenharmony_ci                                                             ir::FunctionSignature(nullptr, std::move(params), nullptr),
6573af6ab5fSopenharmony_ci                                                             ir::ScriptFunctionFlags::CONSTRUCTOR |
6583af6ab5fSopenharmony_ci                                                                 ir::ScriptFunctionFlags::IMPLICIT_SUPER_CALL_NEEDED,
6593af6ab5fSopenharmony_ci                                                             {},
6603af6ab5fSopenharmony_ci                                                             false,
6613af6ab5fSopenharmony_ci                                                             context_.GetLanguage()});
6623af6ab5fSopenharmony_ci
6633af6ab5fSopenharmony_ci    auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
6643af6ab5fSopenharmony_ci    auto *key = AllocNode<ir::Identifier>("constructor", Allocator());
6653af6ab5fSopenharmony_ci
6663af6ab5fSopenharmony_ci    if ((modifiers & ir::ClassDefinitionModifiers::SET_CTOR_ID) != 0U) {
6673af6ab5fSopenharmony_ci        func->SetIdent(key->Clone(Allocator(), nullptr));
6683af6ab5fSopenharmony_ci    }
6693af6ab5fSopenharmony_ci
6703af6ab5fSopenharmony_ci    auto *ctor = AllocNode<ir::MethodDefinition>(ir::MethodDefinitionKind::CONSTRUCTOR, key, funcExpr,
6713af6ab5fSopenharmony_ci                                                 ir::ModifierFlags::NONE, Allocator(), false);
6723af6ab5fSopenharmony_ci
6733af6ab5fSopenharmony_ci    ctor->SetRange({startLoc, lexer_->GetToken().End()});
6743af6ab5fSopenharmony_ci
6753af6ab5fSopenharmony_ci    return ctor;
6763af6ab5fSopenharmony_ci}
6773af6ab5fSopenharmony_ci
6783af6ab5fSopenharmony_civoid ParserImpl::CreateImplicitConstructor(ir::MethodDefinition *&ctor,
6793af6ab5fSopenharmony_ci                                           [[maybe_unused]] ArenaVector<ir::AstNode *> &properties,
6803af6ab5fSopenharmony_ci                                           ir::ClassDefinitionModifiers modifiers,
6813af6ab5fSopenharmony_ci                                           const lexer::SourcePosition &startLoc)
6823af6ab5fSopenharmony_ci{
6833af6ab5fSopenharmony_ci    if (ctor != nullptr) {
6843af6ab5fSopenharmony_ci        return;
6853af6ab5fSopenharmony_ci    }
6863af6ab5fSopenharmony_ci
6873af6ab5fSopenharmony_ci    ctor = BuildImplicitConstructor(modifiers, startLoc);
6883af6ab5fSopenharmony_ci}
6893af6ab5fSopenharmony_ci
6903af6ab5fSopenharmony_ciir::Identifier *ParserImpl::ParseClassIdent(ir::ClassDefinitionModifiers modifiers)
6913af6ab5fSopenharmony_ci{
6923af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
6933af6ab5fSopenharmony_ci        return ExpectIdentifier();
6943af6ab5fSopenharmony_ci    }
6953af6ab5fSopenharmony_ci
6963af6ab5fSopenharmony_ci    auto idRequired =
6973af6ab5fSopenharmony_ci        static_cast<ir::ClassDefinitionModifiers>(modifiers & ir::ClassDefinitionModifiers::DECLARATION_ID_REQUIRED);
6983af6ab5fSopenharmony_ci
6993af6ab5fSopenharmony_ci    if (idRequired == ir::ClassDefinitionModifiers::DECLARATION_ID_REQUIRED) {
7003af6ab5fSopenharmony_ci        ThrowSyntaxError("Unexpected token, expected an identifier.");
7013af6ab5fSopenharmony_ci    }
7023af6ab5fSopenharmony_ci
7033af6ab5fSopenharmony_ci    return nullptr;
7043af6ab5fSopenharmony_ci}
7053af6ab5fSopenharmony_ci
7063af6ab5fSopenharmony_cibool ParserImpl::CheckClassElement(ir::AstNode *property, ir::MethodDefinition *&ctor,
7073af6ab5fSopenharmony_ci                                   [[maybe_unused]] ArenaVector<ir::AstNode *> &properties)
7083af6ab5fSopenharmony_ci{
7093af6ab5fSopenharmony_ci    if (!property->IsMethodDefinition()) {
7103af6ab5fSopenharmony_ci        return false;
7113af6ab5fSopenharmony_ci    }
7123af6ab5fSopenharmony_ci
7133af6ab5fSopenharmony_ci    ir::MethodDefinition *def = property->AsMethodDefinition();
7143af6ab5fSopenharmony_ci    if (!def->IsConstructor()) {
7153af6ab5fSopenharmony_ci        return false;
7163af6ab5fSopenharmony_ci    }
7173af6ab5fSopenharmony_ci
7183af6ab5fSopenharmony_ci    if (ctor != nullptr) {
7193af6ab5fSopenharmony_ci        ThrowSyntaxError("Multiple constructor implementations are not allowed.", property->Start());
7203af6ab5fSopenharmony_ci    }
7213af6ab5fSopenharmony_ci    ctor = def;
7223af6ab5fSopenharmony_ci
7233af6ab5fSopenharmony_ci    return true;
7243af6ab5fSopenharmony_ci}
7253af6ab5fSopenharmony_ci
7263af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParseSuperClassReference()
7273af6ab5fSopenharmony_ci{
7283af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
7293af6ab5fSopenharmony_ci        lexer_->NextToken();
7303af6ab5fSopenharmony_ci        return ParseLeftHandSideExpression();
7313af6ab5fSopenharmony_ci    }
7323af6ab5fSopenharmony_ci
7333af6ab5fSopenharmony_ci    return nullptr;
7343af6ab5fSopenharmony_ci}
7353af6ab5fSopenharmony_ci
7363af6ab5fSopenharmony_cistd::tuple<ir::Expression *, ir::TSTypeParameterInstantiation *> ParserImpl::ParseSuperClass()
7373af6ab5fSopenharmony_ci{
7383af6ab5fSopenharmony_ci    return {ParseSuperClassReference(), nullptr};
7393af6ab5fSopenharmony_ci}
7403af6ab5fSopenharmony_ci
7413af6ab5fSopenharmony_ci// NOLINTNEXTLINE(google-default-arguments)
7423af6ab5fSopenharmony_ciir::ClassDefinition *ParserImpl::ParseClassDefinition(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags)
7433af6ab5fSopenharmony_ci{
7443af6ab5fSopenharmony_ci    lexer_->NextToken();
7453af6ab5fSopenharmony_ci
7463af6ab5fSopenharmony_ci    ir::Identifier *identNode = ParseClassIdent(modifiers);
7473af6ab5fSopenharmony_ci
7483af6ab5fSopenharmony_ci    if (identNode == nullptr && (modifiers & ir::ClassDefinitionModifiers::DECLARATION) != 0U) {
7493af6ab5fSopenharmony_ci        ThrowSyntaxError("Unexpected token, expected an identifier.");
7503af6ab5fSopenharmony_ci    }
7513af6ab5fSopenharmony_ci
7523af6ab5fSopenharmony_ci    varbinder::PrivateBinding privateBinding(Allocator(), classId_++);
7533af6ab5fSopenharmony_ci
7543af6ab5fSopenharmony_ci    // Parse SuperClass
7553af6ab5fSopenharmony_ci    auto [superClass, superTypeParams] = ParseSuperClass();
7563af6ab5fSopenharmony_ci
7573af6ab5fSopenharmony_ci    if (superClass != nullptr) {
7583af6ab5fSopenharmony_ci        modifiers |= ir::ClassDefinitionModifiers::HAS_SUPER;
7593af6ab5fSopenharmony_ci    }
7603af6ab5fSopenharmony_ci
7613af6ab5fSopenharmony_ci    ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE, false);
7623af6ab5fSopenharmony_ci
7633af6ab5fSopenharmony_ci    auto [ctor, properties, bodyRange] = ParseClassBody(modifiers, flags);
7643af6ab5fSopenharmony_ci
7653af6ab5fSopenharmony_ci    ArenaVector<ir::TSClassImplements *> implements(Allocator()->Adapter());
7663af6ab5fSopenharmony_ci    auto *classDefinition = AllocNode<ir::ClassDefinition>(
7673af6ab5fSopenharmony_ci        privateBinding.View(), identNode, nullptr, superTypeParams, std::move(implements), ctor, superClass,
7683af6ab5fSopenharmony_ci        std::move(properties), modifiers, flags, GetContext().GetLanguage());
7693af6ab5fSopenharmony_ci
7703af6ab5fSopenharmony_ci    classDefinition->SetRange(bodyRange);
7713af6ab5fSopenharmony_ci
7723af6ab5fSopenharmony_ci    return classDefinition;
7733af6ab5fSopenharmony_ci}
7743af6ab5fSopenharmony_ci
7753af6ab5fSopenharmony_ciParserImpl::ClassBody ParserImpl::ParseClassBody(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags)
7763af6ab5fSopenharmony_ci{
7773af6ab5fSopenharmony_ci    auto savedCtx = SavedStatusContext<ParserStatus::IN_CLASS_BODY>(&context_);
7783af6ab5fSopenharmony_ci
7793af6ab5fSopenharmony_ci    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
7803af6ab5fSopenharmony_ci    lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
7813af6ab5fSopenharmony_ci
7823af6ab5fSopenharmony_ci    ir::MethodDefinition *ctor = nullptr;
7833af6ab5fSopenharmony_ci    ArenaVector<ir::AstNode *> properties(Allocator()->Adapter());
7843af6ab5fSopenharmony_ci
7853af6ab5fSopenharmony_ci    SavedClassPrivateContext classContext(this);
7863af6ab5fSopenharmony_ci
7873af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
7883af6ab5fSopenharmony_ci        lexer_->Lookahead() == static_cast<char32_t>(ARRAY_FORMAT_NODE)) {
7893af6ab5fSopenharmony_ci        properties = std::move(ParseAstNodesArrayFormatPlaceholder());
7903af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
7913af6ab5fSopenharmony_ci            ThrowSyntaxError("Expected a '}'");
7923af6ab5fSopenharmony_ci        }
7933af6ab5fSopenharmony_ci    } else {
7943af6ab5fSopenharmony_ci        while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
7953af6ab5fSopenharmony_ci               lexer_->GetToken().Type() != lexer::TokenType::EOS) {
7963af6ab5fSopenharmony_ci            if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
7973af6ab5fSopenharmony_ci                lexer_->NextToken();
7983af6ab5fSopenharmony_ci                continue;
7993af6ab5fSopenharmony_ci            }
8003af6ab5fSopenharmony_ci
8013af6ab5fSopenharmony_ci            ir::AstNode *property = ParseClassElement(properties, modifiers, flags);
8023af6ab5fSopenharmony_ci            if (property == nullptr) {  // Error processing.
8033af6ab5fSopenharmony_ci                lexer_->NextToken();
8043af6ab5fSopenharmony_ci                continue;
8053af6ab5fSopenharmony_ci            }
8063af6ab5fSopenharmony_ci
8073af6ab5fSopenharmony_ci            if (CheckClassElement(property, ctor, properties)) {
8083af6ab5fSopenharmony_ci                continue;
8093af6ab5fSopenharmony_ci            }
8103af6ab5fSopenharmony_ci
8113af6ab5fSopenharmony_ci            properties.push_back(property);
8123af6ab5fSopenharmony_ci        }
8133af6ab5fSopenharmony_ci    }
8143af6ab5fSopenharmony_ci
8153af6ab5fSopenharmony_ci    lexer::SourcePosition endLoc = lexer_->GetToken().End();
8163af6ab5fSopenharmony_ci    CreateImplicitConstructor(ctor, properties, modifiers, endLoc);
8173af6ab5fSopenharmony_ci    lexer_->NextToken();
8183af6ab5fSopenharmony_ci
8193af6ab5fSopenharmony_ci    return {ctor, std::move(properties), lexer::SourceRange {startLoc, endLoc}};
8203af6ab5fSopenharmony_ci}
8213af6ab5fSopenharmony_ci
8223af6ab5fSopenharmony_civoid ParserImpl::ValidateRestParameter(ir::Expression *param)
8233af6ab5fSopenharmony_ci{
8243af6ab5fSopenharmony_ci    if (!param->IsIdentifier()) {
8253af6ab5fSopenharmony_ci        context_.Status() |= ParserStatus::HAS_COMPLEX_PARAM;
8263af6ab5fSopenharmony_ci        if (!param->IsRestElement()) {
8273af6ab5fSopenharmony_ci            return;
8283af6ab5fSopenharmony_ci        }
8293af6ab5fSopenharmony_ci
8303af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
8313af6ab5fSopenharmony_ci            ThrowSyntaxError("Rest parameter must be last formal parameter.");
8323af6ab5fSopenharmony_ci        }
8333af6ab5fSopenharmony_ci    }
8343af6ab5fSopenharmony_ci}
8353af6ab5fSopenharmony_ci
8363af6ab5fSopenharmony_cibool ParserImpl::ValidateBreakLabel(util::StringView label)
8373af6ab5fSopenharmony_ci{
8383af6ab5fSopenharmony_ci    return context_.FindLabel(label) != nullptr;
8393af6ab5fSopenharmony_ci}
8403af6ab5fSopenharmony_ci
8413af6ab5fSopenharmony_cibool ParserImpl::ValidateContinueLabel(util::StringView label)
8423af6ab5fSopenharmony_ci{
8433af6ab5fSopenharmony_ci    const ParserContext *labelCtx = context_.FindLabel(label);
8443af6ab5fSopenharmony_ci    return labelCtx != nullptr && ((labelCtx->Status() & ParserStatus::IN_ITERATION) != 0);
8453af6ab5fSopenharmony_ci}
8463af6ab5fSopenharmony_ci
8473af6ab5fSopenharmony_ciArenaVector<ir::Expression *> ParserImpl::ParseFunctionParams()
8483af6ab5fSopenharmony_ci{
8493af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
8503af6ab5fSopenharmony_ci        lexer_->NextToken();  // eat '('
8513af6ab5fSopenharmony_ci    }
8523af6ab5fSopenharmony_ci
8533af6ab5fSopenharmony_ci    ArenaVector<ir::Expression *> params(Allocator()->Adapter());
8543af6ab5fSopenharmony_ci
8553af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
8563af6ab5fSopenharmony_ci        lexer_->Lookahead() == static_cast<char32_t>(ARRAY_FORMAT_NODE)) {
8573af6ab5fSopenharmony_ci        params = std::move(ParseExpressionsArrayFormatPlaceholder());
8583af6ab5fSopenharmony_ci    } else {
8593af6ab5fSopenharmony_ci        while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
8603af6ab5fSopenharmony_ci            ir::Expression *parameter = ParseFunctionParameter();
8613af6ab5fSopenharmony_ci            if (parameter == nullptr) {  // Error processing.
8623af6ab5fSopenharmony_ci                continue;
8633af6ab5fSopenharmony_ci            }
8643af6ab5fSopenharmony_ci
8653af6ab5fSopenharmony_ci            ValidateRestParameter(parameter);
8663af6ab5fSopenharmony_ci            params.push_back(parameter);
8673af6ab5fSopenharmony_ci
8683af6ab5fSopenharmony_ci            if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
8693af6ab5fSopenharmony_ci                lexer_->NextToken();
8703af6ab5fSopenharmony_ci            } else if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
8713af6ab5fSopenharmony_ci                ThrowSyntaxError("Invalid token: comma or right parenthesis expected.");
8723af6ab5fSopenharmony_ci            }
8733af6ab5fSopenharmony_ci        }
8743af6ab5fSopenharmony_ci    }
8753af6ab5fSopenharmony_ci
8763af6ab5fSopenharmony_ci    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
8773af6ab5fSopenharmony_ci    lexer_->NextToken();
8783af6ab5fSopenharmony_ci    return params;
8793af6ab5fSopenharmony_ci}
8803af6ab5fSopenharmony_ci
8813af6ab5fSopenharmony_ciir::Expression *ParserImpl::CreateParameterThis([[maybe_unused]] util::StringView className)
8823af6ab5fSopenharmony_ci{
8833af6ab5fSopenharmony_ci    ThrowSyntaxError({"Unexpected token: ", className.Utf8()});
8843af6ab5fSopenharmony_ci}
8853af6ab5fSopenharmony_ci
8863af6ab5fSopenharmony_cistd::tuple<bool, ir::BlockStatement *, lexer::SourcePosition, bool> ParserImpl::ParseFunctionBody(
8873af6ab5fSopenharmony_ci    [[maybe_unused]] const ArenaVector<ir::Expression *> &params, [[maybe_unused]] ParserStatus newStatus,
8883af6ab5fSopenharmony_ci    [[maybe_unused]] ParserStatus contextStatus)
8893af6ab5fSopenharmony_ci{
8903af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
8913af6ab5fSopenharmony_ci        ThrowSyntaxError("Unexpected token, expected '{'");
8923af6ab5fSopenharmony_ci    }
8933af6ab5fSopenharmony_ci
8943af6ab5fSopenharmony_ci    ir::BlockStatement *body = ParseBlockStatement();
8953af6ab5fSopenharmony_ci
8963af6ab5fSopenharmony_ci    return {true, body, body->End(), false};
8973af6ab5fSopenharmony_ci}
8983af6ab5fSopenharmony_ci
8993af6ab5fSopenharmony_ciFunctionSignature ParserImpl::ParseFunctionSignature(ParserStatus status, ir::Identifier *className)
9003af6ab5fSopenharmony_ci{
9013af6ab5fSopenharmony_ci    ir::TSTypeParameterDeclaration *typeParamDecl = ParseFunctionTypeParameters();
9023af6ab5fSopenharmony_ci
9033af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
9043af6ab5fSopenharmony_ci        ThrowSyntaxError("Unexpected token, expected '('");
9053af6ab5fSopenharmony_ci    }
9063af6ab5fSopenharmony_ci
9073af6ab5fSopenharmony_ci    FunctionParameterContext funcParamContext(&context_);
9083af6ab5fSopenharmony_ci
9093af6ab5fSopenharmony_ci    ir::Expression *parameterThis = nullptr;
9103af6ab5fSopenharmony_ci    if (className != nullptr) {
9113af6ab5fSopenharmony_ci        const auto savedPos = Lexer()->Save();
9123af6ab5fSopenharmony_ci        lexer_->NextToken();  // eat '('
9133af6ab5fSopenharmony_ci        parameterThis = CreateParameterThis(className->Name());
9143af6ab5fSopenharmony_ci        Lexer()->Rewind(savedPos);
9153af6ab5fSopenharmony_ci    }
9163af6ab5fSopenharmony_ci
9173af6ab5fSopenharmony_ci    auto params = ParseFunctionParams();
9183af6ab5fSopenharmony_ci
9193af6ab5fSopenharmony_ci    if (className != nullptr) {
9203af6ab5fSopenharmony_ci        params.emplace(params.begin(), parameterThis);
9213af6ab5fSopenharmony_ci    }
9223af6ab5fSopenharmony_ci
9233af6ab5fSopenharmony_ci    ir::TypeNode *returnTypeAnnotation = ParseFunctionReturnType(status);
9243af6ab5fSopenharmony_ci    ir::ScriptFunctionFlags throwMarker = ParseFunctionThrowMarker(true);
9253af6ab5fSopenharmony_ci
9263af6ab5fSopenharmony_ci    auto res = ir::FunctionSignature(typeParamDecl, std::move(params), returnTypeAnnotation);
9273af6ab5fSopenharmony_ci    return {std::move(res), throwMarker};
9283af6ab5fSopenharmony_ci}
9293af6ab5fSopenharmony_ci
9303af6ab5fSopenharmony_ciir::ScriptFunction *ParserImpl::ParseFunction(ParserStatus newStatus)
9313af6ab5fSopenharmony_ci{
9323af6ab5fSopenharmony_ci    FunctionContext functionContext(this, newStatus | ParserStatus::FUNCTION | ParserStatus::ALLOW_NEW_TARGET);
9333af6ab5fSopenharmony_ci
9343af6ab5fSopenharmony_ci    bool isDeclare = InAmbientContext();
9353af6ab5fSopenharmony_ci
9363af6ab5fSopenharmony_ci    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
9373af6ab5fSopenharmony_ci
9383af6ab5fSopenharmony_ci    auto [signature, throw_marker] = ParseFunctionSignature(newStatus);
9393af6ab5fSopenharmony_ci
9403af6ab5fSopenharmony_ci    auto [letDeclare, body, endLoc, isOverload] = ParseFunctionBody(signature.Params(), newStatus, context_.Status());
9413af6ab5fSopenharmony_ci
9423af6ab5fSopenharmony_ci    if (isOverload) {
9433af6ab5fSopenharmony_ci        functionContext.AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
9443af6ab5fSopenharmony_ci    }
9453af6ab5fSopenharmony_ci
9463af6ab5fSopenharmony_ci    functionContext.AddFlag(throw_marker);
9473af6ab5fSopenharmony_ci    auto *funcNode = AllocNode<ir::ScriptFunction>(
9483af6ab5fSopenharmony_ci        Allocator(),
9493af6ab5fSopenharmony_ci        ir::ScriptFunction::ScriptFunctionData {
9503af6ab5fSopenharmony_ci            body, std::move(signature), functionContext.Flags(), {}, isDeclare && letDeclare, context_.GetLanguage()});
9513af6ab5fSopenharmony_ci    funcNode->SetRange({startLoc, endLoc});
9523af6ab5fSopenharmony_ci
9533af6ab5fSopenharmony_ci    return funcNode;
9543af6ab5fSopenharmony_ci}
9553af6ab5fSopenharmony_ci
9563af6ab5fSopenharmony_ciir::SpreadElement *ParserImpl::ParseSpreadElement(ExpressionParseFlags flags)
9573af6ab5fSopenharmony_ci{
9583af6ab5fSopenharmony_ci    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD);
9593af6ab5fSopenharmony_ci    lexer::SourcePosition startLocation = lexer_->GetToken().Start();
9603af6ab5fSopenharmony_ci    bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0;
9613af6ab5fSopenharmony_ci    lexer_->NextToken();
9623af6ab5fSopenharmony_ci
9633af6ab5fSopenharmony_ci    ir::Expression *argument {};
9643af6ab5fSopenharmony_ci    if (inPattern) {
9653af6ab5fSopenharmony_ci        argument = ParsePatternElement(ExpressionParseFlags::IN_REST);
9663af6ab5fSopenharmony_ci        if ((flags & ExpressionParseFlags::OBJECT_PATTERN) != 0 && !argument->IsIdentifier()) {
9673af6ab5fSopenharmony_ci            ThrowSyntaxError("RestParameter must be followed by an identifier in declaration contexts");
9683af6ab5fSopenharmony_ci        }
9693af6ab5fSopenharmony_ci    } else {
9703af6ab5fSopenharmony_ci        argument = ParseExpression(flags);
9713af6ab5fSopenharmony_ci    }
9723af6ab5fSopenharmony_ci
9733af6ab5fSopenharmony_ci    if (inPattern && argument->IsAssignmentExpression()) {
9743af6ab5fSopenharmony_ci        ThrowSyntaxError("RestParameter does not support an initializer");
9753af6ab5fSopenharmony_ci    }
9763af6ab5fSopenharmony_ci
9773af6ab5fSopenharmony_ci    auto nodeType = inPattern ? ir::AstNodeType::REST_ELEMENT : ir::AstNodeType::SPREAD_ELEMENT;
9783af6ab5fSopenharmony_ci    auto *spreadElementNode = AllocNode<ir::SpreadElement>(nodeType, Allocator(), argument);
9793af6ab5fSopenharmony_ci    spreadElementNode->SetRange({startLocation, argument->End()});
9803af6ab5fSopenharmony_ci    return spreadElementNode;
9813af6ab5fSopenharmony_ci}
9823af6ab5fSopenharmony_ci
9833af6ab5fSopenharmony_civoid ParserImpl::CheckRestrictedBinding() const
9843af6ab5fSopenharmony_ci{
9853af6ab5fSopenharmony_ci    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT);
9863af6ab5fSopenharmony_ci    CheckRestrictedBinding(lexer_->GetToken().KeywordType());
9873af6ab5fSopenharmony_ci}
9883af6ab5fSopenharmony_ci
9893af6ab5fSopenharmony_civoid ParserImpl::CheckRestrictedBinding(lexer::TokenType keywordType) const
9903af6ab5fSopenharmony_ci{
9913af6ab5fSopenharmony_ci    if (keywordType == lexer::TokenType::KEYW_ARGUMENTS || keywordType == lexer::TokenType::KEYW_EVAL) {
9923af6ab5fSopenharmony_ci        ThrowSyntaxError(
9933af6ab5fSopenharmony_ci            "'eval' or 'arguments' can't be defined or assigned to "
9943af6ab5fSopenharmony_ci            "in strict mode code",
9953af6ab5fSopenharmony_ci            lexer_->GetToken().Start());
9963af6ab5fSopenharmony_ci    }
9973af6ab5fSopenharmony_ci}
9983af6ab5fSopenharmony_ci
9993af6ab5fSopenharmony_civoid ParserImpl::CheckRestrictedBinding(const util::StringView &ident, const lexer::SourcePosition &pos) const
10003af6ab5fSopenharmony_ci{
10013af6ab5fSopenharmony_ci    if (ident.Is("eval") || ident.Is("arguments")) {
10023af6ab5fSopenharmony_ci        ThrowSyntaxError(
10033af6ab5fSopenharmony_ci            "'eval' or 'arguments' can't be defined or assigned to "
10043af6ab5fSopenharmony_ci            "in strict mode code",
10053af6ab5fSopenharmony_ci            pos);
10063af6ab5fSopenharmony_ci    }
10073af6ab5fSopenharmony_ci}
10083af6ab5fSopenharmony_ci
10093af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParseFunctionParameter()
10103af6ab5fSopenharmony_ci{
10113af6ab5fSopenharmony_ci    ConvertThisKeywordToIdentIfNecessary();
10123af6ab5fSopenharmony_ci
10133af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
10143af6ab5fSopenharmony_ci        CheckRestrictedBinding();
10153af6ab5fSopenharmony_ci    }
10163af6ab5fSopenharmony_ci
10173af6ab5fSopenharmony_ci    return ParsePatternElement(ExpressionParseFlags::NO_OPTS, true);
10183af6ab5fSopenharmony_ci}
10193af6ab5fSopenharmony_ci
10203af6ab5fSopenharmony_civoid ParserImpl::ValidateLvalueAssignmentTarget(ir::Expression *node)
10213af6ab5fSopenharmony_ci{
10223af6ab5fSopenharmony_ci    switch (node->Type()) {
10233af6ab5fSopenharmony_ci        case ir::AstNodeType::IDENTIFIER: {
10243af6ab5fSopenharmony_ci            CheckRestrictedBinding(node->AsIdentifier()->Name(), node->Start());
10253af6ab5fSopenharmony_ci            break;
10263af6ab5fSopenharmony_ci        }
10273af6ab5fSopenharmony_ci        case ir::AstNodeType::MEMBER_EXPRESSION: {
10283af6ab5fSopenharmony_ci            break;
10293af6ab5fSopenharmony_ci        }
10303af6ab5fSopenharmony_ci        default: {
10313af6ab5fSopenharmony_ci            ThrowSyntaxError("Invalid left-hand side in assignment expression");
10323af6ab5fSopenharmony_ci        }
10333af6ab5fSopenharmony_ci    }
10343af6ab5fSopenharmony_ci}
10353af6ab5fSopenharmony_ci
10363af6ab5fSopenharmony_civoid ParserImpl::ValidateAssignmentTarget(ExpressionParseFlags flags, ir::Expression *node)
10373af6ab5fSopenharmony_ci{
10383af6ab5fSopenharmony_ci    switch (node->Type()) {
10393af6ab5fSopenharmony_ci        case ir::AstNodeType::ARRAY_PATTERN:
10403af6ab5fSopenharmony_ci        case ir::AstNodeType::OBJECT_PATTERN: {
10413af6ab5fSopenharmony_ci            break;
10423af6ab5fSopenharmony_ci        }
10433af6ab5fSopenharmony_ci        case ir::AstNodeType::ARRAY_EXPRESSION:
10443af6ab5fSopenharmony_ci        case ir::AstNodeType::OBJECT_EXPRESSION: {
10453af6ab5fSopenharmony_ci            if ((flags & ExpressionParseFlags::POTENTIALLY_IN_PATTERN) != 0) {
10463af6ab5fSopenharmony_ci                return;
10473af6ab5fSopenharmony_ci            }
10483af6ab5fSopenharmony_ci
10493af6ab5fSopenharmony_ci            [[fallthrough]];
10503af6ab5fSopenharmony_ci        }
10513af6ab5fSopenharmony_ci        default: {
10523af6ab5fSopenharmony_ci            return ValidateLvalueAssignmentTarget(node);
10533af6ab5fSopenharmony_ci        }
10543af6ab5fSopenharmony_ci    }
10553af6ab5fSopenharmony_ci}
10563af6ab5fSopenharmony_ci
10573af6ab5fSopenharmony_civoid ParserImpl::ValidateArrowParameterBindings(const ir::Expression *node)
10583af6ab5fSopenharmony_ci{
10593af6ab5fSopenharmony_ci    switch (node->Type()) {
10603af6ab5fSopenharmony_ci        case ir::AstNodeType::IDENTIFIER: {
10613af6ab5fSopenharmony_ci            CheckRestrictedBinding(node->AsIdentifier()->Name(), node->Start());
10623af6ab5fSopenharmony_ci            break;
10633af6ab5fSopenharmony_ci        }
10643af6ab5fSopenharmony_ci        case ir::AstNodeType::OMITTED_EXPRESSION: {
10653af6ab5fSopenharmony_ci            break;
10663af6ab5fSopenharmony_ci        }
10673af6ab5fSopenharmony_ci        case ir::AstNodeType::REST_ELEMENT: {
10683af6ab5fSopenharmony_ci            ValidateArrowParameterBindings(node->AsRestElement()->Argument());
10693af6ab5fSopenharmony_ci            break;
10703af6ab5fSopenharmony_ci        }
10713af6ab5fSopenharmony_ci        case ir::AstNodeType::PROPERTY: {
10723af6ab5fSopenharmony_ci            break;
10733af6ab5fSopenharmony_ci        }
10743af6ab5fSopenharmony_ci        case ir::AstNodeType::OBJECT_PATTERN: {
10753af6ab5fSopenharmony_ci            const auto &props = node->AsObjectPattern()->Properties();
10763af6ab5fSopenharmony_ci
10773af6ab5fSopenharmony_ci            for (auto *it : props) {
10783af6ab5fSopenharmony_ci                ValidateArrowParameterBindings(it);
10793af6ab5fSopenharmony_ci            }
10803af6ab5fSopenharmony_ci            break;
10813af6ab5fSopenharmony_ci        }
10823af6ab5fSopenharmony_ci        case ir::AstNodeType::ARRAY_PATTERN: {
10833af6ab5fSopenharmony_ci            const auto &elements = node->AsArrayPattern()->Elements();
10843af6ab5fSopenharmony_ci
10853af6ab5fSopenharmony_ci            for (auto *it : elements) {
10863af6ab5fSopenharmony_ci                ValidateArrowParameterBindings(it);
10873af6ab5fSopenharmony_ci            }
10883af6ab5fSopenharmony_ci            break;
10893af6ab5fSopenharmony_ci        }
10903af6ab5fSopenharmony_ci        case ir::AstNodeType::ASSIGNMENT_PATTERN: {
10913af6ab5fSopenharmony_ci            ValidateArrowParameterBindings(node->AsAssignmentPattern()->Left());
10923af6ab5fSopenharmony_ci            break;
10933af6ab5fSopenharmony_ci        }
10943af6ab5fSopenharmony_ci        default: {
10953af6ab5fSopenharmony_ci            ThrowSyntaxError("Unexpected ArrowParameter element");
10963af6ab5fSopenharmony_ci        }
10973af6ab5fSopenharmony_ci    }
10983af6ab5fSopenharmony_ci}
10993af6ab5fSopenharmony_ci
11003af6ab5fSopenharmony_civoid ParserImpl::ThrowParameterModifierError(ir::ModifierFlags status) const
11013af6ab5fSopenharmony_ci{
11023af6ab5fSopenharmony_ci    ThrowSyntaxError({"'",
11033af6ab5fSopenharmony_ci                      (status & ir::ModifierFlags::STATIC) != 0  ? "static"
11043af6ab5fSopenharmony_ci                      : (status & ir::ModifierFlags::ASYNC) != 0 ? "async"
11053af6ab5fSopenharmony_ci                                                                 : "declare",
11063af6ab5fSopenharmony_ci                      "' modifier cannot appear on a parameter."},
11073af6ab5fSopenharmony_ci                     lexer_->GetToken().Start());
11083af6ab5fSopenharmony_ci}
11093af6ab5fSopenharmony_ci
11103af6ab5fSopenharmony_ciir::Identifier *ParserImpl::ParseIdentifierFormatPlaceholder(
11113af6ab5fSopenharmony_ci    [[maybe_unused]] std::optional<NodeFormatType> nodeFormat) const
11123af6ab5fSopenharmony_ci{
11133af6ab5fSopenharmony_ci    ThrowSyntaxError("Identifier expected.");
11143af6ab5fSopenharmony_ci}
11153af6ab5fSopenharmony_ci
11163af6ab5fSopenharmony_ciir::Statement *ParserImpl::ParseStatementFormatPlaceholder() const
11173af6ab5fSopenharmony_ci{
11183af6ab5fSopenharmony_ci    ThrowSyntaxError("Statement expected.");
11193af6ab5fSopenharmony_ci}
11203af6ab5fSopenharmony_ci
11213af6ab5fSopenharmony_ciir::AstNode *ParserImpl::ParseTypeParametersFormatPlaceholder() const
11223af6ab5fSopenharmony_ci{
11233af6ab5fSopenharmony_ci    ThrowSyntaxError("Type parameter(s) expected.");
11243af6ab5fSopenharmony_ci}
11253af6ab5fSopenharmony_ci
11263af6ab5fSopenharmony_ciArenaVector<ir::Statement *> &ParserImpl::ParseStatementsArrayFormatPlaceholder() const
11273af6ab5fSopenharmony_ci{
11283af6ab5fSopenharmony_ci    ThrowSyntaxError("ArenaVector of ir::Statement *'s expected.");
11293af6ab5fSopenharmony_ci}
11303af6ab5fSopenharmony_ci
11313af6ab5fSopenharmony_ciArenaVector<ir::AstNode *> &ParserImpl::ParseAstNodesArrayFormatPlaceholder() const
11323af6ab5fSopenharmony_ci{
11333af6ab5fSopenharmony_ci    ThrowSyntaxError("ArenaVector of ir::AstNode *'s expected.");
11343af6ab5fSopenharmony_ci}
11353af6ab5fSopenharmony_ci
11363af6ab5fSopenharmony_ciArenaVector<ir::Expression *> &ParserImpl::ParseExpressionsArrayFormatPlaceholder() const
11373af6ab5fSopenharmony_ci{
11383af6ab5fSopenharmony_ci    ThrowSyntaxError("ArenaVector of ir::Expression *'s expected.");
11393af6ab5fSopenharmony_ci}
11403af6ab5fSopenharmony_ci
11413af6ab5fSopenharmony_ciutil::StringView ParserImpl::ParseSymbolIteratorIdentifier() const noexcept
11423af6ab5fSopenharmony_ci{
11433af6ab5fSopenharmony_ci    // Duplicate check - just in case of improper call!
11443af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
11453af6ab5fSopenharmony_ci        return util::StringView {};
11463af6ab5fSopenharmony_ci    }
11473af6ab5fSopenharmony_ci
11483af6ab5fSopenharmony_ci    lexer_->NextToken();
11493af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT || !lexer_->GetToken().Ident().Is("Symbol")) {
11503af6ab5fSopenharmony_ci        return util::StringView {};
11513af6ab5fSopenharmony_ci    }
11523af6ab5fSopenharmony_ci
11533af6ab5fSopenharmony_ci    lexer_->NextToken();
11543af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_PERIOD) {
11553af6ab5fSopenharmony_ci        return util::StringView {};
11563af6ab5fSopenharmony_ci    }
11573af6ab5fSopenharmony_ci
11583af6ab5fSopenharmony_ci    lexer_->NextToken();
11593af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT || !lexer_->GetToken().Ident().Is("iterator")) {
11603af6ab5fSopenharmony_ci        return util::StringView {};
11613af6ab5fSopenharmony_ci    }
11623af6ab5fSopenharmony_ci
11633af6ab5fSopenharmony_ci    lexer_->NextToken();
11643af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
11653af6ab5fSopenharmony_ci        return util::StringView {};
11663af6ab5fSopenharmony_ci    }
11673af6ab5fSopenharmony_ci
11683af6ab5fSopenharmony_ci    //  Just replace '[Symbol.iterator]` identifier with the standard '$_iterator' name.
11693af6ab5fSopenharmony_ci    return util::StringView {compiler::Signatures::ITERATOR_METHOD};
11703af6ab5fSopenharmony_ci}
11713af6ab5fSopenharmony_ci
11723af6ab5fSopenharmony_ciir::Identifier *ParserImpl::ExpectIdentifier(bool isReference, bool isUserDefinedType)
11733af6ab5fSopenharmony_ci{
11743af6ab5fSopenharmony_ci    auto const &token = lexer_->GetToken();
11753af6ab5fSopenharmony_ci    auto const tokenType = token.Type();
11763af6ab5fSopenharmony_ci    if (tokenType == lexer::TokenType::PUNCTUATOR_FORMAT) {
11773af6ab5fSopenharmony_ci        return ParseIdentifierFormatPlaceholder(std::nullopt);
11783af6ab5fSopenharmony_ci    }
11793af6ab5fSopenharmony_ci
11803af6ab5fSopenharmony_ci    if (token.IsDefinableTypeName() && isUserDefinedType) {
11813af6ab5fSopenharmony_ci        ThrowSyntaxError("Cannot be used as user-defined type.");
11823af6ab5fSopenharmony_ci    }
11833af6ab5fSopenharmony_ci
11843af6ab5fSopenharmony_ci    auto const &tokenStart = token.Start();
11853af6ab5fSopenharmony_ci    util::StringView tokenName {};
11863af6ab5fSopenharmony_ci
11873af6ab5fSopenharmony_ci    if (tokenType == lexer::TokenType::LITERAL_IDENT) {
11883af6ab5fSopenharmony_ci        tokenName = token.Ident();
11893af6ab5fSopenharmony_ci    } else if (tokenType == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
11903af6ab5fSopenharmony_ci        // Special case for processing of special '[Symbol.iterator]` identifier using in stdlib.
11913af6ab5fSopenharmony_ci        tokenName = ParseSymbolIteratorIdentifier();
11923af6ab5fSopenharmony_ci    }
11933af6ab5fSopenharmony_ci
11943af6ab5fSopenharmony_ci    if (tokenName.Empty()) {
11953af6ab5fSopenharmony_ci        LogSyntaxError({"Identifier expected, got '", TokenToString(tokenType), "'."}, tokenStart);
11963af6ab5fSopenharmony_ci        return nullptr;  // Error processing.
11973af6ab5fSopenharmony_ci    }
11983af6ab5fSopenharmony_ci
11993af6ab5fSopenharmony_ci    auto *ident = AllocNode<ir::Identifier>(tokenName, Allocator());
12003af6ab5fSopenharmony_ci    ident->SetReference(isReference);
12013af6ab5fSopenharmony_ci    //  NOTE: here actual token can be changed!
12023af6ab5fSopenharmony_ci    ident->SetRange({tokenStart, lexer_->GetToken().End()});
12033af6ab5fSopenharmony_ci
12043af6ab5fSopenharmony_ci    lexer_->NextToken();
12053af6ab5fSopenharmony_ci
12063af6ab5fSopenharmony_ci    return ident;
12073af6ab5fSopenharmony_ci}
12083af6ab5fSopenharmony_ci
12093af6ab5fSopenharmony_civoid ParserImpl::ExpectToken(lexer::TokenType tokenType, bool consumeToken)
12103af6ab5fSopenharmony_ci{
12113af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == tokenType) {
12123af6ab5fSopenharmony_ci        if (consumeToken) {
12133af6ab5fSopenharmony_ci            lexer_->NextToken();
12143af6ab5fSopenharmony_ci        }
12153af6ab5fSopenharmony_ci        return;
12163af6ab5fSopenharmony_ci    }
12173af6ab5fSopenharmony_ci    ThrowExpectedToken(tokenType);
12183af6ab5fSopenharmony_ci}
12193af6ab5fSopenharmony_ci
12203af6ab5fSopenharmony_civoid ParserImpl::ThrowUnexpectedToken(lexer::TokenType const tokenType) const
12213af6ab5fSopenharmony_ci{
12223af6ab5fSopenharmony_ci    ThrowSyntaxError("Unexpected token: '"s + TokenToString(tokenType) + "'."s);
12233af6ab5fSopenharmony_ci}
12243af6ab5fSopenharmony_ci
12253af6ab5fSopenharmony_civoid ParserImpl::ThrowExpectedToken(lexer::TokenType const tokenType) const
12263af6ab5fSopenharmony_ci{
12273af6ab5fSopenharmony_ci    ThrowSyntaxError("Unexpected token, expected: '"s + TokenToString(tokenType) + "'."s);
12283af6ab5fSopenharmony_ci}
12293af6ab5fSopenharmony_ci
12303af6ab5fSopenharmony_civoid ParserImpl::ThrowSyntaxError(std::string_view const errorMessage) const
12313af6ab5fSopenharmony_ci{
12323af6ab5fSopenharmony_ci    ThrowSyntaxError(errorMessage, lexer_->GetToken().Start());
12333af6ab5fSopenharmony_ci}
12343af6ab5fSopenharmony_ci
12353af6ab5fSopenharmony_civoid ParserImpl::ThrowSyntaxError(std::initializer_list<std::string_view> list) const
12363af6ab5fSopenharmony_ci{
12373af6ab5fSopenharmony_ci    ThrowSyntaxError(list, lexer_->GetToken().Start());
12383af6ab5fSopenharmony_ci}
12393af6ab5fSopenharmony_ci
12403af6ab5fSopenharmony_civoid ParserImpl::ThrowSyntaxError(std::initializer_list<std::string_view> list, const lexer::SourcePosition &pos) const
12413af6ab5fSopenharmony_ci{
12423af6ab5fSopenharmony_ci    std::stringstream ss;
12433af6ab5fSopenharmony_ci
12443af6ab5fSopenharmony_ci    for (const auto &it : list) {
12453af6ab5fSopenharmony_ci        ss << it;
12463af6ab5fSopenharmony_ci    }
12473af6ab5fSopenharmony_ci
12483af6ab5fSopenharmony_ci    std::string err = ss.str();
12493af6ab5fSopenharmony_ci
12503af6ab5fSopenharmony_ci    ThrowSyntaxError(std::string_view {err}, pos);
12513af6ab5fSopenharmony_ci}
12523af6ab5fSopenharmony_ci
12533af6ab5fSopenharmony_civoid ParserImpl::ThrowSyntaxError(std::string_view errorMessage, const lexer::SourcePosition &pos) const
12543af6ab5fSopenharmony_ci{
12553af6ab5fSopenharmony_ci    lexer::LineIndex index(program_->SourceCode());
12563af6ab5fSopenharmony_ci    lexer::SourceLocation loc = index.GetLocation(pos);
12573af6ab5fSopenharmony_ci
12583af6ab5fSopenharmony_ci    throw Error {ErrorType::SYNTAX, program_->SourceFilePath().Utf8(), errorMessage, loc.line, loc.col};
12593af6ab5fSopenharmony_ci}
12603af6ab5fSopenharmony_ci
12613af6ab5fSopenharmony_civoid ParserImpl::LogExpectedToken(lexer::TokenType const tokenType)
12623af6ab5fSopenharmony_ci{
12633af6ab5fSopenharmony_ci    LogSyntaxError("Unexpected token, expected: '"s + TokenToString(tokenType) + "'."s);
12643af6ab5fSopenharmony_ci    lexer_->GetToken().SetTokenType(tokenType);
12653af6ab5fSopenharmony_ci}
12663af6ab5fSopenharmony_ci
12673af6ab5fSopenharmony_civoid ParserImpl::LogSyntaxError(std::string_view const errorMessage)
12683af6ab5fSopenharmony_ci{
12693af6ab5fSopenharmony_ci    LogSyntaxError(errorMessage, lexer_->GetToken().Start());
12703af6ab5fSopenharmony_ci}
12713af6ab5fSopenharmony_ci
12723af6ab5fSopenharmony_civoid ParserImpl::LogSyntaxError(std::initializer_list<std::string_view> list)
12733af6ab5fSopenharmony_ci{
12743af6ab5fSopenharmony_ci    LogSyntaxError(list, lexer_->GetToken().Start());
12753af6ab5fSopenharmony_ci}
12763af6ab5fSopenharmony_ci
12773af6ab5fSopenharmony_civoid ParserImpl::LogSyntaxError(std::initializer_list<std::string_view> list, const lexer::SourcePosition &pos)
12783af6ab5fSopenharmony_ci{
12793af6ab5fSopenharmony_ci    std::stringstream ss;
12803af6ab5fSopenharmony_ci
12813af6ab5fSopenharmony_ci    for (const auto &it : list) {
12823af6ab5fSopenharmony_ci        ss << it;
12833af6ab5fSopenharmony_ci    }
12843af6ab5fSopenharmony_ci
12853af6ab5fSopenharmony_ci    std::string err = ss.str();
12863af6ab5fSopenharmony_ci
12873af6ab5fSopenharmony_ci    LogSyntaxError(std::string_view {err}, pos);
12883af6ab5fSopenharmony_ci}
12893af6ab5fSopenharmony_ci
12903af6ab5fSopenharmony_civoid ParserImpl::LogSyntaxError(std::string_view errorMessage, const lexer::SourcePosition &pos)
12913af6ab5fSopenharmony_ci{
12923af6ab5fSopenharmony_ci    lexer::LineIndex index(program_->SourceCode());
12933af6ab5fSopenharmony_ci    lexer::SourceLocation loc = index.GetLocation(pos);
12943af6ab5fSopenharmony_ci
12953af6ab5fSopenharmony_ci    errorLogger_.WriteLog(
12963af6ab5fSopenharmony_ci        Error {ErrorType::SYNTAX, program_->SourceFilePath().Utf8(), errorMessage, loc.line, loc.col});
12973af6ab5fSopenharmony_ci}
12983af6ab5fSopenharmony_ci
12993af6ab5fSopenharmony_civoid ParserImpl::ThrowAllocationError(std::string_view message) const
13003af6ab5fSopenharmony_ci{
13013af6ab5fSopenharmony_ci    throw Error(ErrorType::GENERIC, program_->SourceFilePath().Utf8(), message);
13023af6ab5fSopenharmony_ci}
13033af6ab5fSopenharmony_ci
13043af6ab5fSopenharmony_ciScriptExtension ParserImpl::Extension() const
13053af6ab5fSopenharmony_ci{
13063af6ab5fSopenharmony_ci    return program_->Extension();
13073af6ab5fSopenharmony_ci}
13083af6ab5fSopenharmony_ci
13093af6ab5fSopenharmony_cibool ParserImpl::CheckModuleAsModifier()
13103af6ab5fSopenharmony_ci{
13113af6ab5fSopenharmony_ci    if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_AS) {
13123af6ab5fSopenharmony_ci        return false;
13133af6ab5fSopenharmony_ci    }
13143af6ab5fSopenharmony_ci
13153af6ab5fSopenharmony_ci    if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0U) {
13163af6ab5fSopenharmony_ci        ThrowSyntaxError("Escape sequences are not allowed in 'as' keyword");
13173af6ab5fSopenharmony_ci    }
13183af6ab5fSopenharmony_ci
13193af6ab5fSopenharmony_ci    return true;
13203af6ab5fSopenharmony_ci}
13213af6ab5fSopenharmony_ci
13223af6ab5fSopenharmony_ci}  // namespace ark::es2panda::parser
1323