• 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 
47 using namespace std::literals::string_literals;
48 
49 namespace ark::es2panda::parser {
ParserImpl(Program * program,const CompilerOptions & options,ParserStatus status)50 ParserImpl::ParserImpl(Program *program, const CompilerOptions &options, ParserStatus status)
51     : program_(program), context_(program_, status), options_(options)
52 {
53 }
54 
InitLexer(const SourceFile & sourceFile)55 std::unique_ptr<lexer::Lexer> ParserImpl::InitLexer(const SourceFile &sourceFile)
56 {
57     program_->SetSource(sourceFile);
58     std::unique_ptr<lexer::Lexer> lexer = std::make_unique<lexer::Lexer>(&context_);
59     lexer_ = lexer.get();
60     return lexer;
61 }
62 
ParseScript(const SourceFile & sourceFile,bool genStdLib)63 void ParserImpl::ParseScript(const SourceFile &sourceFile, bool genStdLib)
64 {
65     auto lexer = InitLexer(sourceFile);
66 
67     if (sourceFile.isModule) {
68         context_.Status() |= (ParserStatus::MODULE);
69         ParseProgram(ScriptKind::MODULE);
70     } else if (genStdLib) {
71         ParseProgram(ScriptKind::STDLIB);
72     } else {
73         ParseProgram(ScriptKind::SCRIPT);
74     }
75 }
76 
ParseProgram(ScriptKind kind)77 void ParserImpl::ParseProgram(ScriptKind kind)
78 {
79     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
80     lexer_->NextToken();
81     program_->SetKind(kind);
82 
83     auto statements = ParseStatementList(StatementParsingFlags::STMT_GLOBAL_LEXICAL);
84 
85     auto *blockStmt = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
86     blockStmt->SetRange({startLoc, lexer_->GetToken().End()});
87 
88     program_->SetAst(blockStmt);
89 }
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             ThrowSyntaxError("Keyword must not contain escaped characters");
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         auto pos = lexer_->Save();
183         lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
184 
185         if ((prevStatus & actualStatus) == 0) {
186             lexer_->Rewind(pos);
187             ThrowSyntaxError("Unexpected modifier");
188         }
189 
190         if ((resultStatus & actualStatus) != 0) {
191             lexer_->Rewind(pos);
192             ThrowSyntaxError("Duplicated modifier is not allowed");
193         }
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             ThrowSyntaxError("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     ThrowIfPrivateIdent(desc, "Unexpected identifier");
269 
270     if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0) {
271         ThrowSyntaxError("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 
ThrowIfPrivateIdent(ClassElementDescriptor * desc,const char * msg)282 void ParserImpl::ThrowIfPrivateIdent(ClassElementDescriptor *desc, const char *msg)
283 {
284     if (desc->isPrivateIdent) {
285         ThrowSyntaxError(msg);
286     }
287 }
288 
ThrowErrorIfStaticConstructor(ir::ModifierFlags flags)289 void ParserImpl::ThrowErrorIfStaticConstructor([[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         ThrowSyntaxError("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             ThrowSyntaxError("Classes may not have a field named 'constructor'");
303         }
304 
305         ThrowIfPrivateIdent(desc, "Private identifier can not be constructor");
306 
307         if ((desc->modifiers & ir::ModifierFlags::STATIC) == 0) {
308             if ((desc->modifiers & ir::ModifierFlags::ASYNC) != 0 ||
309                 desc->methodKind == ir::MethodDefinitionKind::GET ||
310                 desc->methodKind == ir::MethodDefinitionKind::SET || desc->isGenerator) {
311                 ThrowSyntaxError("Constructor can not be special method");
312             }
313 
314             desc->methodKind = ir::MethodDefinitionKind::CONSTRUCTOR;
315             desc->methodStart = lexer_->GetToken().Start();
316             desc->newStatus |= ParserStatus::CONSTRUCTOR_FUNCTION;
317 
318             if (desc->hasSuperClass) {
319                 desc->newStatus |= ParserStatus::ALLOW_SUPER_CALL;
320             }
321         }
322 
323         ThrowErrorIfStaticConstructor(desc->modifiers);
324     } else if (propNameStr.Is("prototype") && (desc->modifiers & ir::ModifierFlags::STATIC) != 0) {
325         ThrowSyntaxError("Classes may not have static property named prototype");
326     }
327 }
328 
ParseComputedClassFieldOrIndexSignature(ir::Expression ** propName)329 std::tuple<bool, bool, bool> ParserImpl::ParseComputedClassFieldOrIndexSignature(ir::Expression **propName)
330 {
331     lexer_->NextToken();  // eat left square bracket
332 
333     *propName = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
334 
335     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
336         ThrowSyntaxError("Unexpected token, expected ']'");
337     }
338 
339     return {true, false, false};
340 }
341 
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     }
348 
349     switch (lexer_->GetToken().Type()) {
350         case lexer::TokenType::LITERAL_IDENT: {
351             ValidateClassKey(desc);
352 
353             propName = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
354             propName->SetRange(lexer_->GetToken().Loc());
355             propName->AsIdentifier()->SetPrivate(desc->isPrivateIdent);
356             break;
357         }
358         case lexer::TokenType::LITERAL_STRING: {
359             ThrowIfPrivateIdent(desc, "Private identifier name can not be string");
360 
361             if (lexer_->GetToken().Ident().Is("constructor")) {
362                 ThrowSyntaxError("Classes may not have a field named 'constructor'");
363             }
364 
365             if (lexer_->GetToken().Ident().Is("prototype") && (desc->modifiers & ir::ModifierFlags::STATIC) != 0) {
366                 ThrowSyntaxError("Classes may not have a static property named 'prototype'");
367             }
368 
369             propName = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
370             propName->SetRange(lexer_->GetToken().Loc());
371             break;
372         }
373         case lexer::TokenType::LITERAL_NUMBER: {
374             ThrowIfPrivateIdent(desc, "Private identifier name can not be number");
375 
376             if ((lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) != 0) {
377                 propName = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
378             } else {
379                 propName = AllocNode<ir::NumberLiteral>(lexer_->GetToken().GetNumber());
380             }
381 
382             propName->SetRange(lexer_->GetToken().Loc());
383             break;
384         }
385         case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
386             ThrowIfPrivateIdent(desc, "Unexpected character in private identifier");
387             std::tie(desc->isComputed, desc->invalidComputedProperty, desc->isIndexSignature) =
388                 ParseComputedClassFieldOrIndexSignature(&propName);
389             break;
390         }
391         default: {
392             ThrowSyntaxError("Unexpected token in class property");
393         }
394     }
395 
396     lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
397 
398     return propName;
399 }
400 
ValidateClassMethodStart(ClassElementDescriptor * desc,ir::TypeNode * typeAnnotation)401 void ParserImpl::ValidateClassMethodStart(ClassElementDescriptor *desc, [[maybe_unused]] ir::TypeNode *typeAnnotation)
402 {
403     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
404         return;
405     }
406     desc->classMethod = true;
407 
408     if ((desc->modifiers & ir::ModifierFlags::ASYNC) != 0) {
409         desc->newStatus |= ParserStatus::ASYNC_FUNCTION;
410     }
411 
412     if (desc->isGenerator) {
413         desc->newStatus |= ParserStatus::GENERATOR_FUNCTION;
414     }
415 }
416 
ValidateClassSetter(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,ir::ScriptFunction * func)417 void ParserImpl::ValidateClassSetter([[maybe_unused]] ClassElementDescriptor *desc,
418                                      [[maybe_unused]] const ArenaVector<ir::AstNode *> &properties,
419                                      [[maybe_unused]] ir::Expression *propName, ir::ScriptFunction *func)
420 {
421     if (func->Params().size() != 1) {
422         ThrowSyntaxError("Setter must have exactly one formal parameter");
423     }
424 }
425 
ValidateClassGetter(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,ir::ScriptFunction * func)426 void ParserImpl::ValidateClassGetter([[maybe_unused]] ClassElementDescriptor *desc,
427                                      [[maybe_unused]] const ArenaVector<ir::AstNode *> &properties,
428                                      [[maybe_unused]] ir::Expression *propName, ir::ScriptFunction *func)
429 {
430     if (!func->Params().empty()) {
431         ThrowSyntaxError("Getter must not have formal parameters");
432     }
433 }
434 
ParseClassMethod(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,lexer::SourcePosition * propEnd)435 ir::MethodDefinition *ParserImpl::ParseClassMethod(ClassElementDescriptor *desc,
436                                                    const ArenaVector<ir::AstNode *> &properties,
437                                                    ir::Expression *propName, lexer::SourcePosition *propEnd)
438 {
439     if (desc->methodKind != ir::MethodDefinitionKind::SET &&
440         (desc->newStatus & ParserStatus::CONSTRUCTOR_FUNCTION) == 0) {
441         desc->newStatus |= ParserStatus::NEED_RETURN_TYPE;
442     }
443 
444     ir::ScriptFunction *func = ParseFunction(desc->newStatus);
445 
446     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
447     funcExpr->SetRange(func->Range());
448 
449     if (desc->methodKind == ir::MethodDefinitionKind::SET) {
450         ValidateClassSetter(desc, properties, propName, func);
451     } else if (desc->methodKind == ir::MethodDefinitionKind::GET) {
452         ValidateClassGetter(desc, properties, propName, func);
453     }
454 
455     *propEnd = func->End();
456     func->AddFlag(ir::ScriptFunctionFlags::METHOD);
457 
458     auto *ident = !propName->IsArrowFunctionExpression() && !propName->IsFunctionExpression()
459                       ? propName->Clone(Allocator(), nullptr)->AsExpression()
460                       : propName;
461     auto *method = AllocNode<ir::MethodDefinition>(desc->methodKind, ident, funcExpr, desc->modifiers, Allocator(),
462                                                    desc->isComputed);
463     method->SetRange(funcExpr->Range());
464 
465     return method;
466 }
467 
ParseClassProperty(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,ir::TypeNode * typeAnnotation)468 ir::ClassElement *ParserImpl::ParseClassProperty(ClassElementDescriptor *desc,
469                                                  const ArenaVector<ir::AstNode *> &properties, ir::Expression *propName,
470                                                  ir::TypeNode *typeAnnotation)
471 {
472     lexer::SourcePosition propEnd = propName->End();
473     ir::ClassElement *property = nullptr;
474 
475     if (desc->classMethod) {
476         if ((desc->modifiers & ir::ModifierFlags::DECLARE) != 0) {
477             ThrowSyntaxError("'declare modifier cannot appear on class elements of this kind.");
478         }
479 
480         property = ParseClassMethod(desc, properties, propName, &propEnd);
481         property->SetRange({desc->propStart, propEnd});
482         return property;
483     }
484 
485     ir::Expression *value = nullptr;
486 
487     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
488         lexer_->NextToken();  // eat equals
489 
490         if (InAmbientContext() || (desc->modifiers & ir::ModifierFlags::DECLARE) != 0) {
491             ThrowSyntaxError("Initializers are not allowed in ambient contexts.");
492         }
493 
494         value = ParseExpression();
495         propEnd = value->End();
496     }
497 
498     property =
499         AllocNode<ir::ClassProperty>(propName, value, typeAnnotation, desc->modifiers, Allocator(), desc->isComputed);
500 
501     property->SetRange({desc->propStart, propEnd});
502 
503     return property;
504 }
505 
CheckClassGeneratorMethod(ClassElementDescriptor * desc,char32_t * nextCp)506 void ParserImpl::CheckClassGeneratorMethod(ClassElementDescriptor *desc, char32_t *nextCp)
507 {
508     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_MULTIPLY) {
509         return;
510     }
511 
512     desc->isGenerator = true;
513     lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
514     *nextCp = lexer_->Lookahead();
515 }
516 
ValidatePrivateIdentifier()517 void ParserImpl::ValidatePrivateIdentifier()
518 {
519     size_t iterIdx = lexer_->GetToken().Start().index;
520     lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
521 
522     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT ||
523         (lexer_->GetToken().Start().index - iterIdx > 1)) {
524         ThrowSyntaxError("Unexpected token in private field");
525     }
526 }
527 
ConsumeClassPrivateIdentifier(ClassElementDescriptor * desc,char32_t * nextCp)528 void ParserImpl::ConsumeClassPrivateIdentifier(ClassElementDescriptor *desc, char32_t *nextCp)
529 {
530     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_HASH_MARK) {
531         return;
532     }
533 
534     desc->isPrivateIdent = true;
535     ValidatePrivateIdentifier();
536     *nextCp = lexer_->Lookahead();
537 }
538 
AddPrivateElement(const ir::ClassElement * elem)539 void ParserImpl::AddPrivateElement(const ir::ClassElement *elem)
540 {
541     if (!classPrivateContext_.AddElement(elem)) {
542         ThrowSyntaxError("Private field has already been declared");
543     }
544 }
545 
ParseClassStaticBlock()546 ir::ClassElement *ParserImpl::ParseClassStaticBlock()
547 {
548     const lexer::SourcePosition &startPos = lexer_->GetToken().Start();
549 
550     lexer_->NextToken();  // eat 'static'
551 
552     SavedParserContext context(this, ParserStatus::ALLOW_SUPER);
553     context_.Status() &= ~(ParserStatus::ASYNC_FUNCTION | ParserStatus::GENERATOR_FUNCTION);
554 
555     lexer_->NextToken();  // eat '{'
556 
557     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
558 
559     ArenaVector<ir::Statement *> statements = ParseStatementList();
560 
561     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
562         ThrowSyntaxError("Expected a '}'");
563     }
564 
565     auto *body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
566     // clang-format off
567     auto *func = AllocNode<ir::ScriptFunction>(
568         Allocator(), ir::ScriptFunction::ScriptFunctionData {
569             body, ir::FunctionSignature(nullptr, std::move(params), nullptr),
570             ir::ScriptFunctionFlags::EXPRESSION | ir::ScriptFunctionFlags::STATIC_BLOCK,
571             ir::ModifierFlags::STATIC, false, context_.GetLanguage()});
572     // clang-format on
573 
574     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
575     auto *staticBlock = AllocNode<ir::ClassStaticBlock>(funcExpr, Allocator());
576     staticBlock->SetRange({startPos, lexer_->GetToken().End()});
577 
578     lexer_->NextToken();  // eat '}'
579 
580     return staticBlock;
581 }
582 
ParseClassElement(const ArenaVector<ir::AstNode * > & properties,ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)583 ir::AstNode *ParserImpl::ParseClassElement(const ArenaVector<ir::AstNode *> &properties,
584                                            ir::ClassDefinitionModifiers modifiers,
585                                            [[maybe_unused]] ir::ModifierFlags flags)
586 {
587     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_STATIC &&
588         lexer_->Lookahead() == lexer::LEX_CHAR_LEFT_BRACE) {
589         return ParseClassStaticBlock();
590     }
591 
592     ClassElementDescriptor desc(Allocator());
593 
594     desc.methodKind = ir::MethodDefinitionKind::METHOD;
595     desc.newStatus = ParserStatus::ALLOW_SUPER;
596     desc.hasSuperClass = (modifiers & ir::ClassDefinitionModifiers::HAS_SUPER) != 0U;
597     desc.propStart = lexer_->GetToken().Start();
598     desc.modifiers = ParseModifiers();
599 
600     char32_t nextCp = lexer_->Lookahead();
601     CheckClassGeneratorMethod(&desc, &nextCp);
602     ParseClassAccessor(&desc, &nextCp);
603 
604     if ((desc.modifiers & ir::ModifierFlags::STATIC) == 0) {
605         context_.Status() |= ParserStatus::ALLOW_THIS_TYPE;
606     }
607 
608     ir::Expression *propName = ParseClassKey(&desc);
609     ValidateClassMethodStart(&desc, nullptr);
610     ir::ClassElement *property = ParseClassProperty(&desc, properties, propName, nullptr);
611 
612     if (property != nullptr && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
613         lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
614         (lexer_->GetToken().Flags() & lexer::TokenFlags::NEW_LINE) == 0 &&
615         !(property->IsMethodDefinition() &&
616           property->AsMethodDefinition()->Value()->AsFunctionExpression()->Function()->Body() != nullptr)) {
617         ThrowSyntaxError("';' expected.");
618     }
619 
620     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
621         lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
622     }
623 
624     context_.Status() &= ~ParserStatus::ALLOW_THIS_TYPE;
625 
626     if (desc.isPrivateIdent) {
627         AddPrivateElement(property);
628     }
629 
630     return property;
631 }
632 
BuildImplicitConstructor(ir::ClassDefinitionModifiers modifiers,const lexer::SourcePosition & startLoc)633 ir::MethodDefinition *ParserImpl::BuildImplicitConstructor(ir::ClassDefinitionModifiers modifiers,
634                                                            const lexer::SourcePosition &startLoc)
635 {
636     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
637     ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
638 
639     if ((modifiers & ir::ClassDefinitionModifiers::HAS_SUPER) != 0U) {
640         util::StringView argsStr = "args";
641         params.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::REST_ELEMENT, Allocator(),
642                                                       AllocNode<ir::Identifier>(argsStr, Allocator())));
643         ArenaVector<ir::Expression *> callArgs(Allocator()->Adapter());
644         auto *superExpr = AllocNode<ir::SuperExpression>();
645         callArgs.push_back(AllocNode<ir::SpreadElement>(ir::AstNodeType::SPREAD_ELEMENT, Allocator(),
646                                                         AllocNode<ir::Identifier>(argsStr, Allocator())));
647 
648         auto *callExpr = AllocNode<ir::CallExpression>(superExpr, std::move(callArgs), nullptr, false);
649         statements.push_back(AllocNode<ir::ExpressionStatement>(callExpr));
650     }
651 
652     auto *body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
653     auto *func = AllocNode<ir::ScriptFunction>(
654         Allocator(), ir::ScriptFunction::ScriptFunctionData {body,
655                                                              ir::FunctionSignature(nullptr, std::move(params), nullptr),
656                                                              ir::ScriptFunctionFlags::CONSTRUCTOR |
657                                                                  ir::ScriptFunctionFlags::IMPLICIT_SUPER_CALL_NEEDED,
658                                                              {},
659                                                              false,
660                                                              context_.GetLanguage()});
661 
662     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
663     auto *key = AllocNode<ir::Identifier>("constructor", Allocator());
664 
665     if ((modifiers & ir::ClassDefinitionModifiers::SET_CTOR_ID) != 0U) {
666         func->SetIdent(key->Clone(Allocator(), nullptr));
667     }
668 
669     auto *ctor = AllocNode<ir::MethodDefinition>(ir::MethodDefinitionKind::CONSTRUCTOR, key, funcExpr,
670                                                  ir::ModifierFlags::NONE, Allocator(), false);
671 
672     ctor->SetRange({startLoc, lexer_->GetToken().End()});
673 
674     return ctor;
675 }
676 
CreateImplicitConstructor(ir::MethodDefinition * & ctor,ArenaVector<ir::AstNode * > & properties,ir::ClassDefinitionModifiers modifiers,const lexer::SourcePosition & startLoc)677 void ParserImpl::CreateImplicitConstructor(ir::MethodDefinition *&ctor,
678                                            [[maybe_unused]] ArenaVector<ir::AstNode *> &properties,
679                                            ir::ClassDefinitionModifiers modifiers,
680                                            const lexer::SourcePosition &startLoc)
681 {
682     if (ctor != nullptr) {
683         return;
684     }
685 
686     ctor = BuildImplicitConstructor(modifiers, startLoc);
687 }
688 
ParseClassIdent(ir::ClassDefinitionModifiers modifiers)689 ir::Identifier *ParserImpl::ParseClassIdent(ir::ClassDefinitionModifiers modifiers)
690 {
691     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
692         return ExpectIdentifier();
693     }
694 
695     auto idRequired =
696         static_cast<ir::ClassDefinitionModifiers>(modifiers & ir::ClassDefinitionModifiers::DECLARATION_ID_REQUIRED);
697 
698     if (idRequired == ir::ClassDefinitionModifiers::DECLARATION_ID_REQUIRED) {
699         ThrowSyntaxError("Unexpected token, expected an identifier.");
700     }
701 
702     return nullptr;
703 }
704 
CheckClassElement(ir::AstNode * property,ir::MethodDefinition * & ctor,ArenaVector<ir::AstNode * > & properties)705 bool ParserImpl::CheckClassElement(ir::AstNode *property, ir::MethodDefinition *&ctor,
706                                    [[maybe_unused]] ArenaVector<ir::AstNode *> &properties)
707 {
708     if (!property->IsMethodDefinition()) {
709         return false;
710     }
711 
712     ir::MethodDefinition *def = property->AsMethodDefinition();
713     if (!def->IsConstructor()) {
714         return false;
715     }
716 
717     if (ctor != nullptr) {
718         ThrowSyntaxError("Multiple constructor implementations are not allowed.", property->Start());
719     }
720     ctor = def;
721 
722     return true;
723 }
724 
ParseSuperClassReference()725 ir::Expression *ParserImpl::ParseSuperClassReference()
726 {
727     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
728         lexer_->NextToken();
729         return ParseLeftHandSideExpression();
730     }
731 
732     return nullptr;
733 }
734 
ParseSuperClass()735 std::tuple<ir::Expression *, ir::TSTypeParameterInstantiation *> ParserImpl::ParseSuperClass()
736 {
737     return {ParseSuperClassReference(), nullptr};
738 }
739 
740 // NOLINTNEXTLINE(google-default-arguments)
ParseClassDefinition(ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)741 ir::ClassDefinition *ParserImpl::ParseClassDefinition(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags)
742 {
743     lexer_->NextToken();
744 
745     ir::Identifier *identNode = ParseClassIdent(modifiers);
746 
747     if (identNode == nullptr && (modifiers & ir::ClassDefinitionModifiers::DECLARATION) != 0U) {
748         ThrowSyntaxError("Unexpected token, expected an identifier.");
749     }
750 
751     varbinder::PrivateBinding privateBinding(Allocator(), classId_++);
752 
753     // Parse SuperClass
754     auto [superClass, superTypeParams] = ParseSuperClass();
755 
756     if (superClass != nullptr) {
757         modifiers |= ir::ClassDefinitionModifiers::HAS_SUPER;
758     }
759 
760     ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE, false);
761 
762     auto [ctor, properties, bodyRange] = ParseClassBody(modifiers, flags);
763 
764     ArenaVector<ir::TSClassImplements *> implements(Allocator()->Adapter());
765     auto *classDefinition = AllocNode<ir::ClassDefinition>(
766         privateBinding.View(), identNode, nullptr, superTypeParams, std::move(implements), ctor, superClass,
767         std::move(properties), modifiers, flags, GetContext().GetLanguage());
768 
769     classDefinition->SetRange(bodyRange);
770 
771     return classDefinition;
772 }
773 
ParseClassBody(ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)774 ParserImpl::ClassBody ParserImpl::ParseClassBody(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags)
775 {
776     auto savedCtx = SavedStatusContext<ParserStatus::IN_CLASS_BODY>(&context_);
777 
778     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
779     lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
780 
781     ir::MethodDefinition *ctor = nullptr;
782     ArenaVector<ir::AstNode *> properties(Allocator()->Adapter());
783 
784     SavedClassPrivateContext classContext(this);
785 
786     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
787         lexer_->Lookahead() == static_cast<char32_t>(ARRAY_FORMAT_NODE)) {
788         properties = std::move(ParseAstNodesArrayFormatPlaceholder());
789         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
790             ThrowSyntaxError("Expected a '}'");
791         }
792     } else {
793         while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
794             if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
795                 lexer_->NextToken();
796                 continue;
797             }
798 
799             ir::AstNode *property = ParseClassElement(properties, modifiers, flags);
800 
801             if (CheckClassElement(property, ctor, properties)) {
802                 continue;
803             }
804 
805             properties.push_back(property);
806         }
807     }
808 
809     lexer::SourcePosition endLoc = lexer_->GetToken().End();
810     CreateImplicitConstructor(ctor, properties, modifiers, endLoc);
811     lexer_->NextToken();
812 
813     return {ctor, std::move(properties), lexer::SourceRange {startLoc, endLoc}};
814 }
815 
ValidateRestParameter(ir::Expression * param)816 void ParserImpl::ValidateRestParameter(ir::Expression *param)
817 {
818     if (!param->IsIdentifier()) {
819         context_.Status() |= ParserStatus::HAS_COMPLEX_PARAM;
820         if (!param->IsRestElement()) {
821             return;
822         }
823 
824         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
825             ThrowSyntaxError("Rest parameter must be last formal parameter.");
826         }
827     }
828 }
829 
ValidateBreakLabel(util::StringView label)830 bool ParserImpl::ValidateBreakLabel(util::StringView label)
831 {
832     return context_.FindLabel(label) != nullptr;
833 }
834 
ValidateContinueLabel(util::StringView label)835 bool ParserImpl::ValidateContinueLabel(util::StringView label)
836 {
837     const ParserContext *labelCtx = context_.FindLabel(label);
838     return labelCtx != nullptr && ((labelCtx->Status() & ParserStatus::IN_ITERATION) != 0);
839 }
840 
ParseFunctionParams()841 ArenaVector<ir::Expression *> ParserImpl::ParseFunctionParams()
842 {
843     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
844         lexer_->NextToken();  // eat '('
845     }
846 
847     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
848 
849     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
850         lexer_->Lookahead() == static_cast<char32_t>(ARRAY_FORMAT_NODE)) {
851         params = std::move(ParseExpressionsArrayFormatPlaceholder());
852     } else {
853         while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
854             ir::Expression *parameter = ParseFunctionParameter();
855             ValidateRestParameter(parameter);
856 
857             params.push_back(parameter);
858 
859             if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
860                 lexer_->NextToken();
861             } else if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
862                 ThrowSyntaxError("Invalid token: comma or right parenthesis expected.");
863             }
864         }
865     }
866 
867     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
868     lexer_->NextToken();
869     return params;
870 }
871 
CreateParameterThis(util::StringView className)872 ir::Expression *ParserImpl::CreateParameterThis([[maybe_unused]] util::StringView className)
873 {
874     ThrowSyntaxError({"Unexpected token: ", className.Utf8()});
875 }
876 
ParseFunctionBody(const ArenaVector<ir::Expression * > & params,ParserStatus newStatus,ParserStatus contextStatus)877 std::tuple<bool, ir::BlockStatement *, lexer::SourcePosition, bool> ParserImpl::ParseFunctionBody(
878     [[maybe_unused]] const ArenaVector<ir::Expression *> &params, [[maybe_unused]] ParserStatus newStatus,
879     [[maybe_unused]] ParserStatus contextStatus)
880 {
881     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
882         ThrowSyntaxError("Unexpected token, expected '{'");
883     }
884 
885     ir::BlockStatement *body = ParseBlockStatement();
886 
887     return {true, body, body->End(), false};
888 }
889 
ParseFunctionSignature(ParserStatus status,ir::Identifier * className)890 FunctionSignature ParserImpl::ParseFunctionSignature(ParserStatus status, ir::Identifier *className)
891 {
892     ir::TSTypeParameterDeclaration *typeParamDecl = ParseFunctionTypeParameters();
893 
894     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
895         ThrowSyntaxError("Unexpected token, expected '('");
896     }
897 
898     FunctionParameterContext funcParamContext(&context_);
899 
900     ir::Expression *parameterThis = nullptr;
901     if (className != nullptr) {
902         const auto savedPos = Lexer()->Save();
903         lexer_->NextToken();  // eat '('
904         parameterThis = CreateParameterThis(className->Name());
905         Lexer()->Rewind(savedPos);
906     }
907 
908     auto params = ParseFunctionParams();
909 
910     if (className != nullptr) {
911         params.emplace(params.begin(), parameterThis);
912     }
913 
914     ir::TypeNode *returnTypeAnnotation = ParseFunctionReturnType(status);
915     ir::ScriptFunctionFlags throwMarker = ParseFunctionThrowMarker(true);
916 
917     auto res = ir::FunctionSignature(typeParamDecl, std::move(params), returnTypeAnnotation);
918     return {std::move(res), throwMarker};
919 }
920 
ParseFunction(ParserStatus newStatus)921 ir::ScriptFunction *ParserImpl::ParseFunction(ParserStatus newStatus)
922 {
923     FunctionContext functionContext(this, newStatus | ParserStatus::FUNCTION | ParserStatus::ALLOW_NEW_TARGET);
924 
925     bool isDeclare = InAmbientContext();
926 
927     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
928 
929     auto [signature, throw_marker] = ParseFunctionSignature(newStatus);
930 
931     auto [letDeclare, body, endLoc, isOverload] = ParseFunctionBody(signature.Params(), newStatus, context_.Status());
932 
933     if (isOverload) {
934         functionContext.AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
935     }
936 
937     functionContext.AddFlag(throw_marker);
938     auto *funcNode = AllocNode<ir::ScriptFunction>(
939         Allocator(),
940         ir::ScriptFunction::ScriptFunctionData {
941             body, std::move(signature), functionContext.Flags(), {}, isDeclare && letDeclare, context_.GetLanguage()});
942     funcNode->SetRange({startLoc, endLoc});
943 
944     return funcNode;
945 }
946 
ParseSpreadElement(ExpressionParseFlags flags)947 ir::SpreadElement *ParserImpl::ParseSpreadElement(ExpressionParseFlags flags)
948 {
949     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD);
950     lexer::SourcePosition startLocation = lexer_->GetToken().Start();
951     bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0;
952     lexer_->NextToken();
953 
954     ir::Expression *argument {};
955     if (inPattern) {
956         argument = ParsePatternElement(ExpressionParseFlags::IN_REST);
957         if ((flags & ExpressionParseFlags::OBJECT_PATTERN) != 0 && !argument->IsIdentifier()) {
958             ThrowSyntaxError("RestParameter must be followed by an identifier in declaration contexts");
959         }
960     } else {
961         argument = ParseExpression(flags);
962     }
963 
964     if (inPattern && argument->IsAssignmentExpression()) {
965         ThrowSyntaxError("RestParameter does not support an initializer");
966     }
967 
968     auto nodeType = inPattern ? ir::AstNodeType::REST_ELEMENT : ir::AstNodeType::SPREAD_ELEMENT;
969     auto *spreadElementNode = AllocNode<ir::SpreadElement>(nodeType, Allocator(), argument);
970     spreadElementNode->SetRange({startLocation, argument->End()});
971     return spreadElementNode;
972 }
973 
CheckRestrictedBinding() const974 void ParserImpl::CheckRestrictedBinding() const
975 {
976     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT);
977     CheckRestrictedBinding(lexer_->GetToken().KeywordType());
978 }
979 
CheckRestrictedBinding(lexer::TokenType keywordType) const980 void ParserImpl::CheckRestrictedBinding(lexer::TokenType keywordType) const
981 {
982     if (keywordType == lexer::TokenType::KEYW_ARGUMENTS || keywordType == lexer::TokenType::KEYW_EVAL) {
983         ThrowSyntaxError(
984             "'eval' or 'arguments' can't be defined or assigned to "
985             "in strict mode code",
986             lexer_->GetToken().Start());
987     }
988 }
989 
CheckRestrictedBinding(const util::StringView & ident,const lexer::SourcePosition & pos) const990 void ParserImpl::CheckRestrictedBinding(const util::StringView &ident, const lexer::SourcePosition &pos) const
991 {
992     if (ident.Is("eval") || ident.Is("arguments")) {
993         ThrowSyntaxError(
994             "'eval' or 'arguments' can't be defined or assigned to "
995             "in strict mode code",
996             pos);
997     }
998 }
999 
ParseFunctionParameter()1000 ir::Expression *ParserImpl::ParseFunctionParameter()
1001 {
1002     ConvertThisKeywordToIdentIfNecessary();
1003 
1004     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1005         CheckRestrictedBinding();
1006     }
1007 
1008     return ParsePatternElement(ExpressionParseFlags::NO_OPTS, true);
1009 }
1010 
ValidateLvalueAssignmentTarget(ir::Expression * node)1011 void ParserImpl::ValidateLvalueAssignmentTarget(ir::Expression *node)
1012 {
1013     switch (node->Type()) {
1014         case ir::AstNodeType::IDENTIFIER: {
1015             CheckRestrictedBinding(node->AsIdentifier()->Name(), node->Start());
1016             break;
1017         }
1018         case ir::AstNodeType::MEMBER_EXPRESSION: {
1019             break;
1020         }
1021         default: {
1022             ThrowSyntaxError("Invalid left-hand side in assignment expression");
1023         }
1024     }
1025 }
1026 
ValidateAssignmentTarget(ExpressionParseFlags flags,ir::Expression * node)1027 void ParserImpl::ValidateAssignmentTarget(ExpressionParseFlags flags, ir::Expression *node)
1028 {
1029     switch (node->Type()) {
1030         case ir::AstNodeType::ARRAY_PATTERN:
1031         case ir::AstNodeType::OBJECT_PATTERN: {
1032             break;
1033         }
1034         case ir::AstNodeType::ARRAY_EXPRESSION:
1035         case ir::AstNodeType::OBJECT_EXPRESSION: {
1036             if ((flags & ExpressionParseFlags::POTENTIALLY_IN_PATTERN) != 0) {
1037                 return;
1038             }
1039 
1040             [[fallthrough]];
1041         }
1042         default: {
1043             return ValidateLvalueAssignmentTarget(node);
1044         }
1045     }
1046 }
1047 
ValidateArrowParameterBindings(const ir::Expression * node)1048 void ParserImpl::ValidateArrowParameterBindings(const ir::Expression *node)
1049 {
1050     switch (node->Type()) {
1051         case ir::AstNodeType::IDENTIFIER: {
1052             CheckRestrictedBinding(node->AsIdentifier()->Name(), node->Start());
1053             break;
1054         }
1055         case ir::AstNodeType::OMITTED_EXPRESSION: {
1056             break;
1057         }
1058         case ir::AstNodeType::REST_ELEMENT: {
1059             ValidateArrowParameterBindings(node->AsRestElement()->Argument());
1060             break;
1061         }
1062         case ir::AstNodeType::PROPERTY: {
1063             break;
1064         }
1065         case ir::AstNodeType::OBJECT_PATTERN: {
1066             const auto &props = node->AsObjectPattern()->Properties();
1067 
1068             for (auto *it : props) {
1069                 ValidateArrowParameterBindings(it);
1070             }
1071             break;
1072         }
1073         case ir::AstNodeType::ARRAY_PATTERN: {
1074             const auto &elements = node->AsArrayPattern()->Elements();
1075 
1076             for (auto *it : elements) {
1077                 ValidateArrowParameterBindings(it);
1078             }
1079             break;
1080         }
1081         case ir::AstNodeType::ASSIGNMENT_PATTERN: {
1082             ValidateArrowParameterBindings(node->AsAssignmentPattern()->Left());
1083             break;
1084         }
1085         default: {
1086             ThrowSyntaxError("Unexpected ArrowParameter element");
1087         }
1088     }
1089 }
1090 
ThrowParameterModifierError(ir::ModifierFlags status) const1091 void ParserImpl::ThrowParameterModifierError(ir::ModifierFlags status) const
1092 {
1093     ThrowSyntaxError({"'",
1094                       (status & ir::ModifierFlags::STATIC) != 0  ? "static"
1095                       : (status & ir::ModifierFlags::ASYNC) != 0 ? "async"
1096                                                                  : "declare",
1097                       "' modifier cannot appear on a parameter."},
1098                      lexer_->GetToken().Start());
1099 }
1100 
ParseIdentifierFormatPlaceholder(std::optional<NodeFormatType> nodeFormat) const1101 ir::Identifier *ParserImpl::ParseIdentifierFormatPlaceholder(
1102     [[maybe_unused]] std::optional<NodeFormatType> nodeFormat) const
1103 {
1104     ThrowSyntaxError("Identifier expected.");
1105 }
1106 
ParseStatementFormatPlaceholder() const1107 ir::Statement *ParserImpl::ParseStatementFormatPlaceholder() const
1108 {
1109     ThrowSyntaxError("Statement expected.");
1110 }
1111 
ParseTypeParametersFormatPlaceholder() const1112 ir::AstNode *ParserImpl::ParseTypeParametersFormatPlaceholder() const
1113 {
1114     ThrowSyntaxError("Type parameter(s) expected.");
1115 }
1116 
ParseStatementsArrayFormatPlaceholder() const1117 ArenaVector<ir::Statement *> &ParserImpl::ParseStatementsArrayFormatPlaceholder() const
1118 {
1119     ThrowSyntaxError("ArenaVector of ir::Statement *'s expected.");
1120 }
1121 
ParseAstNodesArrayFormatPlaceholder() const1122 ArenaVector<ir::AstNode *> &ParserImpl::ParseAstNodesArrayFormatPlaceholder() const
1123 {
1124     ThrowSyntaxError("ArenaVector of ir::AstNode *'s expected.");
1125 }
1126 
ParseExpressionsArrayFormatPlaceholder() const1127 ArenaVector<ir::Expression *> &ParserImpl::ParseExpressionsArrayFormatPlaceholder() const
1128 {
1129     ThrowSyntaxError("ArenaVector of ir::Expression *'s expected.");
1130 }
1131 
ParseSymbolIteratorIdentifier() const1132 util::StringView ParserImpl::ParseSymbolIteratorIdentifier() const noexcept
1133 {
1134     // Duplicate check - just in case of improper call!
1135     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1136         return util::StringView {};
1137     }
1138 
1139     lexer_->NextToken();
1140     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT || !lexer_->GetToken().Ident().Is("Symbol")) {
1141         return util::StringView {};
1142     }
1143 
1144     lexer_->NextToken();
1145     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_PERIOD) {
1146         return util::StringView {};
1147     }
1148 
1149     lexer_->NextToken();
1150     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT || !lexer_->GetToken().Ident().Is("iterator")) {
1151         return util::StringView {};
1152     }
1153 
1154     lexer_->NextToken();
1155     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1156         return util::StringView {};
1157     }
1158 
1159     //  Just replace '[Symbol.iterator]` identifier with the standard '$_iterator' name.
1160     return util::StringView {compiler::Signatures::ITERATOR_METHOD};
1161 }
1162 
ExpectIdentifier(bool isReference,bool isUserDefinedType)1163 ir::Identifier *ParserImpl::ExpectIdentifier(bool isReference, bool isUserDefinedType)
1164 {
1165     auto const &token = lexer_->GetToken();
1166     auto const tokenType = token.Type();
1167     if (tokenType == lexer::TokenType::PUNCTUATOR_FORMAT) {
1168         return ParseIdentifierFormatPlaceholder(std::nullopt);
1169     }
1170 
1171     if (token.IsDefinableTypeName() && isUserDefinedType) {
1172         ThrowSyntaxError("Cannot be used as user-defined type.");
1173     }
1174 
1175     auto const &tokenStart = token.Start();
1176     util::StringView tokenName {};
1177 
1178     if (tokenType == lexer::TokenType::LITERAL_IDENT) {
1179         tokenName = token.Ident();
1180     } else if (tokenType == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1181         // Special case for processing of special '[Symbol.iterator]` identifier using in stdlib.
1182         tokenName = ParseSymbolIteratorIdentifier();
1183     }
1184 
1185     if (tokenName.Empty()) {
1186         ThrowSyntaxError("Identifier expected.", tokenStart);
1187     }
1188 
1189     auto *ident = AllocNode<ir::Identifier>(tokenName, Allocator());
1190     ident->SetReference(isReference);
1191     //  NOTE: here actual token can be changed!
1192     ident->SetRange({tokenStart, lexer_->GetToken().End()});
1193 
1194     lexer_->NextToken();
1195 
1196     return ident;
1197 }
1198 
ExpectToken(lexer::TokenType tokenType,bool consumeToken)1199 void ParserImpl::ExpectToken(lexer::TokenType tokenType, bool consumeToken)
1200 {
1201     if (lexer_->GetToken().Type() == tokenType) {
1202         if (consumeToken) {
1203             lexer_->NextToken();
1204         }
1205         return;
1206     }
1207     ThrowExpectedToken(tokenType);
1208 }
1209 
ThrowUnexpectedToken(lexer::TokenType const tokenType) const1210 void ParserImpl::ThrowUnexpectedToken(lexer::TokenType const tokenType) const
1211 {
1212     ThrowSyntaxError("Unexpected token: '"s + TokenToString(tokenType) + "'."s);
1213 }
1214 
ThrowExpectedToken(lexer::TokenType const tokenType) const1215 void ParserImpl::ThrowExpectedToken(lexer::TokenType const tokenType) const
1216 {
1217     ThrowSyntaxError("Unexpected token, expected: '"s + TokenToString(tokenType) + "'."s);
1218 }
1219 
ThrowSyntaxError(std::string_view const errorMessage) const1220 void ParserImpl::ThrowSyntaxError(std::string_view const errorMessage) const
1221 {
1222     ThrowSyntaxError(errorMessage, lexer_->GetToken().Start());
1223 }
1224 
ThrowSyntaxError(std::initializer_list<std::string_view> list) const1225 void ParserImpl::ThrowSyntaxError(std::initializer_list<std::string_view> list) const
1226 {
1227     ThrowSyntaxError(list, lexer_->GetToken().Start());
1228 }
1229 
ThrowSyntaxError(std::initializer_list<std::string_view> list,const lexer::SourcePosition & pos) const1230 void ParserImpl::ThrowSyntaxError(std::initializer_list<std::string_view> list, const lexer::SourcePosition &pos) const
1231 {
1232     std::stringstream ss;
1233 
1234     for (const auto &it : list) {
1235         ss << it;
1236     }
1237 
1238     std::string err = ss.str();
1239 
1240     ThrowSyntaxError(std::string_view {err}, pos);
1241 }
1242 
ThrowSyntaxError(std::string_view errorMessage,const lexer::SourcePosition & pos) const1243 void ParserImpl::ThrowSyntaxError(std::string_view errorMessage, const lexer::SourcePosition &pos) const
1244 {
1245     lexer::LineIndex index(program_->SourceCode());
1246     lexer::SourceLocation loc = index.GetLocation(pos);
1247 
1248     throw Error {ErrorType::SYNTAX, program_->SourceFilePath().Utf8(), errorMessage, loc.line, loc.col};
1249 }
1250 
ThrowAllocationError(std::string_view message) const1251 void ParserImpl::ThrowAllocationError(std::string_view message) const
1252 {
1253     throw Error(ErrorType::GENERIC, program_->SourceFilePath().Utf8(), message);
1254 }
1255 
Extension() const1256 ScriptExtension ParserImpl::Extension() const
1257 {
1258     return program_->Extension();
1259 }
1260 
CheckModuleAsModifier()1261 bool ParserImpl::CheckModuleAsModifier()
1262 {
1263     if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_AS) {
1264         return false;
1265     }
1266 
1267     if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0U) {
1268         ThrowSyntaxError("Escape sequences are not allowed in 'as' keyword");
1269     }
1270 
1271     return true;
1272 }
1273 
1274 }  // namespace ark::es2panda::parser
1275