1/** 2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "parserImpl.h" 17#include "parserStatusContext.h" 18 19#include "varbinder/privateBinding.h" 20#include "ir/astNode.h" 21#include "ir/base/classDefinition.h" 22#include "ir/base/classProperty.h" 23#include "ir/base/classStaticBlock.h" 24#include "ir/base/methodDefinition.h" 25#include "ir/base/scriptFunction.h" 26#include "ir/base/spreadElement.h" 27#include "ir/expression.h" 28#include "ir/expressions/arrayExpression.h" 29#include "ir/expressions/assignmentExpression.h" 30#include "ir/expressions/callExpression.h" 31#include "ir/expressions/functionExpression.h" 32#include "ir/expressions/identifier.h" 33#include "ir/expressions/literals/bigIntLiteral.h" 34#include "ir/expressions/literals/numberLiteral.h" 35#include "ir/expressions/literals/stringLiteral.h" 36#include "ir/expressions/objectExpression.h" 37#include "ir/expressions/superExpression.h" 38#include "ir/module/exportNamedDeclaration.h" 39#include "ir/module/exportSpecifier.h" 40#include "ir/statements/blockStatement.h" 41#include "ir/statements/expressionStatement.h" 42#include "ir/statements/functionDeclaration.h" 43#include "lexer/lexer.h" 44#include "lexer/token/letters.h" 45#include "lexer/token/sourceLocation.h" 46 47using namespace std::literals::string_literals; 48 49namespace ark::es2panda::parser { 50ParserImpl::ParserImpl(Program *program, const CompilerOptions &options, ParserStatus status) 51 : program_(program), context_(program_, status), options_(options) 52{ 53} 54 55std::unique_ptr<lexer::Lexer> ParserImpl::InitLexer(const SourceFile &sourceFile) 56{ 57 program_->SetSource(sourceFile); 58 std::unique_ptr<lexer::Lexer> lexer = std::make_unique<lexer::Lexer>(&context_); 59 lexer_ = lexer.get(); 60 return lexer; 61} 62 63void ParserImpl::ParseScript(const SourceFile &sourceFile, bool genStdLib) 64{ 65 auto lexer = InitLexer(sourceFile); 66 67 if (sourceFile.isModule) { 68 context_.Status() |= (ParserStatus::MODULE); 69 ParseProgram(ScriptKind::MODULE); 70 } else if (genStdLib) { 71 ParseProgram(ScriptKind::STDLIB); 72 } else { 73 ParseProgram(ScriptKind::SCRIPT); 74 } 75} 76 77void ParserImpl::ParseProgram(ScriptKind kind) 78{ 79 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 80 lexer_->NextToken(); 81 program_->SetKind(kind); 82 83 auto statements = ParseStatementList(StatementParsingFlags::STMT_GLOBAL_LEXICAL); 84 85 auto *blockStmt = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements)); 86 blockStmt->SetRange({startLoc, lexer_->GetToken().End()}); 87 88 program_->SetAst(blockStmt); 89 program_->SetDeclarationModuleInfo(); 90} 91 92bool ParserImpl::InAmbientContext() 93{ 94 return (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT) != 0; 95} 96 97ExpressionParseFlags ParserImpl::CarryExpressionParserFlag(ExpressionParseFlags origin, ExpressionParseFlags carry) 98{ 99 return static_cast<ExpressionParseFlags>(origin & carry); 100} 101 102ExpressionParseFlags ParserImpl::CarryPatternFlags(ExpressionParseFlags flags) 103{ 104 return CarryExpressionParserFlag(flags, ExpressionParseFlags::POTENTIALLY_IN_PATTERN | 105 ExpressionParseFlags::OBJECT_PATTERN); 106} 107 108ir::ModifierFlags ParserImpl::GetAccessability(ir::ModifierFlags modifiers) 109{ 110 if ((modifiers & ir::ModifierFlags::PUBLIC) != 0) { 111 return ir::ModifierFlags::PUBLIC; 112 } 113 114 if ((modifiers & ir::ModifierFlags::PRIVATE) != 0) { 115 return ir::ModifierFlags::PRIVATE; 116 } 117 118 if ((modifiers & ir::ModifierFlags::PROTECTED) != 0) { 119 return ir::ModifierFlags::PROTECTED; 120 } 121 122 if ((modifiers & ir::ModifierFlags::INTERNAL) != 0) { 123 return ir::ModifierFlags::INTERNAL; 124 } 125 126 return ir::ModifierFlags::NONE; 127} 128 129bool ParserImpl::IsModifierKind(const lexer::Token &token) 130{ 131 switch (token.KeywordType()) { 132 case lexer::TokenType::KEYW_STATIC: 133 case lexer::TokenType::KEYW_ASYNC: 134 return true; 135 default: 136 break; 137 } 138 139 return false; 140} 141 142ir::ModifierFlags ParserImpl::ParseModifiers() 143{ 144 ir::ModifierFlags resultStatus = ir::ModifierFlags::NONE; 145 ir::ModifierFlags prevStatus = ir::ModifierFlags::ALL; 146 147 while (IsModifierKind(lexer_->GetToken())) { 148 char32_t nextCp = lexer_->Lookahead(); 149 if (nextCp == lexer::LEX_CHAR_LEFT_PAREN) { 150 return resultStatus; 151 } 152 153 lexer::TokenFlags tokenFlags = lexer_->GetToken().Flags(); 154 if ((tokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) { 155 ThrowSyntaxError("Keyword must not contain escaped characters"); 156 } 157 158 ir::ModifierFlags actualStatus = ir::ModifierFlags::NONE; 159 ir::ModifierFlags nextStatus = ir::ModifierFlags::NONE; 160 161 switch (lexer_->GetToken().KeywordType()) { 162 case lexer::TokenType::KEYW_STATIC: { 163 actualStatus = ir::ModifierFlags::STATIC; 164 nextStatus = ir::ModifierFlags::ASYNC; 165 break; 166 } 167 case lexer::TokenType::KEYW_ASYNC: { 168 actualStatus = ir::ModifierFlags::ASYNC; 169 nextStatus = ir::ModifierFlags::NONE; 170 break; 171 } 172 default: { 173 break; 174 } 175 } 176 177 if (lexer_->Lookahead() == lexer::LEX_CHAR_COLON || lexer_->Lookahead() == lexer::LEX_CHAR_COMMA || 178 lexer_->Lookahead() == lexer::LEX_CHAR_RIGHT_PAREN || lexer_->Lookahead() == lexer::LEX_CHAR_QUESTION || 179 lexer_->Lookahead() == lexer::LEX_CHAR_RIGHT_BRACE || lexer_->Lookahead() == lexer::LEX_CHAR_LESS_THAN) { 180 break; 181 } 182 183 auto pos = lexer_->Save(); 184 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); 185 186 if ((prevStatus & actualStatus) == 0) { 187 lexer_->Rewind(pos); 188 ThrowSyntaxError("Unexpected modifier"); 189 } 190 191 if ((resultStatus & actualStatus) != 0) { 192 lexer_->Rewind(pos); 193 ThrowSyntaxError("Duplicated modifier is not allowed"); 194 } 195 196 resultStatus |= actualStatus; 197 prevStatus = nextStatus; 198 } 199 200 return resultStatus; 201} 202 203void ParserImpl::CheckAccessorPair(const ArenaVector<ir::AstNode *> &properties, const ir::Expression *propName, 204 ir::MethodDefinitionKind methodKind, ir::ModifierFlags access) 205{ 206 for (const auto &it : properties) { 207 if (!it->IsMethodDefinition() || it->AsMethodDefinition()->Kind() != methodKind) { 208 continue; 209 } 210 211 const ir::Expression *key = it->AsMethodDefinition()->Key(); 212 213 if (key->Type() != propName->Type()) { 214 continue; 215 } 216 217 bool keyIsSame = false; 218 219 if (key->IsIdentifier()) { 220 const util::StringView &strName = propName->AsIdentifier()->Name(); 221 const util::StringView &compareName = (key->AsIdentifier()->Name()); 222 223 keyIsSame = strName == compareName; 224 } else if (key->IsNumberLiteral()) { 225 keyIsSame = 226 key->AsNumberLiteral()->Number().GetDouble() == propName->AsNumberLiteral()->Number().GetDouble(); 227 } else if (key->IsStringLiteral()) { 228 keyIsSame = *key->AsStringLiteral() == *propName->AsStringLiteral(); 229 } 230 231 if (!keyIsSame) { 232 continue; 233 } 234 235 ir::ModifierFlags getAccess; 236 ir::ModifierFlags setAccess; 237 238 if (methodKind == ir::MethodDefinitionKind::GET) { 239 setAccess = access; 240 getAccess = GetAccessability(it->Modifiers()); 241 } else { 242 getAccess = access; 243 setAccess = GetAccessability(it->Modifiers()); 244 } 245 246 if ((setAccess == ir::ModifierFlags::NONE && getAccess > ir::ModifierFlags::PUBLIC) || 247 (setAccess != ir::ModifierFlags::NONE && getAccess > setAccess)) { 248 ThrowSyntaxError("A get accessor must be at least as accessible as the setter", key->Start()); 249 } 250 } 251} 252 253void ParserImpl::ParseClassAccessor(ClassElementDescriptor *desc, char32_t *nextCp) 254{ 255 ConsumeClassPrivateIdentifier(desc, nextCp); 256 257 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { 258 return; 259 } 260 261 auto keywordType = lexer_->GetToken().KeywordType(); 262 if ((keywordType != lexer::TokenType::KEYW_GET && keywordType != lexer::TokenType::KEYW_SET) || 263 (*nextCp == lexer::LEX_CHAR_EQUALS || *nextCp == lexer::LEX_CHAR_SEMICOLON || 264 *nextCp == lexer::LEX_CHAR_LEFT_PAREN || *nextCp == lexer::LEX_CHAR_COLON || 265 *nextCp == lexer::LEX_CHAR_LESS_THAN)) { 266 return; 267 } 268 269 ThrowIfPrivateIdent(desc, "Unexpected identifier"); 270 271 if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0) { 272 ThrowSyntaxError("Keyword must not contain escaped characters"); 273 } 274 275 desc->methodKind = 276 keywordType == lexer::TokenType::KEYW_GET ? ir::MethodDefinitionKind::GET : ir::MethodDefinitionKind::SET; 277 desc->methodStart = lexer_->GetToken().Start(); 278 279 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); 280 ConsumeClassPrivateIdentifier(desc, nextCp); 281} 282 283void ParserImpl::ThrowIfPrivateIdent(ClassElementDescriptor *desc, const char *msg) 284{ 285 if (desc->isPrivateIdent) { 286 ThrowSyntaxError(msg); 287 } 288} 289 290void ParserImpl::ThrowErrorIfStaticConstructor([[maybe_unused]] ir::ModifierFlags flags) {} 291 292void ParserImpl::ValidateClassKey(ClassElementDescriptor *desc) 293{ 294 if (((desc->modifiers & ir::ModifierFlags::ASYNC) != 0 || desc->isGenerator) && 295 (desc->methodKind == ir::MethodDefinitionKind::GET || desc->methodKind == ir::MethodDefinitionKind::SET)) { 296 ThrowSyntaxError("Invalid accessor"); 297 } 298 299 const util::StringView &propNameStr = lexer_->GetToken().Ident(); 300 301 if (propNameStr.Is("constructor")) { 302 if (lexer_->Lookahead() != lexer::LEX_CHAR_LEFT_PAREN) { 303 ThrowSyntaxError("Classes may not have a field named 'constructor'"); 304 } 305 306 ThrowIfPrivateIdent(desc, "Private identifier can not be constructor"); 307 308 if ((desc->modifiers & ir::ModifierFlags::STATIC) == 0) { 309 if ((desc->modifiers & ir::ModifierFlags::ASYNC) != 0 || 310 desc->methodKind == ir::MethodDefinitionKind::GET || 311 desc->methodKind == ir::MethodDefinitionKind::SET || desc->isGenerator) { 312 ThrowSyntaxError("Constructor can not be special method"); 313 } 314 315 desc->methodKind = ir::MethodDefinitionKind::CONSTRUCTOR; 316 desc->methodStart = lexer_->GetToken().Start(); 317 desc->newStatus |= ParserStatus::CONSTRUCTOR_FUNCTION; 318 319 if (desc->hasSuperClass) { 320 desc->newStatus |= ParserStatus::ALLOW_SUPER_CALL; 321 } 322 } 323 324 ThrowErrorIfStaticConstructor(desc->modifiers); 325 } else if (propNameStr.Is("prototype") && (desc->modifiers & ir::ModifierFlags::STATIC) != 0) { 326 ThrowSyntaxError("Classes may not have static property named prototype"); 327 } 328} 329 330std::tuple<bool, bool, bool> ParserImpl::ParseComputedClassFieldOrIndexSignature(ir::Expression **propName) 331{ 332 lexer_->NextToken(); // eat left square bracket 333 334 *propName = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); 335 336 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) { 337 ThrowSyntaxError("Unexpected token, expected ']'"); 338 } 339 340 return {true, false, false}; 341} 342 343ir::Expression *ParserImpl::ParseClassKey(ClassElementDescriptor *desc) 344{ 345 ir::Expression *propName = nullptr; 346 if (lexer_->GetToken().IsKeyword()) { 347 lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT); 348 } 349 350 switch (lexer_->GetToken().Type()) { 351 case lexer::TokenType::LITERAL_IDENT: { 352 ValidateClassKey(desc); 353 354 propName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator()); 355 propName->SetRange(lexer_->GetToken().Loc()); 356 propName->AsIdentifier()->SetPrivate(desc->isPrivateIdent); 357 break; 358 } 359 case lexer::TokenType::LITERAL_STRING: { 360 ThrowIfPrivateIdent(desc, "Private identifier name can not be string"); 361 362 if (lexer_->GetToken().Ident().Is("constructor")) { 363 ThrowSyntaxError("Classes may not have a field named 'constructor'"); 364 } 365 366 if (lexer_->GetToken().Ident().Is("prototype") && (desc->modifiers & ir::ModifierFlags::STATIC) != 0) { 367 ThrowSyntaxError("Classes may not have a static property named 'prototype'"); 368 } 369 370 propName = AllocNode<ir::StringLiteral>(lexer_->GetToken().String()); 371 propName->SetRange(lexer_->GetToken().Loc()); 372 break; 373 } 374 case lexer::TokenType::LITERAL_NUMBER: { 375 ThrowIfPrivateIdent(desc, "Private identifier name can not be number"); 376 377 if ((lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) != 0) { 378 propName = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt()); 379 } else { 380 propName = AllocNode<ir::NumberLiteral>(lexer_->GetToken().GetNumber()); 381 } 382 383 propName->SetRange(lexer_->GetToken().Loc()); 384 break; 385 } 386 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: { 387 ThrowIfPrivateIdent(desc, "Unexpected character in private identifier"); 388 std::tie(desc->isComputed, desc->invalidComputedProperty, desc->isIndexSignature) = 389 ParseComputedClassFieldOrIndexSignature(&propName); 390 break; 391 } 392 default: { 393 ThrowSyntaxError("Unexpected token in class property"); 394 } 395 } 396 397 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); 398 399 return propName; 400} 401 402void ParserImpl::ValidateClassMethodStart(ClassElementDescriptor *desc, [[maybe_unused]] ir::TypeNode *typeAnnotation) 403{ 404 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { 405 return; 406 } 407 desc->classMethod = true; 408 409 if ((desc->modifiers & ir::ModifierFlags::ASYNC) != 0) { 410 desc->newStatus |= ParserStatus::ASYNC_FUNCTION; 411 } 412 413 if (desc->isGenerator) { 414 desc->newStatus |= ParserStatus::GENERATOR_FUNCTION; 415 } 416} 417 418void ParserImpl::ValidateClassSetter([[maybe_unused]] ClassElementDescriptor *desc, 419 [[maybe_unused]] const ArenaVector<ir::AstNode *> &properties, 420 [[maybe_unused]] ir::Expression *propName, ir::ScriptFunction *func) 421{ 422 if (func->Params().size() != 1) { 423 ThrowSyntaxError("Setter must have exactly one formal parameter"); 424 } 425} 426 427void ParserImpl::ValidateClassGetter([[maybe_unused]] ClassElementDescriptor *desc, 428 [[maybe_unused]] const ArenaVector<ir::AstNode *> &properties, 429 [[maybe_unused]] ir::Expression *propName, ir::ScriptFunction *func) 430{ 431 if (!func->Params().empty()) { 432 ThrowSyntaxError("Getter must not have formal parameters"); 433 } 434} 435 436ir::MethodDefinition *ParserImpl::ParseClassMethod(ClassElementDescriptor *desc, 437 const ArenaVector<ir::AstNode *> &properties, 438 ir::Expression *propName, lexer::SourcePosition *propEnd) 439{ 440 if (desc->methodKind != ir::MethodDefinitionKind::SET && 441 (desc->newStatus & ParserStatus::CONSTRUCTOR_FUNCTION) == 0) { 442 desc->newStatus |= ParserStatus::NEED_RETURN_TYPE; 443 } 444 445 ir::ScriptFunction *func = ParseFunction(desc->newStatus); 446 447 auto *funcExpr = AllocNode<ir::FunctionExpression>(func); 448 funcExpr->SetRange(func->Range()); 449 450 if (desc->methodKind == ir::MethodDefinitionKind::SET) { 451 ValidateClassSetter(desc, properties, propName, func); 452 } else if (desc->methodKind == ir::MethodDefinitionKind::GET) { 453 ValidateClassGetter(desc, properties, propName, func); 454 } 455 456 *propEnd = func->End(); 457 func->AddFlag(ir::ScriptFunctionFlags::METHOD); 458 459 auto *ident = !propName->IsArrowFunctionExpression() && !propName->IsFunctionExpression() 460 ? propName->Clone(Allocator(), nullptr)->AsExpression() 461 : propName; 462 auto *method = AllocNode<ir::MethodDefinition>(desc->methodKind, ident, funcExpr, desc->modifiers, Allocator(), 463 desc->isComputed); 464 method->SetRange(funcExpr->Range()); 465 466 return method; 467} 468 469ir::ClassElement *ParserImpl::ParseClassProperty(ClassElementDescriptor *desc, 470 const ArenaVector<ir::AstNode *> &properties, ir::Expression *propName, 471 ir::TypeNode *typeAnnotation) 472{ 473 lexer::SourcePosition propEnd = propName->End(); 474 ir::ClassElement *property = nullptr; 475 476 if (desc->classMethod) { 477 if ((desc->modifiers & ir::ModifierFlags::DECLARE) != 0) { 478 ThrowSyntaxError("'declare modifier cannot appear on class elements of this kind."); 479 } 480 481 property = ParseClassMethod(desc, properties, propName, &propEnd); 482 property->SetRange({desc->propStart, propEnd}); 483 return property; 484 } 485 486 ir::Expression *value = nullptr; 487 488 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { 489 lexer_->NextToken(); // eat equals 490 491 if (InAmbientContext() || (desc->modifiers & ir::ModifierFlags::DECLARE) != 0) { 492 ThrowSyntaxError("Initializers are not allowed in ambient contexts."); 493 } 494 495 value = ParseExpression(); 496 propEnd = value->End(); 497 } 498 499 property = 500 AllocNode<ir::ClassProperty>(propName, value, typeAnnotation, desc->modifiers, Allocator(), desc->isComputed); 501 502 property->SetRange({desc->propStart, propEnd}); 503 504 return property; 505} 506 507void ParserImpl::CheckClassGeneratorMethod(ClassElementDescriptor *desc, char32_t *nextCp) 508{ 509 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_MULTIPLY) { 510 return; 511 } 512 513 desc->isGenerator = true; 514 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); 515 *nextCp = lexer_->Lookahead(); 516} 517 518void ParserImpl::ValidatePrivateIdentifier() 519{ 520 size_t iterIdx = lexer_->GetToken().Start().index; 521 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); 522 523 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT || 524 (lexer_->GetToken().Start().index - iterIdx > 1)) { 525 ThrowSyntaxError("Unexpected token in private field"); 526 } 527} 528 529void ParserImpl::ConsumeClassPrivateIdentifier(ClassElementDescriptor *desc, char32_t *nextCp) 530{ 531 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_HASH_MARK) { 532 return; 533 } 534 535 desc->isPrivateIdent = true; 536 ValidatePrivateIdentifier(); 537 *nextCp = lexer_->Lookahead(); 538} 539 540void ParserImpl::AddPrivateElement(const ir::ClassElement *elem) 541{ 542 if (!classPrivateContext_.AddElement(elem)) { 543 ThrowSyntaxError("Private field has already been declared"); 544 } 545} 546 547ir::ClassElement *ParserImpl::ParseClassStaticBlock() 548{ 549 const lexer::SourcePosition &startPos = lexer_->GetToken().Start(); 550 551 lexer_->NextToken(); // eat 'static' 552 553 SavedParserContext context(this, ParserStatus::ALLOW_SUPER); 554 context_.Status() &= ~(ParserStatus::ASYNC_FUNCTION | ParserStatus::GENERATOR_FUNCTION); 555 556 lexer_->NextToken(); // eat '{' 557 558 ArenaVector<ir::Expression *> params(Allocator()->Adapter()); 559 560 ArenaVector<ir::Statement *> statements = ParseStatementList(); 561 562 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 563 ThrowSyntaxError("Expected a '}'"); 564 } 565 566 auto *body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements)); 567 // clang-format off 568 auto *func = AllocNode<ir::ScriptFunction>( 569 Allocator(), ir::ScriptFunction::ScriptFunctionData { 570 body, ir::FunctionSignature(nullptr, std::move(params), nullptr), 571 ir::ScriptFunctionFlags::EXPRESSION | ir::ScriptFunctionFlags::STATIC_BLOCK, 572 ir::ModifierFlags::STATIC, false, context_.GetLanguage()}); 573 // clang-format on 574 575 auto *funcExpr = AllocNode<ir::FunctionExpression>(func); 576 auto *staticBlock = AllocNode<ir::ClassStaticBlock>(funcExpr, Allocator()); 577 staticBlock->SetRange({startPos, lexer_->GetToken().End()}); 578 579 lexer_->NextToken(); // eat '}' 580 581 return staticBlock; 582} 583 584ir::AstNode *ParserImpl::ParseClassElement(const ArenaVector<ir::AstNode *> &properties, 585 ir::ClassDefinitionModifiers modifiers, 586 [[maybe_unused]] ir::ModifierFlags flags) 587{ 588 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_STATIC && 589 lexer_->Lookahead() == lexer::LEX_CHAR_LEFT_BRACE) { 590 return ParseClassStaticBlock(); 591 } 592 593 ClassElementDescriptor desc(Allocator()); 594 595 desc.methodKind = ir::MethodDefinitionKind::METHOD; 596 desc.newStatus = ParserStatus::ALLOW_SUPER; 597 desc.hasSuperClass = (modifiers & ir::ClassDefinitionModifiers::HAS_SUPER) != 0U; 598 desc.propStart = lexer_->GetToken().Start(); 599 desc.modifiers = ParseModifiers(); 600 601 char32_t nextCp = lexer_->Lookahead(); 602 CheckClassGeneratorMethod(&desc, &nextCp); 603 ParseClassAccessor(&desc, &nextCp); 604 605 if ((desc.modifiers & ir::ModifierFlags::STATIC) == 0) { 606 context_.Status() |= ParserStatus::ALLOW_THIS_TYPE; 607 } 608 609 ir::Expression *propName = ParseClassKey(&desc); 610 ValidateClassMethodStart(&desc, nullptr); 611 ir::ClassElement *property = ParseClassProperty(&desc, properties, propName, nullptr); 612 613 if (property != nullptr && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON && 614 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE && 615 (lexer_->GetToken().Flags() & lexer::TokenFlags::NEW_LINE) == 0 && 616 !(property->IsMethodDefinition() && 617 property->AsMethodDefinition()->Value()->AsFunctionExpression()->Function()->Body() != nullptr)) { 618 ThrowSyntaxError("';' expected."); 619 } 620 621 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 622 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); 623 } 624 625 context_.Status() &= ~ParserStatus::ALLOW_THIS_TYPE; 626 627 if (desc.isPrivateIdent) { 628 AddPrivateElement(property); 629 } 630 631 return property; 632} 633 634ir::MethodDefinition *ParserImpl::BuildImplicitConstructor(ir::ClassDefinitionModifiers modifiers, 635 const lexer::SourcePosition &startLoc) 636{ 637 ArenaVector<ir::Expression *> params(Allocator()->Adapter()); 638 ArenaVector<ir::Statement *> statements(Allocator()->Adapter()); 639 640 if ((modifiers & ir::ClassDefinitionModifiers::HAS_SUPER) != 0U) { 641 util::StringView argsStr = "args"; 642 params.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::REST_ELEMENT, Allocator(), 643 AllocNode<ir::Identifier>(argsStr, Allocator()))); 644 ArenaVector<ir::Expression *> callArgs(Allocator()->Adapter()); 645 auto *superExpr = AllocNode<ir::SuperExpression>(); 646 callArgs.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::SPREAD_ELEMENT, Allocator(), 647 AllocNode<ir::Identifier>(argsStr, Allocator()))); 648 649 auto *callExpr = AllocNode<ir::CallExpression>(superExpr, std::move(callArgs), nullptr, false); 650 statements.push_back(AllocNode<ir::ExpressionStatement>(callExpr)); 651 } 652 653 auto *body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements)); 654 auto *func = AllocNode<ir::ScriptFunction>( 655 Allocator(), ir::ScriptFunction::ScriptFunctionData {body, 656 ir::FunctionSignature(nullptr, std::move(params), nullptr), 657 ir::ScriptFunctionFlags::CONSTRUCTOR | 658 ir::ScriptFunctionFlags::IMPLICIT_SUPER_CALL_NEEDED, 659 {}, 660 false, 661 context_.GetLanguage()}); 662 663 auto *funcExpr = AllocNode<ir::FunctionExpression>(func); 664 auto *key = AllocNode<ir::Identifier>("constructor", Allocator()); 665 666 if ((modifiers & ir::ClassDefinitionModifiers::SET_CTOR_ID) != 0U) { 667 func->SetIdent(key->Clone(Allocator(), nullptr)); 668 } 669 670 auto *ctor = AllocNode<ir::MethodDefinition>(ir::MethodDefinitionKind::CONSTRUCTOR, key, funcExpr, 671 ir::ModifierFlags::NONE, Allocator(), false); 672 673 ctor->SetRange({startLoc, lexer_->GetToken().End()}); 674 675 return ctor; 676} 677 678void ParserImpl::CreateImplicitConstructor(ir::MethodDefinition *&ctor, 679 [[maybe_unused]] ArenaVector<ir::AstNode *> &properties, 680 ir::ClassDefinitionModifiers modifiers, 681 const lexer::SourcePosition &startLoc) 682{ 683 if (ctor != nullptr) { 684 return; 685 } 686 687 ctor = BuildImplicitConstructor(modifiers, startLoc); 688} 689 690ir::Identifier *ParserImpl::ParseClassIdent(ir::ClassDefinitionModifiers modifiers) 691{ 692 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) { 693 return ExpectIdentifier(); 694 } 695 696 auto idRequired = 697 static_cast<ir::ClassDefinitionModifiers>(modifiers & ir::ClassDefinitionModifiers::DECLARATION_ID_REQUIRED); 698 699 if (idRequired == ir::ClassDefinitionModifiers::DECLARATION_ID_REQUIRED) { 700 ThrowSyntaxError("Unexpected token, expected an identifier."); 701 } 702 703 return nullptr; 704} 705 706bool ParserImpl::CheckClassElement(ir::AstNode *property, ir::MethodDefinition *&ctor, 707 [[maybe_unused]] ArenaVector<ir::AstNode *> &properties) 708{ 709 if (!property->IsMethodDefinition()) { 710 return false; 711 } 712 713 ir::MethodDefinition *def = property->AsMethodDefinition(); 714 if (!def->IsConstructor()) { 715 return false; 716 } 717 718 if (ctor != nullptr) { 719 ThrowSyntaxError("Multiple constructor implementations are not allowed.", property->Start()); 720 } 721 ctor = def; 722 723 return true; 724} 725 726ir::Expression *ParserImpl::ParseSuperClassReference() 727{ 728 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) { 729 lexer_->NextToken(); 730 return ParseLeftHandSideExpression(); 731 } 732 733 return nullptr; 734} 735 736std::tuple<ir::Expression *, ir::TSTypeParameterInstantiation *> ParserImpl::ParseSuperClass() 737{ 738 return {ParseSuperClassReference(), nullptr}; 739} 740 741// NOLINTNEXTLINE(google-default-arguments) 742ir::ClassDefinition *ParserImpl::ParseClassDefinition(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags) 743{ 744 lexer_->NextToken(); 745 746 ir::Identifier *identNode = ParseClassIdent(modifiers); 747 748 if (identNode == nullptr && (modifiers & ir::ClassDefinitionModifiers::DECLARATION) != 0U) { 749 ThrowSyntaxError("Unexpected token, expected an identifier."); 750 } 751 752 varbinder::PrivateBinding privateBinding(Allocator(), classId_++); 753 754 // Parse SuperClass 755 auto [superClass, superTypeParams] = ParseSuperClass(); 756 757 if (superClass != nullptr) { 758 modifiers |= ir::ClassDefinitionModifiers::HAS_SUPER; 759 } 760 761 ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE, false); 762 763 auto [ctor, properties, bodyRange] = ParseClassBody(modifiers, flags); 764 765 ArenaVector<ir::TSClassImplements *> implements(Allocator()->Adapter()); 766 auto *classDefinition = AllocNode<ir::ClassDefinition>( 767 privateBinding.View(), identNode, nullptr, superTypeParams, std::move(implements), ctor, superClass, 768 std::move(properties), modifiers, flags, GetContext().GetLanguage()); 769 770 classDefinition->SetRange(bodyRange); 771 772 return classDefinition; 773} 774 775ParserImpl::ClassBody ParserImpl::ParseClassBody(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags) 776{ 777 auto savedCtx = SavedStatusContext<ParserStatus::IN_CLASS_BODY>(&context_); 778 779 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 780 lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); 781 782 ir::MethodDefinition *ctor = nullptr; 783 ArenaVector<ir::AstNode *> properties(Allocator()->Adapter()); 784 785 SavedClassPrivateContext classContext(this); 786 787 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT && 788 lexer_->Lookahead() == static_cast<char32_t>(ARRAY_FORMAT_NODE)) { 789 properties = std::move(ParseAstNodesArrayFormatPlaceholder()); 790 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { 791 ThrowSyntaxError("Expected a '}'"); 792 } 793 } else { 794 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE && 795 lexer_->GetToken().Type() != lexer::TokenType::EOS) { 796 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { 797 lexer_->NextToken(); 798 continue; 799 } 800 801 ir::AstNode *property = ParseClassElement(properties, modifiers, flags); 802 if (property == nullptr) { // Error processing. 803 lexer_->NextToken(); 804 continue; 805 } 806 807 if (CheckClassElement(property, ctor, properties)) { 808 continue; 809 } 810 811 properties.push_back(property); 812 } 813 } 814 815 lexer::SourcePosition endLoc = lexer_->GetToken().End(); 816 CreateImplicitConstructor(ctor, properties, modifiers, endLoc); 817 lexer_->NextToken(); 818 819 return {ctor, std::move(properties), lexer::SourceRange {startLoc, endLoc}}; 820} 821 822void ParserImpl::ValidateRestParameter(ir::Expression *param) 823{ 824 if (!param->IsIdentifier()) { 825 context_.Status() |= ParserStatus::HAS_COMPLEX_PARAM; 826 if (!param->IsRestElement()) { 827 return; 828 } 829 830 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 831 ThrowSyntaxError("Rest parameter must be last formal parameter."); 832 } 833 } 834} 835 836bool ParserImpl::ValidateBreakLabel(util::StringView label) 837{ 838 return context_.FindLabel(label) != nullptr; 839} 840 841bool ParserImpl::ValidateContinueLabel(util::StringView label) 842{ 843 const ParserContext *labelCtx = context_.FindLabel(label); 844 return labelCtx != nullptr && ((labelCtx->Status() & ParserStatus::IN_ITERATION) != 0); 845} 846 847ArenaVector<ir::Expression *> ParserImpl::ParseFunctionParams() 848{ 849 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { 850 lexer_->NextToken(); // eat '(' 851 } 852 853 ArenaVector<ir::Expression *> params(Allocator()->Adapter()); 854 855 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT && 856 lexer_->Lookahead() == static_cast<char32_t>(ARRAY_FORMAT_NODE)) { 857 params = std::move(ParseExpressionsArrayFormatPlaceholder()); 858 } else { 859 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 860 ir::Expression *parameter = ParseFunctionParameter(); 861 if (parameter == nullptr) { // Error processing. 862 continue; 863 } 864 865 ValidateRestParameter(parameter); 866 params.push_back(parameter); 867 868 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) { 869 lexer_->NextToken(); 870 } else if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { 871 ThrowSyntaxError("Invalid token: comma or right parenthesis expected."); 872 } 873 } 874 } 875 876 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS); 877 lexer_->NextToken(); 878 return params; 879} 880 881ir::Expression *ParserImpl::CreateParameterThis([[maybe_unused]] util::StringView className) 882{ 883 ThrowSyntaxError({"Unexpected token: ", className.Utf8()}); 884} 885 886std::tuple<bool, ir::BlockStatement *, lexer::SourcePosition, bool> ParserImpl::ParseFunctionBody( 887 [[maybe_unused]] const ArenaVector<ir::Expression *> ¶ms, [[maybe_unused]] ParserStatus newStatus, 888 [[maybe_unused]] ParserStatus contextStatus) 889{ 890 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { 891 ThrowSyntaxError("Unexpected token, expected '{'"); 892 } 893 894 ir::BlockStatement *body = ParseBlockStatement(); 895 896 return {true, body, body->End(), false}; 897} 898 899FunctionSignature ParserImpl::ParseFunctionSignature(ParserStatus status, ir::Identifier *className) 900{ 901 ir::TSTypeParameterDeclaration *typeParamDecl = ParseFunctionTypeParameters(); 902 903 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { 904 ThrowSyntaxError("Unexpected token, expected '('"); 905 } 906 907 FunctionParameterContext funcParamContext(&context_); 908 909 ir::Expression *parameterThis = nullptr; 910 if (className != nullptr) { 911 const auto savedPos = Lexer()->Save(); 912 lexer_->NextToken(); // eat '(' 913 parameterThis = CreateParameterThis(className->Name()); 914 Lexer()->Rewind(savedPos); 915 } 916 917 auto params = ParseFunctionParams(); 918 919 if (className != nullptr) { 920 params.emplace(params.begin(), parameterThis); 921 } 922 923 ir::TypeNode *returnTypeAnnotation = ParseFunctionReturnType(status); 924 ir::ScriptFunctionFlags throwMarker = ParseFunctionThrowMarker(true); 925 926 auto res = ir::FunctionSignature(typeParamDecl, std::move(params), returnTypeAnnotation); 927 return {std::move(res), throwMarker}; 928} 929 930ir::ScriptFunction *ParserImpl::ParseFunction(ParserStatus newStatus) 931{ 932 FunctionContext functionContext(this, newStatus | ParserStatus::FUNCTION | ParserStatus::ALLOW_NEW_TARGET); 933 934 bool isDeclare = InAmbientContext(); 935 936 lexer::SourcePosition startLoc = lexer_->GetToken().Start(); 937 938 auto [signature, throw_marker] = ParseFunctionSignature(newStatus); 939 940 auto [letDeclare, body, endLoc, isOverload] = ParseFunctionBody(signature.Params(), newStatus, context_.Status()); 941 942 if (isOverload) { 943 functionContext.AddFlag(ir::ScriptFunctionFlags::OVERLOAD); 944 } 945 946 functionContext.AddFlag(throw_marker); 947 auto *funcNode = AllocNode<ir::ScriptFunction>( 948 Allocator(), 949 ir::ScriptFunction::ScriptFunctionData { 950 body, std::move(signature), functionContext.Flags(), {}, isDeclare && letDeclare, context_.GetLanguage()}); 951 funcNode->SetRange({startLoc, endLoc}); 952 953 return funcNode; 954} 955 956ir::SpreadElement *ParserImpl::ParseSpreadElement(ExpressionParseFlags flags) 957{ 958 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD); 959 lexer::SourcePosition startLocation = lexer_->GetToken().Start(); 960 bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0; 961 lexer_->NextToken(); 962 963 ir::Expression *argument {}; 964 if (inPattern) { 965 argument = ParsePatternElement(ExpressionParseFlags::IN_REST); 966 if ((flags & ExpressionParseFlags::OBJECT_PATTERN) != 0 && !argument->IsIdentifier()) { 967 ThrowSyntaxError("RestParameter must be followed by an identifier in declaration contexts"); 968 } 969 } else { 970 argument = ParseExpression(flags); 971 } 972 973 if (inPattern && argument->IsAssignmentExpression()) { 974 ThrowSyntaxError("RestParameter does not support an initializer"); 975 } 976 977 auto nodeType = inPattern ? ir::AstNodeType::REST_ELEMENT : ir::AstNodeType::SPREAD_ELEMENT; 978 auto *spreadElementNode = AllocNode<ir::SpreadElement>(nodeType, Allocator(), argument); 979 spreadElementNode->SetRange({startLocation, argument->End()}); 980 return spreadElementNode; 981} 982 983void ParserImpl::CheckRestrictedBinding() const 984{ 985 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT); 986 CheckRestrictedBinding(lexer_->GetToken().KeywordType()); 987} 988 989void ParserImpl::CheckRestrictedBinding(lexer::TokenType keywordType) const 990{ 991 if (keywordType == lexer::TokenType::KEYW_ARGUMENTS || keywordType == lexer::TokenType::KEYW_EVAL) { 992 ThrowSyntaxError( 993 "'eval' or 'arguments' can't be defined or assigned to " 994 "in strict mode code", 995 lexer_->GetToken().Start()); 996 } 997} 998 999void ParserImpl::CheckRestrictedBinding(const util::StringView &ident, const lexer::SourcePosition &pos) const 1000{ 1001 if (ident.Is("eval") || ident.Is("arguments")) { 1002 ThrowSyntaxError( 1003 "'eval' or 'arguments' can't be defined or assigned to " 1004 "in strict mode code", 1005 pos); 1006 } 1007} 1008 1009ir::Expression *ParserImpl::ParseFunctionParameter() 1010{ 1011 ConvertThisKeywordToIdentIfNecessary(); 1012 1013 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) { 1014 CheckRestrictedBinding(); 1015 } 1016 1017 return ParsePatternElement(ExpressionParseFlags::NO_OPTS, true); 1018} 1019 1020void ParserImpl::ValidateLvalueAssignmentTarget(ir::Expression *node) 1021{ 1022 switch (node->Type()) { 1023 case ir::AstNodeType::IDENTIFIER: { 1024 CheckRestrictedBinding(node->AsIdentifier()->Name(), node->Start()); 1025 break; 1026 } 1027 case ir::AstNodeType::MEMBER_EXPRESSION: { 1028 break; 1029 } 1030 default: { 1031 ThrowSyntaxError("Invalid left-hand side in assignment expression"); 1032 } 1033 } 1034} 1035 1036void ParserImpl::ValidateAssignmentTarget(ExpressionParseFlags flags, ir::Expression *node) 1037{ 1038 switch (node->Type()) { 1039 case ir::AstNodeType::ARRAY_PATTERN: 1040 case ir::AstNodeType::OBJECT_PATTERN: { 1041 break; 1042 } 1043 case ir::AstNodeType::ARRAY_EXPRESSION: 1044 case ir::AstNodeType::OBJECT_EXPRESSION: { 1045 if ((flags & ExpressionParseFlags::POTENTIALLY_IN_PATTERN) != 0) { 1046 return; 1047 } 1048 1049 [[fallthrough]]; 1050 } 1051 default: { 1052 return ValidateLvalueAssignmentTarget(node); 1053 } 1054 } 1055} 1056 1057void ParserImpl::ValidateArrowParameterBindings(const ir::Expression *node) 1058{ 1059 switch (node->Type()) { 1060 case ir::AstNodeType::IDENTIFIER: { 1061 CheckRestrictedBinding(node->AsIdentifier()->Name(), node->Start()); 1062 break; 1063 } 1064 case ir::AstNodeType::OMITTED_EXPRESSION: { 1065 break; 1066 } 1067 case ir::AstNodeType::REST_ELEMENT: { 1068 ValidateArrowParameterBindings(node->AsRestElement()->Argument()); 1069 break; 1070 } 1071 case ir::AstNodeType::PROPERTY: { 1072 break; 1073 } 1074 case ir::AstNodeType::OBJECT_PATTERN: { 1075 const auto &props = node->AsObjectPattern()->Properties(); 1076 1077 for (auto *it : props) { 1078 ValidateArrowParameterBindings(it); 1079 } 1080 break; 1081 } 1082 case ir::AstNodeType::ARRAY_PATTERN: { 1083 const auto &elements = node->AsArrayPattern()->Elements(); 1084 1085 for (auto *it : elements) { 1086 ValidateArrowParameterBindings(it); 1087 } 1088 break; 1089 } 1090 case ir::AstNodeType::ASSIGNMENT_PATTERN: { 1091 ValidateArrowParameterBindings(node->AsAssignmentPattern()->Left()); 1092 break; 1093 } 1094 default: { 1095 ThrowSyntaxError("Unexpected ArrowParameter element"); 1096 } 1097 } 1098} 1099 1100void ParserImpl::ThrowParameterModifierError(ir::ModifierFlags status) const 1101{ 1102 ThrowSyntaxError({"'", 1103 (status & ir::ModifierFlags::STATIC) != 0 ? "static" 1104 : (status & ir::ModifierFlags::ASYNC) != 0 ? "async" 1105 : "declare", 1106 "' modifier cannot appear on a parameter."}, 1107 lexer_->GetToken().Start()); 1108} 1109 1110ir::Identifier *ParserImpl::ParseIdentifierFormatPlaceholder( 1111 [[maybe_unused]] std::optional<NodeFormatType> nodeFormat) const 1112{ 1113 ThrowSyntaxError("Identifier expected."); 1114} 1115 1116ir::Statement *ParserImpl::ParseStatementFormatPlaceholder() const 1117{ 1118 ThrowSyntaxError("Statement expected."); 1119} 1120 1121ir::AstNode *ParserImpl::ParseTypeParametersFormatPlaceholder() const 1122{ 1123 ThrowSyntaxError("Type parameter(s) expected."); 1124} 1125 1126ArenaVector<ir::Statement *> &ParserImpl::ParseStatementsArrayFormatPlaceholder() const 1127{ 1128 ThrowSyntaxError("ArenaVector of ir::Statement *'s expected."); 1129} 1130 1131ArenaVector<ir::AstNode *> &ParserImpl::ParseAstNodesArrayFormatPlaceholder() const 1132{ 1133 ThrowSyntaxError("ArenaVector of ir::AstNode *'s expected."); 1134} 1135 1136ArenaVector<ir::Expression *> &ParserImpl::ParseExpressionsArrayFormatPlaceholder() const 1137{ 1138 ThrowSyntaxError("ArenaVector of ir::Expression *'s expected."); 1139} 1140 1141util::StringView ParserImpl::ParseSymbolIteratorIdentifier() const noexcept 1142{ 1143 // Duplicate check - just in case of improper call! 1144 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) { 1145 return util::StringView {}; 1146 } 1147 1148 lexer_->NextToken(); 1149 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT || !lexer_->GetToken().Ident().Is("Symbol")) { 1150 return util::StringView {}; 1151 } 1152 1153 lexer_->NextToken(); 1154 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_PERIOD) { 1155 return util::StringView {}; 1156 } 1157 1158 lexer_->NextToken(); 1159 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT || !lexer_->GetToken().Ident().Is("iterator")) { 1160 return util::StringView {}; 1161 } 1162 1163 lexer_->NextToken(); 1164 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) { 1165 return util::StringView {}; 1166 } 1167 1168 // Just replace '[Symbol.iterator]` identifier with the standard '$_iterator' name. 1169 return util::StringView {compiler::Signatures::ITERATOR_METHOD}; 1170} 1171 1172ir::Identifier *ParserImpl::ExpectIdentifier(bool isReference, bool isUserDefinedType) 1173{ 1174 auto const &token = lexer_->GetToken(); 1175 auto const tokenType = token.Type(); 1176 if (tokenType == lexer::TokenType::PUNCTUATOR_FORMAT) { 1177 return ParseIdentifierFormatPlaceholder(std::nullopt); 1178 } 1179 1180 if (token.IsDefinableTypeName() && isUserDefinedType) { 1181 ThrowSyntaxError("Cannot be used as user-defined type."); 1182 } 1183 1184 auto const &tokenStart = token.Start(); 1185 util::StringView tokenName {}; 1186 1187 if (tokenType == lexer::TokenType::LITERAL_IDENT) { 1188 tokenName = token.Ident(); 1189 } else if (tokenType == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) { 1190 // Special case for processing of special '[Symbol.iterator]` identifier using in stdlib. 1191 tokenName = ParseSymbolIteratorIdentifier(); 1192 } 1193 1194 if (tokenName.Empty()) { 1195 LogSyntaxError({"Identifier expected, got '", TokenToString(tokenType), "'."}, tokenStart); 1196 return nullptr; // Error processing. 1197 } 1198 1199 auto *ident = AllocNode<ir::Identifier>(tokenName, Allocator()); 1200 ident->SetReference(isReference); 1201 // NOTE: here actual token can be changed! 1202 ident->SetRange({tokenStart, lexer_->GetToken().End()}); 1203 1204 lexer_->NextToken(); 1205 1206 return ident; 1207} 1208 1209void ParserImpl::ExpectToken(lexer::TokenType tokenType, bool consumeToken) 1210{ 1211 if (lexer_->GetToken().Type() == tokenType) { 1212 if (consumeToken) { 1213 lexer_->NextToken(); 1214 } 1215 return; 1216 } 1217 ThrowExpectedToken(tokenType); 1218} 1219 1220void ParserImpl::ThrowUnexpectedToken(lexer::TokenType const tokenType) const 1221{ 1222 ThrowSyntaxError("Unexpected token: '"s + TokenToString(tokenType) + "'."s); 1223} 1224 1225void ParserImpl::ThrowExpectedToken(lexer::TokenType const tokenType) const 1226{ 1227 ThrowSyntaxError("Unexpected token, expected: '"s + TokenToString(tokenType) + "'."s); 1228} 1229 1230void ParserImpl::ThrowSyntaxError(std::string_view const errorMessage) const 1231{ 1232 ThrowSyntaxError(errorMessage, lexer_->GetToken().Start()); 1233} 1234 1235void ParserImpl::ThrowSyntaxError(std::initializer_list<std::string_view> list) const 1236{ 1237 ThrowSyntaxError(list, lexer_->GetToken().Start()); 1238} 1239 1240void ParserImpl::ThrowSyntaxError(std::initializer_list<std::string_view> list, const lexer::SourcePosition &pos) const 1241{ 1242 std::stringstream ss; 1243 1244 for (const auto &it : list) { 1245 ss << it; 1246 } 1247 1248 std::string err = ss.str(); 1249 1250 ThrowSyntaxError(std::string_view {err}, pos); 1251} 1252 1253void ParserImpl::ThrowSyntaxError(std::string_view errorMessage, const lexer::SourcePosition &pos) const 1254{ 1255 lexer::LineIndex index(program_->SourceCode()); 1256 lexer::SourceLocation loc = index.GetLocation(pos); 1257 1258 throw Error {ErrorType::SYNTAX, program_->SourceFilePath().Utf8(), errorMessage, loc.line, loc.col}; 1259} 1260 1261void ParserImpl::LogExpectedToken(lexer::TokenType const tokenType) 1262{ 1263 LogSyntaxError("Unexpected token, expected: '"s + TokenToString(tokenType) + "'."s); 1264 lexer_->GetToken().SetTokenType(tokenType); 1265} 1266 1267void ParserImpl::LogSyntaxError(std::string_view const errorMessage) 1268{ 1269 LogSyntaxError(errorMessage, lexer_->GetToken().Start()); 1270} 1271 1272void ParserImpl::LogSyntaxError(std::initializer_list<std::string_view> list) 1273{ 1274 LogSyntaxError(list, lexer_->GetToken().Start()); 1275} 1276 1277void ParserImpl::LogSyntaxError(std::initializer_list<std::string_view> list, const lexer::SourcePosition &pos) 1278{ 1279 std::stringstream ss; 1280 1281 for (const auto &it : list) { 1282 ss << it; 1283 } 1284 1285 std::string err = ss.str(); 1286 1287 LogSyntaxError(std::string_view {err}, pos); 1288} 1289 1290void ParserImpl::LogSyntaxError(std::string_view errorMessage, const lexer::SourcePosition &pos) 1291{ 1292 lexer::LineIndex index(program_->SourceCode()); 1293 lexer::SourceLocation loc = index.GetLocation(pos); 1294 1295 errorLogger_.WriteLog( 1296 Error {ErrorType::SYNTAX, program_->SourceFilePath().Utf8(), errorMessage, loc.line, loc.col}); 1297} 1298 1299void ParserImpl::ThrowAllocationError(std::string_view message) const 1300{ 1301 throw Error(ErrorType::GENERIC, program_->SourceFilePath().Utf8(), message); 1302} 1303 1304ScriptExtension ParserImpl::Extension() const 1305{ 1306 return program_->Extension(); 1307} 1308 1309bool ParserImpl::CheckModuleAsModifier() 1310{ 1311 if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_AS) { 1312 return false; 1313 } 1314 1315 if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0U) { 1316 ThrowSyntaxError("Escape sequences are not allowed in 'as' keyword"); 1317 } 1318 1319 return true; 1320} 1321 1322} // namespace ark::es2panda::parser 1323