13af6ab5fSopenharmony_ci/*
23af6ab5fSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License.
53af6ab5fSopenharmony_ci * You may obtain a copy of the License at
63af6ab5fSopenharmony_ci *
73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
83af6ab5fSopenharmony_ci *
93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and
133af6ab5fSopenharmony_ci * limitations under the License.
143af6ab5fSopenharmony_ci */
153af6ab5fSopenharmony_ci
163af6ab5fSopenharmony_ci#include "ETSparser.h"
173af6ab5fSopenharmony_ci
183af6ab5fSopenharmony_ci#include "lexer/lexer.h"
193af6ab5fSopenharmony_ci#include "ir/typeNode.h"
203af6ab5fSopenharmony_ci#include "ir/expressions/identifier.h"
213af6ab5fSopenharmony_ci#include "ir/expressions/blockExpression.h"
223af6ab5fSopenharmony_ci#include "ir/expressions/sequenceExpression.h"
233af6ab5fSopenharmony_ci#include "ir/statements/blockStatement.h"
243af6ab5fSopenharmony_ci#include "ir/statements/expressionStatement.h"
253af6ab5fSopenharmony_ci#include "ir/base/methodDefinition.h"
263af6ab5fSopenharmony_ci#include "ir/ts/tsInterfaceBody.h"
273af6ab5fSopenharmony_ci#include "parser/parserStatusContext.h"
283af6ab5fSopenharmony_ci
293af6ab5fSopenharmony_cinamespace ark::es2panda::parser {
303af6ab5fSopenharmony_ci//================================================================================================//
313af6ab5fSopenharmony_ci//  Methods to create AST node(s) from the specified string (part of valid ETS-code!)
323af6ab5fSopenharmony_ci//================================================================================================//
333af6ab5fSopenharmony_ci
343af6ab5fSopenharmony_ci// NOLINTBEGIN(modernize-avoid-c-arrays)
353af6ab5fSopenharmony_ciinline constexpr char const FORMAT_SIGNATURE = '@';
363af6ab5fSopenharmony_ciinline constexpr char const TYPE_FORMAT_NODE = 'T';
373af6ab5fSopenharmony_ciinline constexpr char const GENERAL_FORMAT_NODE = 'N';
383af6ab5fSopenharmony_ciinline constexpr char const IDENTIFIER_FORMAT_NODE = 'I';
393af6ab5fSopenharmony_ci
403af6ab5fSopenharmony_cistatic constexpr char const INVALID_NUMBER_NODE[] = "Invalid node number in format expression.";
413af6ab5fSopenharmony_cistatic constexpr char const INVALID_FORMAT_NODE[] = "Invalid node type in format expression.";
423af6ab5fSopenharmony_cistatic constexpr char const INSERT_NODE_ABSENT[] = "There is no any node to insert at the placeholder position.";
433af6ab5fSopenharmony_cistatic constexpr char const INVALID_INSERT_NODE[] =
443af6ab5fSopenharmony_ci    "Inserting node type differs from that required by format specification.";
453af6ab5fSopenharmony_cistatic constexpr char const INVALID_CLASS_FIELD[] = "Cannot parse class field definition property.";
463af6ab5fSopenharmony_cistatic constexpr char const INVALID_CLASS_METHOD[] = "Cannot parse class method definition property.";
473af6ab5fSopenharmony_ci// NOLINTEND(modernize-avoid-c-arrays)
483af6ab5fSopenharmony_ci
493af6ab5fSopenharmony_ciParserImpl::NodeFormatType ETSParser::GetFormatPlaceholderType() const
503af6ab5fSopenharmony_ci{
513af6ab5fSopenharmony_ci    ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT);
523af6ab5fSopenharmony_ci    Lexer()->NextToken();
533af6ab5fSopenharmony_ci
543af6ab5fSopenharmony_ci    bool isArray = false;
553af6ab5fSopenharmony_ci    if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
563af6ab5fSopenharmony_ci        isArray = true;
573af6ab5fSopenharmony_ci        Lexer()->NextToken();
583af6ab5fSopenharmony_ci    }
593af6ab5fSopenharmony_ci
603af6ab5fSopenharmony_ci    ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT);
613af6ab5fSopenharmony_ci    char const *const identData = Lexer()->GetToken().Ident().Bytes();
623af6ab5fSopenharmony_ci
633af6ab5fSopenharmony_ci    // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic, cert-err34-c)
643af6ab5fSopenharmony_ci    auto identNumber = std::atoi(identData + 1U);
653af6ab5fSopenharmony_ci    if (identNumber <= 0) {
663af6ab5fSopenharmony_ci        ThrowSyntaxError(INVALID_NUMBER_NODE, Lexer()->GetToken().Start());
673af6ab5fSopenharmony_ci    }
683af6ab5fSopenharmony_ci
693af6ab5fSopenharmony_ci    return {isArray, *identData,
703af6ab5fSopenharmony_ci            static_cast<decltype(std::get<2>(std::declval<ParserImpl::NodeFormatType>()))>(identNumber - 1)};
713af6ab5fSopenharmony_ci}
723af6ab5fSopenharmony_ci
733af6ab5fSopenharmony_ciir::Expression *ETSParser::ParseExpressionFormatPlaceholder()
743af6ab5fSopenharmony_ci{
753af6ab5fSopenharmony_ci    if (insertingNodes_.empty()) {
763af6ab5fSopenharmony_ci        ThrowSyntaxError(INSERT_NODE_ABSENT, Lexer()->GetToken().Start());
773af6ab5fSopenharmony_ci    }
783af6ab5fSopenharmony_ci
793af6ab5fSopenharmony_ci    ParserImpl::NodeFormatType nodeFormat = GetFormatPlaceholderType();
803af6ab5fSopenharmony_ci    if (std::get<0>(nodeFormat)) {
813af6ab5fSopenharmony_ci        ThrowSyntaxError(INVALID_FORMAT_NODE, Lexer()->GetToken().Start());
823af6ab5fSopenharmony_ci    }
833af6ab5fSopenharmony_ci
843af6ab5fSopenharmony_ci    if (auto const placeholderType = std::get<1>(nodeFormat); placeholderType == TYPE_FORMAT_NODE) {
853af6ab5fSopenharmony_ci        return ParseTypeFormatPlaceholder(std::make_optional(std::move(nodeFormat)));
863af6ab5fSopenharmony_ci    } else if (placeholderType == IDENTIFIER_FORMAT_NODE) {  // NOLINT(readability-else-after-return)
873af6ab5fSopenharmony_ci        return ParseIdentifierFormatPlaceholder(std::make_optional(std::move(nodeFormat)));
883af6ab5fSopenharmony_ci    } else if (placeholderType != EXPRESSION_FORMAT_NODE) {  // NOLINT(readability-else-after-return)
893af6ab5fSopenharmony_ci        ThrowSyntaxError(INVALID_FORMAT_NODE, Lexer()->GetToken().Start());
903af6ab5fSopenharmony_ci    }
913af6ab5fSopenharmony_ci
923af6ab5fSopenharmony_ci    auto const placeholderNumber = std::get<2>(nodeFormat);
933af6ab5fSopenharmony_ci    auto *const insertingNode =
943af6ab5fSopenharmony_ci        placeholderNumber < insertingNodes_.size() ? insertingNodes_[placeholderNumber] : nullptr;
953af6ab5fSopenharmony_ci    if (insertingNode == nullptr || !insertingNode->IsExpression()) {
963af6ab5fSopenharmony_ci        ThrowSyntaxError(INVALID_INSERT_NODE, Lexer()->GetToken().Start());
973af6ab5fSopenharmony_ci    }
983af6ab5fSopenharmony_ci
993af6ab5fSopenharmony_ci    auto *const insertExpression = insertingNode->AsExpression();
1003af6ab5fSopenharmony_ci    Lexer()->NextToken();
1013af6ab5fSopenharmony_ci    return insertExpression;
1023af6ab5fSopenharmony_ci}
1033af6ab5fSopenharmony_ci
1043af6ab5fSopenharmony_ciir::TypeNode *ETSParser::ParseTypeFormatPlaceholder(std::optional<ParserImpl::NodeFormatType> nodeFormat)
1053af6ab5fSopenharmony_ci{
1063af6ab5fSopenharmony_ci    if (!nodeFormat.has_value()) {
1073af6ab5fSopenharmony_ci        if (insertingNodes_.empty()) {
1083af6ab5fSopenharmony_ci            ThrowSyntaxError(INSERT_NODE_ABSENT, Lexer()->GetToken().Start());
1093af6ab5fSopenharmony_ci        }
1103af6ab5fSopenharmony_ci
1113af6ab5fSopenharmony_ci        nodeFormat = GetFormatPlaceholderType();
1123af6ab5fSopenharmony_ci        if (std::get<0>(*nodeFormat) || std::get<1>(*nodeFormat) != TYPE_FORMAT_NODE) {
1133af6ab5fSopenharmony_ci            ThrowSyntaxError(INVALID_FORMAT_NODE, Lexer()->GetToken().Start());
1143af6ab5fSopenharmony_ci        }
1153af6ab5fSopenharmony_ci    }
1163af6ab5fSopenharmony_ci
1173af6ab5fSopenharmony_ci    auto const placeholderNumber = std::get<2>(*nodeFormat);
1183af6ab5fSopenharmony_ci    auto *const insertingNode =
1193af6ab5fSopenharmony_ci        placeholderNumber < insertingNodes_.size() ? insertingNodes_[placeholderNumber] : nullptr;
1203af6ab5fSopenharmony_ci    if (insertingNode == nullptr || !insertingNode->IsExpression() || !insertingNode->AsExpression()->IsTypeNode()) {
1213af6ab5fSopenharmony_ci        ThrowSyntaxError(INVALID_INSERT_NODE, Lexer()->GetToken().Start());
1223af6ab5fSopenharmony_ci    }
1233af6ab5fSopenharmony_ci
1243af6ab5fSopenharmony_ci    auto *const insertType = insertingNode->AsExpression()->AsTypeNode();
1253af6ab5fSopenharmony_ci    Lexer()->NextToken();
1263af6ab5fSopenharmony_ci    return insertType;
1273af6ab5fSopenharmony_ci}
1283af6ab5fSopenharmony_ci
1293af6ab5fSopenharmony_ciir::Identifier *ETSParser::ParseIdentifierFormatPlaceholder(std::optional<ParserImpl::NodeFormatType> nodeFormat) const
1303af6ab5fSopenharmony_ci{
1313af6ab5fSopenharmony_ci    if (!nodeFormat.has_value()) {
1323af6ab5fSopenharmony_ci        if (insertingNodes_.empty()) {
1333af6ab5fSopenharmony_ci            ThrowSyntaxError(INSERT_NODE_ABSENT, Lexer()->GetToken().Start());
1343af6ab5fSopenharmony_ci        }
1353af6ab5fSopenharmony_ci
1363af6ab5fSopenharmony_ci        nodeFormat = GetFormatPlaceholderType();
1373af6ab5fSopenharmony_ci        if (std::get<0>(*nodeFormat) || std::get<1>(*nodeFormat) != IDENTIFIER_FORMAT_NODE) {
1383af6ab5fSopenharmony_ci            ThrowSyntaxError(INVALID_FORMAT_NODE, Lexer()->GetToken().Start());
1393af6ab5fSopenharmony_ci        }
1403af6ab5fSopenharmony_ci    }
1413af6ab5fSopenharmony_ci
1423af6ab5fSopenharmony_ci    auto const placeholderNumber = std::get<2>(*nodeFormat);
1433af6ab5fSopenharmony_ci    auto *const insertingNode =
1443af6ab5fSopenharmony_ci        placeholderNumber < insertingNodes_.size() ? insertingNodes_[placeholderNumber] : nullptr;
1453af6ab5fSopenharmony_ci    if (insertingNode == nullptr || !insertingNode->IsExpression() || !insertingNode->AsExpression()->IsIdentifier()) {
1463af6ab5fSopenharmony_ci        ThrowSyntaxError(INVALID_INSERT_NODE, Lexer()->GetToken().Start());
1473af6ab5fSopenharmony_ci    }
1483af6ab5fSopenharmony_ci
1493af6ab5fSopenharmony_ci    auto *const insertIdentifier = insertingNode->AsExpression()->AsIdentifier();
1503af6ab5fSopenharmony_ci    Lexer()->NextToken();
1513af6ab5fSopenharmony_ci    return insertIdentifier;
1523af6ab5fSopenharmony_ci}
1533af6ab5fSopenharmony_ci
1543af6ab5fSopenharmony_ciir::Statement *ETSParser::ParseStatementFormatPlaceholder() const
1553af6ab5fSopenharmony_ci{
1563af6ab5fSopenharmony_ci    if (insertingNodes_.empty()) {
1573af6ab5fSopenharmony_ci        ThrowSyntaxError(INSERT_NODE_ABSENT, Lexer()->GetToken().Start());
1583af6ab5fSopenharmony_ci    }
1593af6ab5fSopenharmony_ci
1603af6ab5fSopenharmony_ci    ParserImpl::NodeFormatType nodeFormat = GetFormatPlaceholderType();
1613af6ab5fSopenharmony_ci    if (std::get<0>(nodeFormat) || std::get<1>(nodeFormat) != STATEMENT_FORMAT_NODE) {
1623af6ab5fSopenharmony_ci        ThrowSyntaxError(INVALID_FORMAT_NODE, Lexer()->GetToken().Start());
1633af6ab5fSopenharmony_ci    }
1643af6ab5fSopenharmony_ci
1653af6ab5fSopenharmony_ci    auto const placeholderNumber = std::get<2>(nodeFormat);
1663af6ab5fSopenharmony_ci    auto *const insertingNode =
1673af6ab5fSopenharmony_ci        placeholderNumber < insertingNodes_.size() ? insertingNodes_[placeholderNumber] : nullptr;
1683af6ab5fSopenharmony_ci    if (insertingNode == nullptr || !insertingNode->IsStatement()) {
1693af6ab5fSopenharmony_ci        ThrowSyntaxError(INVALID_INSERT_NODE, Lexer()->GetToken().Start());
1703af6ab5fSopenharmony_ci    }
1713af6ab5fSopenharmony_ci
1723af6ab5fSopenharmony_ci    Lexer()->NextToken();
1733af6ab5fSopenharmony_ci    return insertingNode->AsStatement();
1743af6ab5fSopenharmony_ci}
1753af6ab5fSopenharmony_ci
1763af6ab5fSopenharmony_ciir::AstNode *ETSParser::ParseTypeParametersFormatPlaceholder() const
1773af6ab5fSopenharmony_ci{
1783af6ab5fSopenharmony_ci    ParserImpl::NodeFormatType nodeFormat = GetFormatPlaceholderType();
1793af6ab5fSopenharmony_ci    if (std::get<0>(nodeFormat) || std::get<1>(nodeFormat) != EXPRESSION_FORMAT_NODE) {
1803af6ab5fSopenharmony_ci        ThrowSyntaxError(INVALID_FORMAT_NODE, Lexer()->GetToken().Start());
1813af6ab5fSopenharmony_ci    }
1823af6ab5fSopenharmony_ci
1833af6ab5fSopenharmony_ci    auto const placeholderNumber = std::get<2>(nodeFormat);
1843af6ab5fSopenharmony_ci    if (placeholderNumber >= insertingNodes_.size()) {
1853af6ab5fSopenharmony_ci        ThrowSyntaxError(INSERT_NODE_ABSENT, Lexer()->GetToken().Start());
1863af6ab5fSopenharmony_ci    }
1873af6ab5fSopenharmony_ci
1883af6ab5fSopenharmony_ci    auto *const insertingNode = insertingNodes_[placeholderNumber];
1893af6ab5fSopenharmony_ci    if (insertingNode != nullptr && !insertingNode->IsTSTypeParameterDeclaration() &&
1903af6ab5fSopenharmony_ci        !insertingNode->IsTSTypeParameterInstantiation()) {
1913af6ab5fSopenharmony_ci        ThrowSyntaxError(INVALID_INSERT_NODE, Lexer()->GetToken().Start());
1923af6ab5fSopenharmony_ci    }
1933af6ab5fSopenharmony_ci
1943af6ab5fSopenharmony_ci    Lexer()->NextToken();
1953af6ab5fSopenharmony_ci    return insertingNode;
1963af6ab5fSopenharmony_ci}
1973af6ab5fSopenharmony_ci
1983af6ab5fSopenharmony_ciArenaVector<ir::AstNode *> &ETSParser::ParseAstNodesArrayFormatPlaceholder() const
1993af6ab5fSopenharmony_ci{
2003af6ab5fSopenharmony_ci    if (insertingNodes_.empty()) {
2013af6ab5fSopenharmony_ci        ThrowSyntaxError(INSERT_NODE_ABSENT, Lexer()->GetToken().Start());
2023af6ab5fSopenharmony_ci    }
2033af6ab5fSopenharmony_ci
2043af6ab5fSopenharmony_ci    ParserImpl::NodeFormatType nodeFormat = GetFormatPlaceholderType();
2053af6ab5fSopenharmony_ci    if (!std::get<0>(nodeFormat) || std::get<1>(nodeFormat) != GENERAL_FORMAT_NODE) {
2063af6ab5fSopenharmony_ci        ThrowSyntaxError(INVALID_FORMAT_NODE, Lexer()->GetToken().Start());
2073af6ab5fSopenharmony_ci    }
2083af6ab5fSopenharmony_ci
2093af6ab5fSopenharmony_ci    auto const placeholderNumber = std::get<2>(nodeFormat);
2103af6ab5fSopenharmony_ci    auto *const insertingNode =
2113af6ab5fSopenharmony_ci        placeholderNumber < insertingNodes_.size() ? insertingNodes_[placeholderNumber] : nullptr;
2123af6ab5fSopenharmony_ci    if (insertingNode == nullptr || !insertingNode->IsTSInterfaceBody()) {
2133af6ab5fSopenharmony_ci        ThrowSyntaxError(INVALID_INSERT_NODE, Lexer()->GetToken().Start());
2143af6ab5fSopenharmony_ci    }
2153af6ab5fSopenharmony_ci
2163af6ab5fSopenharmony_ci    Lexer()->NextToken();
2173af6ab5fSopenharmony_ci    return insertingNode->AsTSInterfaceBody()->Body();
2183af6ab5fSopenharmony_ci}
2193af6ab5fSopenharmony_ci
2203af6ab5fSopenharmony_ciArenaVector<ir::Statement *> &ETSParser::ParseStatementsArrayFormatPlaceholder() const
2213af6ab5fSopenharmony_ci{
2223af6ab5fSopenharmony_ci    if (insertingNodes_.empty()) {
2233af6ab5fSopenharmony_ci        ThrowSyntaxError(INSERT_NODE_ABSENT, Lexer()->GetToken().Start());
2243af6ab5fSopenharmony_ci    }
2253af6ab5fSopenharmony_ci
2263af6ab5fSopenharmony_ci    ParserImpl::NodeFormatType nodeFormat = GetFormatPlaceholderType();
2273af6ab5fSopenharmony_ci    if (!std::get<0>(nodeFormat) || std::get<1>(nodeFormat) != STATEMENT_FORMAT_NODE) {
2283af6ab5fSopenharmony_ci        ThrowSyntaxError(INVALID_FORMAT_NODE, Lexer()->GetToken().Start());
2293af6ab5fSopenharmony_ci    }
2303af6ab5fSopenharmony_ci
2313af6ab5fSopenharmony_ci    auto const placeholderNumber = std::get<2>(nodeFormat);
2323af6ab5fSopenharmony_ci    auto *const insertingNode =
2333af6ab5fSopenharmony_ci        placeholderNumber < insertingNodes_.size() ? insertingNodes_[placeholderNumber] : nullptr;
2343af6ab5fSopenharmony_ci    if (insertingNode == nullptr || !insertingNode->IsBlockExpression()) {
2353af6ab5fSopenharmony_ci        ThrowSyntaxError(INVALID_INSERT_NODE, Lexer()->GetToken().Start());
2363af6ab5fSopenharmony_ci    }
2373af6ab5fSopenharmony_ci
2383af6ab5fSopenharmony_ci    Lexer()->NextToken();
2393af6ab5fSopenharmony_ci    return insertingNode->AsBlockExpression()->Statements();
2403af6ab5fSopenharmony_ci}
2413af6ab5fSopenharmony_ci
2423af6ab5fSopenharmony_ciArenaVector<ir::Expression *> &ETSParser::ParseExpressionsArrayFormatPlaceholder() const
2433af6ab5fSopenharmony_ci{
2443af6ab5fSopenharmony_ci    if (insertingNodes_.empty()) {
2453af6ab5fSopenharmony_ci        ThrowSyntaxError(INSERT_NODE_ABSENT, Lexer()->GetToken().Start());
2463af6ab5fSopenharmony_ci    }
2473af6ab5fSopenharmony_ci
2483af6ab5fSopenharmony_ci    ParserImpl::NodeFormatType nodeFormat = GetFormatPlaceholderType();
2493af6ab5fSopenharmony_ci    if (!std::get<0>(nodeFormat) || std::get<1>(nodeFormat) != EXPRESSION_FORMAT_NODE) {
2503af6ab5fSopenharmony_ci        ThrowSyntaxError(INVALID_FORMAT_NODE, Lexer()->GetToken().Start());
2513af6ab5fSopenharmony_ci    }
2523af6ab5fSopenharmony_ci
2533af6ab5fSopenharmony_ci    auto const placeholderNumber = std::get<2>(nodeFormat);
2543af6ab5fSopenharmony_ci    auto *const insertingNode =
2553af6ab5fSopenharmony_ci        placeholderNumber < insertingNodes_.size() ? insertingNodes_[placeholderNumber] : nullptr;
2563af6ab5fSopenharmony_ci    if (insertingNode == nullptr || !insertingNode->IsSequenceExpression()) {
2573af6ab5fSopenharmony_ci        ThrowSyntaxError(INVALID_INSERT_NODE, Lexer()->GetToken().Start());
2583af6ab5fSopenharmony_ci    }
2593af6ab5fSopenharmony_ci
2603af6ab5fSopenharmony_ci    Lexer()->NextToken();
2613af6ab5fSopenharmony_ci    return insertingNode->AsSequenceExpression()->Sequence();
2623af6ab5fSopenharmony_ci}
2633af6ab5fSopenharmony_ci
2643af6ab5fSopenharmony_ciir::Statement *ETSParser::CreateStatement(std::string_view const sourceCode)
2653af6ab5fSopenharmony_ci{
2663af6ab5fSopenharmony_ci    util::UString source {sourceCode, Allocator()};
2673af6ab5fSopenharmony_ci    auto const isp = InnerSourceParser(this);
2683af6ab5fSopenharmony_ci    auto const lexer = InitLexer({GetContext().FormattingFileName(), source.View().Utf8()});
2693af6ab5fSopenharmony_ci
2703af6ab5fSopenharmony_ci    lexer::SourcePosition const startLoc = lexer->GetToken().Start();
2713af6ab5fSopenharmony_ci    lexer->NextToken();
2723af6ab5fSopenharmony_ci
2733af6ab5fSopenharmony_ci    auto statements = ParseStatementList(StatementParsingFlags::STMT_GLOBAL_LEXICAL);
2743af6ab5fSopenharmony_ci    auto const statementNumber = statements.size();
2753af6ab5fSopenharmony_ci    if (statementNumber == 0U) {
2763af6ab5fSopenharmony_ci        return nullptr;
2773af6ab5fSopenharmony_ci    }
2783af6ab5fSopenharmony_ci
2793af6ab5fSopenharmony_ci    if (statementNumber == 1U) {
2803af6ab5fSopenharmony_ci        return statements[0U];
2813af6ab5fSopenharmony_ci    }
2823af6ab5fSopenharmony_ci
2833af6ab5fSopenharmony_ci    auto *const blockStmt = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
2843af6ab5fSopenharmony_ci    blockStmt->SetRange({startLoc, lexer->GetToken().End()});
2853af6ab5fSopenharmony_ci
2863af6ab5fSopenharmony_ci    for (auto *statement : blockStmt->Statements()) {
2873af6ab5fSopenharmony_ci        statement->SetParent(blockStmt);
2883af6ab5fSopenharmony_ci    }
2893af6ab5fSopenharmony_ci
2903af6ab5fSopenharmony_ci    return blockStmt;
2913af6ab5fSopenharmony_ci}
2923af6ab5fSopenharmony_ci
2933af6ab5fSopenharmony_ciir::Statement *ETSParser::CreateFormattedStatement(std::string_view const sourceCode,
2943af6ab5fSopenharmony_ci                                                   std::vector<ir::AstNode *> &insertingNodes)
2953af6ab5fSopenharmony_ci{
2963af6ab5fSopenharmony_ci    insertingNodes_.swap(insertingNodes);
2973af6ab5fSopenharmony_ci    auto const statement = CreateStatement(sourceCode);
2983af6ab5fSopenharmony_ci    insertingNodes_.swap(insertingNodes);
2993af6ab5fSopenharmony_ci    return statement;
3003af6ab5fSopenharmony_ci}
3013af6ab5fSopenharmony_ci
3023af6ab5fSopenharmony_ciArenaVector<ir::Statement *> ETSParser::CreateStatements(std::string_view const sourceCode)
3033af6ab5fSopenharmony_ci{
3043af6ab5fSopenharmony_ci    util::UString source {sourceCode, Allocator()};
3053af6ab5fSopenharmony_ci    auto const isp = InnerSourceParser(this);
3063af6ab5fSopenharmony_ci    auto const lexer = InitLexer({GetContext().FormattingFileName(), source.View().Utf8()});
3073af6ab5fSopenharmony_ci
3083af6ab5fSopenharmony_ci    lexer->NextToken();
3093af6ab5fSopenharmony_ci    return ParseStatementList(StatementParsingFlags::STMT_GLOBAL_LEXICAL);
3103af6ab5fSopenharmony_ci}
3113af6ab5fSopenharmony_ci
3123af6ab5fSopenharmony_ciArenaVector<ir::Statement *> ETSParser::CreateFormattedStatements(std::string_view const sourceCode,
3133af6ab5fSopenharmony_ci                                                                  std::vector<ir::AstNode *> &insertingNodes)
3143af6ab5fSopenharmony_ci{
3153af6ab5fSopenharmony_ci    insertingNodes_.swap(insertingNodes);
3163af6ab5fSopenharmony_ci    auto statements = CreateStatements(sourceCode);
3173af6ab5fSopenharmony_ci    insertingNodes_.swap(insertingNodes);
3183af6ab5fSopenharmony_ci    return statements;
3193af6ab5fSopenharmony_ci}
3203af6ab5fSopenharmony_ci
3213af6ab5fSopenharmony_ci//  NOTE: this method returns only a single (the first) class filed definition.
3223af6ab5fSopenharmony_ci//  It seems that it is possible to have several of them be parsed at a time but nobody knows how...
3233af6ab5fSopenharmony_ciir::AstNode *ETSParser::CreateFormattedClassFieldDefinition(std::string_view sourceCode,
3243af6ab5fSopenharmony_ci                                                            std::vector<ir::AstNode *> &insertingNodes)
3253af6ab5fSopenharmony_ci{
3263af6ab5fSopenharmony_ci    static ArenaVector<ir::AstNode *> const DUMMY_ARRAY {Allocator()->Adapter()};
3273af6ab5fSopenharmony_ci    insertingNodes_.swap(insertingNodes);
3283af6ab5fSopenharmony_ci
3293af6ab5fSopenharmony_ci    auto *const property = CreateClassElement(sourceCode, DUMMY_ARRAY, ir::ClassDefinitionModifiers::NONE);
3303af6ab5fSopenharmony_ci    if (!property->IsTSInterfaceBody() || property->AsTSInterfaceBody()->Body().empty()) {
3313af6ab5fSopenharmony_ci        ThrowSyntaxError(INVALID_CLASS_FIELD);
3323af6ab5fSopenharmony_ci    }
3333af6ab5fSopenharmony_ci
3343af6ab5fSopenharmony_ci    insertingNodes_.swap(insertingNodes);
3353af6ab5fSopenharmony_ci    return property->AsTSInterfaceBody()->Body().front();
3363af6ab5fSopenharmony_ci}
3373af6ab5fSopenharmony_ci
3383af6ab5fSopenharmony_ciir::AstNode *ETSParser::CreateFormattedClassMethodDefinition(std::string_view sourceCode,
3393af6ab5fSopenharmony_ci                                                             std::vector<ir::AstNode *> &insertingNodes)
3403af6ab5fSopenharmony_ci{
3413af6ab5fSopenharmony_ci    static ArenaVector<ir::AstNode *> const DUMMY_ARRAY {Allocator()->Adapter()};
3423af6ab5fSopenharmony_ci    insertingNodes_.swap(insertingNodes);
3433af6ab5fSopenharmony_ci
3443af6ab5fSopenharmony_ci    auto *const property = CreateClassElement(sourceCode, DUMMY_ARRAY, ir::ClassDefinitionModifiers::NONE);
3453af6ab5fSopenharmony_ci    if (!property->IsMethodDefinition()) {
3463af6ab5fSopenharmony_ci        ThrowSyntaxError(INVALID_CLASS_METHOD);
3473af6ab5fSopenharmony_ci    }
3483af6ab5fSopenharmony_ci
3493af6ab5fSopenharmony_ci    insertingNodes_.swap(insertingNodes);
3503af6ab5fSopenharmony_ci    return property;
3513af6ab5fSopenharmony_ci}
3523af6ab5fSopenharmony_ci
3533af6ab5fSopenharmony_ciir::AstNode *ETSParser::CreateFormattedClassElement(std::string_view sourceCode,
3543af6ab5fSopenharmony_ci                                                    std::vector<ir::AstNode *> &insertingNodes,
3553af6ab5fSopenharmony_ci                                                    const ArenaVector<ir::AstNode *> &properties,
3563af6ab5fSopenharmony_ci                                                    ir::ClassDefinitionModifiers modifiers)
3573af6ab5fSopenharmony_ci{
3583af6ab5fSopenharmony_ci    insertingNodes_.swap(insertingNodes);
3593af6ab5fSopenharmony_ci    auto *const classElement = CreateClassElement(sourceCode, properties, modifiers);
3603af6ab5fSopenharmony_ci    insertingNodes_.swap(insertingNodes);
3613af6ab5fSopenharmony_ci    return classElement;
3623af6ab5fSopenharmony_ci}
3633af6ab5fSopenharmony_ci
3643af6ab5fSopenharmony_ci//  NOTE: the method has limited functionality - it returns 'ir::TSInterfaceBody' placeholder for the field
3653af6ab5fSopenharmony_ci//  declaration(s) (properties themselves are in ->Body() member) and does not perform any check of the node returned.
3663af6ab5fSopenharmony_ci//  Also the node isn't placed in the providing properties container.
3673af6ab5fSopenharmony_ciir::AstNode *ETSParser::CreateClassElement(std::string_view sourceCode, const ArenaVector<ir::AstNode *> &properties,
3683af6ab5fSopenharmony_ci                                           ir::ClassDefinitionModifiers modifiers)
3693af6ab5fSopenharmony_ci{
3703af6ab5fSopenharmony_ci    util::UString source {sourceCode, Allocator()};
3713af6ab5fSopenharmony_ci    auto const isp = InnerSourceParser(this);
3723af6ab5fSopenharmony_ci    auto const lexer = InitLexer({GetContext().FormattingFileName(), source.View().Utf8()});
3733af6ab5fSopenharmony_ci
3743af6ab5fSopenharmony_ci    auto savedCtx = SavedStatusContext<ParserStatus::IN_CLASS_BODY>(&GetContext());
3753af6ab5fSopenharmony_ci    SavedClassPrivateContext classContext(this);
3763af6ab5fSopenharmony_ci
3773af6ab5fSopenharmony_ci    lexer->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
3783af6ab5fSopenharmony_ci
3793af6ab5fSopenharmony_ci    return ParseClassElement(properties, modifiers, ir::ModifierFlags::NONE);
3803af6ab5fSopenharmony_ci}
3813af6ab5fSopenharmony_ci
3823af6ab5fSopenharmony_ciir::ClassDeclaration *ETSParser::CreateFormattedClassDeclaration(std::string_view sourceCode,
3833af6ab5fSopenharmony_ci                                                                 std::vector<ir::AstNode *> &insertingNodes,
3843af6ab5fSopenharmony_ci                                                                 bool const allowStatic)
3853af6ab5fSopenharmony_ci{
3863af6ab5fSopenharmony_ci    insertingNodes_.swap(insertingNodes);
3873af6ab5fSopenharmony_ci    auto *const classDeclaration = CreateClassDeclaration(sourceCode, allowStatic);
3883af6ab5fSopenharmony_ci    insertingNodes_.swap(insertingNodes);
3893af6ab5fSopenharmony_ci    return classDeclaration;
3903af6ab5fSopenharmony_ci}
3913af6ab5fSopenharmony_ci
3923af6ab5fSopenharmony_ciir::ClassDeclaration *ETSParser::CreateClassDeclaration(std::string_view sourceCode, bool allowStatic)
3933af6ab5fSopenharmony_ci{
3943af6ab5fSopenharmony_ci    util::UString source {sourceCode, Allocator()};
3953af6ab5fSopenharmony_ci    auto const isp = InnerSourceParser(this);
3963af6ab5fSopenharmony_ci    auto const lexer = InitLexer({GetContext().FormattingFileName(), source.View().Utf8()});
3973af6ab5fSopenharmony_ci
3983af6ab5fSopenharmony_ci    auto savedCtx = SavedStatusContext<ParserStatus::IN_CLASS_BODY>(&GetContext());
3993af6ab5fSopenharmony_ci
4003af6ab5fSopenharmony_ci    auto modifiers = ir::ClassDefinitionModifiers::ID_REQUIRED | ir::ClassDefinitionModifiers::CLASS_DECL;
4013af6ab5fSopenharmony_ci    ir::ModifierFlags flags = ir::ModifierFlags::NONE;
4023af6ab5fSopenharmony_ci
4033af6ab5fSopenharmony_ci    lexer->NextToken();
4043af6ab5fSopenharmony_ci
4053af6ab5fSopenharmony_ci    switch (auto tokenType = Lexer()->GetToken().Type(); tokenType) {
4063af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_STATIC: {
4073af6ab5fSopenharmony_ci            if (!allowStatic) {
4083af6ab5fSopenharmony_ci                ThrowUnexpectedToken(Lexer()->GetToken().Type());
4093af6ab5fSopenharmony_ci            }
4103af6ab5fSopenharmony_ci            [[fallthrough]];
4113af6ab5fSopenharmony_ci        }
4123af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_ABSTRACT:
4133af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_FINAL: {
4143af6ab5fSopenharmony_ci            flags = ParseClassModifiers();
4153af6ab5fSopenharmony_ci            if (allowStatic && (flags & ir::ModifierFlags::STATIC) == 0U) {
4163af6ab5fSopenharmony_ci                modifiers |= ir::ClassDefinitionModifiers::INNER;
4173af6ab5fSopenharmony_ci            }
4183af6ab5fSopenharmony_ci
4193af6ab5fSopenharmony_ci            if (auto const tokType = Lexer()->GetToken().Type(); tokType != lexer::TokenType::KEYW_CLASS) {
4203af6ab5fSopenharmony_ci                ThrowUnexpectedToken(tokType);
4213af6ab5fSopenharmony_ci            }
4223af6ab5fSopenharmony_ci            [[fallthrough]];
4233af6ab5fSopenharmony_ci        }
4243af6ab5fSopenharmony_ci        case lexer::TokenType::KEYW_CLASS: {
4253af6ab5fSopenharmony_ci            return ParseClassDeclaration(modifiers);
4263af6ab5fSopenharmony_ci        }
4273af6ab5fSopenharmony_ci        default: {
4283af6ab5fSopenharmony_ci            ThrowUnexpectedToken(tokenType);
4293af6ab5fSopenharmony_ci        }
4303af6ab5fSopenharmony_ci    }
4313af6ab5fSopenharmony_ci}
4323af6ab5fSopenharmony_ci
4333af6ab5fSopenharmony_ciir::MethodDefinition *ETSParser::CreateConstructorDefinition(ir::ModifierFlags modifiers,
4343af6ab5fSopenharmony_ci                                                             std::string_view const sourceCode)
4353af6ab5fSopenharmony_ci{
4363af6ab5fSopenharmony_ci    util::UString source {sourceCode, Allocator()};
4373af6ab5fSopenharmony_ci    auto const isp = InnerSourceParser(this);
4383af6ab5fSopenharmony_ci    auto const lexer = InitLexer({GetContext().FormattingFileName(), source.View().Utf8()});
4393af6ab5fSopenharmony_ci
4403af6ab5fSopenharmony_ci    auto const startLoc = Lexer()->GetToken().Start();
4413af6ab5fSopenharmony_ci    Lexer()->NextToken();
4423af6ab5fSopenharmony_ci
4433af6ab5fSopenharmony_ci    if (IsClassMethodModifier(Lexer()->GetToken().Type())) {
4443af6ab5fSopenharmony_ci        modifiers |= ParseClassMethodModifiers(false);
4453af6ab5fSopenharmony_ci    }
4463af6ab5fSopenharmony_ci
4473af6ab5fSopenharmony_ci    if (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_CONSTRUCTOR) {
4483af6ab5fSopenharmony_ci        ThrowSyntaxError({"Unexpected token. 'Constructor' keyword is expected."});
4493af6ab5fSopenharmony_ci    }
4503af6ab5fSopenharmony_ci
4513af6ab5fSopenharmony_ci    if ((modifiers & ir::ModifierFlags::ASYNC) != 0) {
4523af6ab5fSopenharmony_ci        ThrowSyntaxError({"Constructor should not be async."});
4533af6ab5fSopenharmony_ci    }
4543af6ab5fSopenharmony_ci
4553af6ab5fSopenharmony_ci    auto *memberName = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
4563af6ab5fSopenharmony_ci    modifiers |= ir::ModifierFlags::CONSTRUCTOR;
4573af6ab5fSopenharmony_ci    Lexer()->NextToken();
4583af6ab5fSopenharmony_ci
4593af6ab5fSopenharmony_ci    auto *const methodDefinition = ParseClassMethodDefinition(memberName, modifiers);
4603af6ab5fSopenharmony_ci    methodDefinition->SetStart(startLoc);
4613af6ab5fSopenharmony_ci
4623af6ab5fSopenharmony_ci    return methodDefinition;
4633af6ab5fSopenharmony_ci}
4643af6ab5fSopenharmony_ci
4653af6ab5fSopenharmony_ciir::Expression *ETSParser::CreateExpression(std::string_view const sourceCode, ExpressionParseFlags const flags)
4663af6ab5fSopenharmony_ci{
4673af6ab5fSopenharmony_ci    util::UString source {sourceCode, Allocator()};
4683af6ab5fSopenharmony_ci    auto const isp = InnerSourceParser(this);
4693af6ab5fSopenharmony_ci    auto const lexer = InitLexer({GetContext().FormattingFileName(), source.View().Utf8()});
4703af6ab5fSopenharmony_ci
4713af6ab5fSopenharmony_ci    lexer::SourcePosition const startLoc = lexer->GetToken().Start();
4723af6ab5fSopenharmony_ci    lexer->NextToken();
4733af6ab5fSopenharmony_ci
4743af6ab5fSopenharmony_ci    ir::Expression *returnExpression = ParseExpression(flags);
4753af6ab5fSopenharmony_ci    returnExpression->SetRange({startLoc, lexer->GetToken().End()});
4763af6ab5fSopenharmony_ci
4773af6ab5fSopenharmony_ci    return returnExpression;
4783af6ab5fSopenharmony_ci}
4793af6ab5fSopenharmony_ci
4803af6ab5fSopenharmony_ciir::Expression *ETSParser::CreateFormattedExpression(std::string_view const sourceCode,
4813af6ab5fSopenharmony_ci                                                     std::vector<ir::AstNode *> &insertingNodes)
4823af6ab5fSopenharmony_ci{
4833af6ab5fSopenharmony_ci    ir::Expression *returnExpression;
4843af6ab5fSopenharmony_ci    insertingNodes_.swap(insertingNodes);
4853af6ab5fSopenharmony_ci
4863af6ab5fSopenharmony_ci    if (auto statements = CreateStatements(sourceCode);
4873af6ab5fSopenharmony_ci        statements.size() == 1U && statements.back()->IsExpressionStatement()) {
4883af6ab5fSopenharmony_ci        returnExpression = statements.back()->AsExpressionStatement()->GetExpression();
4893af6ab5fSopenharmony_ci    } else {
4903af6ab5fSopenharmony_ci        returnExpression = AllocNode<ir::BlockExpression>(std::move(statements));
4913af6ab5fSopenharmony_ci    }
4923af6ab5fSopenharmony_ci
4933af6ab5fSopenharmony_ci    insertingNodes_.swap(insertingNodes);
4943af6ab5fSopenharmony_ci    return returnExpression;
4953af6ab5fSopenharmony_ci}
4963af6ab5fSopenharmony_ci
4973af6ab5fSopenharmony_ciir::Statement *ETSParser::CreateTopLevelStatement(std::string_view const sourceCode)
4983af6ab5fSopenharmony_ci{
4993af6ab5fSopenharmony_ci    util::UString source {sourceCode, Allocator()};
5003af6ab5fSopenharmony_ci    auto const isp = InnerSourceParser(this);
5013af6ab5fSopenharmony_ci    auto const lexer = InitLexer({GetContext().FormattingFileName(), source.View().Utf8()});
5023af6ab5fSopenharmony_ci
5033af6ab5fSopenharmony_ci    lexer->NextToken();
5043af6ab5fSopenharmony_ci
5053af6ab5fSopenharmony_ci    return ParseTopLevelStatement();
5063af6ab5fSopenharmony_ci}
5073af6ab5fSopenharmony_ci
5083af6ab5fSopenharmony_ciir::Statement *ETSParser::CreateFormattedTopLevelStatement(std::string_view const sourceCode,
5093af6ab5fSopenharmony_ci                                                           std::vector<ir::AstNode *> &insertingNodes)
5103af6ab5fSopenharmony_ci{
5113af6ab5fSopenharmony_ci    insertingNodes_.swap(insertingNodes);
5123af6ab5fSopenharmony_ci    auto const statement = CreateTopLevelStatement(sourceCode);
5133af6ab5fSopenharmony_ci    insertingNodes_.swap(insertingNodes);
5143af6ab5fSopenharmony_ci    return statement;
5153af6ab5fSopenharmony_ci}
5163af6ab5fSopenharmony_ci
5173af6ab5fSopenharmony_ciir::TypeNode *ETSParser::CreateTypeAnnotation(TypeAnnotationParsingOptions *options, std::string_view const sourceCode)
5183af6ab5fSopenharmony_ci{
5193af6ab5fSopenharmony_ci    util::UString source {sourceCode, Allocator()};
5203af6ab5fSopenharmony_ci    auto const isp = InnerSourceParser(this);
5213af6ab5fSopenharmony_ci    auto const lexer = InitLexer({GetContext().FormattingFileName(), source.View().Utf8()});
5223af6ab5fSopenharmony_ci
5233af6ab5fSopenharmony_ci    lexer->NextToken();
5243af6ab5fSopenharmony_ci    return ParseTypeAnnotation(options);
5253af6ab5fSopenharmony_ci}
5263af6ab5fSopenharmony_ci}  // namespace ark::es2panda::parser
527