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 "lexer/token/tokenType.h"
173af6ab5fSopenharmony_ci#include "parser/parserFlags.h"
183af6ab5fSopenharmony_ci#include "ir/astNode.h"
193af6ab5fSopenharmony_ci#include "ir/base/classDefinition.h"
203af6ab5fSopenharmony_ci#include "ir/base/decorator.h"
213af6ab5fSopenharmony_ci#include "ir/base/metaProperty.h"
223af6ab5fSopenharmony_ci#include "ir/base/methodDefinition.h"
233af6ab5fSopenharmony_ci#include "ir/base/property.h"
243af6ab5fSopenharmony_ci#include "ir/base/scriptFunction.h"
253af6ab5fSopenharmony_ci#include "ir/base/spreadElement.h"
263af6ab5fSopenharmony_ci#include "ir/base/templateElement.h"
273af6ab5fSopenharmony_ci#include "ir/expression.h"
283af6ab5fSopenharmony_ci#include "ir/expressions/arrayExpression.h"
293af6ab5fSopenharmony_ci#include "ir/expressions/arrowFunctionExpression.h"
303af6ab5fSopenharmony_ci#include "ir/expressions/assignmentExpression.h"
313af6ab5fSopenharmony_ci#include "ir/expressions/awaitExpression.h"
323af6ab5fSopenharmony_ci#include "ir/expressions/binaryExpression.h"
333af6ab5fSopenharmony_ci#include "ir/expressions/callExpression.h"
343af6ab5fSopenharmony_ci#include "ir/expressions/chainExpression.h"
353af6ab5fSopenharmony_ci#include "ir/expressions/classExpression.h"
363af6ab5fSopenharmony_ci#include "ir/expressions/conditionalExpression.h"
373af6ab5fSopenharmony_ci#include "ir/expressions/directEvalExpression.h"
383af6ab5fSopenharmony_ci#include "ir/expressions/functionExpression.h"
393af6ab5fSopenharmony_ci#include "ir/expressions/identifier.h"
403af6ab5fSopenharmony_ci#include "ir/expressions/importExpression.h"
413af6ab5fSopenharmony_ci#include "ir/expressions/literals/bigIntLiteral.h"
423af6ab5fSopenharmony_ci#include "ir/expressions/literals/booleanLiteral.h"
433af6ab5fSopenharmony_ci#include "ir/expressions/literals/nullLiteral.h"
443af6ab5fSopenharmony_ci#include "ir/expressions/literals/numberLiteral.h"
453af6ab5fSopenharmony_ci#include "ir/expressions/literals/regExpLiteral.h"
463af6ab5fSopenharmony_ci#include "ir/expressions/literals/charLiteral.h"
473af6ab5fSopenharmony_ci#include "ir/expressions/literals/stringLiteral.h"
483af6ab5fSopenharmony_ci#include "ir/expressions/literals/undefinedLiteral.h"
493af6ab5fSopenharmony_ci#include "ir/expressions/memberExpression.h"
503af6ab5fSopenharmony_ci#include "ir/expressions/newExpression.h"
513af6ab5fSopenharmony_ci#include "ir/expressions/objectExpression.h"
523af6ab5fSopenharmony_ci#include "ir/expressions/omittedExpression.h"
533af6ab5fSopenharmony_ci#include "ir/expressions/sequenceExpression.h"
543af6ab5fSopenharmony_ci#include "ir/expressions/superExpression.h"
553af6ab5fSopenharmony_ci#include "ir/expressions/taggedTemplateExpression.h"
563af6ab5fSopenharmony_ci#include "ir/expressions/templateLiteral.h"
573af6ab5fSopenharmony_ci#include "ir/expressions/thisExpression.h"
583af6ab5fSopenharmony_ci#include "ir/expressions/typeofExpression.h"
593af6ab5fSopenharmony_ci#include "ir/expressions/unaryExpression.h"
603af6ab5fSopenharmony_ci#include "ir/expressions/updateExpression.h"
613af6ab5fSopenharmony_ci#include "ir/expressions/yieldExpression.h"
623af6ab5fSopenharmony_ci#include "ir/statements/blockStatement.h"
633af6ab5fSopenharmony_ci#include "ir/statements/classDeclaration.h"
643af6ab5fSopenharmony_ci#include "ir/ts/tsAsExpression.h"
653af6ab5fSopenharmony_ci#include "ir/ts/tsNonNullExpression.h"
663af6ab5fSopenharmony_ci#include "ir/validationInfo.h"
673af6ab5fSopenharmony_ci#include "lexer/lexer.h"
683af6ab5fSopenharmony_ci#include "lexer/regexp/regexp.h"
693af6ab5fSopenharmony_ci#include "lexer/token/letters.h"
703af6ab5fSopenharmony_ci#include "lexer/token/sourceLocation.h"
713af6ab5fSopenharmony_ci#include "lexer/token/token.h"
723af6ab5fSopenharmony_ci#include "macros.h"
733af6ab5fSopenharmony_ci
743af6ab5fSopenharmony_ci#include <memory>
753af6ab5fSopenharmony_ci
763af6ab5fSopenharmony_ci#include "parser/parserStatusContext.h"
773af6ab5fSopenharmony_ci#include "parserImpl.h"
783af6ab5fSopenharmony_ci
793af6ab5fSopenharmony_cinamespace ark::es2panda::parser {
803af6ab5fSopenharmony_ciir::YieldExpression *ParserImpl::ParseYieldExpression()
813af6ab5fSopenharmony_ci{
823af6ab5fSopenharmony_ci    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_YIELD);
833af6ab5fSopenharmony_ci
843af6ab5fSopenharmony_ci    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
853af6ab5fSopenharmony_ci    lexer::SourcePosition endLoc = lexer_->GetToken().End();
863af6ab5fSopenharmony_ci
873af6ab5fSopenharmony_ci    if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0) {
883af6ab5fSopenharmony_ci        ThrowSyntaxError("Unexpected identifier");
893af6ab5fSopenharmony_ci    }
903af6ab5fSopenharmony_ci
913af6ab5fSopenharmony_ci    lexer_->NextToken();
923af6ab5fSopenharmony_ci
933af6ab5fSopenharmony_ci    bool isDelegate = false;
943af6ab5fSopenharmony_ci    ir::Expression *argument = nullptr;
953af6ab5fSopenharmony_ci
963af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY && !lexer_->GetToken().NewLine()) {
973af6ab5fSopenharmony_ci        isDelegate = true;
983af6ab5fSopenharmony_ci        lexer_->NextToken();
993af6ab5fSopenharmony_ci
1003af6ab5fSopenharmony_ci        argument = ParseExpression();
1013af6ab5fSopenharmony_ci        endLoc = argument->End();
1023af6ab5fSopenharmony_ci    } else if (!lexer_->GetToken().NewLine() && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
1033af6ab5fSopenharmony_ci               lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS &&
1043af6ab5fSopenharmony_ci               lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET &&
1053af6ab5fSopenharmony_ci               lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
1063af6ab5fSopenharmony_ci               lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
1073af6ab5fSopenharmony_ci               lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON &&
1083af6ab5fSopenharmony_ci               lexer_->GetToken().Type() != lexer::TokenType::EOS) {
1093af6ab5fSopenharmony_ci        argument = ParseExpression();
1103af6ab5fSopenharmony_ci        endLoc = argument->End();
1113af6ab5fSopenharmony_ci    }
1123af6ab5fSopenharmony_ci
1133af6ab5fSopenharmony_ci    auto *yieldNode = AllocNode<ir::YieldExpression>(argument, isDelegate);
1143af6ab5fSopenharmony_ci    yieldNode->SetRange({startLoc, endLoc});
1153af6ab5fSopenharmony_ci
1163af6ab5fSopenharmony_ci    return yieldNode;
1173af6ab5fSopenharmony_ci}
1183af6ab5fSopenharmony_ci
1193af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParsePotentialExpressionSequence(ir::Expression *expr, ExpressionParseFlags flags)
1203af6ab5fSopenharmony_ci{
1213af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA &&
1223af6ab5fSopenharmony_ci        (flags & ExpressionParseFlags::ACCEPT_COMMA) != 0) {
1233af6ab5fSopenharmony_ci        return ParseSequenceExpression(expr, (flags & ExpressionParseFlags::ACCEPT_REST) != 0);
1243af6ab5fSopenharmony_ci    }
1253af6ab5fSopenharmony_ci
1263af6ab5fSopenharmony_ci    return expr;
1273af6ab5fSopenharmony_ci}
1283af6ab5fSopenharmony_ci
1293af6ab5fSopenharmony_ci// NOLINTNEXTLINE(google-default-arguments)
1303af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParseExpression(ExpressionParseFlags flags)
1313af6ab5fSopenharmony_ci{
1323af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_YIELD &&
1333af6ab5fSopenharmony_ci        (flags & ExpressionParseFlags::DISALLOW_YIELD) == 0U) {
1343af6ab5fSopenharmony_ci        ir::YieldExpression *yieldExpr = ParseYieldExpression();
1353af6ab5fSopenharmony_ci
1363af6ab5fSopenharmony_ci        return ParsePotentialExpressionSequence(yieldExpr, flags);
1373af6ab5fSopenharmony_ci    }
1383af6ab5fSopenharmony_ci
1393af6ab5fSopenharmony_ci    ir::Expression *unaryExpressionNode = ParseUnaryOrPrefixUpdateExpression(flags);
1403af6ab5fSopenharmony_ci    ir::Expression *assignmentExpression = ParseAssignmentExpression(unaryExpressionNode, flags);
1413af6ab5fSopenharmony_ci
1423af6ab5fSopenharmony_ci    if (lexer_->GetToken().NewLine()) {
1433af6ab5fSopenharmony_ci        return assignmentExpression;
1443af6ab5fSopenharmony_ci    }
1453af6ab5fSopenharmony_ci
1463af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA &&
1473af6ab5fSopenharmony_ci        (flags & ExpressionParseFlags::ACCEPT_COMMA) != 0U) {
1483af6ab5fSopenharmony_ci        return ParseSequenceExpression(assignmentExpression, (flags & ExpressionParseFlags::ACCEPT_REST) != 0U);
1493af6ab5fSopenharmony_ci    }
1503af6ab5fSopenharmony_ci
1513af6ab5fSopenharmony_ci    return assignmentExpression;
1523af6ab5fSopenharmony_ci}
1533af6ab5fSopenharmony_ci
1543af6ab5fSopenharmony_ci// NOLINTNEXTLINE(google-default-arguments)
1553af6ab5fSopenharmony_ciir::ArrayExpression *ParserImpl::ParseArrayExpression(ExpressionParseFlags flags)
1563af6ab5fSopenharmony_ci{
1573af6ab5fSopenharmony_ci    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1583af6ab5fSopenharmony_ci
1593af6ab5fSopenharmony_ci    ArenaVector<ir::Expression *> elements(Allocator()->Adapter());
1603af6ab5fSopenharmony_ci
1613af6ab5fSopenharmony_ci    lexer_->NextToken();
1623af6ab5fSopenharmony_ci
1633af6ab5fSopenharmony_ci    bool trailingComma = false;
1643af6ab5fSopenharmony_ci    bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0;
1653af6ab5fSopenharmony_ci
1663af6ab5fSopenharmony_ci    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1673af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
1683af6ab5fSopenharmony_ci            auto *omitted = AllocNode<ir::OmittedExpression>();
1693af6ab5fSopenharmony_ci            omitted->SetRange(lexer_->GetToken().Loc());
1703af6ab5fSopenharmony_ci            elements.push_back(omitted);
1713af6ab5fSopenharmony_ci            lexer_->NextToken();
1723af6ab5fSopenharmony_ci            continue;
1733af6ab5fSopenharmony_ci        }
1743af6ab5fSopenharmony_ci
1753af6ab5fSopenharmony_ci        ir::Expression *element {};
1763af6ab5fSopenharmony_ci        if (inPattern) {
1773af6ab5fSopenharmony_ci            element = ParsePatternElement();
1783af6ab5fSopenharmony_ci        } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
1793af6ab5fSopenharmony_ci            element = ParseSpreadElement(ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
1803af6ab5fSopenharmony_ci        } else {
1813af6ab5fSopenharmony_ci            element = ParseExpression(ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
1823af6ab5fSopenharmony_ci        }
1833af6ab5fSopenharmony_ci
1843af6ab5fSopenharmony_ci        bool containsRest = element->IsRestElement();
1853af6ab5fSopenharmony_ci
1863af6ab5fSopenharmony_ci        elements.push_back(element);
1873af6ab5fSopenharmony_ci
1883af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
1893af6ab5fSopenharmony_ci            if (containsRest) {
1903af6ab5fSopenharmony_ci                ThrowSyntaxError("Rest element must be last element", startLoc);
1913af6ab5fSopenharmony_ci            }
1923af6ab5fSopenharmony_ci
1933af6ab5fSopenharmony_ci            lexer_->NextToken();  // eat comma
1943af6ab5fSopenharmony_ci
1953af6ab5fSopenharmony_ci            if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1963af6ab5fSopenharmony_ci                trailingComma = true;
1973af6ab5fSopenharmony_ci                break;
1983af6ab5fSopenharmony_ci            }
1993af6ab5fSopenharmony_ci
2003af6ab5fSopenharmony_ci            continue;
2013af6ab5fSopenharmony_ci        }
2023af6ab5fSopenharmony_ci
2033af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
2043af6ab5fSopenharmony_ci            ThrowSyntaxError("Unexpected token, expected ',' or ']'");
2053af6ab5fSopenharmony_ci        }
2063af6ab5fSopenharmony_ci    }
2073af6ab5fSopenharmony_ci
2083af6ab5fSopenharmony_ci    auto nodeType = inPattern ? ir::AstNodeType::ARRAY_PATTERN : ir::AstNodeType::ARRAY_EXPRESSION;
2093af6ab5fSopenharmony_ci    auto *arrayExpressionNode =
2103af6ab5fSopenharmony_ci        AllocNode<ir::ArrayExpression>(nodeType, std::move(elements), Allocator(), trailingComma);
2113af6ab5fSopenharmony_ci    arrayExpressionNode->SetRange({startLoc, lexer_->GetToken().End()});
2123af6ab5fSopenharmony_ci    lexer_->NextToken();
2133af6ab5fSopenharmony_ci
2143af6ab5fSopenharmony_ci    if (inPattern) {
2153af6ab5fSopenharmony_ci        arrayExpressionNode->SetDeclaration();
2163af6ab5fSopenharmony_ci    }
2173af6ab5fSopenharmony_ci
2183af6ab5fSopenharmony_ci    ParseArrayExpressionErrorCheck(arrayExpressionNode, flags, inPattern);
2193af6ab5fSopenharmony_ci    return arrayExpressionNode;
2203af6ab5fSopenharmony_ci}
2213af6ab5fSopenharmony_ci
2223af6ab5fSopenharmony_civoid ParserImpl::ParseArrayExpressionErrorCheck(ir::ArrayExpression *arrayExpressionNode,
2233af6ab5fSopenharmony_ci                                                const ExpressionParseFlags flags, const bool inPattern)
2243af6ab5fSopenharmony_ci{
2253af6ab5fSopenharmony_ci    if ((flags & ExpressionParseFlags::POTENTIALLY_IN_PATTERN) == 0) {
2263af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION &&
2273af6ab5fSopenharmony_ci            !arrayExpressionNode->ConvertibleToArrayPattern()) {
2283af6ab5fSopenharmony_ci            ThrowSyntaxError("Invalid left-hand side in array destructuring pattern", arrayExpressionNode->Start());
2293af6ab5fSopenharmony_ci        } else if (!inPattern && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
2303af6ab5fSopenharmony_ci            ir::ValidationInfo info = arrayExpressionNode->ValidateExpression();
2313af6ab5fSopenharmony_ci            if (info.Fail()) {
2323af6ab5fSopenharmony_ci                ThrowSyntaxError(info.msg.Utf8(), info.pos);
2333af6ab5fSopenharmony_ci            }
2343af6ab5fSopenharmony_ci        }
2353af6ab5fSopenharmony_ci    }
2363af6ab5fSopenharmony_ci}
2373af6ab5fSopenharmony_ci
2383af6ab5fSopenharmony_ciParserStatus ParserImpl::ValidateArrowParameter(ir::Expression *expr, [[maybe_unused]] bool *seenOptional)
2393af6ab5fSopenharmony_ci{
2403af6ab5fSopenharmony_ci    switch (expr->Type()) {
2413af6ab5fSopenharmony_ci        case ir::AstNodeType::SPREAD_ELEMENT: {
2423af6ab5fSopenharmony_ci            if (!expr->AsSpreadElement()->ConvertibleToRest(true)) {
2433af6ab5fSopenharmony_ci                ThrowSyntaxError("Invalid rest element.");
2443af6ab5fSopenharmony_ci            }
2453af6ab5fSopenharmony_ci
2463af6ab5fSopenharmony_ci            [[fallthrough]];
2473af6ab5fSopenharmony_ci        }
2483af6ab5fSopenharmony_ci        case ir::AstNodeType::REST_ELEMENT: {
2493af6ab5fSopenharmony_ci            ValidateArrowParameterBindings(expr->AsRestElement()->Argument());
2503af6ab5fSopenharmony_ci            return ParserStatus::HAS_COMPLEX_PARAM;
2513af6ab5fSopenharmony_ci        }
2523af6ab5fSopenharmony_ci        case ir::AstNodeType::IDENTIFIER: {
2533af6ab5fSopenharmony_ci            ValidateArrowParameterBindings(expr);
2543af6ab5fSopenharmony_ci            return ParserStatus::NO_OPTS;
2553af6ab5fSopenharmony_ci        }
2563af6ab5fSopenharmony_ci        case ir::AstNodeType::OBJECT_EXPRESSION: {
2573af6ab5fSopenharmony_ci            if (ir::ObjectExpression *objectPattern = expr->AsObjectExpression();
2583af6ab5fSopenharmony_ci                !objectPattern->ConvertibleToObjectPattern()) {
2593af6ab5fSopenharmony_ci                ThrowSyntaxError("Invalid destructuring assignment target");
2603af6ab5fSopenharmony_ci            }
2613af6ab5fSopenharmony_ci
2623af6ab5fSopenharmony_ci            ValidateArrowParameterBindings(expr);
2633af6ab5fSopenharmony_ci            return ParserStatus::HAS_COMPLEX_PARAM;
2643af6ab5fSopenharmony_ci        }
2653af6ab5fSopenharmony_ci        case ir::AstNodeType::ARRAY_EXPRESSION: {
2663af6ab5fSopenharmony_ci            if (ir::ArrayExpression *arrayPattern = expr->AsArrayExpression();
2673af6ab5fSopenharmony_ci                !arrayPattern->ConvertibleToArrayPattern()) {
2683af6ab5fSopenharmony_ci                ThrowSyntaxError("Invalid destructuring assignment target");
2693af6ab5fSopenharmony_ci            }
2703af6ab5fSopenharmony_ci
2713af6ab5fSopenharmony_ci            ValidateArrowParameterBindings(expr);
2723af6ab5fSopenharmony_ci            return ParserStatus::HAS_COMPLEX_PARAM;
2733af6ab5fSopenharmony_ci        }
2743af6ab5fSopenharmony_ci        case ir::AstNodeType::ASSIGNMENT_EXPRESSION: {
2753af6ab5fSopenharmony_ci            ValidateArrowParameterAssignment(expr->AsAssignmentExpression());
2763af6ab5fSopenharmony_ci            ValidateArrowParameterBindings(expr);
2773af6ab5fSopenharmony_ci            return ParserStatus::HAS_COMPLEX_PARAM;
2783af6ab5fSopenharmony_ci        }
2793af6ab5fSopenharmony_ci        default: {
2803af6ab5fSopenharmony_ci            break;
2813af6ab5fSopenharmony_ci        }
2823af6ab5fSopenharmony_ci    }
2833af6ab5fSopenharmony_ci    ThrowSyntaxError("Insufficient formal parameter in arrow function.");
2843af6ab5fSopenharmony_ci    return ParserStatus::NO_OPTS;
2853af6ab5fSopenharmony_ci}
2863af6ab5fSopenharmony_ci
2873af6ab5fSopenharmony_civoid ParserImpl::ValidateArrowParameterAssignment(ir::AssignmentExpression *expr)
2883af6ab5fSopenharmony_ci{
2893af6ab5fSopenharmony_ci    if (expr->Right()->IsYieldExpression()) {
2903af6ab5fSopenharmony_ci        ThrowSyntaxError("yield is not allowed in arrow function parameters");
2913af6ab5fSopenharmony_ci    } else if (expr->Right()->IsAwaitExpression()) {
2923af6ab5fSopenharmony_ci        ThrowSyntaxError("await is not allowed in arrow function parameters");
2933af6ab5fSopenharmony_ci    } else if (!expr->ConvertibleToAssignmentPattern()) {
2943af6ab5fSopenharmony_ci        ThrowSyntaxError("Invalid destructuring assignment target");
2953af6ab5fSopenharmony_ci    }
2963af6ab5fSopenharmony_ci}
2973af6ab5fSopenharmony_ci
2983af6ab5fSopenharmony_ciir::ArrowFunctionExpression *ParserImpl::ParseArrowFunctionExpressionBody(ArrowFunctionContext *arrowFunctionContext,
2993af6ab5fSopenharmony_ci                                                                          ArrowFunctionDescriptor *desc,
3003af6ab5fSopenharmony_ci                                                                          ir::TSTypeParameterDeclaration *typeParamDecl,
3013af6ab5fSopenharmony_ci                                                                          ir::TypeNode *returnTypeAnnotation)
3023af6ab5fSopenharmony_ci{
3033af6ab5fSopenharmony_ci    context_.Status() |= desc->newStatus;
3043af6ab5fSopenharmony_ci
3053af6ab5fSopenharmony_ci    lexer_->NextToken();  // eat '=>'
3063af6ab5fSopenharmony_ci    ir::ScriptFunction *funcNode {};
3073af6ab5fSopenharmony_ci
3083af6ab5fSopenharmony_ci    ir::AstNode *body = nullptr;
3093af6ab5fSopenharmony_ci    lexer::SourcePosition endLoc;
3103af6ab5fSopenharmony_ci    lexer::SourcePosition bodyStart = lexer_->GetToken().Start();
3113af6ab5fSopenharmony_ci
3123af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
3133af6ab5fSopenharmony_ci        body = ParseExpression();
3143af6ab5fSopenharmony_ci        endLoc = body->AsExpression()->End();
3153af6ab5fSopenharmony_ci        arrowFunctionContext->AddFlag(ir::ScriptFunctionFlags::EXPRESSION);
3163af6ab5fSopenharmony_ci    } else {
3173af6ab5fSopenharmony_ci        lexer_->NextToken();
3183af6ab5fSopenharmony_ci        auto statements = ParseStatementList();
3193af6ab5fSopenharmony_ci        body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
3203af6ab5fSopenharmony_ci        body->SetRange({bodyStart, lexer_->GetToken().End()});
3213af6ab5fSopenharmony_ci
3223af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
3233af6ab5fSopenharmony_ci            ThrowSyntaxError("Expected a '}'");
3243af6ab5fSopenharmony_ci        }
3253af6ab5fSopenharmony_ci
3263af6ab5fSopenharmony_ci        lexer_->NextToken();
3273af6ab5fSopenharmony_ci        endLoc = body->End();
3283af6ab5fSopenharmony_ci    }
3293af6ab5fSopenharmony_ci
3303af6ab5fSopenharmony_ci    // clang-format off
3313af6ab5fSopenharmony_ci    funcNode = AllocNode<ir::ScriptFunction>(
3323af6ab5fSopenharmony_ci        Allocator(), ir::ScriptFunction::ScriptFunctionData {
3333af6ab5fSopenharmony_ci                        body,
3343af6ab5fSopenharmony_ci                        ir::FunctionSignature(typeParamDecl, std::move(desc->params), returnTypeAnnotation),
3353af6ab5fSopenharmony_ci                        arrowFunctionContext->Flags(),
3363af6ab5fSopenharmony_ci                        {},
3373af6ab5fSopenharmony_ci                        false,
3383af6ab5fSopenharmony_ci                        context_.GetLanguage()});
3393af6ab5fSopenharmony_ci    // clang-format on
3403af6ab5fSopenharmony_ci    funcNode->SetRange({desc->startLoc, endLoc});
3413af6ab5fSopenharmony_ci
3423af6ab5fSopenharmony_ci    auto *arrowFuncNode = AllocNode<ir::ArrowFunctionExpression>(funcNode);
3433af6ab5fSopenharmony_ci    arrowFuncNode->SetRange(funcNode->Range());
3443af6ab5fSopenharmony_ci
3453af6ab5fSopenharmony_ci    return arrowFuncNode;
3463af6ab5fSopenharmony_ci}
3473af6ab5fSopenharmony_ci
3483af6ab5fSopenharmony_ciArrowFunctionDescriptor ParserImpl::ConvertToArrowParameter(ir::Expression *expr, bool isAsync)
3493af6ab5fSopenharmony_ci{
3503af6ab5fSopenharmony_ci    auto arrowStatus = isAsync ? ParserStatus::ASYNC_FUNCTION : ParserStatus::NO_OPTS;
3513af6ab5fSopenharmony_ci    ArenaVector<ir::Expression *> params(Allocator()->Adapter());
3523af6ab5fSopenharmony_ci
3533af6ab5fSopenharmony_ci    if (expr == nullptr) {
3543af6ab5fSopenharmony_ci        return ArrowFunctionDescriptor {std::move(params), lexer_->GetToken().Start(), arrowStatus};
3553af6ab5fSopenharmony_ci    }
3563af6ab5fSopenharmony_ci
3573af6ab5fSopenharmony_ci    bool seenOptional = false;
3583af6ab5fSopenharmony_ci
3593af6ab5fSopenharmony_ci    switch (expr->Type()) {
3603af6ab5fSopenharmony_ci        case ir::AstNodeType::REST_ELEMENT:
3613af6ab5fSopenharmony_ci        case ir::AstNodeType::IDENTIFIER:
3623af6ab5fSopenharmony_ci        case ir::AstNodeType::OBJECT_EXPRESSION:
3633af6ab5fSopenharmony_ci        case ir::AstNodeType::ASSIGNMENT_EXPRESSION:
3643af6ab5fSopenharmony_ci        case ir::AstNodeType::ARRAY_EXPRESSION: {
3653af6ab5fSopenharmony_ci            arrowStatus |= ValidateArrowParameter(expr, &seenOptional);
3663af6ab5fSopenharmony_ci
3673af6ab5fSopenharmony_ci            params.push_back(expr);
3683af6ab5fSopenharmony_ci            break;
3693af6ab5fSopenharmony_ci        }
3703af6ab5fSopenharmony_ci        case ir::AstNodeType::SEQUENCE_EXPRESSION: {
3713af6ab5fSopenharmony_ci            auto &sequence = expr->AsSequenceExpression()->Sequence();
3723af6ab5fSopenharmony_ci
3733af6ab5fSopenharmony_ci            for (auto *it : sequence) {
3743af6ab5fSopenharmony_ci                arrowStatus |= ValidateArrowParameter(it, &seenOptional);
3753af6ab5fSopenharmony_ci            }
3763af6ab5fSopenharmony_ci
3773af6ab5fSopenharmony_ci            params.swap(sequence);
3783af6ab5fSopenharmony_ci            break;
3793af6ab5fSopenharmony_ci        }
3803af6ab5fSopenharmony_ci        case ir::AstNodeType::CALL_EXPRESSION: {
3813af6ab5fSopenharmony_ci            if (isAsync) {
3823af6ab5fSopenharmony_ci                auto *callExpression = expr->AsCallExpression();
3833af6ab5fSopenharmony_ci                auto &arguments = callExpression->Arguments();
3843af6ab5fSopenharmony_ci
3853af6ab5fSopenharmony_ci                if (callExpression->HasTrailingComma()) {
3863af6ab5fSopenharmony_ci                    ASSERT(!arguments.empty());
3873af6ab5fSopenharmony_ci                    ThrowSyntaxError("Rest parameter must be last formal parameter", arguments.back()->End());
3883af6ab5fSopenharmony_ci                }
3893af6ab5fSopenharmony_ci
3903af6ab5fSopenharmony_ci                for (auto *it : arguments) {
3913af6ab5fSopenharmony_ci                    arrowStatus |= ValidateArrowParameter(it, &seenOptional);
3923af6ab5fSopenharmony_ci                }
3933af6ab5fSopenharmony_ci
3943af6ab5fSopenharmony_ci                params.swap(arguments);
3953af6ab5fSopenharmony_ci                break;
3963af6ab5fSopenharmony_ci            }
3973af6ab5fSopenharmony_ci
3983af6ab5fSopenharmony_ci            [[fallthrough]];
3993af6ab5fSopenharmony_ci        }
4003af6ab5fSopenharmony_ci        default: {
4013af6ab5fSopenharmony_ci            ThrowSyntaxError("Unexpected token, arrow (=>)");
4023af6ab5fSopenharmony_ci        }
4033af6ab5fSopenharmony_ci    }
4043af6ab5fSopenharmony_ci
4053af6ab5fSopenharmony_ci    return ArrowFunctionDescriptor {std::move(params), expr->Start(), arrowStatus};
4063af6ab5fSopenharmony_ci}
4073af6ab5fSopenharmony_ci
4083af6ab5fSopenharmony_ciir::ArrowFunctionExpression *ParserImpl::ParseArrowFunctionExpression(ir::Expression *expr,
4093af6ab5fSopenharmony_ci                                                                      ir::TSTypeParameterDeclaration *typeParamDecl,
4103af6ab5fSopenharmony_ci                                                                      ir::TypeNode *returnTypeAnnotation, bool isAsync)
4113af6ab5fSopenharmony_ci{
4123af6ab5fSopenharmony_ci    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW);
4133af6ab5fSopenharmony_ci
4143af6ab5fSopenharmony_ci    if (lexer_->GetToken().NewLine()) {
4153af6ab5fSopenharmony_ci        ThrowSyntaxError(
4163af6ab5fSopenharmony_ci            "expected '=>' on the same line after an argument list, "
4173af6ab5fSopenharmony_ci            "got line terminator");
4183af6ab5fSopenharmony_ci    }
4193af6ab5fSopenharmony_ci
4203af6ab5fSopenharmony_ci    ArrowFunctionContext arrowFunctionContext(this, isAsync);
4213af6ab5fSopenharmony_ci    FunctionParameterContext functionParamContext(&context_);
4223af6ab5fSopenharmony_ci    ArrowFunctionDescriptor desc = ConvertToArrowParameter(expr, isAsync);
4233af6ab5fSopenharmony_ci
4243af6ab5fSopenharmony_ci    return ParseArrowFunctionExpressionBody(&arrowFunctionContext, &desc, typeParamDecl, returnTypeAnnotation);
4253af6ab5fSopenharmony_ci}
4263af6ab5fSopenharmony_ci
4273af6ab5fSopenharmony_civoid ParserImpl::ValidateArrowFunctionRestParameter([[maybe_unused]] ir::SpreadElement *restElement)
4283af6ab5fSopenharmony_ci{
4293af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
4303af6ab5fSopenharmony_ci        ThrowSyntaxError("Rest parameter must be last formal parameter");
4313af6ab5fSopenharmony_ci    }
4323af6ab5fSopenharmony_ci}
4333af6ab5fSopenharmony_ci
4343af6ab5fSopenharmony_ci// NOLINTNEXTLINE(google-default-arguments)
4353af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParseCoverParenthesizedExpressionAndArrowParameterList(
4363af6ab5fSopenharmony_ci    [[maybe_unused]] ExpressionParseFlags flags)
4373af6ab5fSopenharmony_ci{
4383af6ab5fSopenharmony_ci    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
4393af6ab5fSopenharmony_ci    lexer::SourcePosition start = lexer_->GetToken().Start();
4403af6ab5fSopenharmony_ci    lexer_->NextToken();
4413af6ab5fSopenharmony_ci
4423af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
4433af6ab5fSopenharmony_ci        ir::SpreadElement *restElement = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN);
4443af6ab5fSopenharmony_ci
4453af6ab5fSopenharmony_ci        restElement->SetGrouped();
4463af6ab5fSopenharmony_ci        restElement->SetStart(start);
4473af6ab5fSopenharmony_ci
4483af6ab5fSopenharmony_ci        ValidateArrowFunctionRestParameter(restElement);
4493af6ab5fSopenharmony_ci
4503af6ab5fSopenharmony_ci        lexer_->NextToken();
4513af6ab5fSopenharmony_ci
4523af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
4533af6ab5fSopenharmony_ci            ThrowSyntaxError("Unexpected token");
4543af6ab5fSopenharmony_ci        }
4553af6ab5fSopenharmony_ci
4563af6ab5fSopenharmony_ci        return ParseArrowFunctionExpression(restElement, nullptr, nullptr, false);
4573af6ab5fSopenharmony_ci    }
4583af6ab5fSopenharmony_ci
4593af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
4603af6ab5fSopenharmony_ci        lexer_->NextToken();
4613af6ab5fSopenharmony_ci
4623af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
4633af6ab5fSopenharmony_ci            ThrowSyntaxError("Unexpected token");
4643af6ab5fSopenharmony_ci        }
4653af6ab5fSopenharmony_ci
4663af6ab5fSopenharmony_ci        auto *arrowExpr = ParseArrowFunctionExpression(nullptr, nullptr, nullptr, false);
4673af6ab5fSopenharmony_ci        arrowExpr->SetStart(start);
4683af6ab5fSopenharmony_ci        arrowExpr->AsArrowFunctionExpression()->Function()->SetStart(start);
4693af6ab5fSopenharmony_ci
4703af6ab5fSopenharmony_ci        return arrowExpr;
4713af6ab5fSopenharmony_ci    }
4723af6ab5fSopenharmony_ci
4733af6ab5fSopenharmony_ci    ir::Expression *expr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::ACCEPT_REST |
4743af6ab5fSopenharmony_ci                                           ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
4753af6ab5fSopenharmony_ci
4763af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
4773af6ab5fSopenharmony_ci        ThrowSyntaxError("Unexpected token, expected ')'");
4783af6ab5fSopenharmony_ci    }
4793af6ab5fSopenharmony_ci
4803af6ab5fSopenharmony_ci    expr->SetGrouped();
4813af6ab5fSopenharmony_ci    expr->SetRange({start, lexer_->GetToken().End()});
4823af6ab5fSopenharmony_ci    lexer_->NextToken();
4833af6ab5fSopenharmony_ci
4843af6ab5fSopenharmony_ci    return expr;
4853af6ab5fSopenharmony_ci}
4863af6ab5fSopenharmony_ci
4873af6ab5fSopenharmony_civoid ParserImpl::CheckInvalidDestructuring(const ir::AstNode *object) const
4883af6ab5fSopenharmony_ci{
4893af6ab5fSopenharmony_ci    object->Iterate([this](ir::AstNode *childNode) -> void {
4903af6ab5fSopenharmony_ci        switch (childNode->Type()) {
4913af6ab5fSopenharmony_ci            case ir::AstNodeType::ASSIGNMENT_PATTERN: {
4923af6ab5fSopenharmony_ci                ThrowSyntaxError("Invalid property initializer");
4933af6ab5fSopenharmony_ci                break;
4943af6ab5fSopenharmony_ci            }
4953af6ab5fSopenharmony_ci            case ir::AstNodeType::REST_ELEMENT:
4963af6ab5fSopenharmony_ci            case ir::AstNodeType::PROPERTY:
4973af6ab5fSopenharmony_ci            case ir::AstNodeType::OBJECT_EXPRESSION: {
4983af6ab5fSopenharmony_ci                CheckInvalidDestructuring(childNode);
4993af6ab5fSopenharmony_ci                break;
5003af6ab5fSopenharmony_ci            }
5013af6ab5fSopenharmony_ci            default: {
5023af6ab5fSopenharmony_ci                break;
5033af6ab5fSopenharmony_ci            }
5043af6ab5fSopenharmony_ci        }
5053af6ab5fSopenharmony_ci    });
5063af6ab5fSopenharmony_ci}
5073af6ab5fSopenharmony_ci
5083af6ab5fSopenharmony_civoid ParserImpl::ValidateGroupedExpression(ir::Expression *lhsExpression)
5093af6ab5fSopenharmony_ci{
5103af6ab5fSopenharmony_ci    lexer::TokenType tokenType = lexer_->GetToken().Type();
5113af6ab5fSopenharmony_ci    if (lhsExpression->IsGrouped() && tokenType != lexer::TokenType::PUNCTUATOR_ARROW) {
5123af6ab5fSopenharmony_ci        if (lhsExpression->IsSequenceExpression()) {
5133af6ab5fSopenharmony_ci            for (auto *seq : lhsExpression->AsSequenceExpression()->Sequence()) {
5143af6ab5fSopenharmony_ci                ValidateParenthesizedExpression(seq);
5153af6ab5fSopenharmony_ci            }
5163af6ab5fSopenharmony_ci        } else {
5173af6ab5fSopenharmony_ci            ValidateParenthesizedExpression(lhsExpression);
5183af6ab5fSopenharmony_ci        }
5193af6ab5fSopenharmony_ci    }
5203af6ab5fSopenharmony_ci}
5213af6ab5fSopenharmony_ci
5223af6ab5fSopenharmony_civoid ParserImpl::ValidateParenthesizedExpression(ir::Expression *lhsExpression)
5233af6ab5fSopenharmony_ci{
5243af6ab5fSopenharmony_ci    switch (lhsExpression->Type()) {
5253af6ab5fSopenharmony_ci        case ir::AstNodeType::IDENTIFIER: {
5263af6ab5fSopenharmony_ci            auto info = lhsExpression->AsIdentifier()->ValidateExpression();
5273af6ab5fSopenharmony_ci            if (info.Fail()) {
5283af6ab5fSopenharmony_ci                ThrowSyntaxError(info.msg.Utf8(), info.pos);
5293af6ab5fSopenharmony_ci            }
5303af6ab5fSopenharmony_ci            break;
5313af6ab5fSopenharmony_ci        }
5323af6ab5fSopenharmony_ci        case ir::AstNodeType::MEMBER_EXPRESSION: {
5333af6ab5fSopenharmony_ci            break;
5343af6ab5fSopenharmony_ci        }
5353af6ab5fSopenharmony_ci        case ir::AstNodeType::ARRAY_EXPRESSION: {
5363af6ab5fSopenharmony_ci            auto info = lhsExpression->AsArrayExpression()->ValidateExpression();
5373af6ab5fSopenharmony_ci            if (info.Fail()) {
5383af6ab5fSopenharmony_ci                ThrowSyntaxError(info.msg.Utf8(), info.pos);
5393af6ab5fSopenharmony_ci            }
5403af6ab5fSopenharmony_ci            break;
5413af6ab5fSopenharmony_ci        }
5423af6ab5fSopenharmony_ci        case ir::AstNodeType::OBJECT_EXPRESSION: {
5433af6ab5fSopenharmony_ci            auto info = lhsExpression->AsObjectExpression()->ValidateExpression();
5443af6ab5fSopenharmony_ci            if (info.Fail()) {
5453af6ab5fSopenharmony_ci                ThrowSyntaxError(info.msg.Utf8(), info.pos);
5463af6ab5fSopenharmony_ci            }
5473af6ab5fSopenharmony_ci            break;
5483af6ab5fSopenharmony_ci        }
5493af6ab5fSopenharmony_ci        case ir::AstNodeType::ASSIGNMENT_EXPRESSION: {
5503af6ab5fSopenharmony_ci            if (lhsExpression->AsAssignmentExpression()->ConvertibleToAssignmentPattern(false)) {
5513af6ab5fSopenharmony_ci                break;
5523af6ab5fSopenharmony_ci            }
5533af6ab5fSopenharmony_ci            [[fallthrough]];
5543af6ab5fSopenharmony_ci        }
5553af6ab5fSopenharmony_ci        case ir::AstNodeType::SPREAD_ELEMENT: {
5563af6ab5fSopenharmony_ci            ThrowSyntaxError("Invalid left-hand side in assignment expression");
5573af6ab5fSopenharmony_ci        }
5583af6ab5fSopenharmony_ci        default: {
5593af6ab5fSopenharmony_ci            break;
5603af6ab5fSopenharmony_ci        }
5613af6ab5fSopenharmony_ci    }
5623af6ab5fSopenharmony_ci}
5633af6ab5fSopenharmony_ci
5643af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParsePrefixAssertionExpression()
5653af6ab5fSopenharmony_ci{
5663af6ab5fSopenharmony_ci    ThrowSyntaxError({"Unexpected token '", lexer::TokenToString(lexer_->GetToken().Type()), "'."});
5673af6ab5fSopenharmony_ci    return nullptr;
5683af6ab5fSopenharmony_ci}
5693af6ab5fSopenharmony_ci
5703af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParseAssignmentExpression(ir::Expression *lhsExpression, ExpressionParseFlags flags)
5713af6ab5fSopenharmony_ci{
5723af6ab5fSopenharmony_ci    ValidateGroupedExpression(lhsExpression);
5733af6ab5fSopenharmony_ci
5743af6ab5fSopenharmony_ci    lexer::TokenType tokenType = lexer_->GetToken().Type();
5753af6ab5fSopenharmony_ci    switch (tokenType) {
5763af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_QUESTION_MARK: {
5773af6ab5fSopenharmony_ci            lexer_->NextToken();
5783af6ab5fSopenharmony_ci            ir::Expression *consequent = ParseExpression();
5793af6ab5fSopenharmony_ci
5803af6ab5fSopenharmony_ci            if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
5813af6ab5fSopenharmony_ci                ThrowSyntaxError("Unexpected token, expected ':'");
5823af6ab5fSopenharmony_ci            }
5833af6ab5fSopenharmony_ci
5843af6ab5fSopenharmony_ci            lexer_->NextToken();
5853af6ab5fSopenharmony_ci            ir::Expression *alternate = ParseExpression();
5863af6ab5fSopenharmony_ci
5873af6ab5fSopenharmony_ci            auto *conditionalExpr = AllocNode<ir::ConditionalExpression>(lhsExpression, consequent, alternate);
5883af6ab5fSopenharmony_ci            conditionalExpr->SetRange({lhsExpression->Start(), alternate->End()});
5893af6ab5fSopenharmony_ci            return conditionalExpr;
5903af6ab5fSopenharmony_ci        }
5913af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_ARROW: {
5923af6ab5fSopenharmony_ci            if (lexer_->GetToken().NewLine()) {
5933af6ab5fSopenharmony_ci                ThrowSyntaxError("Uncaught SyntaxError: expected expression, got '=>'");
5943af6ab5fSopenharmony_ci            }
5953af6ab5fSopenharmony_ci
5963af6ab5fSopenharmony_ci            return ParseArrowFunctionExpression(lhsExpression, nullptr, nullptr, false);
5973af6ab5fSopenharmony_ci        }
5983af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: {
5993af6ab5fSopenharmony_ci            ValidateAssignmentTarget(flags, lhsExpression);
6003af6ab5fSopenharmony_ci
6013af6ab5fSopenharmony_ci            lexer_->NextToken();
6023af6ab5fSopenharmony_ci            ir::Expression *assignmentExpression = ParseExpression(CarryPatternFlags(flags));
6033af6ab5fSopenharmony_ci
6043af6ab5fSopenharmony_ci            auto *binaryAssignmentExpression =
6053af6ab5fSopenharmony_ci                AllocNode<ir::AssignmentExpression>(lhsExpression, assignmentExpression, tokenType);
6063af6ab5fSopenharmony_ci
6073af6ab5fSopenharmony_ci            binaryAssignmentExpression->SetRange({lhsExpression->Start(), assignmentExpression->End()});
6083af6ab5fSopenharmony_ci            return binaryAssignmentExpression;
6093af6ab5fSopenharmony_ci        }
6103af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_AS: {
6113af6ab5fSopenharmony_ci            if (auto asExpression = ParsePotentialAsExpression(lhsExpression); asExpression != nullptr) {
6123af6ab5fSopenharmony_ci                return ParseAssignmentExpression(asExpression);
6133af6ab5fSopenharmony_ci            }
6143af6ab5fSopenharmony_ci            break;
6153af6ab5fSopenharmony_ci        }
6163af6ab5fSopenharmony_ci        default: {
6173af6ab5fSopenharmony_ci            auto expression = ParseAssignmentBinaryExpression(tokenType, lhsExpression, flags);
6183af6ab5fSopenharmony_ci            if (expression == nullptr) {
6193af6ab5fSopenharmony_ci                expression = ParseAssignmentEqualExpression(tokenType, lhsExpression, flags);
6203af6ab5fSopenharmony_ci            }
6213af6ab5fSopenharmony_ci
6223af6ab5fSopenharmony_ci            if (expression != nullptr) {
6233af6ab5fSopenharmony_ci                return expression;
6243af6ab5fSopenharmony_ci            }
6253af6ab5fSopenharmony_ci
6263af6ab5fSopenharmony_ci            break;
6273af6ab5fSopenharmony_ci        }
6283af6ab5fSopenharmony_ci    }
6293af6ab5fSopenharmony_ci
6303af6ab5fSopenharmony_ci    return lhsExpression;
6313af6ab5fSopenharmony_ci}
6323af6ab5fSopenharmony_ci
6333af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParseAssignmentBinaryExpression(const lexer::TokenType tokenType,
6343af6ab5fSopenharmony_ci                                                            ir::Expression *lhsExpression,
6353af6ab5fSopenharmony_ci                                                            const ExpressionParseFlags flags)
6363af6ab5fSopenharmony_ci{
6373af6ab5fSopenharmony_ci    switch (tokenType) {
6383af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_IN: {
6393af6ab5fSopenharmony_ci            if ((flags & ExpressionParseFlags::STOP_AT_IN) != 0) {
6403af6ab5fSopenharmony_ci                break;
6413af6ab5fSopenharmony_ci            }
6423af6ab5fSopenharmony_ci
6433af6ab5fSopenharmony_ci            [[fallthrough]];
6443af6ab5fSopenharmony_ci        }
6453af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING:
6463af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LOGICAL_OR:
6473af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LOGICAL_AND:
6483af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_BITWISE_OR:
6493af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_BITWISE_XOR:
6503af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_BITWISE_AND:
6513af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_EQUAL:
6523af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_NOT_EQUAL:
6533af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL:
6543af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL:
6553af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LESS_THAN:
6563af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL:
6573af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_GREATER_THAN:
6583af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL:
6593af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT:
6603af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT:
6613af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT:
6623af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_PLUS:
6633af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_MINUS:
6643af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_MULTIPLY:
6653af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_DIVIDE:
6663af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_MOD:
6673af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_INSTANCEOF:
6683af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_EXPONENTIATION: {
6693af6ab5fSopenharmony_ci            return ParseAssignmentExpression(ParseBinaryExpression(lhsExpression));
6703af6ab5fSopenharmony_ci        }
6713af6ab5fSopenharmony_ci        default:
6723af6ab5fSopenharmony_ci            break;
6733af6ab5fSopenharmony_ci    }
6743af6ab5fSopenharmony_ci
6753af6ab5fSopenharmony_ci    return nullptr;
6763af6ab5fSopenharmony_ci}
6773af6ab5fSopenharmony_ci
6783af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParseAssignmentEqualExpression(const lexer::TokenType tokenType,
6793af6ab5fSopenharmony_ci                                                           ir::Expression *lhsExpression,
6803af6ab5fSopenharmony_ci                                                           const ExpressionParseFlags flags)
6813af6ab5fSopenharmony_ci{
6823af6ab5fSopenharmony_ci    switch (tokenType) {
6833af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL:
6843af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL:
6853af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL:
6863af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_PLUS_EQUAL:
6873af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_MINUS_EQUAL:
6883af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL:
6893af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL:
6903af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_MOD_EQUAL:
6913af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL:
6923af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL:
6933af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL:
6943af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_EXPONENTIATION_EQUAL: {
6953af6ab5fSopenharmony_ci            ValidateLvalueAssignmentTarget(lhsExpression);
6963af6ab5fSopenharmony_ci
6973af6ab5fSopenharmony_ci            lexer_->NextToken();
6983af6ab5fSopenharmony_ci            ir::Expression *assignmentExpression = ParseExpression(CarryPatternFlags(flags));
6993af6ab5fSopenharmony_ci
7003af6ab5fSopenharmony_ci            auto *binaryAssignmentExpression =
7013af6ab5fSopenharmony_ci                AllocNode<ir::AssignmentExpression>(lhsExpression, assignmentExpression, tokenType);
7023af6ab5fSopenharmony_ci
7033af6ab5fSopenharmony_ci            binaryAssignmentExpression->SetRange({lhsExpression->Start(), assignmentExpression->End()});
7043af6ab5fSopenharmony_ci            return binaryAssignmentExpression;
7053af6ab5fSopenharmony_ci        }
7063af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LOGICAL_AND_EQUAL:
7073af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LOGICAL_OR_EQUAL:
7083af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LOGICAL_NULLISH_EQUAL: {
7093af6ab5fSopenharmony_ci            ThrowUnexpectedToken(tokenType);
7103af6ab5fSopenharmony_ci        }
7113af6ab5fSopenharmony_ci        default:
7123af6ab5fSopenharmony_ci            break;
7133af6ab5fSopenharmony_ci    }
7143af6ab5fSopenharmony_ci
7153af6ab5fSopenharmony_ci    return nullptr;
7163af6ab5fSopenharmony_ci}
7173af6ab5fSopenharmony_ci
7183af6ab5fSopenharmony_ciir::TemplateLiteral *ParserImpl::ParseTemplateLiteral()
7193af6ab5fSopenharmony_ci{
7203af6ab5fSopenharmony_ci    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
7213af6ab5fSopenharmony_ci
7223af6ab5fSopenharmony_ci    ArenaVector<ir::TemplateElement *> quasis(Allocator()->Adapter());
7233af6ab5fSopenharmony_ci    ArenaVector<ir::Expression *> expressions(Allocator()->Adapter());
7243af6ab5fSopenharmony_ci
7253af6ab5fSopenharmony_ci    while (true) {
7263af6ab5fSopenharmony_ci        lexer_->ResetTokenEnd();
7273af6ab5fSopenharmony_ci        const auto startPos = lexer_->Save();
7283af6ab5fSopenharmony_ci
7293af6ab5fSopenharmony_ci        lexer_->ScanString<lexer::LEX_CHAR_BACK_TICK>();
7303af6ab5fSopenharmony_ci        util::StringView cooked = lexer_->GetToken().String();
7313af6ab5fSopenharmony_ci
7323af6ab5fSopenharmony_ci        lexer_->Rewind(startPos);
7333af6ab5fSopenharmony_ci        auto [raw, end, scanExpression] = lexer_->ScanTemplateString();
7343af6ab5fSopenharmony_ci
7353af6ab5fSopenharmony_ci        auto *element = AllocNode<ir::TemplateElement>(raw.View(), cooked);
7363af6ab5fSopenharmony_ci        element->SetRange({lexer::SourcePosition {startPos.Iterator().Index(), startPos.Line()},
7373af6ab5fSopenharmony_ci                           lexer::SourcePosition {end, lexer_->Line()}});
7383af6ab5fSopenharmony_ci        quasis.push_back(element);
7393af6ab5fSopenharmony_ci
7403af6ab5fSopenharmony_ci        if (!scanExpression) {
7413af6ab5fSopenharmony_ci            lexer_->ScanTemplateStringEnd();
7423af6ab5fSopenharmony_ci            break;
7433af6ab5fSopenharmony_ci        }
7443af6ab5fSopenharmony_ci
7453af6ab5fSopenharmony_ci        ir::Expression *expression = nullptr;
7463af6ab5fSopenharmony_ci
7473af6ab5fSopenharmony_ci        {
7483af6ab5fSopenharmony_ci            lexer::TemplateLiteralParserContext ctx(lexer_);
7493af6ab5fSopenharmony_ci            lexer_->PushTemplateContext(&ctx);
7503af6ab5fSopenharmony_ci            lexer_->NextToken();
7513af6ab5fSopenharmony_ci            expression = ParseExpression();
7523af6ab5fSopenharmony_ci        }
7533af6ab5fSopenharmony_ci
7543af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
7553af6ab5fSopenharmony_ci            ThrowSyntaxError("Unexpected token, expected '}'.");
7563af6ab5fSopenharmony_ci        }
7573af6ab5fSopenharmony_ci
7583af6ab5fSopenharmony_ci        expressions.push_back(expression);
7593af6ab5fSopenharmony_ci    }
7603af6ab5fSopenharmony_ci
7613af6ab5fSopenharmony_ci    auto *templateNode = AllocNode<ir::TemplateLiteral>(std::move(quasis), std::move(expressions));
7623af6ab5fSopenharmony_ci    templateNode->SetRange({startLoc, lexer_->GetToken().End()});
7633af6ab5fSopenharmony_ci
7643af6ab5fSopenharmony_ci    lexer_->NextToken();
7653af6ab5fSopenharmony_ci
7663af6ab5fSopenharmony_ci    return templateNode;
7673af6ab5fSopenharmony_ci}
7683af6ab5fSopenharmony_ci
7693af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParseNewExpression()
7703af6ab5fSopenharmony_ci{
7713af6ab5fSopenharmony_ci    lexer::SourcePosition start = lexer_->GetToken().Start();
7723af6ab5fSopenharmony_ci
7733af6ab5fSopenharmony_ci    lexer_->NextToken();  // eat new
7743af6ab5fSopenharmony_ci
7753af6ab5fSopenharmony_ci    // parse callee part of NewExpression
7763af6ab5fSopenharmony_ci    ir::Expression *callee = ParseMemberExpression(true);
7773af6ab5fSopenharmony_ci    if (callee->IsImportExpression() && !callee->IsGrouped()) {
7783af6ab5fSopenharmony_ci        ThrowSyntaxError("Cannot use new with import(...)");
7793af6ab5fSopenharmony_ci    }
7803af6ab5fSopenharmony_ci
7813af6ab5fSopenharmony_ci    ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
7823af6ab5fSopenharmony_ci
7833af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
7843af6ab5fSopenharmony_ci        lexer::SourcePosition endLoc = callee->End();
7853af6ab5fSopenharmony_ci        auto *newExprNode = AllocNode<ir::NewExpression>(callee, std::move(arguments));
7863af6ab5fSopenharmony_ci        newExprNode->SetRange({start, endLoc});
7873af6ab5fSopenharmony_ci
7883af6ab5fSopenharmony_ci        return newExprNode;
7893af6ab5fSopenharmony_ci    }
7903af6ab5fSopenharmony_ci
7913af6ab5fSopenharmony_ci    lexer_->NextToken();  // eat left parenthesis
7923af6ab5fSopenharmony_ci
7933af6ab5fSopenharmony_ci    // parse argument part of NewExpression
7943af6ab5fSopenharmony_ci    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
7953af6ab5fSopenharmony_ci        ir::Expression *argument = nullptr;
7963af6ab5fSopenharmony_ci
7973af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
7983af6ab5fSopenharmony_ci            argument = ParseSpreadElement();
7993af6ab5fSopenharmony_ci        } else {
8003af6ab5fSopenharmony_ci            argument = ParseExpression();
8013af6ab5fSopenharmony_ci        }
8023af6ab5fSopenharmony_ci
8033af6ab5fSopenharmony_ci        arguments.push_back(argument);
8043af6ab5fSopenharmony_ci
8053af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
8063af6ab5fSopenharmony_ci            lexer_->NextToken();  // eat comma
8073af6ab5fSopenharmony_ci        }
8083af6ab5fSopenharmony_ci
8093af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() == lexer::TokenType::EOS) {
8103af6ab5fSopenharmony_ci            ThrowSyntaxError("Unexpected token in argument parsing");
8113af6ab5fSopenharmony_ci        }
8123af6ab5fSopenharmony_ci    }
8133af6ab5fSopenharmony_ci
8143af6ab5fSopenharmony_ci    auto *newExprNode = AllocNode<ir::NewExpression>(callee, std::move(arguments));
8153af6ab5fSopenharmony_ci    newExprNode->SetRange({start, lexer_->GetToken().End()});
8163af6ab5fSopenharmony_ci
8173af6ab5fSopenharmony_ci    lexer_->NextToken();
8183af6ab5fSopenharmony_ci
8193af6ab5fSopenharmony_ci    return newExprNode;
8203af6ab5fSopenharmony_ci}
8213af6ab5fSopenharmony_ci
8223af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParseLeftHandSideExpression(ExpressionParseFlags flags)
8233af6ab5fSopenharmony_ci{
8243af6ab5fSopenharmony_ci    return ParseMemberExpression(false, flags);
8253af6ab5fSopenharmony_ci}
8263af6ab5fSopenharmony_ci
8273af6ab5fSopenharmony_ciir::MetaProperty *ParserImpl::ParsePotentialNewTarget()
8283af6ab5fSopenharmony_ci{
8293af6ab5fSopenharmony_ci    lexer::SourceRange loc = lexer_->GetToken().Loc();
8303af6ab5fSopenharmony_ci
8313af6ab5fSopenharmony_ci    if (lexer_->Lookahead() == lexer::LEX_CHAR_DOT) {
8323af6ab5fSopenharmony_ci        lexer_->NextToken();
8333af6ab5fSopenharmony_ci        lexer_->NextToken();
8343af6ab5fSopenharmony_ci
8353af6ab5fSopenharmony_ci        if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TARGET) {
8363af6ab5fSopenharmony_ci            if ((context_.Status() & ParserStatus::ALLOW_NEW_TARGET) == 0) {
8373af6ab5fSopenharmony_ci                ThrowSyntaxError("'new.Target' is not allowed here");
8383af6ab5fSopenharmony_ci            }
8393af6ab5fSopenharmony_ci
8403af6ab5fSopenharmony_ci            if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0) {
8413af6ab5fSopenharmony_ci                ThrowSyntaxError("'new.Target' must not contain escaped characters");
8423af6ab5fSopenharmony_ci            }
8433af6ab5fSopenharmony_ci
8443af6ab5fSopenharmony_ci            auto *metaProperty = AllocNode<ir::MetaProperty>(ir::MetaProperty::MetaPropertyKind::NEW_TARGET);
8453af6ab5fSopenharmony_ci            metaProperty->SetRange(loc);
8463af6ab5fSopenharmony_ci            lexer_->NextToken();
8473af6ab5fSopenharmony_ci            return metaProperty;
8483af6ab5fSopenharmony_ci        }
8493af6ab5fSopenharmony_ci    }
8503af6ab5fSopenharmony_ci
8513af6ab5fSopenharmony_ci    return nullptr;
8523af6ab5fSopenharmony_ci}
8533af6ab5fSopenharmony_ci
8543af6ab5fSopenharmony_ciir::Identifier *ParserImpl::ParsePrimaryExpressionIdent([[maybe_unused]] ExpressionParseFlags flags)
8553af6ab5fSopenharmony_ci{
8563af6ab5fSopenharmony_ci    auto *identNode = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
8573af6ab5fSopenharmony_ci    identNode->SetReference();
8583af6ab5fSopenharmony_ci    identNode->SetRange(lexer_->GetToken().Loc());
8593af6ab5fSopenharmony_ci
8603af6ab5fSopenharmony_ci    lexer_->NextToken();
8613af6ab5fSopenharmony_ci    return identNode;
8623af6ab5fSopenharmony_ci}
8633af6ab5fSopenharmony_ci
8643af6ab5fSopenharmony_ciir::BooleanLiteral *ParserImpl::ParseBooleanLiteral()
8653af6ab5fSopenharmony_ci{
8663af6ab5fSopenharmony_ci    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_TRUE ||
8673af6ab5fSopenharmony_ci           lexer_->GetToken().Type() == lexer::TokenType::LITERAL_FALSE);
8683af6ab5fSopenharmony_ci
8693af6ab5fSopenharmony_ci    auto *booleanNode = AllocNode<ir::BooleanLiteral>(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_TRUE);
8703af6ab5fSopenharmony_ci    booleanNode->SetRange(lexer_->GetToken().Loc());
8713af6ab5fSopenharmony_ci
8723af6ab5fSopenharmony_ci    lexer_->NextToken();
8733af6ab5fSopenharmony_ci    return booleanNode;
8743af6ab5fSopenharmony_ci}
8753af6ab5fSopenharmony_ci
8763af6ab5fSopenharmony_ciir::NullLiteral *ParserImpl::ParseNullLiteral()
8773af6ab5fSopenharmony_ci{
8783af6ab5fSopenharmony_ci    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_NULL);
8793af6ab5fSopenharmony_ci    auto *nullNode = AllocNode<ir::NullLiteral>();
8803af6ab5fSopenharmony_ci    nullNode->SetRange(lexer_->GetToken().Loc());
8813af6ab5fSopenharmony_ci
8823af6ab5fSopenharmony_ci    lexer_->NextToken();
8833af6ab5fSopenharmony_ci    return nullNode;
8843af6ab5fSopenharmony_ci}
8853af6ab5fSopenharmony_ci
8863af6ab5fSopenharmony_ciir::Literal *ParserImpl::ParseNumberLiteral()
8873af6ab5fSopenharmony_ci{
8883af6ab5fSopenharmony_ci    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_NUMBER);
8893af6ab5fSopenharmony_ci
8903af6ab5fSopenharmony_ci    ir::Literal *numberNode {};
8913af6ab5fSopenharmony_ci
8923af6ab5fSopenharmony_ci    if ((lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) != 0U) {
8933af6ab5fSopenharmony_ci        numberNode = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
8943af6ab5fSopenharmony_ci    } else {
8953af6ab5fSopenharmony_ci        numberNode = AllocNode<ir::NumberLiteral>(lexer_->GetToken().GetNumber());
8963af6ab5fSopenharmony_ci    }
8973af6ab5fSopenharmony_ci
8983af6ab5fSopenharmony_ci    numberNode->SetRange(lexer_->GetToken().Loc());
8993af6ab5fSopenharmony_ci
9003af6ab5fSopenharmony_ci    lexer_->NextToken();
9013af6ab5fSopenharmony_ci    return numberNode;
9023af6ab5fSopenharmony_ci}
9033af6ab5fSopenharmony_ci
9043af6ab5fSopenharmony_ciir::CharLiteral *ParserImpl::ParseCharLiteral()
9053af6ab5fSopenharmony_ci{
9063af6ab5fSopenharmony_ci    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_CHAR);
9073af6ab5fSopenharmony_ci
9083af6ab5fSopenharmony_ci    auto *charNode = AllocNode<ir::CharLiteral>(lexer_->GetToken().Utf16());
9093af6ab5fSopenharmony_ci    charNode->SetRange(lexer_->GetToken().Loc());
9103af6ab5fSopenharmony_ci
9113af6ab5fSopenharmony_ci    lexer_->NextToken();
9123af6ab5fSopenharmony_ci    return charNode;
9133af6ab5fSopenharmony_ci}
9143af6ab5fSopenharmony_ci
9153af6ab5fSopenharmony_ciir::StringLiteral *ParserImpl::ParseStringLiteral()
9163af6ab5fSopenharmony_ci{
9173af6ab5fSopenharmony_ci    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
9183af6ab5fSopenharmony_ci
9193af6ab5fSopenharmony_ci    auto *stringNode = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
9203af6ab5fSopenharmony_ci    stringNode->SetRange(lexer_->GetToken().Loc());
9213af6ab5fSopenharmony_ci
9223af6ab5fSopenharmony_ci    lexer_->NextToken();
9233af6ab5fSopenharmony_ci    return stringNode;
9243af6ab5fSopenharmony_ci}
9253af6ab5fSopenharmony_ci
9263af6ab5fSopenharmony_ciir::UndefinedLiteral *ParserImpl::ParseUndefinedLiteral()
9273af6ab5fSopenharmony_ci{
9283af6ab5fSopenharmony_ci    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_UNDEFINED);
9293af6ab5fSopenharmony_ci    auto *undefinedNode = AllocNode<ir::UndefinedLiteral>();
9303af6ab5fSopenharmony_ci    undefinedNode->SetRange(lexer_->GetToken().Loc());
9313af6ab5fSopenharmony_ci
9323af6ab5fSopenharmony_ci    lexer_->NextToken();
9333af6ab5fSopenharmony_ci    return undefinedNode;
9343af6ab5fSopenharmony_ci}
9353af6ab5fSopenharmony_ci
9363af6ab5fSopenharmony_ciir::ThisExpression *ParserImpl::ParseThisExpression()
9373af6ab5fSopenharmony_ci{
9383af6ab5fSopenharmony_ci    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_THIS);
9393af6ab5fSopenharmony_ci
9403af6ab5fSopenharmony_ci    auto *thisExprNode = AllocNode<ir::ThisExpression>();
9413af6ab5fSopenharmony_ci    thisExprNode->SetRange(lexer_->GetToken().Loc());
9423af6ab5fSopenharmony_ci
9433af6ab5fSopenharmony_ci    lexer_->NextToken();
9443af6ab5fSopenharmony_ci    return thisExprNode;
9453af6ab5fSopenharmony_ci}
9463af6ab5fSopenharmony_ci
9473af6ab5fSopenharmony_ciir::RegExpLiteral *ParserImpl::ParseRegularExpression()
9483af6ab5fSopenharmony_ci{
9493af6ab5fSopenharmony_ci    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_DIVIDE ||
9503af6ab5fSopenharmony_ci           lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL);
9513af6ab5fSopenharmony_ci
9523af6ab5fSopenharmony_ci    lexer_->ResetTokenEnd();
9533af6ab5fSopenharmony_ci    auto regexp = lexer_->ScanRegExp();
9543af6ab5fSopenharmony_ci
9553af6ab5fSopenharmony_ci    lexer::RegExpParser reParser(regexp, Allocator(), *this);
9563af6ab5fSopenharmony_ci
9573af6ab5fSopenharmony_ci    reParser.ParsePattern();
9583af6ab5fSopenharmony_ci
9593af6ab5fSopenharmony_ci    auto *regexpNode = AllocNode<ir::RegExpLiteral>(regexp.patternStr, regexp.flags, regexp.flagsStr);
9603af6ab5fSopenharmony_ci    regexpNode->SetRange(lexer_->GetToken().Loc());
9613af6ab5fSopenharmony_ci
9623af6ab5fSopenharmony_ci    lexer_->NextToken();
9633af6ab5fSopenharmony_ci    return regexpNode;
9643af6ab5fSopenharmony_ci}
9653af6ab5fSopenharmony_ci
9663af6ab5fSopenharmony_ciir::SuperExpression *ParserImpl::ParseSuperExpression()
9673af6ab5fSopenharmony_ci{
9683af6ab5fSopenharmony_ci    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_SUPER);
9693af6ab5fSopenharmony_ci
9703af6ab5fSopenharmony_ci    auto *superExprNode = AllocNode<ir::SuperExpression>();
9713af6ab5fSopenharmony_ci    superExprNode->SetRange(lexer_->GetToken().Loc());
9723af6ab5fSopenharmony_ci
9733af6ab5fSopenharmony_ci    lexer_->NextToken();  // eat super
9743af6ab5fSopenharmony_ci
9753af6ab5fSopenharmony_ci    if ((lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD ||
9763af6ab5fSopenharmony_ci         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) &&
9773af6ab5fSopenharmony_ci        (context_.Status() & ParserStatus::ALLOW_SUPER) != 0U) {
9783af6ab5fSopenharmony_ci        return superExprNode;
9793af6ab5fSopenharmony_ci    }
9803af6ab5fSopenharmony_ci
9813af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
9823af6ab5fSopenharmony_ci        (context_.Status() & ParserStatus::ALLOW_SUPER_CALL) != 0U) {
9833af6ab5fSopenharmony_ci        return superExprNode;
9843af6ab5fSopenharmony_ci    }
9853af6ab5fSopenharmony_ci
9863af6ab5fSopenharmony_ci    ThrowSyntaxError("Unexpected super keyword");
9873af6ab5fSopenharmony_ci}
9883af6ab5fSopenharmony_ci
9893af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParsePrimaryExpressionWithLiterals(ExpressionParseFlags flags)
9903af6ab5fSopenharmony_ci{
9913af6ab5fSopenharmony_ci    switch (lexer_->GetToken().Type()) {
9923af6ab5fSopenharmony_ci        case lexer::TokenType::LITERAL_IDENT: {
9933af6ab5fSopenharmony_ci            return ParsePrimaryExpressionIdent(flags);
9943af6ab5fSopenharmony_ci        }
9953af6ab5fSopenharmony_ci        case lexer::TokenType::LITERAL_TRUE:
9963af6ab5fSopenharmony_ci        case lexer::TokenType::LITERAL_FALSE: {
9973af6ab5fSopenharmony_ci            return ParseBooleanLiteral();
9983af6ab5fSopenharmony_ci        }
9993af6ab5fSopenharmony_ci        case lexer::TokenType::LITERAL_NULL: {
10003af6ab5fSopenharmony_ci            return ParseNullLiteral();
10013af6ab5fSopenharmony_ci        }
10023af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_UNDEFINED: {
10033af6ab5fSopenharmony_ci            return ParseUndefinedLiteral();
10043af6ab5fSopenharmony_ci        }
10053af6ab5fSopenharmony_ci        case lexer::TokenType::LITERAL_NUMBER: {
10063af6ab5fSopenharmony_ci            return ParseNumberLiteral();
10073af6ab5fSopenharmony_ci        }
10083af6ab5fSopenharmony_ci        case lexer::TokenType::LITERAL_STRING: {
10093af6ab5fSopenharmony_ci            return ParseStringLiteral();
10103af6ab5fSopenharmony_ci        }
10113af6ab5fSopenharmony_ci        default: {
10123af6ab5fSopenharmony_ci            break;
10133af6ab5fSopenharmony_ci        }
10143af6ab5fSopenharmony_ci    }
10153af6ab5fSopenharmony_ci
10163af6ab5fSopenharmony_ci    ThrowSyntaxError({"Unexpected token '", lexer::TokenToString(lexer_->GetToken().Type()), "'."});
10173af6ab5fSopenharmony_ci    return nullptr;
10183af6ab5fSopenharmony_ci}
10193af6ab5fSopenharmony_ci
10203af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParseHashMaskOperator()
10213af6ab5fSopenharmony_ci{
10223af6ab5fSopenharmony_ci    ValidatePrivateIdentifier();
10233af6ab5fSopenharmony_ci    auto *privateIdent = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
10243af6ab5fSopenharmony_ci    privateIdent->SetPrivate(true);
10253af6ab5fSopenharmony_ci    privateIdent->SetReference();
10263af6ab5fSopenharmony_ci    lexer_->NextToken();
10273af6ab5fSopenharmony_ci
10283af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_IN) {
10293af6ab5fSopenharmony_ci        ThrowSyntaxError("Unexpected private identifier");
10303af6ab5fSopenharmony_ci    }
10313af6ab5fSopenharmony_ci
10323af6ab5fSopenharmony_ci    return privateIdent;
10333af6ab5fSopenharmony_ci}
10343af6ab5fSopenharmony_ci
10353af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParseClassExpression()
10363af6ab5fSopenharmony_ci{
10373af6ab5fSopenharmony_ci    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
10383af6ab5fSopenharmony_ci    ir::ClassDefinition *classDefinition = ParseClassDefinition(ir::ClassDefinitionModifiers::ID_REQUIRED);
10393af6ab5fSopenharmony_ci
10403af6ab5fSopenharmony_ci    auto *classExpr = AllocNode<ir::ClassExpression>(classDefinition);
10413af6ab5fSopenharmony_ci    classExpr->SetRange({startLoc, classDefinition->End()});
10423af6ab5fSopenharmony_ci
10433af6ab5fSopenharmony_ci    return classExpr;
10443af6ab5fSopenharmony_ci}
10453af6ab5fSopenharmony_ci
10463af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParsePunctuators(ExpressionParseFlags flags)
10473af6ab5fSopenharmony_ci{
10483af6ab5fSopenharmony_ci    switch (lexer_->GetToken().Type()) {
10493af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_DIVIDE:
10503af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL: {
10513af6ab5fSopenharmony_ci            return ParseRegularExpression();
10523af6ab5fSopenharmony_ci        }
10533af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
10543af6ab5fSopenharmony_ci            return ParseArrayExpression(CarryPatternFlags(flags));
10553af6ab5fSopenharmony_ci        }
10563af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
10573af6ab5fSopenharmony_ci            return ParseCoverParenthesizedExpressionAndArrowParameterList();
10583af6ab5fSopenharmony_ci        }
10593af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
10603af6ab5fSopenharmony_ci            return ParseObjectExpression(CarryPatternFlags(flags));
10613af6ab5fSopenharmony_ci        }
10623af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_BACK_TICK: {
10633af6ab5fSopenharmony_ci            return ParseTemplateLiteral();
10643af6ab5fSopenharmony_ci        }
10653af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_HASH_MARK: {
10663af6ab5fSopenharmony_ci            return ParseHashMaskOperator();
10673af6ab5fSopenharmony_ci        }
10683af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
10693af6ab5fSopenharmony_ci            return ParsePrefixAssertionExpression();
10703af6ab5fSopenharmony_ci        }
10713af6ab5fSopenharmony_ci        default: {
10723af6ab5fSopenharmony_ci            UNREACHABLE();
10733af6ab5fSopenharmony_ci        }
10743af6ab5fSopenharmony_ci    }
10753af6ab5fSopenharmony_ci    return nullptr;
10763af6ab5fSopenharmony_ci}
10773af6ab5fSopenharmony_ci
10783af6ab5fSopenharmony_ci// NOLINTNEXTLINE(google-default-arguments)
10793af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParsePrimaryExpression(ExpressionParseFlags flags)
10803af6ab5fSopenharmony_ci{
10813af6ab5fSopenharmony_ci    switch (lexer_->GetToken().Type()) {
10823af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_IMPORT: {
10833af6ab5fSopenharmony_ci            return ParseImportExpression();
10843af6ab5fSopenharmony_ci        }
10853af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_DIVIDE:
10863af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL:
10873af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET:
10883af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS:
10893af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LEFT_BRACE:
10903af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_BACK_TICK:
10913af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_HASH_MARK:
10923af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
10933af6ab5fSopenharmony_ci            return ParsePunctuators(flags);
10943af6ab5fSopenharmony_ci        }
10953af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_FUNCTION: {
10963af6ab5fSopenharmony_ci            return ParseFunctionExpression();
10973af6ab5fSopenharmony_ci        }
10983af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_CLASS: {
10993af6ab5fSopenharmony_ci            return ParseClassExpression();
11003af6ab5fSopenharmony_ci        }
11013af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_THIS: {
11023af6ab5fSopenharmony_ci            return ParseThisExpression();
11033af6ab5fSopenharmony_ci        }
11043af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_TYPEOF: {
11053af6ab5fSopenharmony_ci            return ParseUnaryOrPrefixUpdateExpression();
11063af6ab5fSopenharmony_ci        }
11073af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_SUPER: {
11083af6ab5fSopenharmony_ci            return ParseSuperExpression();
11093af6ab5fSopenharmony_ci        }
11103af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_NEW: {
11113af6ab5fSopenharmony_ci            ir::MetaProperty *newTarget = ParsePotentialNewTarget();
11123af6ab5fSopenharmony_ci
11133af6ab5fSopenharmony_ci            if (newTarget != nullptr) {
11143af6ab5fSopenharmony_ci                return newTarget;
11153af6ab5fSopenharmony_ci            }
11163af6ab5fSopenharmony_ci
11173af6ab5fSopenharmony_ci            return ParseNewExpression();
11183af6ab5fSopenharmony_ci        }
11193af6ab5fSopenharmony_ci        default: {
11203af6ab5fSopenharmony_ci            break;
11213af6ab5fSopenharmony_ci        }
11223af6ab5fSopenharmony_ci    }
11233af6ab5fSopenharmony_ci
11243af6ab5fSopenharmony_ci    return ParsePrimaryExpressionWithLiterals(flags);
11253af6ab5fSopenharmony_ci}
11263af6ab5fSopenharmony_ci
11273af6ab5fSopenharmony_cistatic constexpr size_t GetOperatorPrecedenceArithmeticAndComparison(const lexer::TokenType operatorType)
11283af6ab5fSopenharmony_ci{
11293af6ab5fSopenharmony_ci    switch (operatorType) {
11303af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_EQUAL:
11313af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_NOT_EQUAL:
11323af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL:
11333af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: {
11343af6ab5fSopenharmony_ci            constexpr auto PRECEDENCE = 8;
11353af6ab5fSopenharmony_ci            return PRECEDENCE;
11363af6ab5fSopenharmony_ci        }
11373af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LESS_THAN:
11383af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL:
11393af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_GREATER_THAN:
11403af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL:
11413af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_INSTANCEOF:
11423af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_IN: {
11433af6ab5fSopenharmony_ci            constexpr auto PRECEDENCE = 9;
11443af6ab5fSopenharmony_ci            return PRECEDENCE;
11453af6ab5fSopenharmony_ci        }
11463af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_PLUS:
11473af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_MINUS: {
11483af6ab5fSopenharmony_ci            constexpr auto PRECEDENCE = 12;
11493af6ab5fSopenharmony_ci            return PRECEDENCE;
11503af6ab5fSopenharmony_ci        }
11513af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_MULTIPLY:
11523af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_DIVIDE:
11533af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_MOD: {
11543af6ab5fSopenharmony_ci            constexpr auto PRECEDENCE = 13;
11553af6ab5fSopenharmony_ci            return PRECEDENCE;
11563af6ab5fSopenharmony_ci        }
11573af6ab5fSopenharmony_ci        default: {
11583af6ab5fSopenharmony_ci            UNREACHABLE();
11593af6ab5fSopenharmony_ci        }
11603af6ab5fSopenharmony_ci    }
11613af6ab5fSopenharmony_ci}
11623af6ab5fSopenharmony_ci
11633af6ab5fSopenharmony_cistatic constexpr size_t GetOperatorPrecedence(const lexer::TokenType operatorType)
11643af6ab5fSopenharmony_ci{
11653af6ab5fSopenharmony_ci    ASSERT(operatorType == lexer::TokenType::KEYW_AS || lexer::Token::IsBinaryToken(operatorType));
11663af6ab5fSopenharmony_ci
11673af6ab5fSopenharmony_ci    switch (operatorType) {
11683af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING: {
11693af6ab5fSopenharmony_ci            constexpr auto PRECEDENCE = 1;
11703af6ab5fSopenharmony_ci            return PRECEDENCE;
11713af6ab5fSopenharmony_ci        }
11723af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LOGICAL_OR: {
11733af6ab5fSopenharmony_ci            constexpr auto PRECEDENCE = 2;
11743af6ab5fSopenharmony_ci            return PRECEDENCE;
11753af6ab5fSopenharmony_ci        }
11763af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LOGICAL_AND: {
11773af6ab5fSopenharmony_ci            constexpr auto PRECEDENCE = 4;
11783af6ab5fSopenharmony_ci            return PRECEDENCE;
11793af6ab5fSopenharmony_ci        }
11803af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_BITWISE_OR: {
11813af6ab5fSopenharmony_ci            constexpr auto PRECEDENCE = 5;
11823af6ab5fSopenharmony_ci            return PRECEDENCE;
11833af6ab5fSopenharmony_ci        }
11843af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: {
11853af6ab5fSopenharmony_ci            constexpr auto PRECEDENCE = 6;
11863af6ab5fSopenharmony_ci            return PRECEDENCE;
11873af6ab5fSopenharmony_ci        }
11883af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_BITWISE_AND: {
11893af6ab5fSopenharmony_ci            constexpr auto PRECEDENCE = 7;
11903af6ab5fSopenharmony_ci            return PRECEDENCE;
11913af6ab5fSopenharmony_ci        }
11923af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT:
11933af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT:
11943af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: {
11953af6ab5fSopenharmony_ci            constexpr auto PRECEDENCE = 10;
11963af6ab5fSopenharmony_ci            return PRECEDENCE;
11973af6ab5fSopenharmony_ci        }
11983af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_AS: {
11993af6ab5fSopenharmony_ci            constexpr auto PRECEDENCE = 11;
12003af6ab5fSopenharmony_ci            return PRECEDENCE;
12013af6ab5fSopenharmony_ci        }
12023af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_EXPONENTIATION: {
12033af6ab5fSopenharmony_ci            constexpr auto PRECEDENCE = 14;
12043af6ab5fSopenharmony_ci            return PRECEDENCE;
12053af6ab5fSopenharmony_ci        }
12063af6ab5fSopenharmony_ci        default: {
12073af6ab5fSopenharmony_ci            return GetOperatorPrecedenceArithmeticAndComparison(operatorType);
12083af6ab5fSopenharmony_ci        }
12093af6ab5fSopenharmony_ci    }
12103af6ab5fSopenharmony_ci}
12113af6ab5fSopenharmony_ci
12123af6ab5fSopenharmony_cistatic inline bool ShouldBinaryExpressionBeAmended(const ir::BinaryExpression *const binaryExpression,
12133af6ab5fSopenharmony_ci                                                   const lexer::TokenType operatorType)
12143af6ab5fSopenharmony_ci{
12153af6ab5fSopenharmony_ci    return GetOperatorPrecedence(binaryExpression->OperatorType()) <= GetOperatorPrecedence(operatorType) &&
12163af6ab5fSopenharmony_ci           !binaryExpression->IsGrouped() &&
12173af6ab5fSopenharmony_ci           (operatorType != lexer::TokenType::PUNCTUATOR_EXPONENTIATION ||
12183af6ab5fSopenharmony_ci            binaryExpression->OperatorType() != lexer::TokenType::PUNCTUATOR_EXPONENTIATION);
12193af6ab5fSopenharmony_ci}
12203af6ab5fSopenharmony_ci
12213af6ab5fSopenharmony_cistatic inline bool ShouldAsExpressionBeAmended(const ir::TSAsExpression *const asExpression,
12223af6ab5fSopenharmony_ci                                               const lexer::TokenType operatorType)
12233af6ab5fSopenharmony_ci{
12243af6ab5fSopenharmony_ci    return GetOperatorPrecedence(lexer::TokenType::KEYW_AS) <= GetOperatorPrecedence(operatorType) &&
12253af6ab5fSopenharmony_ci           !asExpression->IsGrouped() && operatorType != lexer::TokenType::PUNCTUATOR_EXPONENTIATION;
12263af6ab5fSopenharmony_ci}
12273af6ab5fSopenharmony_ci
12283af6ab5fSopenharmony_cistatic inline bool ShouldExpressionBeAmended(const ir::Expression *const expression,
12293af6ab5fSopenharmony_ci                                             const lexer::TokenType operatorType)
12303af6ab5fSopenharmony_ci{
12313af6ab5fSopenharmony_ci    bool shouldBeAmended = false;
12323af6ab5fSopenharmony_ci
12333af6ab5fSopenharmony_ci    if (expression->IsBinaryExpression()) {
12343af6ab5fSopenharmony_ci        shouldBeAmended = ShouldBinaryExpressionBeAmended(expression->AsBinaryExpression(), operatorType);
12353af6ab5fSopenharmony_ci    } else if (expression->IsTSAsExpression()) {
12363af6ab5fSopenharmony_ci        shouldBeAmended = ShouldAsExpressionBeAmended(expression->AsTSAsExpression(), operatorType);
12373af6ab5fSopenharmony_ci    }
12383af6ab5fSopenharmony_ci
12393af6ab5fSopenharmony_ci    return shouldBeAmended;
12403af6ab5fSopenharmony_ci}
12413af6ab5fSopenharmony_ci
12423af6ab5fSopenharmony_cistatic inline bool AreLogicalAndNullishMixedIncorrectly(const ir::Expression *const expression,
12433af6ab5fSopenharmony_ci                                                        const lexer::TokenType operatorType)
12443af6ab5fSopenharmony_ci{
12453af6ab5fSopenharmony_ci    return ((operatorType == lexer::TokenType::PUNCTUATOR_LOGICAL_OR ||
12463af6ab5fSopenharmony_ci             operatorType == lexer::TokenType::PUNCTUATOR_LOGICAL_AND) &&
12473af6ab5fSopenharmony_ci            expression->IsBinaryExpression() &&
12483af6ab5fSopenharmony_ci            expression->AsBinaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING &&
12493af6ab5fSopenharmony_ci            !expression->IsGrouped()) ||
12503af6ab5fSopenharmony_ci           (operatorType == lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING && expression->IsBinaryExpression() &&
12513af6ab5fSopenharmony_ci            (expression->AsBinaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_LOGICAL_OR ||
12523af6ab5fSopenharmony_ci             expression->AsBinaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_LOGICAL_AND) &&
12533af6ab5fSopenharmony_ci            !expression->IsGrouped());
12543af6ab5fSopenharmony_ci}
12553af6ab5fSopenharmony_ci
12563af6ab5fSopenharmony_cistatic inline ir::Expression *GetAmendedChildExpression(ir::Expression *const expression)
12573af6ab5fSopenharmony_ci{
12583af6ab5fSopenharmony_ci    ir::Expression *amendedChild = nullptr;
12593af6ab5fSopenharmony_ci
12603af6ab5fSopenharmony_ci    if (expression->IsBinaryExpression()) {
12613af6ab5fSopenharmony_ci        amendedChild = expression->AsBinaryExpression()->Left();
12623af6ab5fSopenharmony_ci    } else if (expression->IsTSAsExpression()) {
12633af6ab5fSopenharmony_ci        amendedChild = expression->AsTSAsExpression()->Expr();
12643af6ab5fSopenharmony_ci    } else {
12653af6ab5fSopenharmony_ci        UNREACHABLE();
12663af6ab5fSopenharmony_ci    }
12673af6ab5fSopenharmony_ci
12683af6ab5fSopenharmony_ci    return amendedChild;
12693af6ab5fSopenharmony_ci}
12703af6ab5fSopenharmony_ci
12713af6ab5fSopenharmony_cistatic inline void SetAmendedChildExpression(ir::Expression *const parent, ir::Expression *const amended)
12723af6ab5fSopenharmony_ci{
12733af6ab5fSopenharmony_ci    if (parent->IsBinaryExpression()) {
12743af6ab5fSopenharmony_ci        parent->AsBinaryExpression()->SetLeft(amended);
12753af6ab5fSopenharmony_ci        amended->SetParent(parent);
12763af6ab5fSopenharmony_ci    } else if (parent->IsTSAsExpression()) {
12773af6ab5fSopenharmony_ci        parent->AsTSAsExpression()->SetExpr(amended);
12783af6ab5fSopenharmony_ci        amended->SetParent(parent);
12793af6ab5fSopenharmony_ci    } else {
12803af6ab5fSopenharmony_ci        UNREACHABLE();
12813af6ab5fSopenharmony_ci    }
12823af6ab5fSopenharmony_ci}
12833af6ab5fSopenharmony_ci
12843af6ab5fSopenharmony_civoid ParserImpl::CreateAmendedBinaryExpression(ir::Expression *const left, ir::Expression *const right,
12853af6ab5fSopenharmony_ci                                               const lexer::TokenType operatorType)
12863af6ab5fSopenharmony_ci{
12873af6ab5fSopenharmony_ci    auto *amended = GetAmendedChildExpression(right);
12883af6ab5fSopenharmony_ci
12893af6ab5fSopenharmony_ci    amended->SetParent(nullptr);  // Next line overwrite parent
12903af6ab5fSopenharmony_ci    auto *binaryExpr = AllocNode<ir::BinaryExpression>(left, amended, operatorType);
12913af6ab5fSopenharmony_ci
12923af6ab5fSopenharmony_ci    binaryExpr->SetRange({left->Start(), amended->End()});
12933af6ab5fSopenharmony_ci    SetAmendedChildExpression(right, binaryExpr);
12943af6ab5fSopenharmony_ci}
12953af6ab5fSopenharmony_ci
12963af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParseExpressionOrTypeAnnotation([[maybe_unused]] lexer::TokenType type,
12973af6ab5fSopenharmony_ci                                                            [[maybe_unused]] ExpressionParseFlags flags)
12983af6ab5fSopenharmony_ci{
12993af6ab5fSopenharmony_ci    return ParseExpression(ExpressionParseFlags::DISALLOW_YIELD);
13003af6ab5fSopenharmony_ci}
13013af6ab5fSopenharmony_ci
13023af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParseBinaryExpression(ir::Expression *left, ExpressionParseFlags flags)
13033af6ab5fSopenharmony_ci{
13043af6ab5fSopenharmony_ci    lexer::TokenType operatorType = lexer_->GetToken().Type();
13053af6ab5fSopenharmony_ci    ASSERT(lexer::Token::IsBinaryToken(operatorType));
13063af6ab5fSopenharmony_ci
13073af6ab5fSopenharmony_ci    if (operatorType == lexer::TokenType::PUNCTUATOR_EXPONENTIATION) {
13083af6ab5fSopenharmony_ci        if ((left->IsUnaryExpression() || left->IsTypeofExpression()) && !left->IsGrouped()) {
13093af6ab5fSopenharmony_ci            ThrowSyntaxError(
13103af6ab5fSopenharmony_ci                "Illegal expression. Wrap left hand side or entire "
13113af6ab5fSopenharmony_ci                "exponentiation in parentheses.");
13123af6ab5fSopenharmony_ci        }
13133af6ab5fSopenharmony_ci    }
13143af6ab5fSopenharmony_ci
13153af6ab5fSopenharmony_ci    lexer_->NextToken();
13163af6ab5fSopenharmony_ci
13173af6ab5fSopenharmony_ci    ExpressionParseFlags newFlags = ExpressionParseFlags::DISALLOW_YIELD;
13183af6ab5fSopenharmony_ci    if ((operatorType == lexer::TokenType::KEYW_INSTANCEOF) || ((flags & ExpressionParseFlags::INSTANCEOF) != 0)) {
13193af6ab5fSopenharmony_ci        newFlags |= ExpressionParseFlags::INSTANCEOF;
13203af6ab5fSopenharmony_ci    }
13213af6ab5fSopenharmony_ci
13223af6ab5fSopenharmony_ci    ir::Expression *rightExpr = ParseExpressionOrTypeAnnotation(operatorType, ExpressionParseFlags::DISALLOW_YIELD);
13233af6ab5fSopenharmony_ci    ir::ConditionalExpression *conditionalExpr = nullptr;
13243af6ab5fSopenharmony_ci
13253af6ab5fSopenharmony_ci    if (rightExpr->IsConditionalExpression() && !rightExpr->IsGrouped()) {
13263af6ab5fSopenharmony_ci        conditionalExpr = rightExpr->AsConditionalExpression();
13273af6ab5fSopenharmony_ci        rightExpr = conditionalExpr->Test();
13283af6ab5fSopenharmony_ci    }
13293af6ab5fSopenharmony_ci
13303af6ab5fSopenharmony_ci    if (ShouldExpressionBeAmended(rightExpr, operatorType)) {
13313af6ab5fSopenharmony_ci        if (AreLogicalAndNullishMixedIncorrectly(rightExpr, operatorType)) {
13323af6ab5fSopenharmony_ci            ThrowSyntaxError("Nullish coalescing operator ?? requires parens when mixing with logical operators.");
13333af6ab5fSopenharmony_ci        }
13343af6ab5fSopenharmony_ci
13353af6ab5fSopenharmony_ci        bool shouldBeAmended = true;
13363af6ab5fSopenharmony_ci
13373af6ab5fSopenharmony_ci        ir::Expression *expression = rightExpr;
13383af6ab5fSopenharmony_ci        ir::Expression *parentExpression = nullptr;
13393af6ab5fSopenharmony_ci
13403af6ab5fSopenharmony_ci        while (shouldBeAmended && GetAmendedChildExpression(expression)->IsBinaryExpression()) {
13413af6ab5fSopenharmony_ci            parentExpression = expression;
13423af6ab5fSopenharmony_ci            parentExpression->SetStart(left->Start());
13433af6ab5fSopenharmony_ci
13443af6ab5fSopenharmony_ci            expression = GetAmendedChildExpression(expression);
13453af6ab5fSopenharmony_ci
13463af6ab5fSopenharmony_ci            shouldBeAmended = ShouldExpressionBeAmended(expression, operatorType);
13473af6ab5fSopenharmony_ci        }
13483af6ab5fSopenharmony_ci
13493af6ab5fSopenharmony_ci        CreateAmendedBinaryExpression(left, shouldBeAmended ? expression : parentExpression, operatorType);
13503af6ab5fSopenharmony_ci    } else {
13513af6ab5fSopenharmony_ci        if (AreLogicalAndNullishMixedIncorrectly(rightExpr, operatorType)) {
13523af6ab5fSopenharmony_ci            ThrowSyntaxError("Nullish coalescing operator ?? requires parens when mixing with logical operators.");
13533af6ab5fSopenharmony_ci        }
13543af6ab5fSopenharmony_ci        const lexer::SourcePosition &endPos = rightExpr->End();
13553af6ab5fSopenharmony_ci        rightExpr = AllocNode<ir::BinaryExpression>(left, rightExpr, operatorType);
13563af6ab5fSopenharmony_ci        rightExpr->SetRange({left->Start(), endPos});
13573af6ab5fSopenharmony_ci    }
13583af6ab5fSopenharmony_ci
13593af6ab5fSopenharmony_ci    if (conditionalExpr != nullptr) {
13603af6ab5fSopenharmony_ci        conditionalExpr->SetStart(rightExpr->Start());
13613af6ab5fSopenharmony_ci        conditionalExpr->SetTest(rightExpr);
13623af6ab5fSopenharmony_ci        return conditionalExpr;
13633af6ab5fSopenharmony_ci    }
13643af6ab5fSopenharmony_ci
13653af6ab5fSopenharmony_ci    return rightExpr;
13663af6ab5fSopenharmony_ci}
13673af6ab5fSopenharmony_ci
13683af6ab5fSopenharmony_ciArenaVector<ir::Expression *> ParserImpl::ParseCallExpressionArguments(bool &trailingComma)
13693af6ab5fSopenharmony_ci{
13703af6ab5fSopenharmony_ci    ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
13713af6ab5fSopenharmony_ci
13723af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
13733af6ab5fSopenharmony_ci        lexer_->Lookahead() == static_cast<char32_t>(ARRAY_FORMAT_NODE)) {
13743af6ab5fSopenharmony_ci        arguments = std::move(ParseExpressionsArrayFormatPlaceholder());
13753af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
13763af6ab5fSopenharmony_ci            ThrowSyntaxError("Expected a ')'");
13773af6ab5fSopenharmony_ci        }
13783af6ab5fSopenharmony_ci    } else {
13793af6ab5fSopenharmony_ci        while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
13803af6ab5fSopenharmony_ci            trailingComma = false;
13813af6ab5fSopenharmony_ci            ir::Expression *argument {};
13823af6ab5fSopenharmony_ci            if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
13833af6ab5fSopenharmony_ci                argument = ParseSpreadElement();
13843af6ab5fSopenharmony_ci            } else {
13853af6ab5fSopenharmony_ci                argument = ParseExpression();
13863af6ab5fSopenharmony_ci            }
13873af6ab5fSopenharmony_ci
13883af6ab5fSopenharmony_ci            arguments.push_back(argument);
13893af6ab5fSopenharmony_ci
13903af6ab5fSopenharmony_ci            if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
13913af6ab5fSopenharmony_ci                lexer_->NextToken();
13923af6ab5fSopenharmony_ci                trailingComma = true;
13933af6ab5fSopenharmony_ci            } else if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
13943af6ab5fSopenharmony_ci                ThrowSyntaxError("Expected a ')'");
13953af6ab5fSopenharmony_ci            }
13963af6ab5fSopenharmony_ci        }
13973af6ab5fSopenharmony_ci    }
13983af6ab5fSopenharmony_ci
13993af6ab5fSopenharmony_ci    return arguments;
14003af6ab5fSopenharmony_ci}
14013af6ab5fSopenharmony_ci
14023af6ab5fSopenharmony_ciir::CallExpression *ParserImpl::ParseCallExpression(ir::Expression *callee, bool isOptionalChain, bool handleEval)
14033af6ab5fSopenharmony_ci{
14043af6ab5fSopenharmony_ci    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
14053af6ab5fSopenharmony_ci    bool trailingComma {};
14063af6ab5fSopenharmony_ci
14073af6ab5fSopenharmony_ci    while (true) {
14083af6ab5fSopenharmony_ci        lexer_->NextToken();
14093af6ab5fSopenharmony_ci        ArenaVector<ir::Expression *> arguments = ParseCallExpressionArguments(trailingComma);
14103af6ab5fSopenharmony_ci        ir::CallExpression *callExpr {};
14113af6ab5fSopenharmony_ci
14123af6ab5fSopenharmony_ci        if (!isOptionalChain && handleEval && callee->IsIdentifier() && callee->AsIdentifier()->Name().Is("eval")) {
14133af6ab5fSopenharmony_ci            auto parserStatus = static_cast<uint32_t>(context_.Status() | ParserStatus::DIRECT_EVAL);
14143af6ab5fSopenharmony_ci            callExpr = AllocNode<ir::DirectEvalExpression>(callee, std::move(arguments), nullptr, isOptionalChain,
14153af6ab5fSopenharmony_ci                                                           parserStatus);
14163af6ab5fSopenharmony_ci        } else {
14173af6ab5fSopenharmony_ci            callExpr =
14183af6ab5fSopenharmony_ci                AllocNode<ir::CallExpression>(callee, std::move(arguments), nullptr, isOptionalChain, trailingComma);
14193af6ab5fSopenharmony_ci        }
14203af6ab5fSopenharmony_ci
14213af6ab5fSopenharmony_ci        callExpr->SetRange({callee->Start(), lexer_->GetToken().End()});
14223af6ab5fSopenharmony_ci        isOptionalChain = false;
14233af6ab5fSopenharmony_ci
14243af6ab5fSopenharmony_ci        lexer_->NextToken();
14253af6ab5fSopenharmony_ci
14263af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
14273af6ab5fSopenharmony_ci            ParseTrailingBlock(callExpr);
14283af6ab5fSopenharmony_ci            return callExpr;
14293af6ab5fSopenharmony_ci        }
14303af6ab5fSopenharmony_ci
14313af6ab5fSopenharmony_ci        callee = callExpr;
14323af6ab5fSopenharmony_ci    }
14333af6ab5fSopenharmony_ci
14343af6ab5fSopenharmony_ci    UNREACHABLE();
14353af6ab5fSopenharmony_ci}
14363af6ab5fSopenharmony_ci
14373af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParseOptionalChain(ir::Expression *leftSideExpr)
14383af6ab5fSopenharmony_ci{
14393af6ab5fSopenharmony_ci    ir::Expression *returnExpression = nullptr;
14403af6ab5fSopenharmony_ci
14413af6ab5fSopenharmony_ci    bool isPrivate = false;
14423af6ab5fSopenharmony_ci
14433af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_HASH_MARK) {
14443af6ab5fSopenharmony_ci        isPrivate = true;
14453af6ab5fSopenharmony_ci        ValidatePrivateIdentifier();
14463af6ab5fSopenharmony_ci    }
14473af6ab5fSopenharmony_ci
14483af6ab5fSopenharmony_ci    const auto tokenType = lexer_->GetToken().Type();
14493af6ab5fSopenharmony_ci    if (tokenType == lexer::TokenType::LITERAL_IDENT) {
14503af6ab5fSopenharmony_ci        auto *identNode = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
14513af6ab5fSopenharmony_ci        identNode->SetReference();
14523af6ab5fSopenharmony_ci        identNode->SetPrivate(isPrivate);
14533af6ab5fSopenharmony_ci        identNode->SetRange(lexer_->GetToken().Loc());
14543af6ab5fSopenharmony_ci
14553af6ab5fSopenharmony_ci        returnExpression = AllocNode<ir::MemberExpression>(leftSideExpr, identNode,
14563af6ab5fSopenharmony_ci                                                           ir::MemberExpressionKind::PROPERTY_ACCESS, false, true);
14573af6ab5fSopenharmony_ci        returnExpression->SetRange({leftSideExpr->Start(), identNode->End()});
14583af6ab5fSopenharmony_ci        lexer_->NextToken();
14593af6ab5fSopenharmony_ci    }
14603af6ab5fSopenharmony_ci
14613af6ab5fSopenharmony_ci    if (tokenType == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
14623af6ab5fSopenharmony_ci        lexer_->NextToken();  // eat '['
14633af6ab5fSopenharmony_ci        ir::Expression *propertyNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
14643af6ab5fSopenharmony_ci
14653af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
14663af6ab5fSopenharmony_ci            ThrowSyntaxError("Unexpected token");
14673af6ab5fSopenharmony_ci        }
14683af6ab5fSopenharmony_ci
14693af6ab5fSopenharmony_ci        returnExpression = AllocNode<ir::MemberExpression>(leftSideExpr, propertyNode,
14703af6ab5fSopenharmony_ci                                                           ir::MemberExpressionKind::ELEMENT_ACCESS, true, true);
14713af6ab5fSopenharmony_ci        returnExpression->SetRange({leftSideExpr->Start(), lexer_->GetToken().End()});
14723af6ab5fSopenharmony_ci        lexer_->NextToken();
14733af6ab5fSopenharmony_ci    }
14743af6ab5fSopenharmony_ci
14753af6ab5fSopenharmony_ci    if (tokenType == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
14763af6ab5fSopenharmony_ci        returnExpression = ParseCallExpression(leftSideExpr, true);
14773af6ab5fSopenharmony_ci    }
14783af6ab5fSopenharmony_ci
14793af6ab5fSopenharmony_ci    // Static semantic
14803af6ab5fSopenharmony_ci    if (tokenType == lexer::TokenType::PUNCTUATOR_BACK_TICK ||
14813af6ab5fSopenharmony_ci        lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BACK_TICK) {
14823af6ab5fSopenharmony_ci        ThrowSyntaxError("Tagged Template Literals are not allowed in optionalChain");
14833af6ab5fSopenharmony_ci    }
14843af6ab5fSopenharmony_ci
14853af6ab5fSopenharmony_ci    return returnExpression;
14863af6ab5fSopenharmony_ci}
14873af6ab5fSopenharmony_ci
14883af6ab5fSopenharmony_ciir::ArrowFunctionExpression *ParserImpl::ParsePotentialArrowExpression(ir::Expression **returnExpression,
14893af6ab5fSopenharmony_ci                                                                       const lexer::SourcePosition &startLoc)
14903af6ab5fSopenharmony_ci{
14913af6ab5fSopenharmony_ci    switch (lexer_->GetToken().Type()) {
14923af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_FUNCTION: {
14933af6ab5fSopenharmony_ci            *returnExpression = ParseFunctionExpression(ParserStatus::ASYNC_FUNCTION);
14943af6ab5fSopenharmony_ci            (*returnExpression)->SetStart(startLoc);
14953af6ab5fSopenharmony_ci            break;
14963af6ab5fSopenharmony_ci        }
14973af6ab5fSopenharmony_ci        case lexer::TokenType::LITERAL_IDENT: {
14983af6ab5fSopenharmony_ci            ir::Expression *identRef = ParsePrimaryExpression();
14993af6ab5fSopenharmony_ci            ASSERT(identRef->IsIdentifier());
15003af6ab5fSopenharmony_ci
15013af6ab5fSopenharmony_ci            if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
15023af6ab5fSopenharmony_ci                ThrowSyntaxError("Unexpected token, expected '=>'");
15033af6ab5fSopenharmony_ci            }
15043af6ab5fSopenharmony_ci
15053af6ab5fSopenharmony_ci            ir::ArrowFunctionExpression *arrowFuncExpr = ParseArrowFunctionExpression(identRef, nullptr, nullptr, true);
15063af6ab5fSopenharmony_ci            arrowFuncExpr->SetStart(startLoc);
15073af6ab5fSopenharmony_ci
15083af6ab5fSopenharmony_ci            return arrowFuncExpr;
15093af6ab5fSopenharmony_ci        }
15103af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_ARROW: {
15113af6ab5fSopenharmony_ci            ir::ArrowFunctionExpression *arrowFuncExpr =
15123af6ab5fSopenharmony_ci                ParseArrowFunctionExpression(*returnExpression, nullptr, nullptr, true);
15133af6ab5fSopenharmony_ci            arrowFuncExpr->SetStart(startLoc);
15143af6ab5fSopenharmony_ci            return arrowFuncExpr;
15153af6ab5fSopenharmony_ci        }
15163af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
15173af6ab5fSopenharmony_ci            ir::CallExpression *callExpression = ParseCallExpression(*returnExpression, false);
15183af6ab5fSopenharmony_ci
15193af6ab5fSopenharmony_ci            if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW) {
15203af6ab5fSopenharmony_ci                ir::ArrowFunctionExpression *arrowFuncExpr =
15213af6ab5fSopenharmony_ci                    ParseArrowFunctionExpression(callExpression, nullptr, nullptr, true);
15223af6ab5fSopenharmony_ci                arrowFuncExpr->SetStart(startLoc);
15233af6ab5fSopenharmony_ci
15243af6ab5fSopenharmony_ci                return arrowFuncExpr;
15253af6ab5fSopenharmony_ci            }
15263af6ab5fSopenharmony_ci
15273af6ab5fSopenharmony_ci            *returnExpression = callExpression;
15283af6ab5fSopenharmony_ci            break;
15293af6ab5fSopenharmony_ci        }
15303af6ab5fSopenharmony_ci        default: {
15313af6ab5fSopenharmony_ci            break;
15323af6ab5fSopenharmony_ci        }
15333af6ab5fSopenharmony_ci    }
15343af6ab5fSopenharmony_ci
15353af6ab5fSopenharmony_ci    return nullptr;
15363af6ab5fSopenharmony_ci}
15373af6ab5fSopenharmony_ci
15383af6ab5fSopenharmony_cibool ParserImpl::ParsePotentialGenericFunctionCall([[maybe_unused]] ir::Expression *primaryExpr,
15393af6ab5fSopenharmony_ci                                                   [[maybe_unused]] ir::Expression **returnExpression,
15403af6ab5fSopenharmony_ci                                                   [[maybe_unused]] const lexer::SourcePosition &startLoc,
15413af6ab5fSopenharmony_ci                                                   [[maybe_unused]] bool ignoreCallExpression)
15423af6ab5fSopenharmony_ci{
15433af6ab5fSopenharmony_ci    return true;
15443af6ab5fSopenharmony_ci}
15453af6ab5fSopenharmony_ci
15463af6ab5fSopenharmony_cibool ParserImpl::ParsePotentialNonNullExpression([[maybe_unused]] ir::Expression **returnExpression,
15473af6ab5fSopenharmony_ci                                                 [[maybe_unused]] lexer::SourcePosition startLoc)
15483af6ab5fSopenharmony_ci{
15493af6ab5fSopenharmony_ci    return true;
15503af6ab5fSopenharmony_ci}
15513af6ab5fSopenharmony_ci
15523af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParsePotentialAsExpression([[maybe_unused]] ir::Expression *primaryExpression)
15533af6ab5fSopenharmony_ci{
15543af6ab5fSopenharmony_ci    return nullptr;
15553af6ab5fSopenharmony_ci}
15563af6ab5fSopenharmony_ci
15573af6ab5fSopenharmony_ciir::MemberExpression *ParserImpl::ParseElementAccess(ir::Expression *primaryExpr, bool isOptional)
15583af6ab5fSopenharmony_ci{
15593af6ab5fSopenharmony_ci    lexer_->NextToken();  // eat '['
15603af6ab5fSopenharmony_ci    ir::Expression *propertyNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
15613af6ab5fSopenharmony_ci
15623af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
15633af6ab5fSopenharmony_ci        ThrowSyntaxError("Unexpected token");
15643af6ab5fSopenharmony_ci    }
15653af6ab5fSopenharmony_ci
15663af6ab5fSopenharmony_ci    auto *memberExpr = AllocNode<ir::MemberExpression>(primaryExpr, propertyNode,
15673af6ab5fSopenharmony_ci                                                       ir::MemberExpressionKind::ELEMENT_ACCESS, true, isOptional);
15683af6ab5fSopenharmony_ci    memberExpr->SetRange({primaryExpr->Start(), lexer_->GetToken().End()});
15693af6ab5fSopenharmony_ci    lexer_->NextToken();
15703af6ab5fSopenharmony_ci    return memberExpr;
15713af6ab5fSopenharmony_ci}
15723af6ab5fSopenharmony_ci
15733af6ab5fSopenharmony_ciir::MemberExpression *ParserImpl::ParsePrivatePropertyAccess(ir::Expression *primaryExpr)
15743af6ab5fSopenharmony_ci{
15753af6ab5fSopenharmony_ci    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_HASH_MARK);
15763af6ab5fSopenharmony_ci
15773af6ab5fSopenharmony_ci    lexer::SourcePosition memberStart = lexer_->GetToken().Start();
15783af6ab5fSopenharmony_ci    ValidatePrivateIdentifier();
15793af6ab5fSopenharmony_ci
15803af6ab5fSopenharmony_ci    auto *privateIdent = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
15813af6ab5fSopenharmony_ci    privateIdent->SetRange({memberStart, lexer_->GetToken().End()});
15823af6ab5fSopenharmony_ci    privateIdent->SetPrivate(true);
15833af6ab5fSopenharmony_ci    privateIdent->SetReference();
15843af6ab5fSopenharmony_ci    lexer_->NextToken();
15853af6ab5fSopenharmony_ci
15863af6ab5fSopenharmony_ci    auto *memberExpr = AllocNode<ir::MemberExpression>(primaryExpr, privateIdent,
15873af6ab5fSopenharmony_ci                                                       ir::MemberExpressionKind::PROPERTY_ACCESS, false, false);
15883af6ab5fSopenharmony_ci    memberExpr->SetRange({primaryExpr->Start(), privateIdent->End()});
15893af6ab5fSopenharmony_ci    return memberExpr;
15903af6ab5fSopenharmony_ci}
15913af6ab5fSopenharmony_ci
15923af6ab5fSopenharmony_ciir::MemberExpression *ParserImpl::ParsePropertyAccess(ir::Expression *primaryExpr, bool isOptional)
15933af6ab5fSopenharmony_ci{
15943af6ab5fSopenharmony_ci    ir::Identifier *ident = ExpectIdentifier(true);
15953af6ab5fSopenharmony_ci    if (ident == nullptr) {  // Error processing.
15963af6ab5fSopenharmony_ci        return nullptr;
15973af6ab5fSopenharmony_ci    }
15983af6ab5fSopenharmony_ci
15993af6ab5fSopenharmony_ci    auto *memberExpr = AllocNode<ir::MemberExpression>(primaryExpr, ident, ir::MemberExpressionKind::PROPERTY_ACCESS,
16003af6ab5fSopenharmony_ci                                                       false, isOptional);
16013af6ab5fSopenharmony_ci    memberExpr->SetRange({primaryExpr->Start(), ident->End()});
16023af6ab5fSopenharmony_ci
16033af6ab5fSopenharmony_ci    return memberExpr;
16043af6ab5fSopenharmony_ci}
16053af6ab5fSopenharmony_ci
16063af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParsePostPrimaryExpression(ir::Expression *primaryExpr, lexer::SourcePosition startLoc,
16073af6ab5fSopenharmony_ci                                                       bool ignoreCallExpression, bool *isChainExpression)
16083af6ab5fSopenharmony_ci{
16093af6ab5fSopenharmony_ci    ir::Expression *returnExpr = primaryExpr;
16103af6ab5fSopenharmony_ci    while (true) {
16113af6ab5fSopenharmony_ci        switch (lexer_->GetToken().Type()) {
16123af6ab5fSopenharmony_ci            case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
16133af6ab5fSopenharmony_ci                returnExpr = ParseElementAccess(returnExpr);
16143af6ab5fSopenharmony_ci                continue;
16153af6ab5fSopenharmony_ci            }
16163af6ab5fSopenharmony_ci            case lexer::TokenType::LITERAL_IDENT: {
16173af6ab5fSopenharmony_ci                if (auto *asExpression = ParsePotentialAsExpression(returnExpr); asExpression != nullptr) {
16183af6ab5fSopenharmony_ci                    return asExpression;
16193af6ab5fSopenharmony_ci                }
16203af6ab5fSopenharmony_ci                break;
16213af6ab5fSopenharmony_ci            }
16223af6ab5fSopenharmony_ci            case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT:
16233af6ab5fSopenharmony_ci            case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
16243af6ab5fSopenharmony_ci                if (ParsePotentialGenericFunctionCall(primaryExpr, &returnExpr, startLoc, ignoreCallExpression)) {
16253af6ab5fSopenharmony_ci                    break;
16263af6ab5fSopenharmony_ci                }
16273af6ab5fSopenharmony_ci                continue;
16283af6ab5fSopenharmony_ci            }
16293af6ab5fSopenharmony_ci            case lexer::TokenType::PUNCTUATOR_BACK_TICK: {
16303af6ab5fSopenharmony_ci                returnExpr = ParsePostPrimaryExpressionBackTick(returnExpr, startLoc);
16313af6ab5fSopenharmony_ci                continue;
16323af6ab5fSopenharmony_ci            }
16333af6ab5fSopenharmony_ci            case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
16343af6ab5fSopenharmony_ci                if (ignoreCallExpression) {
16353af6ab5fSopenharmony_ci                    break;
16363af6ab5fSopenharmony_ci                }
16373af6ab5fSopenharmony_ci                returnExpr = ParseCallExpression(returnExpr, false);
16383af6ab5fSopenharmony_ci                continue;
16393af6ab5fSopenharmony_ci            }
16403af6ab5fSopenharmony_ci            case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: {
16413af6ab5fSopenharmony_ci                if (ParsePotentialNonNullExpression(&returnExpr, startLoc)) {
16423af6ab5fSopenharmony_ci                    break;
16433af6ab5fSopenharmony_ci                }
16443af6ab5fSopenharmony_ci                continue;
16453af6ab5fSopenharmony_ci            }
16463af6ab5fSopenharmony_ci            default: {
16473af6ab5fSopenharmony_ci                auto tmp = ParsePostPrimaryExpressionDot(returnExpr, lexer_->GetToken().Type(), isChainExpression);
16483af6ab5fSopenharmony_ci                if (tmp != nullptr) {
16493af6ab5fSopenharmony_ci                    returnExpr = tmp;
16503af6ab5fSopenharmony_ci                    continue;
16513af6ab5fSopenharmony_ci                }
16523af6ab5fSopenharmony_ci            }
16533af6ab5fSopenharmony_ci        }
16543af6ab5fSopenharmony_ci        break;
16553af6ab5fSopenharmony_ci    }
16563af6ab5fSopenharmony_ci    return returnExpr;
16573af6ab5fSopenharmony_ci}
16583af6ab5fSopenharmony_ci
16593af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParsePostPrimaryExpressionBackTick(ir::Expression *returnExpression,
16603af6ab5fSopenharmony_ci                                                               const lexer::SourcePosition startLoc)
16613af6ab5fSopenharmony_ci{
16623af6ab5fSopenharmony_ci    ir::TemplateLiteral *propertyNode = ParseTemplateLiteral();
16633af6ab5fSopenharmony_ci    lexer::SourcePosition endLoc = propertyNode->End();
16643af6ab5fSopenharmony_ci
16653af6ab5fSopenharmony_ci    returnExpression = AllocNode<ir::TaggedTemplateExpression>(returnExpression, propertyNode, nullptr);
16663af6ab5fSopenharmony_ci    returnExpression->SetRange({startLoc, endLoc});
16673af6ab5fSopenharmony_ci
16683af6ab5fSopenharmony_ci    return returnExpression;
16693af6ab5fSopenharmony_ci}
16703af6ab5fSopenharmony_ci
16713af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParsePostPrimaryExpressionDot(ir::Expression *returnExpression,
16723af6ab5fSopenharmony_ci                                                          const lexer::TokenType tokenType, bool *isChainExpression)
16733af6ab5fSopenharmony_ci{
16743af6ab5fSopenharmony_ci    switch (tokenType) {
16753af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_QUESTION_DOT: {
16763af6ab5fSopenharmony_ci            *isChainExpression = true;
16773af6ab5fSopenharmony_ci            lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat ?.
16783af6ab5fSopenharmony_ci            return ParseOptionalChain(returnExpression);
16793af6ab5fSopenharmony_ci        }
16803af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_PERIOD: {
16813af6ab5fSopenharmony_ci            lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat period
16823af6ab5fSopenharmony_ci
16833af6ab5fSopenharmony_ci            if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_HASH_MARK) {
16843af6ab5fSopenharmony_ci                return ParsePrivatePropertyAccess(returnExpression);
16853af6ab5fSopenharmony_ci            }
16863af6ab5fSopenharmony_ci
16873af6ab5fSopenharmony_ci            return ParsePropertyAccess(returnExpression);
16883af6ab5fSopenharmony_ci        }
16893af6ab5fSopenharmony_ci        default: {
16903af6ab5fSopenharmony_ci            break;
16913af6ab5fSopenharmony_ci        }
16923af6ab5fSopenharmony_ci    }
16933af6ab5fSopenharmony_ci
16943af6ab5fSopenharmony_ci    return nullptr;
16953af6ab5fSopenharmony_ci}
16963af6ab5fSopenharmony_ci
16973af6ab5fSopenharmony_civoid ParserImpl::ValidateUpdateExpression(ir::Expression *returnExpression, bool isChainExpression)
16983af6ab5fSopenharmony_ci{
16993af6ab5fSopenharmony_ci    if ((!returnExpression->IsMemberExpression() && !returnExpression->IsIdentifier() &&
17003af6ab5fSopenharmony_ci         !returnExpression->IsTSNonNullExpression()) ||
17013af6ab5fSopenharmony_ci        isChainExpression) {
17023af6ab5fSopenharmony_ci        ThrowSyntaxError("Invalid left-hand side operator.");
17033af6ab5fSopenharmony_ci    }
17043af6ab5fSopenharmony_ci
17053af6ab5fSopenharmony_ci    if (returnExpression->IsIdentifier()) {
17063af6ab5fSopenharmony_ci        const util::StringView &returnExpressionStr = returnExpression->AsIdentifier()->Name();
17073af6ab5fSopenharmony_ci
17083af6ab5fSopenharmony_ci        if (returnExpressionStr.Is("eval")) {
17093af6ab5fSopenharmony_ci            ThrowSyntaxError("Assigning to 'eval' in strict mode is invalid");
17103af6ab5fSopenharmony_ci        }
17113af6ab5fSopenharmony_ci
17123af6ab5fSopenharmony_ci        if (returnExpressionStr.Is("arguments")) {
17133af6ab5fSopenharmony_ci            ThrowSyntaxError("Assigning to 'arguments' in strict mode is invalid");
17143af6ab5fSopenharmony_ci        }
17153af6ab5fSopenharmony_ci    }
17163af6ab5fSopenharmony_ci}
17173af6ab5fSopenharmony_ci
17183af6ab5fSopenharmony_ciir::Expression *ParserImpl::SetupChainExpr(ir::Expression *const top, lexer::SourcePosition startLoc)
17193af6ab5fSopenharmony_ci{
17203af6ab5fSopenharmony_ci    auto expr = top;
17213af6ab5fSopenharmony_ci    while (expr->IsTSNonNullExpression()) {
17223af6ab5fSopenharmony_ci        expr = expr->AsTSNonNullExpression()->Expr();
17233af6ab5fSopenharmony_ci    }
17243af6ab5fSopenharmony_ci    auto chainParent = expr->Parent();
17253af6ab5fSopenharmony_ci
17263af6ab5fSopenharmony_ci    lexer::SourcePosition endLoc = expr->End();
17273af6ab5fSopenharmony_ci    auto chain = AllocNode<ir::ChainExpression>(expr);
17283af6ab5fSopenharmony_ci    chain->SetRange({startLoc, endLoc});
17293af6ab5fSopenharmony_ci
17303af6ab5fSopenharmony_ci    if (expr == top) {
17313af6ab5fSopenharmony_ci        return chain;
17323af6ab5fSopenharmony_ci    }
17333af6ab5fSopenharmony_ci    chainParent->AsTSNonNullExpression()->SetExpr(chain);
17343af6ab5fSopenharmony_ci    chain->SetParent(chainParent);
17353af6ab5fSopenharmony_ci    return top;
17363af6ab5fSopenharmony_ci}
17373af6ab5fSopenharmony_ci
17383af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParseMemberExpression(bool ignoreCallExpression, ExpressionParseFlags flags)
17393af6ab5fSopenharmony_ci{
17403af6ab5fSopenharmony_ci    bool isAsync = lexer_->GetToken().IsAsyncModifier();
17413af6ab5fSopenharmony_ci    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
17423af6ab5fSopenharmony_ci    ir::Expression *returnExpression = ParsePrimaryExpression(flags);
17433af6ab5fSopenharmony_ci
17443af6ab5fSopenharmony_ci    if (lexer_->GetToken().NewLine() && returnExpression->IsArrowFunctionExpression()) {
17453af6ab5fSopenharmony_ci        return returnExpression;
17463af6ab5fSopenharmony_ci    }
17473af6ab5fSopenharmony_ci
17483af6ab5fSopenharmony_ci    if (isAsync && !lexer_->GetToken().NewLine()) {
17493af6ab5fSopenharmony_ci        context_.Status() |= ParserStatus::ASYNC_FUNCTION;
17503af6ab5fSopenharmony_ci        ir::ArrowFunctionExpression *arrow = ParsePotentialArrowExpression(&returnExpression, startLoc);
17513af6ab5fSopenharmony_ci
17523af6ab5fSopenharmony_ci        if (arrow != nullptr) {
17533af6ab5fSopenharmony_ci            return arrow;
17543af6ab5fSopenharmony_ci        }
17553af6ab5fSopenharmony_ci    }
17563af6ab5fSopenharmony_ci
17573af6ab5fSopenharmony_ci    bool isChainExpression;
17583af6ab5fSopenharmony_ci    ir::Expression *prevExpression;
17593af6ab5fSopenharmony_ci    do {
17603af6ab5fSopenharmony_ci        isChainExpression = false;
17613af6ab5fSopenharmony_ci        prevExpression = returnExpression;
17623af6ab5fSopenharmony_ci        returnExpression =
17633af6ab5fSopenharmony_ci            ParsePostPrimaryExpression(returnExpression, startLoc, ignoreCallExpression, &isChainExpression);
17643af6ab5fSopenharmony_ci        if (isChainExpression) {
17653af6ab5fSopenharmony_ci            returnExpression = SetupChainExpr(returnExpression, startLoc);
17663af6ab5fSopenharmony_ci        }
17673af6ab5fSopenharmony_ci    } while (prevExpression != returnExpression);
17683af6ab5fSopenharmony_ci
17693af6ab5fSopenharmony_ci    if (!lexer_->GetToken().NewLine() && lexer::Token::IsUpdateToken(lexer_->GetToken().Type())) {
17703af6ab5fSopenharmony_ci        lexer::SourcePosition start = returnExpression->Start();
17713af6ab5fSopenharmony_ci
17723af6ab5fSopenharmony_ci        ValidateUpdateExpression(returnExpression, isChainExpression);
17733af6ab5fSopenharmony_ci
17743af6ab5fSopenharmony_ci        returnExpression = AllocNode<ir::UpdateExpression>(returnExpression, lexer_->GetToken().Type(), false);
17753af6ab5fSopenharmony_ci
17763af6ab5fSopenharmony_ci        returnExpression->SetRange({start, lexer_->GetToken().End()});
17773af6ab5fSopenharmony_ci        lexer_->NextToken();
17783af6ab5fSopenharmony_ci    }
17793af6ab5fSopenharmony_ci
17803af6ab5fSopenharmony_ci    return returnExpression;
17813af6ab5fSopenharmony_ci}
17823af6ab5fSopenharmony_ci
17833af6ab5fSopenharmony_ci// NOLINTNEXTLINE(google-default-arguments)
17843af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParsePatternElement(ExpressionParseFlags flags, bool allowDefault)
17853af6ab5fSopenharmony_ci{
17863af6ab5fSopenharmony_ci    ir::Expression *returnNode = nullptr;
17873af6ab5fSopenharmony_ci
17883af6ab5fSopenharmony_ci    switch (lexer_->GetToken().Type()) {
17893af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
17903af6ab5fSopenharmony_ci            returnNode = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
17913af6ab5fSopenharmony_ci            break;
17923af6ab5fSopenharmony_ci        }
17933af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD: {
17943af6ab5fSopenharmony_ci            if ((flags & ExpressionParseFlags::IN_REST) != 0) {
17953af6ab5fSopenharmony_ci                ThrowSyntaxError("Unexpected token");
17963af6ab5fSopenharmony_ci            }
17973af6ab5fSopenharmony_ci            returnNode = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN);
17983af6ab5fSopenharmony_ci            break;
17993af6ab5fSopenharmony_ci        }
18003af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
18013af6ab5fSopenharmony_ci            returnNode =
18023af6ab5fSopenharmony_ci                ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN | ExpressionParseFlags::OBJECT_PATTERN);
18033af6ab5fSopenharmony_ci            break;
18043af6ab5fSopenharmony_ci        }
18053af6ab5fSopenharmony_ci        case lexer::TokenType::LITERAL_IDENT: {
18063af6ab5fSopenharmony_ci            returnNode = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
18073af6ab5fSopenharmony_ci            returnNode->AsIdentifier()->SetReference();
18083af6ab5fSopenharmony_ci            returnNode->SetRange(lexer_->GetToken().Loc());
18093af6ab5fSopenharmony_ci            lexer_->NextToken();
18103af6ab5fSopenharmony_ci            break;
18113af6ab5fSopenharmony_ci        }
18123af6ab5fSopenharmony_ci        default: {
18133af6ab5fSopenharmony_ci            ThrowSyntaxError("Unexpected token, expected an identifier.");
18143af6ab5fSopenharmony_ci        }
18153af6ab5fSopenharmony_ci    }
18163af6ab5fSopenharmony_ci
18173af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
18183af6ab5fSopenharmony_ci        return returnNode;
18193af6ab5fSopenharmony_ci    }
18203af6ab5fSopenharmony_ci
18213af6ab5fSopenharmony_ci    ParsePatternElementErrorCheck(flags, allowDefault);
18223af6ab5fSopenharmony_ci
18233af6ab5fSopenharmony_ci    ir::Expression *rightNode = ParseExpression();
18243af6ab5fSopenharmony_ci
18253af6ab5fSopenharmony_ci    auto *assignmentExpression = AllocNode<ir::AssignmentExpression>(
18263af6ab5fSopenharmony_ci        ir::AstNodeType::ASSIGNMENT_PATTERN, returnNode, rightNode, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
18273af6ab5fSopenharmony_ci    assignmentExpression->SetRange({returnNode->Start(), rightNode->End()});
18283af6ab5fSopenharmony_ci
18293af6ab5fSopenharmony_ci    return assignmentExpression;
18303af6ab5fSopenharmony_ci}
18313af6ab5fSopenharmony_ci
18323af6ab5fSopenharmony_civoid ParserImpl::ParsePatternElementErrorCheck(const ExpressionParseFlags flags, const bool allowDefault)
18333af6ab5fSopenharmony_ci{
18343af6ab5fSopenharmony_ci    if ((flags & ExpressionParseFlags::IN_REST) != 0) {
18353af6ab5fSopenharmony_ci        ThrowSyntaxError("Unexpected token, expected ')'");
18363af6ab5fSopenharmony_ci    }
18373af6ab5fSopenharmony_ci
18383af6ab5fSopenharmony_ci    if (!allowDefault) {
18393af6ab5fSopenharmony_ci        ThrowSyntaxError("Invalid destructuring assignment target");
18403af6ab5fSopenharmony_ci    }
18413af6ab5fSopenharmony_ci
18423af6ab5fSopenharmony_ci    lexer_->NextToken();
18433af6ab5fSopenharmony_ci
18443af6ab5fSopenharmony_ci    if (context_.IsGenerator() && lexer_->GetToken().Type() == lexer::TokenType::KEYW_YIELD) {
18453af6ab5fSopenharmony_ci        ThrowSyntaxError("Yield is not allowed in generator parameters");
18463af6ab5fSopenharmony_ci    }
18473af6ab5fSopenharmony_ci
18483af6ab5fSopenharmony_ci    if (context_.IsAsync() && lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) {
18493af6ab5fSopenharmony_ci        ThrowSyntaxError("Illegal await-expression in formal parameters of async function");
18503af6ab5fSopenharmony_ci    }
18513af6ab5fSopenharmony_ci}
18523af6ab5fSopenharmony_ci
18533af6ab5fSopenharmony_civoid ParserImpl::CheckPropertyKeyAsyncModifier(ParserStatus *methodStatus)
18543af6ab5fSopenharmony_ci{
18553af6ab5fSopenharmony_ci    const auto asyncPos = lexer_->Save();
18563af6ab5fSopenharmony_ci    lexer_->NextToken();
18573af6ab5fSopenharmony_ci
18583af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
18593af6ab5fSopenharmony_ci        lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON &&
18603af6ab5fSopenharmony_ci        lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
18613af6ab5fSopenharmony_ci        lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
18623af6ab5fSopenharmony_ci        if (lexer_->GetToken().NewLine()) {
18633af6ab5fSopenharmony_ci            ThrowSyntaxError(
18643af6ab5fSopenharmony_ci                "Async methods cannot have a line terminator between "
18653af6ab5fSopenharmony_ci                "'async' and the property name");
18663af6ab5fSopenharmony_ci        }
18673af6ab5fSopenharmony_ci
18683af6ab5fSopenharmony_ci        *methodStatus |= ParserStatus::ASYNC_FUNCTION;
18693af6ab5fSopenharmony_ci    } else {
18703af6ab5fSopenharmony_ci        lexer_->Rewind(asyncPos);
18713af6ab5fSopenharmony_ci    }
18723af6ab5fSopenharmony_ci}
18733af6ab5fSopenharmony_ci
18743af6ab5fSopenharmony_cistatic bool IsAccessorDelimiter(char32_t cp)
18753af6ab5fSopenharmony_ci{
18763af6ab5fSopenharmony_ci    switch (cp) {
18773af6ab5fSopenharmony_ci        case lexer::LEX_CHAR_LEFT_PAREN:
18783af6ab5fSopenharmony_ci        case lexer::LEX_CHAR_COLON:
18793af6ab5fSopenharmony_ci        case lexer::LEX_CHAR_COMMA:
18803af6ab5fSopenharmony_ci        case lexer::LEX_CHAR_RIGHT_BRACE: {
18813af6ab5fSopenharmony_ci            return true;
18823af6ab5fSopenharmony_ci        }
18833af6ab5fSopenharmony_ci        default: {
18843af6ab5fSopenharmony_ci            return false;
18853af6ab5fSopenharmony_ci        }
18863af6ab5fSopenharmony_ci    }
18873af6ab5fSopenharmony_ci}
18883af6ab5fSopenharmony_ci
18893af6ab5fSopenharmony_cistatic bool IsShorthandDelimiter(char32_t cp)
18903af6ab5fSopenharmony_ci{
18913af6ab5fSopenharmony_ci    switch (cp) {
18923af6ab5fSopenharmony_ci        case lexer::LEX_CHAR_EQUALS:
18933af6ab5fSopenharmony_ci        case lexer::LEX_CHAR_COMMA:
18943af6ab5fSopenharmony_ci        case lexer::LEX_CHAR_RIGHT_BRACE: {
18953af6ab5fSopenharmony_ci            return true;
18963af6ab5fSopenharmony_ci        }
18973af6ab5fSopenharmony_ci        default: {
18983af6ab5fSopenharmony_ci            return false;
18993af6ab5fSopenharmony_ci        }
19003af6ab5fSopenharmony_ci    }
19013af6ab5fSopenharmony_ci}
19023af6ab5fSopenharmony_ci
19033af6ab5fSopenharmony_civoid ParserImpl::ValidateAccessor(ExpressionParseFlags flags, lexer::TokenFlags currentTokenFlags)
19043af6ab5fSopenharmony_ci{
19053af6ab5fSopenharmony_ci    if ((flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0) {
19063af6ab5fSopenharmony_ci        ThrowSyntaxError("Unexpected token");
19073af6ab5fSopenharmony_ci    }
19083af6ab5fSopenharmony_ci
19093af6ab5fSopenharmony_ci    if ((currentTokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) {
19103af6ab5fSopenharmony_ci        ThrowSyntaxError("Keyword must not contain escaped characters");
19113af6ab5fSopenharmony_ci    }
19123af6ab5fSopenharmony_ci}
19133af6ab5fSopenharmony_ci
19143af6ab5fSopenharmony_ciir::Property *ParserImpl::ParseShorthandProperty(const lexer::LexerPosition *startPos)
19153af6ab5fSopenharmony_ci{
19163af6ab5fSopenharmony_ci    char32_t nextCp = lexer_->Lookahead();
19173af6ab5fSopenharmony_ci    lexer::TokenType keywordType = lexer_->GetToken().KeywordType();
19183af6ab5fSopenharmony_ci
19193af6ab5fSopenharmony_ci    /* Rewind the lexer to the beginning of the ident to reparse as common
19203af6ab5fSopenharmony_ci     * identifier */
19213af6ab5fSopenharmony_ci    lexer_->Rewind(*startPos);
19223af6ab5fSopenharmony_ci    lexer_->NextToken();
19233af6ab5fSopenharmony_ci    lexer::SourcePosition start = lexer_->GetToken().Start();
19243af6ab5fSopenharmony_ci
19253af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
19263af6ab5fSopenharmony_ci        ThrowSyntaxError("Expected an identifier");
19273af6ab5fSopenharmony_ci    }
19283af6ab5fSopenharmony_ci
19293af6ab5fSopenharmony_ci    const util::StringView &ident = lexer_->GetToken().Ident();
19303af6ab5fSopenharmony_ci
19313af6ab5fSopenharmony_ci    auto *key = AllocNode<ir::Identifier>(ident, Allocator());
19323af6ab5fSopenharmony_ci    key->SetRange(lexer_->GetToken().Loc());
19333af6ab5fSopenharmony_ci
19343af6ab5fSopenharmony_ci    ir::Expression *value = AllocNode<ir::Identifier>(ident, Allocator());
19353af6ab5fSopenharmony_ci    value->AsIdentifier()->SetReference();
19363af6ab5fSopenharmony_ci    value->SetRange(lexer_->GetToken().Loc());
19373af6ab5fSopenharmony_ci
19383af6ab5fSopenharmony_ci    lexer::SourcePosition end;
19393af6ab5fSopenharmony_ci
19403af6ab5fSopenharmony_ci    if (nextCp == lexer::LEX_CHAR_EQUALS) {
19413af6ab5fSopenharmony_ci        CheckRestrictedBinding(keywordType);
19423af6ab5fSopenharmony_ci
19433af6ab5fSopenharmony_ci        lexer_->NextToken();  // substitution
19443af6ab5fSopenharmony_ci        lexer_->NextToken();  // eat substitution
19453af6ab5fSopenharmony_ci
19463af6ab5fSopenharmony_ci        ir::Expression *rightNode = ParseExpression();
19473af6ab5fSopenharmony_ci
19483af6ab5fSopenharmony_ci        auto *assignmentExpression = AllocNode<ir::AssignmentExpression>(
19493af6ab5fSopenharmony_ci            ir::AstNodeType::ASSIGNMENT_PATTERN, value, rightNode, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
19503af6ab5fSopenharmony_ci        assignmentExpression->SetRange({value->Start(), rightNode->End()});
19513af6ab5fSopenharmony_ci        end = rightNode->End();
19523af6ab5fSopenharmony_ci        value = assignmentExpression;
19533af6ab5fSopenharmony_ci    } else {
19543af6ab5fSopenharmony_ci        end = lexer_->GetToken().End();
19553af6ab5fSopenharmony_ci        lexer_->NextToken();
19563af6ab5fSopenharmony_ci    }
19573af6ab5fSopenharmony_ci
19583af6ab5fSopenharmony_ci    auto *returnProperty = AllocNode<ir::Property>(key, value);
19593af6ab5fSopenharmony_ci    returnProperty->SetRange({start, end});
19603af6ab5fSopenharmony_ci
19613af6ab5fSopenharmony_ci    return returnProperty;
19623af6ab5fSopenharmony_ci}
19633af6ab5fSopenharmony_ci
19643af6ab5fSopenharmony_cibool ParserImpl::ParsePropertyModifiers(ExpressionParseFlags flags, ir::PropertyKind *propertyKind,
19653af6ab5fSopenharmony_ci                                        ParserStatus *methodStatus)
19663af6ab5fSopenharmony_ci{
19673af6ab5fSopenharmony_ci    if (lexer_->GetToken().IsAsyncModifier()) {
19683af6ab5fSopenharmony_ci        CheckPropertyKeyAsyncModifier(methodStatus);
19693af6ab5fSopenharmony_ci    }
19703af6ab5fSopenharmony_ci
19713af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
19723af6ab5fSopenharmony_ci        if ((flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0) {
19733af6ab5fSopenharmony_ci            ThrowSyntaxError("Unexpected token");
19743af6ab5fSopenharmony_ci        }
19753af6ab5fSopenharmony_ci
19763af6ab5fSopenharmony_ci        lexer_->NextToken();
19773af6ab5fSopenharmony_ci        *methodStatus |= ParserStatus::GENERATOR_FUNCTION;
19783af6ab5fSopenharmony_ci    }
19793af6ab5fSopenharmony_ci
19803af6ab5fSopenharmony_ci    lexer::TokenFlags currentTokenFlags = lexer_->GetToken().Flags();
19813af6ab5fSopenharmony_ci    char32_t nextCp = lexer_->Lookahead();
19823af6ab5fSopenharmony_ci    lexer::TokenType keywordType = lexer_->GetToken().KeywordType();
19833af6ab5fSopenharmony_ci    // Parse getter property
19843af6ab5fSopenharmony_ci    if (keywordType == lexer::TokenType::KEYW_GET && !IsAccessorDelimiter(nextCp)) {
19853af6ab5fSopenharmony_ci        ValidateAccessor(flags, currentTokenFlags);
19863af6ab5fSopenharmony_ci
19873af6ab5fSopenharmony_ci        *propertyKind = ir::PropertyKind::GET;
19883af6ab5fSopenharmony_ci        lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
19893af6ab5fSopenharmony_ci
19903af6ab5fSopenharmony_ci        return false;
19913af6ab5fSopenharmony_ci    }
19923af6ab5fSopenharmony_ci
19933af6ab5fSopenharmony_ci    // Parse setter property
19943af6ab5fSopenharmony_ci    if (keywordType == lexer::TokenType::KEYW_SET && !IsAccessorDelimiter(nextCp)) {
19953af6ab5fSopenharmony_ci        ValidateAccessor(flags, currentTokenFlags);
19963af6ab5fSopenharmony_ci
19973af6ab5fSopenharmony_ci        *propertyKind = ir::PropertyKind::SET;
19983af6ab5fSopenharmony_ci        lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
19993af6ab5fSopenharmony_ci
20003af6ab5fSopenharmony_ci        return false;
20013af6ab5fSopenharmony_ci    }
20023af6ab5fSopenharmony_ci
20033af6ab5fSopenharmony_ci    // Parse shorthand property or assignment pattern
20043af6ab5fSopenharmony_ci    return (IsShorthandDelimiter(nextCp) && (*methodStatus & ParserStatus::ASYNC_FUNCTION) == 0);
20053af6ab5fSopenharmony_ci}
20063af6ab5fSopenharmony_ci
20073af6ab5fSopenharmony_civoid ParserImpl::ParseGeneratorPropertyModifier(ExpressionParseFlags flags, ParserStatus *methodStatus)
20083af6ab5fSopenharmony_ci{
20093af6ab5fSopenharmony_ci    if ((flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0) {
20103af6ab5fSopenharmony_ci        ThrowSyntaxError("Unexpected token");
20113af6ab5fSopenharmony_ci    }
20123af6ab5fSopenharmony_ci
20133af6ab5fSopenharmony_ci    lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
20143af6ab5fSopenharmony_ci    *methodStatus |= ParserStatus::GENERATOR_FUNCTION;
20153af6ab5fSopenharmony_ci}
20163af6ab5fSopenharmony_ci
20173af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParsePropertyKey(ExpressionParseFlags flags)
20183af6ab5fSopenharmony_ci{
20193af6ab5fSopenharmony_ci    ir::Expression *key = nullptr;
20203af6ab5fSopenharmony_ci
20213af6ab5fSopenharmony_ci    switch (lexer_->GetToken().Type()) {
20223af6ab5fSopenharmony_ci        case lexer::TokenType::LITERAL_IDENT: {
20233af6ab5fSopenharmony_ci            const util::StringView &ident = lexer_->GetToken().Ident();
20243af6ab5fSopenharmony_ci            key = AllocNode<ir::Identifier>(ident, Allocator());
20253af6ab5fSopenharmony_ci            key->SetRange(lexer_->GetToken().Loc());
20263af6ab5fSopenharmony_ci            break;
20273af6ab5fSopenharmony_ci        }
20283af6ab5fSopenharmony_ci        case lexer::TokenType::LITERAL_STRING: {
20293af6ab5fSopenharmony_ci            const util::StringView &string = lexer_->GetToken().String();
20303af6ab5fSopenharmony_ci            key = AllocNode<ir::StringLiteral>(string);
20313af6ab5fSopenharmony_ci            key->SetRange(lexer_->GetToken().Loc());
20323af6ab5fSopenharmony_ci            break;
20333af6ab5fSopenharmony_ci        }
20343af6ab5fSopenharmony_ci        case lexer::TokenType::LITERAL_NUMBER: {
20353af6ab5fSopenharmony_ci            if ((lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) != 0) {
20363af6ab5fSopenharmony_ci                key = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
20373af6ab5fSopenharmony_ci            } else {
20383af6ab5fSopenharmony_ci                key = AllocNode<ir::NumberLiteral>(lexer_->GetToken().GetNumber());
20393af6ab5fSopenharmony_ci            }
20403af6ab5fSopenharmony_ci
20413af6ab5fSopenharmony_ci            key->SetRange(lexer_->GetToken().Loc());
20423af6ab5fSopenharmony_ci            break;
20433af6ab5fSopenharmony_ci        }
20443af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
20453af6ab5fSopenharmony_ci            lexer_->NextToken();  // eat left square bracket
20463af6ab5fSopenharmony_ci
20473af6ab5fSopenharmony_ci            key = ParseExpression(flags | ExpressionParseFlags::ACCEPT_COMMA);
20483af6ab5fSopenharmony_ci
20493af6ab5fSopenharmony_ci            if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
20503af6ab5fSopenharmony_ci                ThrowSyntaxError("Unexpected token, expected ']'");
20513af6ab5fSopenharmony_ci            }
20523af6ab5fSopenharmony_ci            break;
20533af6ab5fSopenharmony_ci        }
20543af6ab5fSopenharmony_ci        default: {
20553af6ab5fSopenharmony_ci            ThrowSyntaxError("Unexpected token in property key");
20563af6ab5fSopenharmony_ci        }
20573af6ab5fSopenharmony_ci    }
20583af6ab5fSopenharmony_ci
20593af6ab5fSopenharmony_ci    lexer_->NextToken();
20603af6ab5fSopenharmony_ci    return key;
20613af6ab5fSopenharmony_ci}
20623af6ab5fSopenharmony_ci
20633af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParsePropertyValue(const ir::PropertyKind *propertyKind, const ParserStatus *methodStatus,
20643af6ab5fSopenharmony_ci                                               ExpressionParseFlags flags)
20653af6ab5fSopenharmony_ci{
20663af6ab5fSopenharmony_ci    bool isMethod = (*methodStatus & ParserStatus::FUNCTION) != 0;
20673af6ab5fSopenharmony_ci    bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0;
20683af6ab5fSopenharmony_ci
20693af6ab5fSopenharmony_ci    if (!isMethod && !ir::Property::IsAccessorKind(*propertyKind)) {
20703af6ab5fSopenharmony_ci        // If the actual property is not getter/setter nor method, the following
20713af6ab5fSopenharmony_ci        // token must be ':'
20723af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
20733af6ab5fSopenharmony_ci            ThrowSyntaxError("Unexpected token, expected ':'");
20743af6ab5fSopenharmony_ci        }
20753af6ab5fSopenharmony_ci
20763af6ab5fSopenharmony_ci        lexer_->NextToken();  // eat colon
20773af6ab5fSopenharmony_ci
20783af6ab5fSopenharmony_ci        if (!inPattern) {
20793af6ab5fSopenharmony_ci            return ParseExpression(flags);
20803af6ab5fSopenharmony_ci        }
20813af6ab5fSopenharmony_ci
20823af6ab5fSopenharmony_ci        return ParsePatternElement();
20833af6ab5fSopenharmony_ci    }
20843af6ab5fSopenharmony_ci
20853af6ab5fSopenharmony_ci    if (inPattern) {
20863af6ab5fSopenharmony_ci        ThrowSyntaxError("Object pattern can't contain methods");
20873af6ab5fSopenharmony_ci    }
20883af6ab5fSopenharmony_ci
20893af6ab5fSopenharmony_ci    ParserStatus newStatus = *methodStatus | ParserStatus::FUNCTION | ParserStatus::ALLOW_SUPER;
20903af6ab5fSopenharmony_ci
20913af6ab5fSopenharmony_ci    if (*propertyKind != ir::PropertyKind::SET) {
20923af6ab5fSopenharmony_ci        newStatus |= ParserStatus::NEED_RETURN_TYPE;
20933af6ab5fSopenharmony_ci    }
20943af6ab5fSopenharmony_ci
20953af6ab5fSopenharmony_ci    ir::ScriptFunction *methodDefinitonNode = ParseFunction(newStatus);
20963af6ab5fSopenharmony_ci    methodDefinitonNode->AddFlag(ir::ScriptFunctionFlags::METHOD);
20973af6ab5fSopenharmony_ci
20983af6ab5fSopenharmony_ci    size_t paramsSize = methodDefinitonNode->Params().size();
20993af6ab5fSopenharmony_ci
21003af6ab5fSopenharmony_ci    auto *value = AllocNode<ir::FunctionExpression>(methodDefinitonNode);
21013af6ab5fSopenharmony_ci    value->SetRange(methodDefinitonNode->Range());
21023af6ab5fSopenharmony_ci
21033af6ab5fSopenharmony_ci    if (*propertyKind == ir::PropertyKind::SET && paramsSize != 1) {
21043af6ab5fSopenharmony_ci        ThrowSyntaxError("Setter must have exactly one formal parameter");
21053af6ab5fSopenharmony_ci    }
21063af6ab5fSopenharmony_ci
21073af6ab5fSopenharmony_ci    if (*propertyKind == ir::PropertyKind::GET && paramsSize != 0) {
21083af6ab5fSopenharmony_ci        ThrowSyntaxError("Getter must not have formal parameters");
21093af6ab5fSopenharmony_ci    }
21103af6ab5fSopenharmony_ci
21113af6ab5fSopenharmony_ci    return value;
21123af6ab5fSopenharmony_ci}
21133af6ab5fSopenharmony_ci
21143af6ab5fSopenharmony_ci// NOLINTNEXTLINE(google-default-arguments)
21153af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParsePropertyDefinition([[maybe_unused]] ExpressionParseFlags flags)
21163af6ab5fSopenharmony_ci{
21173af6ab5fSopenharmony_ci    ir::PropertyKind propertyKind = ir::PropertyKind::INIT;
21183af6ab5fSopenharmony_ci    ParserStatus methodStatus = ParserStatus::NO_OPTS;
21193af6ab5fSopenharmony_ci
21203af6ab5fSopenharmony_ci    const auto startPos = lexer_->Save();
21213af6ab5fSopenharmony_ci    lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
21223af6ab5fSopenharmony_ci    lexer::SourcePosition start = lexer_->GetToken().Start();
21233af6ab5fSopenharmony_ci
21243af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
21253af6ab5fSopenharmony_ci        return ParseSpreadElement(flags);
21263af6ab5fSopenharmony_ci    }
21273af6ab5fSopenharmony_ci
21283af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
21293af6ab5fSopenharmony_ci        if (ParsePropertyModifiers(flags, &propertyKind, &methodStatus)) {
21303af6ab5fSopenharmony_ci            return ParseShorthandProperty(&startPos);
21313af6ab5fSopenharmony_ci        }
21323af6ab5fSopenharmony_ci    } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
21333af6ab5fSopenharmony_ci        ParseGeneratorPropertyModifier(flags, &methodStatus);
21343af6ab5fSopenharmony_ci    }
21353af6ab5fSopenharmony_ci
21363af6ab5fSopenharmony_ci    bool isComputed = lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET;
21373af6ab5fSopenharmony_ci    ir::Expression *key = ParsePropertyKey(flags);
21383af6ab5fSopenharmony_ci
21393af6ab5fSopenharmony_ci    // Parse method property
21403af6ab5fSopenharmony_ci    if ((lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS ||
21413af6ab5fSopenharmony_ci         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) &&
21423af6ab5fSopenharmony_ci        !ir::Property::IsAccessorKind(propertyKind)) {
21433af6ab5fSopenharmony_ci        methodStatus |= ParserStatus::FUNCTION | ParserStatus::ALLOW_SUPER;
21443af6ab5fSopenharmony_ci        propertyKind = ir::PropertyKind::INIT;
21453af6ab5fSopenharmony_ci    } else if ((methodStatus & (ParserStatus::GENERATOR_FUNCTION | ParserStatus::ASYNC_FUNCTION)) != 0) {
21463af6ab5fSopenharmony_ci        ThrowSyntaxError("Unexpected identifier");
21473af6ab5fSopenharmony_ci    }
21483af6ab5fSopenharmony_ci
21493af6ab5fSopenharmony_ci    ir::Expression *value = ParsePropertyValue(&propertyKind, &methodStatus, flags);
21503af6ab5fSopenharmony_ci    lexer::SourcePosition end = value->End();
21513af6ab5fSopenharmony_ci
21523af6ab5fSopenharmony_ci    ASSERT(key);
21533af6ab5fSopenharmony_ci    ASSERT(value);
21543af6ab5fSopenharmony_ci
21553af6ab5fSopenharmony_ci    auto *returnProperty =
21563af6ab5fSopenharmony_ci        AllocNode<ir::Property>(propertyKind, key, value, methodStatus != ParserStatus::NO_OPTS, isComputed);
21573af6ab5fSopenharmony_ci    returnProperty->SetRange({start, end});
21583af6ab5fSopenharmony_ci
21593af6ab5fSopenharmony_ci    return returnProperty;
21603af6ab5fSopenharmony_ci}
21613af6ab5fSopenharmony_ci
21623af6ab5fSopenharmony_cibool ParserImpl::ParsePropertyEnd()
21633af6ab5fSopenharmony_ci{
21643af6ab5fSopenharmony_ci    // Property definiton must end with ',' or '}' otherwise we throw SyntaxError
21653af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
21663af6ab5fSopenharmony_ci        lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
21673af6ab5fSopenharmony_ci        ThrowSyntaxError("Unexpected token, expected ',' or '}'");
21683af6ab5fSopenharmony_ci    }
21693af6ab5fSopenharmony_ci
21703af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA &&
21713af6ab5fSopenharmony_ci        lexer_->Lookahead() == lexer::LEX_CHAR_RIGHT_BRACE) {
21723af6ab5fSopenharmony_ci        lexer_->NextToken();
21733af6ab5fSopenharmony_ci        return true;
21743af6ab5fSopenharmony_ci    }
21753af6ab5fSopenharmony_ci
21763af6ab5fSopenharmony_ci    return false;
21773af6ab5fSopenharmony_ci}
21783af6ab5fSopenharmony_ci
21793af6ab5fSopenharmony_ci// NOLINTNEXTLINE(google-default-arguments)
21803af6ab5fSopenharmony_ciir::ObjectExpression *ParserImpl::ParseObjectExpression(ExpressionParseFlags flags)
21813af6ab5fSopenharmony_ci{
21823af6ab5fSopenharmony_ci    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
21833af6ab5fSopenharmony_ci    lexer::SourcePosition start = lexer_->GetToken().Start();
21843af6ab5fSopenharmony_ci    ArenaVector<ir::Expression *> properties(Allocator()->Adapter());
21853af6ab5fSopenharmony_ci    bool trailingComma = false;
21863af6ab5fSopenharmony_ci    bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0;
21873af6ab5fSopenharmony_ci
21883af6ab5fSopenharmony_ci    if (lexer_->Lookahead() == lexer::LEX_CHAR_RIGHT_BRACE) {
21893af6ab5fSopenharmony_ci        lexer_->NextToken();
21903af6ab5fSopenharmony_ci    }
21913af6ab5fSopenharmony_ci
21923af6ab5fSopenharmony_ci    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
21933af6ab5fSopenharmony_ci        ir::Expression *property = ParsePropertyDefinition(flags | ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
21943af6ab5fSopenharmony_ci        properties.push_back(property);
21953af6ab5fSopenharmony_ci        trailingComma = ParsePropertyEnd();
21963af6ab5fSopenharmony_ci    }
21973af6ab5fSopenharmony_ci
21983af6ab5fSopenharmony_ci    auto nodeType = inPattern ? ir::AstNodeType::OBJECT_PATTERN : ir::AstNodeType::OBJECT_EXPRESSION;
21993af6ab5fSopenharmony_ci    auto *objectExpression =
22003af6ab5fSopenharmony_ci        AllocNode<ir::ObjectExpression>(nodeType, Allocator(), std::move(properties), trailingComma);
22013af6ab5fSopenharmony_ci    objectExpression->SetRange({start, lexer_->GetToken().End()});
22023af6ab5fSopenharmony_ci    lexer_->NextToken();
22033af6ab5fSopenharmony_ci
22043af6ab5fSopenharmony_ci    if (inPattern) {
22053af6ab5fSopenharmony_ci        objectExpression->SetDeclaration();
22063af6ab5fSopenharmony_ci    }
22073af6ab5fSopenharmony_ci
22083af6ab5fSopenharmony_ci    if ((flags & ExpressionParseFlags::POTENTIALLY_IN_PATTERN) == 0) {
22093af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION &&
22103af6ab5fSopenharmony_ci            !objectExpression->ConvertibleToObjectPattern()) {
22113af6ab5fSopenharmony_ci            ThrowSyntaxError("Invalid left-hand side in array destructuring pattern", objectExpression->Start());
22123af6ab5fSopenharmony_ci        } else if (!inPattern && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
22133af6ab5fSopenharmony_ci            ir::ValidationInfo info = objectExpression->ValidateExpression();
22143af6ab5fSopenharmony_ci            if (info.Fail()) {
22153af6ab5fSopenharmony_ci                ThrowSyntaxError(info.msg.Utf8(), info.pos);
22163af6ab5fSopenharmony_ci            }
22173af6ab5fSopenharmony_ci        }
22183af6ab5fSopenharmony_ci    }
22193af6ab5fSopenharmony_ci
22203af6ab5fSopenharmony_ci    return objectExpression;
22213af6ab5fSopenharmony_ci}
22223af6ab5fSopenharmony_ci
22233af6ab5fSopenharmony_ciir::SequenceExpression *ParserImpl::ParseSequenceExpression(ir::Expression *startExpr, bool acceptRest)
22243af6ab5fSopenharmony_ci{
22253af6ab5fSopenharmony_ci    lexer::SourcePosition start = startExpr->Start();
22263af6ab5fSopenharmony_ci
22273af6ab5fSopenharmony_ci    ArenaVector<ir::Expression *> sequence(Allocator()->Adapter());
22283af6ab5fSopenharmony_ci    sequence.push_back(startExpr);
22293af6ab5fSopenharmony_ci
22303af6ab5fSopenharmony_ci    while (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
22313af6ab5fSopenharmony_ci        lexer_->NextToken();
22323af6ab5fSopenharmony_ci
22333af6ab5fSopenharmony_ci        if (acceptRest && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
22343af6ab5fSopenharmony_ci            ir::SpreadElement *expr = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN);
22353af6ab5fSopenharmony_ci            sequence.push_back(expr);
22363af6ab5fSopenharmony_ci            break;
22373af6ab5fSopenharmony_ci        }
22383af6ab5fSopenharmony_ci
22393af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS && lexer_->CheckArrow()) {
22403af6ab5fSopenharmony_ci            break;
22413af6ab5fSopenharmony_ci        }
22423af6ab5fSopenharmony_ci
22433af6ab5fSopenharmony_ci        sequence.push_back(ParseExpression());
22443af6ab5fSopenharmony_ci    }
22453af6ab5fSopenharmony_ci
22463af6ab5fSopenharmony_ci    lexer::SourcePosition end = sequence.back()->End();
22473af6ab5fSopenharmony_ci    auto *sequenceNode = AllocNode<ir::SequenceExpression>(std::move(sequence));
22483af6ab5fSopenharmony_ci    sequenceNode->SetRange({start, end});
22493af6ab5fSopenharmony_ci
22503af6ab5fSopenharmony_ci    return sequenceNode;
22513af6ab5fSopenharmony_ci}
22523af6ab5fSopenharmony_ci
22533af6ab5fSopenharmony_ci// NOLINTNEXTLINE(google-default-arguments)
22543af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParseUnaryOrPrefixUpdateExpression(ExpressionParseFlags flags)
22553af6ab5fSopenharmony_ci{
22563af6ab5fSopenharmony_ci    if (!lexer_->GetToken().IsUnary()) {
22573af6ab5fSopenharmony_ci        return ParseLeftHandSideExpression(flags);
22583af6ab5fSopenharmony_ci    }
22593af6ab5fSopenharmony_ci
22603af6ab5fSopenharmony_ci    lexer::TokenType operatorType = lexer_->GetToken().Type();
22613af6ab5fSopenharmony_ci    lexer::SourcePosition start = lexer_->GetToken().Start();
22623af6ab5fSopenharmony_ci    lexer_->NextToken();
22633af6ab5fSopenharmony_ci
22643af6ab5fSopenharmony_ci    ir::Expression *argument =
22653af6ab5fSopenharmony_ci        lexer_->GetToken().IsUnary() ? ParseUnaryOrPrefixUpdateExpression() : ParseLeftHandSideExpression();
22663af6ab5fSopenharmony_ci
22673af6ab5fSopenharmony_ci    if (lexer::Token::IsUpdateToken(operatorType)) {
22683af6ab5fSopenharmony_ci        if (!argument->IsIdentifier() && !argument->IsMemberExpression() && !argument->IsTSNonNullExpression()) {
22693af6ab5fSopenharmony_ci            ThrowSyntaxError("Invalid left-hand side in prefix operation");
22703af6ab5fSopenharmony_ci        }
22713af6ab5fSopenharmony_ci
22723af6ab5fSopenharmony_ci        if (argument->IsIdentifier()) {
22733af6ab5fSopenharmony_ci            const util::StringView &argumentStr = argument->AsIdentifier()->Name();
22743af6ab5fSopenharmony_ci
22753af6ab5fSopenharmony_ci            if (argumentStr.Is("eval")) {
22763af6ab5fSopenharmony_ci                ThrowSyntaxError("Assigning to 'eval' in strict mode is invalid");
22773af6ab5fSopenharmony_ci            } else if (argumentStr.Is("arguments")) {
22783af6ab5fSopenharmony_ci                ThrowSyntaxError("Assigning to 'arguments' in strict mode is invalid");
22793af6ab5fSopenharmony_ci            }
22803af6ab5fSopenharmony_ci        }
22813af6ab5fSopenharmony_ci    }
22823af6ab5fSopenharmony_ci
22833af6ab5fSopenharmony_ci    if (operatorType == lexer::TokenType::KEYW_DELETE) {
22843af6ab5fSopenharmony_ci        if (argument->IsIdentifier()) {
22853af6ab5fSopenharmony_ci            ThrowSyntaxError("Deleting local variable in strict mode");
22863af6ab5fSopenharmony_ci        }
22873af6ab5fSopenharmony_ci
22883af6ab5fSopenharmony_ci        if (argument->IsMemberExpression() && argument->AsMemberExpression()->Property()->IsIdentifier() &&
22893af6ab5fSopenharmony_ci            argument->AsMemberExpression()->Property()->AsIdentifier()->IsPrivateIdent()) {
22903af6ab5fSopenharmony_ci            ThrowSyntaxError("Private fields can not be deleted");
22913af6ab5fSopenharmony_ci        }
22923af6ab5fSopenharmony_ci    }
22933af6ab5fSopenharmony_ci
22943af6ab5fSopenharmony_ci    lexer::SourcePosition end = argument->End();
22953af6ab5fSopenharmony_ci
22963af6ab5fSopenharmony_ci    ir::Expression *returnExpr = nullptr;
22973af6ab5fSopenharmony_ci
22983af6ab5fSopenharmony_ci    if (lexer::Token::IsUpdateToken(operatorType)) {
22993af6ab5fSopenharmony_ci        returnExpr = AllocNode<ir::UpdateExpression>(argument, operatorType, true);
23003af6ab5fSopenharmony_ci    } else if (operatorType == lexer::TokenType::KEYW_AWAIT) {
23013af6ab5fSopenharmony_ci        returnExpr = AllocNode<ir::AwaitExpression>(argument);
23023af6ab5fSopenharmony_ci    } else if (operatorType == lexer::TokenType::KEYW_TYPEOF) {
23033af6ab5fSopenharmony_ci        returnExpr = AllocNode<ir::TypeofExpression>(argument);
23043af6ab5fSopenharmony_ci    } else {
23053af6ab5fSopenharmony_ci        returnExpr = AllocNode<ir::UnaryExpression>(argument, operatorType);
23063af6ab5fSopenharmony_ci    }
23073af6ab5fSopenharmony_ci
23083af6ab5fSopenharmony_ci    returnExpr->SetRange({start, end});
23093af6ab5fSopenharmony_ci
23103af6ab5fSopenharmony_ci    return returnExpr;
23113af6ab5fSopenharmony_ci}
23123af6ab5fSopenharmony_ci
23133af6ab5fSopenharmony_ciir::Expression *ParserImpl::ParseImportExpression()
23143af6ab5fSopenharmony_ci{
23153af6ab5fSopenharmony_ci    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
23163af6ab5fSopenharmony_ci    lexer::SourcePosition endLoc = lexer_->GetToken().End();
23173af6ab5fSopenharmony_ci    lexer_->NextToken();  // eat import
23183af6ab5fSopenharmony_ci
23193af6ab5fSopenharmony_ci    // parse import.Meta
23203af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
23213af6ab5fSopenharmony_ci        if (!context_.IsModule()) {
23223af6ab5fSopenharmony_ci            ThrowSyntaxError("'import.Meta' may appear only with 'sourceType: module'");
23233af6ab5fSopenharmony_ci        } else if (GetOptions().isDirectEval) {
23243af6ab5fSopenharmony_ci            ThrowSyntaxError("'import.Meta' is not allowed in direct eval in module code.");
23253af6ab5fSopenharmony_ci        }
23263af6ab5fSopenharmony_ci
23273af6ab5fSopenharmony_ci        lexer_->NextToken();  // eat dot
23283af6ab5fSopenharmony_ci
23293af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT ||
23303af6ab5fSopenharmony_ci            lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_META) {
23313af6ab5fSopenharmony_ci            ThrowSyntaxError("The only valid meta property for import is import.Meta");
23323af6ab5fSopenharmony_ci        }
23333af6ab5fSopenharmony_ci
23343af6ab5fSopenharmony_ci        auto *metaProperty = AllocNode<ir::MetaProperty>(ir::MetaProperty::MetaPropertyKind::IMPORT_META);
23353af6ab5fSopenharmony_ci        metaProperty->SetRange({startLoc, endLoc});
23363af6ab5fSopenharmony_ci
23373af6ab5fSopenharmony_ci        lexer_->NextToken();
23383af6ab5fSopenharmony_ci        return metaProperty;
23393af6ab5fSopenharmony_ci    }
23403af6ab5fSopenharmony_ci
23413af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
23423af6ab5fSopenharmony_ci        ThrowSyntaxError("Unexpected token");
23433af6ab5fSopenharmony_ci    }
23443af6ab5fSopenharmony_ci
23453af6ab5fSopenharmony_ci    lexer_->NextToken();  // eat left parentheses
23463af6ab5fSopenharmony_ci
23473af6ab5fSopenharmony_ci    ir::Expression *source = ParseExpression();
23483af6ab5fSopenharmony_ci
23493af6ab5fSopenharmony_ci    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
23503af6ab5fSopenharmony_ci        ThrowSyntaxError("Unexpected token");
23513af6ab5fSopenharmony_ci    }
23523af6ab5fSopenharmony_ci
23533af6ab5fSopenharmony_ci    auto *importExpression = AllocNode<ir::ImportExpression>(source);
23543af6ab5fSopenharmony_ci    importExpression->SetRange({startLoc, lexer_->GetToken().End()});
23553af6ab5fSopenharmony_ci
23563af6ab5fSopenharmony_ci    lexer_->NextToken();  // eat right paren
23573af6ab5fSopenharmony_ci    return importExpression;
23583af6ab5fSopenharmony_ci}
23593af6ab5fSopenharmony_ci
23603af6ab5fSopenharmony_cibool ParserImpl::IsNamedFunctionExpression()
23613af6ab5fSopenharmony_ci{
23623af6ab5fSopenharmony_ci    return lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS;
23633af6ab5fSopenharmony_ci}
23643af6ab5fSopenharmony_ci
23653af6ab5fSopenharmony_ciir::FunctionExpression *ParserImpl::ParseFunctionExpression(ParserStatus newStatus)
23663af6ab5fSopenharmony_ci{
23673af6ab5fSopenharmony_ci    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
23683af6ab5fSopenharmony_ci    ir::Identifier *ident = nullptr;
23693af6ab5fSopenharmony_ci
23703af6ab5fSopenharmony_ci    if ((newStatus & ParserStatus::ARROW_FUNCTION) == 0) {
23713af6ab5fSopenharmony_ci        ParserStatus savedStatus = context_.Status();
23723af6ab5fSopenharmony_ci        context_.Status() |= static_cast<ParserStatus>(newStatus & ParserStatus::ASYNC_FUNCTION);
23733af6ab5fSopenharmony_ci
23743af6ab5fSopenharmony_ci        lexer_->NextToken();
23753af6ab5fSopenharmony_ci
23763af6ab5fSopenharmony_ci        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
23773af6ab5fSopenharmony_ci            newStatus |= ParserStatus::GENERATOR_FUNCTION;
23783af6ab5fSopenharmony_ci            lexer_->NextToken();
23793af6ab5fSopenharmony_ci        }
23803af6ab5fSopenharmony_ci
23813af6ab5fSopenharmony_ci        if (IsNamedFunctionExpression()) {
23823af6ab5fSopenharmony_ci            CheckRestrictedBinding(lexer_->GetToken().KeywordType());
23833af6ab5fSopenharmony_ci            ident = ExpectIdentifier(false, true);
23843af6ab5fSopenharmony_ci        }
23853af6ab5fSopenharmony_ci
23863af6ab5fSopenharmony_ci        context_.Status() = savedStatus;
23873af6ab5fSopenharmony_ci    }
23883af6ab5fSopenharmony_ci
23893af6ab5fSopenharmony_ci    ir::ScriptFunction *functionNode = ParseFunction(newStatus);
23903af6ab5fSopenharmony_ci    functionNode->SetStart(startLoc);
23913af6ab5fSopenharmony_ci
23923af6ab5fSopenharmony_ci    auto *funcExpr = AllocNode<ir::FunctionExpression>(ident, functionNode);
23933af6ab5fSopenharmony_ci    funcExpr->SetRange(functionNode->Range());
23943af6ab5fSopenharmony_ci
23953af6ab5fSopenharmony_ci    return funcExpr;
23963af6ab5fSopenharmony_ci}
23973af6ab5fSopenharmony_ci}  // namespace ark::es2panda::parser
2398