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