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