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