• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2025 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 "generated/diagnostic.h"
20 #include "varbinder/privateBinding.h"
21 #include "ir/brokenTypeNode.h"
22 #include "ir/base/classDefinition.h"
23 #include "ir/base/classProperty.h"
24 #include "ir/base/classStaticBlock.h"
25 #include "ir/base/methodDefinition.h"
26 #include "ir/base/scriptFunction.h"
27 #include "ir/base/spreadElement.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/literals/bigIntLiteral.h"
33 #include "ir/expressions/literals/numberLiteral.h"
34 #include "ir/expressions/literals/stringLiteral.h"
35 #include "ir/expressions/objectExpression.h"
36 #include "ir/expressions/superExpression.h"
37 #include "ir/ets/etsParameterExpression.h"
38 #include "ir/statements/blockStatement.h"
39 #include "ir/statements/expressionStatement.h"
40 #include "util/errorRecovery.h"
41 
42 using namespace std::literals::string_literals;
43 
44 namespace ark::es2panda::parser {
ParserImpl(Program * program,const util::Options * options,util::DiagnosticEngine & diagnosticEngine,ParserStatus status)45 ParserImpl::ParserImpl(Program *program, const util::Options *options, util::DiagnosticEngine &diagnosticEngine,
46                        ParserStatus status)
47     : program_(program),
48       context_(program_, status, options == nullptr ? false : options->IsEnableJsdocParse()),
49       options_(options),
50       diagnosticEngine_(diagnosticEngine)
51 {
52 }
53 
InitLexer(const SourceFile & sourceFile)54 std::unique_ptr<lexer::Lexer> ParserImpl::InitLexer(const SourceFile &sourceFile)
55 {
56     program_->SetSource(sourceFile);
57     std::unique_ptr<lexer::Lexer> lexer = std::make_unique<lexer::Lexer>(&context_, diagnosticEngine_);
58     lexer_ = lexer.get();
59     return lexer;
60 }
61 
ParseScript(const SourceFile & sourceFile,bool genStdLib)62 void ParserImpl::ParseScript(const SourceFile &sourceFile, bool genStdLib)
63 {
64     auto lexer = InitLexer(sourceFile);
65 
66     if (sourceFile.isModule) {
67         context_.Status() |= (ParserStatus::MODULE);
68         ParseProgram(ScriptKind::MODULE);
69     } else if (genStdLib) {
70         ParseProgram(ScriptKind::STDLIB);
71     } else {
72         ParseProgram(ScriptKind::SCRIPT);
73     }
74 }
75 
ParseProgram(ScriptKind kind)76 void ParserImpl::ParseProgram(ScriptKind kind)
77 {
78     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
79     lexer_->NextToken();
80     program_->SetKind(kind);
81 
82     auto statements = ParseStatementList(StatementParsingFlags::STMT_GLOBAL_LEXICAL);
83 
84     auto *blockStmt = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
85     ES2PANDA_ASSERT(blockStmt != nullptr);
86     blockStmt->SetRange({startLoc, lexer_->GetToken().End()});
87 
88     program_->SetAst(blockStmt);
89 }
90 
InAmbientContext()91 bool ParserImpl::InAmbientContext()
92 {
93     return (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT) != 0;
94 }
95 
CarryExpressionParserFlag(ExpressionParseFlags origin,ExpressionParseFlags carry)96 ExpressionParseFlags ParserImpl::CarryExpressionParserFlag(ExpressionParseFlags origin, ExpressionParseFlags carry)
97 {
98     return static_cast<ExpressionParseFlags>(origin & carry);
99 }
100 
CarryPatternFlags(ExpressionParseFlags flags)101 ExpressionParseFlags ParserImpl::CarryPatternFlags(ExpressionParseFlags flags)
102 {
103     return CarryExpressionParserFlag(flags, ExpressionParseFlags::POTENTIALLY_IN_PATTERN |
104                                                 ExpressionParseFlags::OBJECT_PATTERN);
105 }
106 
GetAccessability(ir::ModifierFlags modifiers)107 ir::ModifierFlags ParserImpl::GetAccessability(ir::ModifierFlags modifiers)
108 {
109     if ((modifiers & ir::ModifierFlags::PUBLIC) != 0) {
110         return ir::ModifierFlags::PUBLIC;
111     }
112 
113     if ((modifiers & ir::ModifierFlags::PRIVATE) != 0) {
114         return ir::ModifierFlags::PRIVATE;
115     }
116 
117     if ((modifiers & ir::ModifierFlags::PROTECTED) != 0) {
118         return ir::ModifierFlags::PROTECTED;
119     }
120 
121     if ((modifiers & ir::ModifierFlags::INTERNAL) != 0) {
122         return ir::ModifierFlags::INTERNAL;
123     }
124 
125     return ir::ModifierFlags::NONE;
126 }
127 
IsModifierKind(const lexer::Token & token)128 bool ParserImpl::IsModifierKind(const lexer::Token &token)
129 {
130     switch (token.KeywordType()) {
131         case lexer::TokenType::KEYW_STATIC:
132         case lexer::TokenType::KEYW_ASYNC:
133             return true;
134         default:
135             break;
136     }
137 
138     return false;
139 }
140 
ParseModifiers()141 ir::ModifierFlags ParserImpl::ParseModifiers()
142 {
143     ir::ModifierFlags resultStatus = ir::ModifierFlags::NONE;
144     ir::ModifierFlags prevStatus = ir::ModifierFlags::ALL;
145 
146     while (IsModifierKind(lexer_->GetToken())) {
147         char32_t nextCp = lexer_->Lookahead();
148         if (nextCp == lexer::LEX_CHAR_LEFT_PAREN) {
149             return resultStatus;
150         }
151 
152         lexer::TokenFlags tokenFlags = lexer_->GetToken().Flags();
153         if ((tokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) {
154             LogError(diagnostic::KEYWORD_CONTAINS_ESCAPED_CHARS);
155         }
156 
157         ir::ModifierFlags actualStatus = ir::ModifierFlags::NONE;
158         ir::ModifierFlags nextStatus = ir::ModifierFlags::NONE;
159 
160         switch (lexer_->GetToken().KeywordType()) {
161             case lexer::TokenType::KEYW_STATIC: {
162                 actualStatus = ir::ModifierFlags::STATIC;
163                 nextStatus = ir::ModifierFlags::ASYNC;
164                 break;
165             }
166             case lexer::TokenType::KEYW_ASYNC: {
167                 actualStatus = ir::ModifierFlags::ASYNC;
168                 nextStatus = ir::ModifierFlags::NONE;
169                 break;
170             }
171             default: {
172                 break;
173             }
174         }
175 
176         if (lexer_->Lookahead() == lexer::LEX_CHAR_COLON || lexer_->Lookahead() == lexer::LEX_CHAR_COMMA ||
177             lexer_->Lookahead() == lexer::LEX_CHAR_RIGHT_PAREN || lexer_->Lookahead() == lexer::LEX_CHAR_QUESTION ||
178             lexer_->Lookahead() == lexer::LEX_CHAR_RIGHT_BRACE || lexer_->Lookahead() == lexer::LEX_CHAR_LESS_THAN) {
179             break;
180         }
181 
182         if ((prevStatus & actualStatus) == 0) {
183             LogError(diagnostic::UNEXPECTED_MODIFIER);
184         }
185 
186         if ((resultStatus & actualStatus) != 0) {
187             LogError(diagnostic::DUPLICATED_MODIFIER);
188         }
189 
190         lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
191 
192         resultStatus |= actualStatus;
193         prevStatus = nextStatus;
194     }
195 
196     return resultStatus;
197 }
198 
CheckAccessorPair(const ArenaVector<ir::AstNode * > & properties,const ir::Expression * propName,ir::MethodDefinitionKind methodKind,ir::ModifierFlags access)199 void ParserImpl::CheckAccessorPair(const ArenaVector<ir::AstNode *> &properties, const ir::Expression *propName,
200                                    ir::MethodDefinitionKind methodKind, ir::ModifierFlags access)
201 {
202     for (const auto &it : properties) {
203         if (!it->IsMethodDefinition() || it->AsMethodDefinition()->Kind() != methodKind) {
204             continue;
205         }
206 
207         const ir::Expression *key = it->AsMethodDefinition()->Key();
208 
209         if (key->Type() != propName->Type()) {
210             continue;
211         }
212 
213         bool keyIsSame = false;
214 
215         if (key->IsIdentifier()) {
216             const util::StringView &strName = propName->AsIdentifier()->Name();
217             const util::StringView &compareName = (key->AsIdentifier()->Name());
218 
219             keyIsSame = strName == compareName;
220         } else if (key->IsNumberLiteral()) {
221             keyIsSame =
222                 key->AsNumberLiteral()->Number().GetDouble() == propName->AsNumberLiteral()->Number().GetDouble();
223         } else if (key->IsStringLiteral()) {
224             keyIsSame = *key->AsStringLiteral() == *propName->AsStringLiteral();
225         }
226 
227         if (!keyIsSame) {
228             continue;
229         }
230 
231         ir::ModifierFlags getAccess;
232         ir::ModifierFlags setAccess;
233 
234         if (methodKind == ir::MethodDefinitionKind::GET) {
235             setAccess = access;
236             getAccess = GetAccessability(it->Modifiers());
237         } else {
238             getAccess = access;
239             setAccess = GetAccessability(it->Modifiers());
240         }
241 
242         if ((setAccess == ir::ModifierFlags::NONE && getAccess > ir::ModifierFlags::PUBLIC) ||
243             (setAccess != ir::ModifierFlags::NONE && getAccess > setAccess)) {
244             LogError(diagnostic::GET_ACCESSOR_MUST_BE_AT_LEAST_AS_ACCESSIBLE, {}, key->Start());
245         }
246     }
247 }
248 
ParseClassAccessor(ClassElementDescriptor * desc,char32_t * nextCp)249 void ParserImpl::ParseClassAccessor(ClassElementDescriptor *desc, char32_t *nextCp)
250 {
251     ConsumeClassPrivateIdentifier(desc, nextCp);
252 
253     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
254         return;
255     }
256 
257     auto keywordType = lexer_->GetToken().KeywordType();
258     if ((keywordType != lexer::TokenType::KEYW_GET && keywordType != lexer::TokenType::KEYW_SET) ||
259         (*nextCp == lexer::LEX_CHAR_EQUALS || *nextCp == lexer::LEX_CHAR_SEMICOLON ||
260          *nextCp == lexer::LEX_CHAR_LEFT_PAREN || *nextCp == lexer::LEX_CHAR_COLON ||
261          *nextCp == lexer::LEX_CHAR_LESS_THAN)) {
262         return;
263     }
264 
265     LogIfPrivateIdent(desc, diagnostic::UNEXPECTED_ID);
266 
267     if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0) {
268         LogError(diagnostic::KEYWORD_CONTAINS_ESCAPED_CHARS);
269     }
270 
271     desc->methodKind =
272         keywordType == lexer::TokenType::KEYW_GET ? ir::MethodDefinitionKind::GET : ir::MethodDefinitionKind::SET;
273     desc->methodStart = lexer_->GetToken().Start();
274 
275     lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
276     ConsumeClassPrivateIdentifier(desc, nextCp);
277 }
278 
LogIfPrivateIdent(ClassElementDescriptor * desc,const diagnostic::DiagnosticKind & diagnostic,const util::DiagnosticMessageParams & diagnosticParams)279 void ParserImpl::LogIfPrivateIdent(ClassElementDescriptor *desc, const diagnostic::DiagnosticKind &diagnostic,
280                                    const util::DiagnosticMessageParams &diagnosticParams)
281 {
282     if (desc->isPrivateIdent) {
283         LogError(diagnostic, diagnosticParams);
284     }
285 }
286 
CheckIfStaticConstructor(ir::ModifierFlags flags)287 void ParserImpl::CheckIfStaticConstructor([[maybe_unused]] ir::ModifierFlags flags) {}
288 
ValidateClassKey(ClassElementDescriptor * desc)289 void ParserImpl::ValidateClassKey(ClassElementDescriptor *desc)
290 {
291     if (((desc->modifiers & ir::ModifierFlags::ASYNC) != 0 || desc->isGenerator) &&
292         (desc->methodKind == ir::MethodDefinitionKind::GET || desc->methodKind == ir::MethodDefinitionKind::SET)) {
293         LogError(diagnostic::INVALID_ACCESSOR);
294     }
295 
296     const util::StringView &propNameStr = lexer_->GetToken().Ident();
297 
298     if (propNameStr.Is("constructor")) {
299         if (lexer_->Lookahead() != lexer::LEX_CHAR_LEFT_PAREN) {
300             // test-class-constructor3.ts
301             LogError(diagnostic::CLASS_FIELD_CONSTRUCTOR);
302         }
303 
304         LogIfPrivateIdent(desc, diagnostic::PRIVATE_IDENTIFIER_NOT_CONSTRUCTOR);
305 
306         if ((desc->modifiers & ir::ModifierFlags::STATIC) == 0) {
307             if ((desc->modifiers & ir::ModifierFlags::ASYNC) != 0 ||
308                 desc->methodKind == ir::MethodDefinitionKind::GET ||
309                 desc->methodKind == ir::MethodDefinitionKind::SET || desc->isGenerator) {
310                 LogError(diagnostic::SPECIAL_METHOD_CONSTRUCTOR);
311             }
312 
313             desc->methodKind = ir::MethodDefinitionKind::CONSTRUCTOR;
314             desc->methodStart = lexer_->GetToken().Start();
315             desc->newStatus |= ParserStatus::CONSTRUCTOR_FUNCTION;
316 
317             if (desc->hasSuperClass) {
318                 desc->newStatus |= ParserStatus::ALLOW_SUPER_CALL;
319             }
320         }
321 
322         CheckIfStaticConstructor(desc->modifiers);
323     } else if (propNameStr.Is("prototype") && (desc->modifiers & ir::ModifierFlags::STATIC) != 0) {
324         LogError(diagnostic::STATIC_PROPERTY_PROTOTYPE);
325     }
326 }
327 
ParseComputedClassFieldOrIndexSignature(ir::Expression ** propName)328 std::tuple<bool, bool, bool> ParserImpl::ParseComputedClassFieldOrIndexSignature(ir::Expression **propName)
329 {
330     lexer_->NextToken();  // eat left square bracket
331     *propName = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
332 
333     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
334         // test exists for js extension only
335         LogExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET);
336     }
337 
338     return {true, false, false};
339 }
340 
341 // CC-OFFNXT(huge_method[C++], G.FUN.01-CPP) solid logic
ParseClassKey(ClassElementDescriptor * desc)342 ir::Expression *ParserImpl::ParseClassKey(ClassElementDescriptor *desc)
343 {
344     ir::Expression *propName = nullptr;
345     if (lexer_->GetToken().IsKeyword()) {
346         lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
347         Lexer()->GetToken().SetTokenStr(ERROR_LITERAL);
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             ES2PANDA_ASSERT(propName != nullptr);
356             propName->SetRange(lexer_->GetToken().Loc());
357             propName->AsIdentifier()->SetPrivate(desc->isPrivateIdent);
358             break;
359         }
360         case lexer::TokenType::LITERAL_STRING: {
361             LogIfPrivateIdent(desc, diagnostic::PRIVATE_IDENTIFIER_STRING);
362 
363             if (lexer_->GetToken().Ident().Is("constructor")) {
364                 LogError(diagnostic::CLASS_FIELD_CONSTRUCTOR);
365             }
366 
367             if (lexer_->GetToken().Ident().Is("prototype") && (desc->modifiers & ir::ModifierFlags::STATIC) != 0) {
368                 LogError(diagnostic::STATIC_PROPERTY_PROTOTYPE);
369             }
370 
371             propName = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
372             ES2PANDA_ASSERT(propName != nullptr);
373             propName->SetRange(lexer_->GetToken().Loc());
374             break;
375         }
376         case lexer::TokenType::LITERAL_NUMBER: {
377             LogIfPrivateIdent(desc, diagnostic::PRIVATE_IDENTIFIER_NUMBER);
378 
379             if ((lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) != 0) {
380                 propName = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
381             } else {
382                 propName = AllocNode<ir::NumberLiteral>(lexer_->GetToken().GetNumber());
383             }
384             ES2PANDA_ASSERT(propName != nullptr);
385 
386             propName->SetRange(lexer_->GetToken().Loc());
387             break;
388         }
389         case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
390             LogIfPrivateIdent(desc, diagnostic::UNEXPECTED_CHAR_PRIVATE_IDENTIFIER);
391             std::tie(desc->isComputed, desc->invalidComputedProperty, desc->isIndexSignature) =
392                 ParseComputedClassFieldOrIndexSignature(&propName);
393             break;
394         }
395         default: {
396             LogError(diagnostic::UNEXPECTED_TOKEN);
397             propName = AllocBrokenExpression(Lexer()->GetToken().Loc());
398         }
399     }
400 
401     lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
402 
403     return propName;
404 }
405 
ValidateClassMethodStart(ClassElementDescriptor * desc,ir::TypeNode * typeAnnotation)406 void ParserImpl::ValidateClassMethodStart(ClassElementDescriptor *desc, [[maybe_unused]] ir::TypeNode *typeAnnotation)
407 {
408     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
409         return;
410     }
411     desc->classMethod = true;
412 
413     if ((desc->modifiers & ir::ModifierFlags::ASYNC) != 0) {
414         desc->newStatus |= ParserStatus::ASYNC_FUNCTION;
415     }
416 
417     if (desc->isGenerator) {
418         desc->newStatus |= ParserStatus::GENERATOR_FUNCTION;
419     }
420 }
421 
ValidateGetterSetter(ir::MethodDefinitionKind methodDefinition,size_t number)422 void ParserImpl::ValidateGetterSetter(ir::MethodDefinitionKind methodDefinition, size_t number)
423 {
424     if (methodDefinition == ir::MethodDefinitionKind::SET) {
425         if (number != 1) {
426             LogError(diagnostic::SETTER_FORMAL_PARAMS);
427         }
428     } else if (methodDefinition == ir::MethodDefinitionKind::GET) {
429         if (number != 0) {
430             LogError(diagnostic::GETTER_FORMAL_PARAMS);
431         }
432     }
433 }
434 
ValidateClassSetter(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,ir::ScriptFunction * func)435 void ParserImpl::ValidateClassSetter([[maybe_unused]] ClassElementDescriptor *desc,
436                                      [[maybe_unused]] const ArenaVector<ir::AstNode *> &properties,
437                                      [[maybe_unused]] ir::Expression *propName, ir::ScriptFunction *func)
438 {
439     ValidateGetterSetter(ir::MethodDefinitionKind::SET, func->Params().size());
440     if (func->ReturnTypeAnnotation() != nullptr) {
441         LogError(diagnostic::SETTER_NO_RETURN_TYPE);
442     }
443 }
444 
ValidateClassGetter(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,ir::ScriptFunction * func)445 void ParserImpl::ValidateClassGetter([[maybe_unused]] ClassElementDescriptor *desc,
446                                      [[maybe_unused]] const ArenaVector<ir::AstNode *> &properties,
447                                      [[maybe_unused]] ir::Expression *propName, ir::ScriptFunction *func)
448 {
449     ValidateGetterSetter(ir::MethodDefinitionKind::GET, func->Params().size());
450 }
451 
ParseClassMethod(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,lexer::SourcePosition * propEnd)452 ir::MethodDefinition *ParserImpl::ParseClassMethod(ClassElementDescriptor *desc,
453                                                    const ArenaVector<ir::AstNode *> &properties,
454                                                    ir::Expression *propName, lexer::SourcePosition *propEnd)
455 {
456     if (desc->methodKind != ir::MethodDefinitionKind::SET &&
457         (desc->newStatus & ParserStatus::CONSTRUCTOR_FUNCTION) == 0) {
458         desc->newStatus |= ParserStatus::NEED_RETURN_TYPE;
459     }
460 
461     ir::ScriptFunction *func = ParseFunction(desc->newStatus);
462 
463     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
464     ES2PANDA_ASSERT(funcExpr != nullptr);
465     funcExpr->SetRange(func->Range());
466 
467     if (desc->methodKind == ir::MethodDefinitionKind::SET) {
468         ValidateClassSetter(desc, properties, propName, func);
469     } else if (desc->methodKind == ir::MethodDefinitionKind::GET) {
470         ValidateClassGetter(desc, properties, propName, func);
471     }
472 
473     *propEnd = func->End();
474     func->AddFlag(ir::ScriptFunctionFlags::METHOD);
475 
476     auto *ident = !propName->IsArrowFunctionExpression() && !propName->IsFunctionExpression()
477                       ? propName->Clone(Allocator(), nullptr)->AsExpression()
478                       : propName;
479     auto *method = AllocNode<ir::MethodDefinition>(desc->methodKind, ident, funcExpr, desc->modifiers, Allocator(),
480                                                    desc->isComputed);
481     ES2PANDA_ASSERT(method != nullptr);
482     method->SetRange(funcExpr->Range());
483 
484     return method;
485 }
486 
ParseClassProperty(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,ir::TypeNode * typeAnnotation)487 ir::ClassElement *ParserImpl::ParseClassProperty(ClassElementDescriptor *desc,
488                                                  const ArenaVector<ir::AstNode *> &properties, ir::Expression *propName,
489                                                  ir::TypeNode *typeAnnotation)
490 {
491     ES2PANDA_ASSERT(propName != nullptr);
492     lexer::SourcePosition propEnd = propName->End();
493     ir::ClassElement *property = nullptr;
494 
495     if (desc->classMethod) {
496         if ((desc->modifiers & ir::ModifierFlags::DECLARE) != 0) {
497             LogError(diagnostic::DECLARE_MODIFIER_ON_INVALID_CLASS_ELEMENT);
498         }
499 
500         property = ParseClassMethod(desc, properties, propName, &propEnd);
501         ES2PANDA_ASSERT(property != nullptr);
502         property->SetRange({desc->propStart, propEnd});
503         return property;
504     }
505 
506     ir::Expression *value = nullptr;
507 
508     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
509         lexer_->NextToken();  // eat equals
510 
511         if (InAmbientContext() || (desc->modifiers & ir::ModifierFlags::DECLARE) != 0) {
512             LogError(diagnostic::INITIALIZERS_IN_AMBIENT_CONTEXTS);
513         }
514 
515         value = ParseExpression();
516         propEnd = value->End();
517     }
518 
519     property =
520         AllocNode<ir::ClassProperty>(propName, value, typeAnnotation, desc->modifiers, Allocator(), desc->isComputed);
521     ES2PANDA_ASSERT(property != nullptr);
522     property->SetRange({desc->propStart, propEnd});
523 
524     return property;
525 }
526 
CheckClassGeneratorMethod(ClassElementDescriptor * desc,char32_t * nextCp)527 void ParserImpl::CheckClassGeneratorMethod(ClassElementDescriptor *desc, char32_t *nextCp)
528 {
529     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_MULTIPLY) {
530         return;
531     }
532 
533     desc->isGenerator = true;
534     lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
535     *nextCp = lexer_->Lookahead();
536 }
537 
ValidatePrivateIdentifier()538 bool ParserImpl::ValidatePrivateIdentifier()
539 {
540     size_t iterIdx = lexer_->GetToken().Start().index;
541     lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
542 
543     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT ||
544         (lexer_->GetToken().Start().index - iterIdx > 1)) {
545         LogError(diagnostic::UNEXPECTED_TOKEN_IN_PRIVATE);
546         return false;
547     }
548 
549     return true;
550 }
551 
ConsumeClassPrivateIdentifier(ClassElementDescriptor * desc,char32_t * nextCp)552 void ParserImpl::ConsumeClassPrivateIdentifier(ClassElementDescriptor *desc, char32_t *nextCp)
553 {
554     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_HASH_MARK) {
555         return;
556     }
557 
558     desc->isPrivateIdent = true;
559     ValidatePrivateIdentifier();
560     *nextCp = lexer_->Lookahead();
561 }
562 
AddPrivateElement(const ir::ClassElement * elem)563 void ParserImpl::AddPrivateElement(const ir::ClassElement *elem)
564 {
565     if (!classPrivateContext_.AddElement(elem)) {
566         LogError(diagnostic::PRIVATE_FIELD_REDEC);
567     }
568 }
569 
ParseClassStaticBlock()570 ir::ClassElement *ParserImpl::ParseClassStaticBlock()
571 {
572     const lexer::SourcePosition &startPos = lexer_->GetToken().Start();
573 
574     lexer_->NextToken();  // eat 'static'
575 
576     SavedParserContext context(this, ParserStatus::ALLOW_SUPER | ParserStatus::STATIC_BLOCK);
577     context_.Status() &= ~(ParserStatus::ASYNC_FUNCTION | ParserStatus::GENERATOR_FUNCTION);
578 
579     lexer_->NextToken();  // eat '{'
580 
581     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
582 
583     ArenaVector<ir::Statement *> statements = ParseStatementList();
584 
585     // redundant check -> we have it in parse statements
586     // we even do not consume '}' after
587     ExpectToken(lexer::TokenType::PUNCTUATOR_RIGHT_BRACE, false);
588 
589     auto *body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
590     // clang-format off
591     auto *func = AllocNode<ir::ScriptFunction>(
592         Allocator(), ir::ScriptFunction::ScriptFunctionData {
593             body, ir::FunctionSignature(nullptr, std::move(params), nullptr),
594             ir::ScriptFunctionFlags::EXPRESSION | ir::ScriptFunctionFlags::STATIC_BLOCK,
595             ir::ModifierFlags::STATIC, context_.GetLanguage()});
596     // clang-format on
597 
598     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
599     auto *staticBlock = AllocNode<ir::ClassStaticBlock>(funcExpr, Allocator());
600     ES2PANDA_ASSERT(staticBlock != nullptr);
601     staticBlock->SetRange({startPos, lexer_->GetToken().End()});
602 
603     lexer_->NextToken();  // eat '}'
604 
605     return staticBlock;
606 }
607 
ParseClassElement(const ArenaVector<ir::AstNode * > & properties,ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)608 ir::AstNode *ParserImpl::ParseClassElement(const ArenaVector<ir::AstNode *> &properties,
609                                            ir::ClassDefinitionModifiers modifiers,
610                                            [[maybe_unused]] ir::ModifierFlags flags)
611 {
612     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_STATIC &&
613         lexer_->Lookahead() == lexer::LEX_CHAR_LEFT_BRACE) {
614         return ParseClassStaticBlock();
615     }
616 
617     ClassElementDescriptor desc(Allocator());
618 
619     desc.methodKind = ir::MethodDefinitionKind::METHOD;
620     desc.newStatus = ParserStatus::ALLOW_SUPER;
621     desc.hasSuperClass = (modifiers & ir::ClassDefinitionModifiers::HAS_SUPER) != 0U;
622     desc.propStart = lexer_->GetToken().Start();
623     desc.modifiers = ParseModifiers();
624 
625     char32_t nextCp = lexer_->Lookahead();
626     CheckClassGeneratorMethod(&desc, &nextCp);
627     ParseClassAccessor(&desc, &nextCp);
628 
629     if ((desc.modifiers & ir::ModifierFlags::STATIC) == 0) {
630         context_.Status() |= ParserStatus::ALLOW_THIS_TYPE;
631     }
632 
633     ir::Expression *propName = ParseClassKey(&desc);
634     ValidateClassMethodStart(&desc, nullptr);
635     ir::ClassElement *property = ParseClassProperty(&desc, properties, propName, nullptr);
636 
637     if (property != nullptr && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
638         lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
639         (lexer_->GetToken().Flags() & lexer::TokenFlags::NEW_LINE) == 0 &&
640         !(property->IsMethodDefinition() &&
641           property->AsMethodDefinition()->Value()->AsFunctionExpression()->Function()->Body() != nullptr)) {
642         // test exists for js extension only
643         LogExpectedToken(lexer::TokenType::PUNCTUATOR_SEMI_COLON);
644     }
645 
646     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
647         lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
648     }
649 
650     context_.Status() &= ~ParserStatus::ALLOW_THIS_TYPE;
651 
652     // if Id() is nullptr, ParseClassKey has logged an error
653     if (desc.isPrivateIdent && property != nullptr && property->Id() != nullptr) {
654         AddPrivateElement(property);
655     }
656 
657     return property;
658 }
659 
BuildImplicitConstructor(ir::ClassDefinitionModifiers modifiers,const lexer::SourcePosition & startLoc)660 ir::MethodDefinition *ParserImpl::BuildImplicitConstructor(ir::ClassDefinitionModifiers modifiers,
661                                                            const lexer::SourcePosition &startLoc)
662 {
663     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
664     ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
665 
666     if ((modifiers & ir::ClassDefinitionModifiers::HAS_SUPER) != 0U) {
667         util::StringView argsStr = "args";
668         params.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::REST_ELEMENT, Allocator(),
669                                                       AllocNode<ir::Identifier>(argsStr, Allocator())));
670         ArenaVector<ir::Expression *> callArgs(Allocator()->Adapter());
671         auto *superExpr = AllocNode<ir::SuperExpression>();
672         callArgs.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::SPREAD_ELEMENT, Allocator(),
673                                                         AllocNode<ir::Identifier>(argsStr, Allocator())));
674 
675         auto *callExpr = AllocNode<ir::CallExpression>(superExpr, std::move(callArgs), nullptr, false);
676         statements.push_back(AllocNode<ir::ExpressionStatement>(callExpr));
677     }
678 
679     auto *body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
680     auto *func = AllocNode<ir::ScriptFunction>(
681         Allocator(), ir::ScriptFunction::ScriptFunctionData {body,
682                                                              ir::FunctionSignature(nullptr, std::move(params), nullptr),
683                                                              ir::ScriptFunctionFlags::CONSTRUCTOR |
684                                                                  ir::ScriptFunctionFlags::IMPLICIT_SUPER_CALL_NEEDED,
685                                                              {},
686                                                              context_.GetLanguage()});
687 
688     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
689     auto *key = AllocNode<ir::Identifier>("constructor", Allocator());
690 
691     if ((modifiers & ir::ClassDefinitionModifiers::SET_CTOR_ID) != 0U) {
692         ES2PANDA_ASSERT(key != nullptr);
693         func->SetIdent(key->Clone(Allocator(), nullptr));
694     }
695 
696     auto *ctor = AllocNode<ir::MethodDefinition>(ir::MethodDefinitionKind::CONSTRUCTOR, key, funcExpr,
697                                                  ir::ModifierFlags::NONE, Allocator(), false);
698     ES2PANDA_ASSERT(ctor != nullptr);
699     const auto rangeImplicitContstuctor = lexer::SourceRange(startLoc, startLoc);
700     ctor->IterateRecursively(
701         [&rangeImplicitContstuctor](ir::AstNode *node) -> void { node->SetRange(rangeImplicitContstuctor); });
702 
703     return ctor;
704 }
705 
CreateImplicitConstructor(ir::MethodDefinition * & ctor,ArenaVector<ir::AstNode * > & properties,ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags,const lexer::SourcePosition & startLoc)706 void ParserImpl::CreateImplicitConstructor(ir::MethodDefinition *&ctor,
707                                            [[maybe_unused]] ArenaVector<ir::AstNode *> &properties,
708                                            ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags,
709                                            const lexer::SourcePosition &startLoc)
710 {
711     if (ctor != nullptr) {
712         return;
713     }
714 
715     ctor = BuildImplicitConstructor(modifiers, startLoc);
716     if ((flags & ir::ModifierFlags::DECLARE) != 0) {
717         ES2PANDA_ASSERT(ctor != nullptr);
718         auto *ctorFunc = ctor->Function();
719         ES2PANDA_ASSERT(ctorFunc != nullptr);
720         ctorFunc->AddFlag(ir::ScriptFunctionFlags::EXTERNAL);
721     }
722 }
723 
ParseClassIdent(ir::ClassDefinitionModifiers modifiers)724 ir::Identifier *ParserImpl::ParseClassIdent(ir::ClassDefinitionModifiers modifiers)
725 {
726     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
727         return ExpectIdentifier();
728     }
729 
730     auto idRequired =
731         static_cast<ir::ClassDefinitionModifiers>(modifiers & ir::ClassDefinitionModifiers::DECLARATION_ID_REQUIRED);
732 
733     if (idRequired == ir::ClassDefinitionModifiers::DECLARATION_ID_REQUIRED) {
734         LogError(diagnostic::UNEXPECTED_TOKEN_ID);
735         return AllocBrokenExpression(Lexer()->GetToken().Loc());
736     }
737 
738     return nullptr;
739 }
740 
CheckClassElement(ir::AstNode * property,ir::MethodDefinition * & ctor,ArenaVector<ir::AstNode * > & properties)741 bool ParserImpl::CheckClassElement(ir::AstNode *property, ir::MethodDefinition *&ctor,
742                                    [[maybe_unused]] ArenaVector<ir::AstNode *> &properties)
743 {
744     if (!property->IsMethodDefinition()) {
745         return false;
746     }
747 
748     ir::MethodDefinition *def = property->AsMethodDefinition();
749     if (!def->IsConstructor()) {
750         return false;
751     }
752 
753     if (ctor != nullptr) {
754         LogError(diagnostic::MULTIPLE_CONSTRUCTOR_IMPLEMENTATIONS, {}, property->Start());
755     }
756     ctor = def;
757 
758     return true;
759 }
760 
ParseSuperClassReference()761 ir::Expression *ParserImpl::ParseSuperClassReference()
762 {
763     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
764         lexer_->NextToken();
765         return ParseLeftHandSideExpression();
766     }
767 
768     return nullptr;
769 }
770 
ParseSuperClass()771 std::tuple<ir::Expression *, ir::TSTypeParameterInstantiation *> ParserImpl::ParseSuperClass()
772 {
773     return {ParseSuperClassReference(), nullptr};
774 }
775 
776 // NOLINTNEXTLINE(google-default-arguments)
ParseClassDefinition(ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)777 ir::ClassDefinition *ParserImpl::ParseClassDefinition(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags)
778 {
779     ExpectToken(lexer::TokenType::KEYW_CLASS);
780 
781     ir::Identifier *identNode = ParseClassIdent(modifiers);
782 
783     if (identNode == nullptr && (modifiers & ir::ClassDefinitionModifiers::DECLARATION) != 0U) {
784         LogError(diagnostic::UNEXPECTED_TOKEN_ID);
785         return nullptr;  // ir::ClassDefinition
786     }
787 
788     varbinder::PrivateBinding privateBinding(Allocator(), classId_++);
789 
790     // Parse SuperClass
791     auto [superClass, superTypeParams] = ParseSuperClass();
792 
793     if (superClass != nullptr) {
794         modifiers |= ir::ClassDefinitionModifiers::HAS_SUPER;
795     }
796 
797     // test exists for js extension only
798     ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE, false);
799 
800     auto [ctor, properties, bodyRange] = ParseClassBody(modifiers, flags);
801 
802     ArenaVector<ir::TSClassImplements *> implements(Allocator()->Adapter());
803     auto *classDefinition =
804         AllocNode<ir::ClassDefinition>(identNode, nullptr, superTypeParams, std::move(implements), ctor, superClass,
805                                        std::move(properties), modifiers, flags, GetContext().GetLanguage());
806     ES2PANDA_ASSERT(classDefinition != nullptr);
807     classDefinition->SetInternalName(privateBinding.View());
808 
809     classDefinition->SetRange(bodyRange);
810 
811     return classDefinition;
812 }
813 
ParseClassBody(ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)814 ParserImpl::ClassBody ParserImpl::ParseClassBody(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags)
815 {
816     auto savedCtx = SavedStatusContext<ParserStatus::IN_CLASS_BODY>(&context_);
817 
818     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
819     const auto startOfInnerBody = lexer_->GetToken().End();
820     lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
821 
822     ir::MethodDefinition *ctor = nullptr;
823     ArenaVector<ir::AstNode *> properties(Allocator()->Adapter());
824 
825     SavedClassPrivateContext classContext(this);
826 
827     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
828         lexer_->Lookahead() == static_cast<char32_t>(ARRAY_FORMAT_NODE)) {
829         properties = std::move(ParseAstNodesArrayFormatPlaceholder());
830         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
831             // NOTE(schernykh): add info about LoC
832             LOG(FATAL, ES2PANDA) << "Unexpected " << lexer::TokenToString(lexer_->GetToken().Type())
833                                  << ", expected '}'.";
834         }
835     } else {
836         while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
837                lexer_->GetToken().Type() != lexer::TokenType::EOS) {
838             if (lexer_->TryEatTokenType(lexer::TokenType::PUNCTUATOR_SEMI_COLON)) {
839                 continue;
840             }
841 
842             util::ErrorRecursionGuard infiniteLoopBlocker(Lexer());
843             ir::AstNode *property = ParseClassElement(properties, modifiers, flags);
844             if (property == nullptr) {
845                 continue;
846             }
847 
848             if (property->IsBrokenStatement()) {  // Error processing.
849                 continue;
850             }
851 
852             if (CheckClassElement(property, ctor, properties)) {
853                 continue;
854             }
855 
856             properties.push_back(property);
857         }
858     }
859 
860     CreateImplicitConstructor(ctor, properties, modifiers, flags, startOfInnerBody);
861     ExpectToken(lexer::TokenType::PUNCTUATOR_RIGHT_BRACE);
862 
863     lexer::SourcePosition endLoc = lexer_->GetToken().End();
864     return {ctor, std::move(properties), lexer::SourceRange {startLoc, endLoc}};
865 }
866 
ValidateRestParameter(ir::Expression * param)867 void ParserImpl::ValidateRestParameter(ir::Expression *param)
868 {
869     if (!param->IsIdentifier()) {
870         context_.Status() |= ParserStatus::HAS_COMPLEX_PARAM;
871         if (!param->IsRestElement()) {
872             return;
873         }
874         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
875             // for now test exists for js extension only
876             LogError(diagnostic::REST_PARAM_NOT_LAST);
877 
878             lexer_->GetToken().SetTokenType(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
879         }
880     }
881 }
882 
ValidateBreakLabel(util::StringView label)883 bool ParserImpl::ValidateBreakLabel(util::StringView label)
884 {
885     return context_.FindLabel(label) != nullptr;
886 }
887 
ValidateContinueLabel(util::StringView label)888 bool ParserImpl::ValidateContinueLabel(util::StringView label)
889 {
890     const ParserContext *labelCtx = context_.FindLabel(label);
891     return labelCtx != nullptr && ((labelCtx->Status() & ParserStatus::IN_ITERATION) != 0);
892 }
893 
ParseFunctionParams()894 ArenaVector<ir::Expression *> ParserImpl::ParseFunctionParams()
895 {
896     ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
897 
898     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
899 
900     auto parseFunc = [this, &params]() {
901         ir::Expression *parameter = ParseFunctionParameter();
902         if (parameter == nullptr) {
903             return false;
904         }
905         bool seenOptional = false;
906         for (auto const param : params) {
907             if (param->IsETSParameterExpression() && param->AsETSParameterExpression()->IsOptional()) {
908                 seenOptional = true;
909                 break;
910             }
911         }
912 
913         if (seenOptional && !(parameter->IsETSParameterExpression() &&
914                               (parameter->AsETSParameterExpression()->IsOptional() ||
915                                parameter->AsETSParameterExpression()->RestParameter() != nullptr))) {
916             LogError(diagnostic::REQUIRED_PARAM_AFTER_OPTIONAL, {}, parameter->Start());
917         }
918 
919         if (parameter->IsETSParameterExpression() && parameter->AsETSParameterExpression()->Ident()->IsReceiver() &&
920             !params.empty()) {
921             LogError(diagnostic::FUNC_PARAM_THIS_FIRST);
922             return false;
923         }
924 
925         ValidateRestParameter(parameter);
926         params.push_back(parameter);
927         return true;
928     };
929 
930     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
931         lexer_->Lookahead() == static_cast<char32_t>(ARRAY_FORMAT_NODE)) {
932         params = std::move(ParseExpressionsArrayFormatPlaceholder());
933     } else {
934         ParseList(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS, lexer::NextTokenFlags::NONE, parseFunc, nullptr,
935                   true);
936     }
937 
938     return params;
939 }
940 
CreateParameterThis(ir::TypeNode * typeAnnotation)941 ir::Expression *ParserImpl::CreateParameterThis([[maybe_unused]] ir::TypeNode *typeAnnotation)
942 {
943     LogError(diagnostic::UNEXPECTED_TOKEN_ID_FUN);
944     return AllocBrokenExpression(Lexer()->GetToken().Loc());
945 }
946 
ParseFunctionBody(const ArenaVector<ir::Expression * > & params,ParserStatus newStatus,ParserStatus contextStatus)947 std::tuple<bool, ir::BlockStatement *, lexer::SourcePosition, bool> ParserImpl::ParseFunctionBody(
948     // CC-OFFNXT(G.FMT.06-CPP) project code style
949     [[maybe_unused]] const ArenaVector<ir::Expression *> &params, [[maybe_unused]] ParserStatus newStatus,
950     [[maybe_unused]] ParserStatus contextStatus)
951 {
952     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
953         LogExpectedToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
954     }
955 
956     ir::BlockStatement *body = ParseBlockStatement();
957     ES2PANDA_ASSERT(body != nullptr);
958 
959     return {true, body, body->End(), false};
960 }
961 
ParseFunctionSignature(ParserStatus status)962 FunctionSignature ParserImpl::ParseFunctionSignature(ParserStatus status)
963 {
964     ir::TSTypeParameterDeclaration *typeParamDecl = ParseFunctionTypeParameters();
965 
966     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
967         auto parameter = (status & ParserStatus::ARROW_FUNCTION) != 0 ? ParseFunctionParameter() : nullptr;
968         if (parameter != nullptr) {
969             ArenaVector<ir::Expression *> param(Allocator()->Adapter());
970             param.push_back(parameter);
971             auto res = ir::FunctionSignature(typeParamDecl, std::move(param), nullptr, false);
972             return {std::move(res), ir::ScriptFunctionFlags::NONE};
973         }
974         LogExpectedToken(lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
975     }
976 
977     FunctionParameterContext funcParamContext(&context_);
978 
979     auto params = ParseFunctionParams();
980 
981     ir::TypeNode *returnTypeAnnotation = nullptr;
982     bool hasReceiver = !params.empty() && params[0]->IsETSParameterExpression() &&
983                        params[0]->AsETSParameterExpression()->Ident()->IsReceiver();
984     if (hasReceiver) {
985         SavedParserContext contextAfterParseParams(this, GetContext().Status() | ParserStatus::HAS_RECEIVER);
986         returnTypeAnnotation = ParseFunctionReturnType(status);
987     } else {
988         returnTypeAnnotation = ParseFunctionReturnType(status);
989     }
990 
991     if (GetContext().IsExtensionAccessor() && !hasReceiver) {
992         LogError(diagnostic::EXTENSION_ACCESSOR_RECEIVER);
993     }
994 
995     ir::ScriptFunctionFlags throwMarker = ParseFunctionThrowMarker(true);
996 
997     auto res = ir::FunctionSignature(typeParamDecl, std::move(params), returnTypeAnnotation, hasReceiver);
998     return {std::move(res), throwMarker};
999 }
1000 
ParseFunction(ParserStatus newStatus)1001 ir::ScriptFunction *ParserImpl::ParseFunction(ParserStatus newStatus)
1002 {
1003     FunctionContext functionContext(this, newStatus | ParserStatus::FUNCTION | ParserStatus::ALLOW_NEW_TARGET);
1004 
1005     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1006 
1007     auto [signature, throw_marker] = ParseFunctionSignature(newStatus);
1008 
1009     auto [letDeclare, body, endLoc, isOverload] = ParseFunctionBody(signature.Params(), newStatus, context_.Status());
1010 
1011     if (isOverload) {
1012         functionContext.AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
1013     }
1014 
1015     functionContext.AddFlag(throw_marker);
1016     auto *funcNode = AllocNode<ir::ScriptFunction>(
1017         Allocator(),
1018         ir::ScriptFunction::ScriptFunctionData {body,
1019                                                 std::move(signature),      // CC-OFFNXT(G.FMT.02-CPP) project code style
1020                                                 functionContext.Flags(),   // CC-OFFNXT(G.FMT.02-CPP) project code style
1021                                                 {},                        // CC-OFFNXT(G.FMT.02-CPP) project code style
1022                                                 context_.GetLanguage()});  // CC-OFF(G.FMT.02-CPP) project code style
1023     ES2PANDA_ASSERT(funcNode != nullptr);
1024 
1025     funcNode->SetRange({startLoc, endLoc});
1026 
1027     return funcNode;
1028 }
1029 
ParseSpreadElement(ExpressionParseFlags flags)1030 ir::SpreadElement *ParserImpl::ParseSpreadElement(ExpressionParseFlags flags)
1031 {
1032     ES2PANDA_ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD);
1033     lexer::SourcePosition startLocation = lexer_->GetToken().Start();
1034     bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0;
1035     lexer_->NextToken();
1036 
1037     ir::Expression *argument {};
1038     if (inPattern) {
1039         argument = ParsePatternElement(ExpressionParseFlags::IN_REST);
1040         if ((flags & ExpressionParseFlags::OBJECT_PATTERN) != 0 && !argument->IsIdentifier()) {
1041             LogError(diagnostic::RESTPARAM_ID_IN_DEC_CONTEXT);
1042         }
1043     } else {
1044         argument = ParseExpression(flags);
1045     }
1046 
1047     if (inPattern && argument->IsAssignmentExpression()) {
1048         LogError(diagnostic::RESTPARAM_INIT);
1049     }
1050 
1051     auto nodeType = inPattern ? ir::AstNodeType::REST_ELEMENT : ir::AstNodeType::SPREAD_ELEMENT;
1052     auto *spreadElementNode = AllocNode<ir::SpreadElement>(nodeType, Allocator(), argument);
1053     ES2PANDA_ASSERT(spreadElementNode != nullptr);
1054     spreadElementNode->SetRange({startLocation, argument->End()});
1055     return spreadElementNode;
1056 }
1057 
CheckRestrictedBinding()1058 void ParserImpl::CheckRestrictedBinding()
1059 {
1060     ES2PANDA_ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT);
1061     CheckRestrictedBinding(lexer_->GetToken().KeywordType());
1062 }
1063 
CheckRestrictedBinding(lexer::TokenType keywordType)1064 void ParserImpl::CheckRestrictedBinding(lexer::TokenType keywordType)
1065 {
1066     if (keywordType == lexer::TokenType::KEYW_ARGUMENTS || keywordType == lexer::TokenType::KEYW_EVAL) {
1067         LogError(diagnostic::EVAL_OR_ARGUMENTS_IN_STRICT_MODE, {}, lexer_->GetToken().Start());
1068     }
1069 }
1070 
CheckRestrictedBinding(const util::StringView & ident,const lexer::SourcePosition & pos)1071 void ParserImpl::CheckRestrictedBinding(const util::StringView &ident, const lexer::SourcePosition &pos)
1072 {
1073     if (ident.Is("eval") || ident.Is("arguments")) {
1074         LogError(diagnostic::EVAL_OR_ARGUMENTS_IN_STRICT_MODE, {}, pos);
1075     }
1076 }
1077 
ParseFunctionParameter()1078 ir::Expression *ParserImpl::ParseFunctionParameter()
1079 {
1080     ConvertThisKeywordToIdentIfNecessary();
1081 
1082     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1083         CheckRestrictedBinding();
1084     }
1085 
1086     return ParsePatternElement(ExpressionParseFlags::NO_OPTS, true);
1087 }
1088 
ValidateLvalueAssignmentTarget(ir::Expression * node)1089 void ParserImpl::ValidateLvalueAssignmentTarget(ir::Expression *node)
1090 {
1091     switch (node->Type()) {
1092         case ir::AstNodeType::IDENTIFIER: {
1093             CheckRestrictedBinding(node->AsIdentifier()->Name(), node->Start());
1094             break;
1095         }
1096         case ir::AstNodeType::MEMBER_EXPRESSION: {
1097             break;
1098         }
1099         default: {
1100             LogError(diagnostic::INVALID_LEFT_SIDE_IN_ASSIGNMENT);
1101         }
1102     }
1103 }
1104 
ValidateAssignmentTarget(ExpressionParseFlags flags,ir::Expression * node)1105 void ParserImpl::ValidateAssignmentTarget(ExpressionParseFlags flags, ir::Expression *node)
1106 {
1107     switch (node->Type()) {
1108         case ir::AstNodeType::ARRAY_PATTERN:
1109         case ir::AstNodeType::OBJECT_PATTERN: {
1110             break;
1111         }
1112         case ir::AstNodeType::ARRAY_EXPRESSION:
1113         case ir::AstNodeType::OBJECT_EXPRESSION: {
1114             if ((flags & ExpressionParseFlags::POTENTIALLY_IN_PATTERN) != 0) {
1115                 return;
1116             }
1117 
1118             [[fallthrough]];
1119         }
1120         default: {
1121             return ValidateLvalueAssignmentTarget(node);
1122         }
1123     }
1124 }
1125 
ValidateArrowParameterBindings(const ir::Expression * node)1126 void ParserImpl::ValidateArrowParameterBindings(const ir::Expression *node)
1127 {
1128     switch (node->Type()) {
1129         case ir::AstNodeType::IDENTIFIER: {
1130             CheckRestrictedBinding(node->AsIdentifier()->Name(), node->Start());
1131             break;
1132         }
1133         case ir::AstNodeType::OMITTED_EXPRESSION: {
1134             break;
1135         }
1136         case ir::AstNodeType::REST_ELEMENT: {
1137             ValidateArrowParameterBindings(node->AsRestElement()->Argument());
1138             break;
1139         }
1140         case ir::AstNodeType::PROPERTY: {
1141             break;
1142         }
1143         case ir::AstNodeType::OBJECT_PATTERN: {
1144             const auto &props = node->AsObjectPattern()->Properties();
1145 
1146             for (auto *it : props) {
1147                 ValidateArrowParameterBindings(it);
1148             }
1149             break;
1150         }
1151         case ir::AstNodeType::ARRAY_PATTERN: {
1152             const auto &elements = node->AsArrayPattern()->Elements();
1153 
1154             for (auto *it : elements) {
1155                 ValidateArrowParameterBindings(it);
1156             }
1157             break;
1158         }
1159         case ir::AstNodeType::ASSIGNMENT_PATTERN: {
1160             ValidateArrowParameterBindings(node->AsAssignmentPattern()->Left());
1161             // CC-OFFNXT(G.FMT.06-CPP) project code style
1162             break;
1163         }
1164         default: {
1165             LogError(diagnostic::UNEXPECTED_ARROWPARAM_ELEMENT);
1166         }
1167     }
1168 }
1169 
LogParameterModifierError(ir::ModifierFlags status)1170 void ParserImpl::LogParameterModifierError(ir::ModifierFlags status)
1171 {
1172     LogError(diagnostic::PARAM_MODIFIER_CANNOT_APPEAR_ON_PARAMETER,
1173              {(status & ir::ModifierFlags::STATIC) != 0  ? "static"
1174               : (status & ir::ModifierFlags::ASYNC) != 0 ? "async"
1175                                                          : "declare"},
1176              lexer_->GetToken().Start());
1177 }
1178 
ParseIdentifierFormatPlaceholder(std::optional<NodeFormatType> nodeFormat)1179 ir::Identifier *ParserImpl::ParseIdentifierFormatPlaceholder([[maybe_unused]] std::optional<NodeFormatType> nodeFormat)
1180 {
1181     // NOTE(schernykh): add info about LoC
1182     LOG(FATAL, ES2PANDA) << "Format placeholder with identifier is not supported";
1183     return nullptr;
1184 }
1185 
ParseStatementFormatPlaceholder()1186 ir::Statement *ParserImpl::ParseStatementFormatPlaceholder()
1187 {
1188     // NOTE(schernykh): add info about LoC
1189     LOG(FATAL, ES2PANDA) << "Statement with format placeholder is not supported";
1190     return nullptr;
1191 }
1192 
ParseTypeParametersFormatPlaceholder()1193 ir::AstNode *ParserImpl::ParseTypeParametersFormatPlaceholder()
1194 {
1195     // NOTE(schernykh): add info about LoC
1196     LOG(FATAL, ES2PANDA) << "Format placeholder with type parameter(s) is not supported";
1197     return nullptr;
1198 }
1199 
ParseStatementsArrayFormatPlaceholder()1200 ArenaVector<ir::Statement *> &ParserImpl::ParseStatementsArrayFormatPlaceholder()
1201 {
1202     // NOTE(schernykh): add info about LoC
1203     LOG(FATAL, ES2PANDA) << "Format placeholder from statements array is not supported";
1204     ES2PANDA_UNREACHABLE();
1205 }
1206 
ParseAstNodesArrayFormatPlaceholder()1207 ArenaVector<ir::AstNode *> &ParserImpl::ParseAstNodesArrayFormatPlaceholder()
1208 {
1209     // NOTE(schernykh): add info about LoC
1210     LOG(FATAL, ES2PANDA) << "Format placeholder from AST nodes is not supported";
1211     ES2PANDA_UNREACHABLE();
1212 }
1213 
ParseExpressionsArrayFormatPlaceholder()1214 ArenaVector<ir::Expression *> &ParserImpl::ParseExpressionsArrayFormatPlaceholder()
1215 {
1216     // NOTE(schernykh): add info about LoC
1217     LOG(FATAL, ES2PANDA) << "Format placeholder from expressions array is not supported";
1218     ES2PANDA_UNREACHABLE();
1219 }
1220 
ParseSymbolIteratorIdentifier() const1221 util::StringView ParserImpl::ParseSymbolIteratorIdentifier() const noexcept
1222 {
1223     // Duplicate check - just in case of improper call!
1224     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1225         return util::StringView {};
1226     }
1227 
1228     lexer_->NextToken();
1229     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT || !lexer_->GetToken().Ident().Is("Symbol")) {
1230         return util::StringView {};
1231     }
1232 
1233     lexer_->NextToken();
1234     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_PERIOD) {
1235         return util::StringView {};
1236     }
1237 
1238     lexer_->NextToken();
1239     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT || !lexer_->GetToken().Ident().Is("iterator")) {
1240         return util::StringView {};
1241     }
1242 
1243     lexer_->NextToken();
1244     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1245         return util::StringView {};
1246     }
1247 
1248     //  Just replace '[Symbol.iterator]` identifier with the standard '$_iterator' name.
1249     return util::StringView {compiler::Signatures::ITERATOR_METHOD};
1250 }
1251 
ExpectIdentifier(bool isReference,bool isUserDefinedType,TypeAnnotationParsingOptions options)1252 ir::Identifier *ParserImpl::ExpectIdentifier([[maybe_unused]] bool isReference, bool isUserDefinedType,
1253                                              TypeAnnotationParsingOptions options)
1254 {
1255     auto const &token = lexer_->GetToken();
1256     auto const tokenType = token.Type();
1257     if (tokenType == lexer::TokenType::PUNCTUATOR_FORMAT) {
1258         if (auto *ident = ParseIdentifierFormatPlaceholder(std::nullopt); ident != nullptr) {
1259             return ident;
1260         }
1261     }
1262 
1263     auto const &tokenStart = token.Start();
1264     if (token.IsPredefinedType() && !util::Helpers::IsStdLib(program_) &&
1265         ((options & TypeAnnotationParsingOptions::ADD_TYPE_PARAMETER_BINDING) == 0)) {
1266         LogError(diagnostic::PREDEFINED_TYPE_AS_IDENTIFIER, {token.Ident()}, tokenStart);
1267         lexer_->NextToken();
1268         return AllocBrokenExpression(tokenStart);
1269     }
1270 
1271     if (token.IsDefinableTypeName() && isUserDefinedType) {
1272         LogError(diagnostic::NOT_ALLOWED_USER_DEFINED_TYPE);
1273     }
1274 
1275     util::StringView tokenName {};
1276 
1277     if (tokenType == lexer::TokenType::LITERAL_IDENT) {
1278         tokenName = token.Ident();
1279     } else if (tokenType == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1280         // Special case for processing of special '[Symbol.iterator]` identifier using in stdlib.
1281         tokenName = ParseSymbolIteratorIdentifier();
1282     }
1283 
1284     if (tokenName.Empty()) {
1285         if ((options & TypeAnnotationParsingOptions::REPORT_ERROR) == 0) {
1286             return nullptr;
1287         }
1288         LogError(diagnostic::IDENTIFIER_EXPECTED_HERE, {TokenToString(tokenType)}, tokenStart);
1289         lexer_->NextToken();
1290         return AllocBrokenExpression(tokenStart);
1291     }
1292 
1293     auto *ident = AllocNode<ir::Identifier>(tokenName, Allocator());
1294     ES2PANDA_ASSERT(ident != nullptr);
1295     //  NOTE: here actual token can be changed!
1296     ident->SetRange({tokenStart, lexer_->GetToken().End()});
1297     lexer_->NextToken();
1298     return ident;
1299 }
1300 
ExpectToken(lexer::TokenType tokenType,bool consumeToken)1301 void ParserImpl::ExpectToken(lexer::TokenType tokenType, bool consumeToken)
1302 {
1303     auto const &token = lexer_->GetToken();
1304     auto const actualType = token.Type();
1305     if (actualType == tokenType) {
1306         if (consumeToken) {
1307             lexer_->NextToken();
1308         }
1309         return;
1310     }
1311 
1312     if (tokenType != lexer::TokenType::LITERAL_IDENT) {
1313         LogError(diagnostic::EXPECTED_PARAM_GOT_PARAM, {TokenToString(tokenType), TokenToString(actualType)});
1314     } else {
1315         LogError(diagnostic::UNEXPECTED_TOKEN_ID);
1316     }
1317 
1318     if (!consumeToken) {
1319         return;
1320     }
1321 
1322     if (!lexer::Token::IsPunctuatorToken(actualType)) {
1323         return;
1324     }
1325 
1326     auto savedPos = lexer_->Save();
1327     lexer_->NextToken();
1328     if (lexer_->GetToken().Type() == tokenType) {
1329         lexer_->NextToken();
1330         return;
1331     }
1332 
1333     lexer_->Rewind(savedPos);
1334 }
1335 
LogUnexpectedToken(lexer::TokenType tokenType)1336 void ParserImpl::LogUnexpectedToken(lexer::TokenType tokenType)
1337 {
1338     LogError(diagnostic::UNEXPECTED_TOKEN_PARAM, {TokenToString(tokenType)});
1339 }
1340 
LogUnexpectedToken(lexer::Token const & token)1341 void ParserImpl::LogUnexpectedToken(lexer::Token const &token)
1342 {
1343     if (token.ToString() != ERROR_LITERAL) {
1344         LogError(diagnostic::UNEXPECTED_TOKEN_PARAM, {token.ToString()});
1345     }
1346 }
1347 
LogExpectedToken(lexer::TokenType tokenType)1348 void ParserImpl::LogExpectedToken(lexer::TokenType tokenType)
1349 {
1350     if (tokenType != lexer::TokenType::LITERAL_IDENT && tokenType != lexer::TokenType::LITERAL_STRING) {
1351         LogError(diagnostic::UNEXPECTED_TOKEN_EXPECTED_PARAM, {TokenToString(tokenType)});
1352     } else if (tokenType == lexer::TokenType::LITERAL_IDENT) {
1353         LogError(diagnostic::UNEXPECTED_TOKEN_ID);
1354         lexer_->GetToken().SetTokenStr(ERROR_LITERAL);
1355     } else if (tokenType == lexer::TokenType::LITERAL_STRING) {
1356         LogError(diagnostic::UNEXPECTED_TOKEN_STRING_LITERAL);
1357         lexer_->GetToken().SetTokenStr(ERROR_LITERAL);
1358     }
1359     lexer_->GetToken().SetTokenType(tokenType);
1360 }
1361 
LogSyntaxError(std::string_view errorMessage,const lexer::SourcePosition & pos)1362 void ParserImpl::LogSyntaxError(std::string_view errorMessage, const lexer::SourcePosition &pos)
1363 {
1364     diagnosticEngine_.LogSyntaxError(errorMessage, pos);
1365 }
1366 
LogSyntaxError(std::string_view const errorMessage)1367 void ParserImpl::LogSyntaxError(std::string_view const errorMessage)
1368 {
1369     diagnosticEngine_.LogSyntaxError(errorMessage, lexer_->GetToken().Start());
1370 }
1371 
LogSyntaxError(const util::DiagnosticMessageParams & list)1372 void ParserImpl::LogSyntaxError(const util::DiagnosticMessageParams &list)
1373 {
1374     diagnosticEngine_.LogSyntaxError(list, lexer_->GetToken().Start());
1375 }
1376 
LogSyntaxError(const util::DiagnosticMessageParams & list,const lexer::SourcePosition & pos)1377 void ParserImpl::LogSyntaxError(const util::DiagnosticMessageParams &list, const lexer::SourcePosition &pos)
1378 {
1379     diagnosticEngine_.LogSyntaxError(list, pos);
1380 }
1381 
LogError(const diagnostic::DiagnosticKind & diagnostic,const util::DiagnosticMessageParams & diagnosticParams,const lexer::SourcePosition & pos)1382 void ParserImpl::LogError(const diagnostic::DiagnosticKind &diagnostic,
1383                           const util::DiagnosticMessageParams &diagnosticParams, const lexer::SourcePosition &pos)
1384 {
1385     diagnosticEngine_.LogDiagnostic(diagnostic, diagnosticParams, pos);
1386 }
1387 
LogError(const diagnostic::DiagnosticKind & diagnostic,const util::DiagnosticMessageParams & diagnosticParams)1388 void ParserImpl::LogError(const diagnostic::DiagnosticKind &diagnostic,
1389                           const util::DiagnosticMessageParams &diagnosticParams)
1390 {
1391     LogError(diagnostic, diagnosticParams, lexer_->GetToken().Start());
1392 }
1393 
GetPositionForDiagnostic() const1394 lexer::SourcePosition ParserImpl::GetPositionForDiagnostic() const
1395 {
1396     return Lexer()->GetToken().Start();
1397 }
1398 
CheckModuleAsModifier()1399 bool ParserImpl::CheckModuleAsModifier()
1400 {
1401     if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_AS) {
1402         return false;
1403     }
1404 
1405     if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0U) {
1406         LogError(diagnostic::ESCAPE_SEQUENCES_IN_AS);
1407     }
1408 
1409     return true;
1410 }
1411 
ParseList(std::optional<lexer::TokenType> termToken,lexer::NextTokenFlags flags,const std::function<bool ()> & parseElement,lexer::SourcePosition * sourceEnd,bool allowTrailingSep)1412 bool ParserImpl::ParseList(std::optional<lexer::TokenType> termToken, lexer::NextTokenFlags flags,
1413                            const std::function<bool()> &parseElement, lexer::SourcePosition *sourceEnd,
1414                            bool allowTrailingSep)
1415 {
1416     bool success = true;
1417     auto sep = lexer::TokenType::PUNCTUATOR_COMMA;
1418     while (Lexer()->GetToken().Type() != termToken && Lexer()->GetToken().Type() != lexer::TokenType::EOS) {
1419         // ErrorRecursionGuard is not feasible because we can break without consuming any tokens
1420         auto savedPos = lexer_->Save();
1421         auto elemSuccess = parseElement();
1422         bool hasSep = false;
1423         if (Lexer()->GetToken().Type() == sep) {
1424             Lexer()->NextToken(flags);
1425             hasSep = true;
1426         }
1427         if (!elemSuccess) {
1428             // list element is invalid
1429             success = false;
1430             if (savedPos == lexer_->Save()) {
1431                 lexer_->NextToken();
1432             }
1433             continue;
1434         }
1435         if (termToken == Lexer()->GetToken().Type() || (!termToken.has_value() && !hasSep)) {
1436             if (hasSep && !allowTrailingSep) {
1437                 LogError(diagnostic::TRAILING_COMMA_NOT_ALLOWED);
1438             }
1439             break;
1440         }
1441         if (hasSep) {
1442             continue;
1443         }
1444         if (termToken.has_value()) {
1445             LogError(diagnostic::UNEXPECTED_TOKEN_EXPECTED_PARAM_OR_PARAM,
1446                      {lexer::TokenToString(sep), lexer::TokenToString(termToken.value())});
1447         } else {
1448             LogExpectedToken(sep);
1449         }
1450         // comma or terminator not found
1451         return false;
1452     }
1453     if (termToken) {
1454         if (sourceEnd != nullptr) {
1455             *sourceEnd = Lexer()->GetToken().End();
1456         }
1457         ExpectToken(termToken.value());
1458     }
1459     return success;
1460 }
1461 
AllocBrokenExpression(const lexer::SourcePosition & pos)1462 ir::Identifier *ParserImpl::AllocBrokenExpression(const lexer::SourcePosition &pos)
1463 {
1464     return AllocBrokenExpression({pos, pos});
1465 }
1466 
AllocBrokenExpression(const lexer::SourceRange & range)1467 ir::Identifier *ParserImpl::AllocBrokenExpression(const lexer::SourceRange &range)
1468 {
1469     auto *node = AllocNode<ir::Identifier>(Allocator());
1470     ES2PANDA_ASSERT(node != nullptr);
1471     node->SetRange(range);
1472     return node;
1473 }
1474 
AllocBrokenType(const lexer::SourcePosition & pos)1475 ir::TypeNode *ParserImpl::AllocBrokenType(const lexer::SourcePosition &pos)
1476 {
1477     return AllocBrokenType({pos, pos});
1478 }
1479 
AllocBrokenType(const lexer::SourceRange & range)1480 ir::TypeNode *ParserImpl::AllocBrokenType(const lexer::SourceRange &range)
1481 {
1482     auto node = AllocNode<ir::BrokenTypeNode>(Allocator());
1483     ES2PANDA_ASSERT(node != nullptr);
1484     node->SetRange(range);
1485     return node;
1486 }
1487 
1488 }  // namespace ark::es2panda::parser
1489