• 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 "TypedParser.h"
17 
18 #include "parser/parserStatusContext.h"
19 #include "varbinder/privateBinding.h"
20 #include "lexer/lexer.h"
21 #include "ir/base/classDefinition.h"
22 #include "ir/base/decorator.h"
23 #include "ir/base/spreadElement.h"
24 #include "ir/base/tsPropertySignature.h"
25 #include "ir/base/tsMethodSignature.h"
26 #include "ir/base/methodDefinition.h"
27 #include "ir/base/tsIndexSignature.h"
28 #include "ir/base/scriptFunction.h"
29 #include "ir/expressions/identifier.h"
30 #include "ir/expressions/yieldExpression.h"
31 #include "ir/expressions/objectExpression.h"
32 #include "ir/expressions/arrayExpression.h"
33 #include "ir/expressions/assignmentExpression.h"
34 #include "ir/expressions/arrowFunctionExpression.h"
35 #include "ir/expressions/sequenceExpression.h"
36 #include "ir/expressions/callExpression.h"
37 #include "ir/expressions/literals/stringLiteral.h"
38 #include "ir/expressions/literals/numberLiteral.h"
39 #include "ir/expressions/functionExpression.h"
40 #include "ir/statement.h"
41 #include "ir/statements/classDeclaration.h"
42 #include "ir/statements/variableDeclarator.h"
43 #include "ir/ts/tsModuleDeclaration.h"
44 #include "ir/ts/tsModuleBlock.h"
45 #include "ir/ts/tsInterfaceBody.h"
46 #include "ir/ts/tsInterfaceDeclaration.h"
47 #include "ir/ts/tsEnumMember.h"
48 #include "ir/ts/tsEnumDeclaration.h"
49 #include "ir/ts/tsTypeParameterInstantiation.h"
50 #include "ir/ts/tsTypeParameterDeclaration.h"
51 #include "ir/ts/tsTypeParameter.h"
52 #include "ir/ts/tsQualifiedName.h"
53 #include "ir/ts/tsTypeReference.h"
54 #include "ir/ts/tsTypeAliasDeclaration.h"
55 #include "ir/ts/tsInterfaceHeritage.h"
56 #include "ir/ts/tsClassImplements.h"
57 #include "ir/ts/tsTypeAssertion.h"
58 
59 namespace ark::es2panda::parser {
60 
ParsePotentialAsExpression(ir::Expression * primaryExpression)61 ir::Expression *TypedParser::ParsePotentialAsExpression([[maybe_unused]] ir::Expression *primaryExpression)
62 {
63     return nullptr;
64 }
65 
66 // NOLINTNEXTLINE(google-default-arguments)
ParseExpression(ExpressionParseFlags flags)67 ir::Expression *TypedParser::ParseExpression(ExpressionParseFlags flags)
68 {
69     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_YIELD &&
70         ((flags & ExpressionParseFlags::DISALLOW_YIELD) == 0)) {
71         ir::YieldExpression *yieldExpr = ParseYieldExpression();
72 
73         return ParsePotentialExpressionSequence(yieldExpr, flags);
74     }
75 
76     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
77         const auto startPos = Lexer()->Save();
78 
79         // NOTE(rsipka): ParseTsGenericArrowFunction and ParseTsTypeAssertion might be in a common function
80         ir::Expression *expr = ParseGenericArrowFunction();
81         // NOTE(rsipka): negative cases are not covered, probably this is not a complete solution yet
82         if (expr == nullptr) {
83             Lexer()->Rewind(startPos);
84             expr = ParseTypeAssertion();
85         }
86 
87         return expr;
88     }
89 
90     ir::Expression *unaryExpressionNode = ParseUnaryOrPrefixUpdateExpression(flags);
91 
92     if (unaryExpressionNode->IsArrowFunctionExpression()) {
93         return unaryExpressionNode;
94     }
95 
96     ir::Expression *assignmentExpression = ParseAssignmentExpression(unaryExpressionNode, flags);
97 
98     if (Lexer()->GetToken().NewLine()) {
99         return assignmentExpression;
100     }
101 
102     switch (Lexer()->GetToken().Type()) {
103         case lexer::TokenType::LITERAL_IDENT: {
104             if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
105                 return ParsePotentialAsExpression(assignmentExpression);
106             }
107             break;
108         }
109         case lexer::TokenType::PUNCTUATOR_COMMA: {
110             if ((flags & ExpressionParseFlags::ACCEPT_COMMA) != 0) {
111                 return ParseSequenceExpression(assignmentExpression,
112                                                ((flags & ExpressionParseFlags::ACCEPT_REST) != 0));
113             }
114             break;
115         }
116         default: {
117             break;
118         }
119     }
120 
121     return assignmentExpression;
122 }
123 
ParsePotentialExpressionStatement(StatementParsingFlags flags)124 ir::Statement *TypedParser::ParsePotentialExpressionStatement(StatementParsingFlags flags)
125 {
126     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT);
127 
128     switch (Lexer()->GetToken().KeywordType()) {
129         case lexer::TokenType::KEYW_TYPE: {
130             return ParseTypeAliasDeclaration();
131         }
132         case lexer::TokenType::KEYW_ABSTRACT: {
133             Lexer()->NextToken();  // eat abstract keyword
134 
135             if (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_CLASS) {
136                 ThrowSyntaxError(
137                     "abstract modifier can only appear on a class, struct, method, or property declaration.");
138             }
139 
140             return ParseClassStatement(flags, ir::ClassDefinitionModifiers::NONE, ir::ModifierFlags::ABSTRACT);
141         }
142         case lexer::TokenType::KEYW_GLOBAL:
143         case lexer::TokenType::KEYW_MODULE:
144         case lexer::TokenType::KEYW_NAMESPACE: {
145             return ParseModuleDeclaration();
146         }
147         default: {
148             break;
149         }
150     }
151     return ParseExpressionStatement(flags);
152 }
153 
ParseTypeAssertion()154 ir::TSTypeAssertion *TypedParser::ParseTypeAssertion()
155 {
156     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN);
157     lexer::SourcePosition start = Lexer()->GetToken().Start();
158     Lexer()->NextToken();  // eat '<'
159 
160     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
161     ir::TypeNode *typeAnnotation = ParseTypeAnnotation(&options);
162 
163     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
164         return nullptr;
165     }
166 
167     Lexer()->NextToken();  // eat '>'
168     ir::Expression *expression = ParseExpression();
169     auto *typeAssertion = AllocNode<ir::TSTypeAssertion>(typeAnnotation, expression);
170     typeAssertion->SetRange({start, Lexer()->GetToken().End()});
171 
172     return typeAssertion;
173 }
174 
175 // NOLINTNEXTLINE(google-default-arguments)
ParseModuleDeclaration(StatementParsingFlags flags)176 ir::Statement *TypedParser::ParseModuleDeclaration([[maybe_unused]] StatementParsingFlags flags)
177 {
178     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
179     GetContext().Status() |= ParserStatus::MODULE;
180 
181     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_GLOBAL) {
182         return ParseAmbientExternalModuleDeclaration(startLoc);
183     }
184 
185     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_NAMESPACE) {
186         Lexer()->NextToken();
187     } else {
188         ASSERT(Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_MODULE);
189         Lexer()->NextToken();
190         if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
191             return ParseAmbientExternalModuleDeclaration(startLoc);
192         }
193     }
194 
195     return ParseModuleOrNamespaceDeclaration(startLoc);
196 }
197 
ParseGenericArrowFunction()198 ir::ArrowFunctionExpression *TypedParser::ParseGenericArrowFunction()
199 {
200     ArrowFunctionContext arrowFunctionContext(this, false);
201 
202     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN);
203     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
204 
205     auto typeParamDeclOptions = TypeAnnotationParsingOptions::NO_OPTS;
206     ir::TSTypeParameterDeclaration *typeParamDecl = ParseTypeParameterDeclaration(&typeParamDeclOptions);
207 
208     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
209         return nullptr;
210     }
211 
212     FunctionParameterContext funcParamContext(&GetContext());
213     auto params = ParseFunctionParams();
214 
215     ParserStatus arrowStatus = ParserStatus::NO_OPTS;
216 
217     if (std::any_of(params.begin(), params.end(), [](const auto *param) { return !param->IsIdentifier(); })) {
218         arrowStatus = ParserStatus::HAS_COMPLEX_PARAM;
219     }
220 
221     ir::TypeNode *returnTypeAnnotation = nullptr;
222     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
223         Lexer()->NextToken();  // eat ':'
224         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
225         returnTypeAnnotation = ParseTypeAnnotation(&options);
226     }
227 
228     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
229         return nullptr;
230     }
231 
232     ArrowFunctionDescriptor desc(std::move(params), startLoc, arrowStatus);
233 
234     return ParseArrowFunctionExpressionBody(&arrowFunctionContext, &desc, typeParamDecl, returnTypeAnnotation);
235 }
236 
ParseAmbientExternalModuleDeclaration(const lexer::SourcePosition & startLoc)237 ir::TSModuleDeclaration *TypedParser::ParseAmbientExternalModuleDeclaration(const lexer::SourcePosition &startLoc)
238 {
239     bool isGlobal = false;
240     ir::Expression *name = nullptr;
241 
242     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_GLOBAL) {
243         isGlobal = true;
244         name = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
245     } else {
246         ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
247 
248         if (!InAmbientContext()) {
249             ThrowSyntaxError("Only ambient modules can use quoted names");
250         }
251 
252         name = AllocNode<ir::StringLiteral>(Lexer()->GetToken().String());
253     }
254 
255     name->SetRange(Lexer()->GetToken().Loc());
256 
257     Lexer()->NextToken();
258 
259     ir::Statement *body = nullptr;
260     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
261         body = ParseTsModuleBlock();
262     } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
263         Lexer()->NextToken();
264     } else {
265         ThrowSyntaxError("';' expected");
266     }
267 
268     auto *moduleDecl = AllocNode<ir::TSModuleDeclaration>(
269         Allocator(), name, body, ir::TSModuleDeclaration::ConstructorFlags {InAmbientContext(), isGlobal, true});
270     moduleDecl->SetRange({startLoc, Lexer()->GetToken().End()});
271 
272     return moduleDecl;
273 }
274 
ParseModuleOrNamespaceDeclaration(const lexer::SourcePosition & startLoc)275 ir::TSModuleDeclaration *TypedParser::ParseModuleOrNamespaceDeclaration(const lexer::SourcePosition &startLoc)
276 {
277     if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
278         ThrowSyntaxError("Identifier expected");
279     }
280 
281     auto *identNode = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
282     identNode->SetRange(Lexer()->GetToken().Loc());
283 
284     Lexer()->NextToken();
285 
286     ir::Statement *body = nullptr;
287 
288     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
289         Lexer()->NextToken();
290         lexer::SourcePosition moduleStart = Lexer()->GetToken().Start();
291         body = ParseModuleOrNamespaceDeclaration(moduleStart);
292     } else {
293         body = ParseTsModuleBlock();
294     }
295 
296     auto *moduleDecl = AllocNode<ir::TSModuleDeclaration>(
297         Allocator(), identNode, body, ir::TSModuleDeclaration::ConstructorFlags {InAmbientContext(), false, false});
298     moduleDecl->SetRange({startLoc, Lexer()->GetToken().End()});
299 
300     return moduleDecl;
301 }
302 
ParseTsModuleBlock()303 ir::TSModuleBlock *TypedParser::ParseTsModuleBlock()
304 {
305     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
306         ThrowSyntaxError("'{' expected.");
307     }
308 
309     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
310     Lexer()->NextToken();
311     auto statements = ParseStatementList();
312 
313     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
314         ThrowSyntaxError("Expected a '}'");
315     }
316 
317     auto *blockNode = AllocNode<ir::TSModuleBlock>(std::move(statements));
318     blockNode->SetRange({startLoc, Lexer()->GetToken().End()});
319 
320     Lexer()->NextToken();
321     return blockNode;
322 }
323 
CheckDeclare()324 void TypedParser::CheckDeclare()
325 {
326     ASSERT(Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE);
327 
328     if (InAmbientContext()) {
329         ThrowSyntaxError("A 'declare' modifier cannot be used in an already ambient context.");
330     }
331 
332     GetContext().Status() |= ParserStatus::IN_AMBIENT_CONTEXT;
333 
334     Lexer()->NextToken();  // eat 'declare'
335 
336     switch (Lexer()->GetToken().KeywordType()) {
337         case lexer::TokenType::KEYW_VAR:
338         case lexer::TokenType::KEYW_LET:
339         case lexer::TokenType::KEYW_CONST:
340         case lexer::TokenType::KEYW_FUNCTION:
341         case lexer::TokenType::KEYW_CLASS:
342         case lexer::TokenType::KEYW_TYPE:
343         case lexer::TokenType::KEYW_MODULE:
344         case lexer::TokenType::KEYW_GLOBAL:
345         case lexer::TokenType::KEYW_NAMESPACE:
346         case lexer::TokenType::KEYW_ENUM:
347         case lexer::TokenType::KEYW_ABSTRACT:
348         case lexer::TokenType::KEYW_INTERFACE: {
349             return;
350         }
351         default: {
352             ThrowSyntaxError("Unexpected token.");
353         }
354     }
355 }
356 
ParseDecorators(ArenaVector<ir::Decorator * > & decorators)357 void TypedParser::ParseDecorators(ArenaVector<ir::Decorator *> &decorators)
358 {
359     while (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_AT) {
360         decorators.push_back(ParseDecorator());
361     }
362 }
363 
ParseFunctionReturnType(ParserStatus status)364 ir::TypeNode *TypedParser::ParseFunctionReturnType(ParserStatus status)
365 {
366     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
367         Lexer()->NextToken();  // eat ':'
368         TypeAnnotationParsingOptions options =
369             TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::RETURN_TYPE;
370         return ParseTypeAnnotation(&options);
371     }
372 
373     if ((status & ParserStatus::NEED_RETURN_TYPE) != 0) {
374         ThrowSyntaxError("Type expected");
375     }
376 
377     return nullptr;
378 }
379 
ParseInterfaceExtendsElement()380 ir::TypeNode *TypedParser::ParseInterfaceExtendsElement()
381 {
382     const lexer::SourcePosition &heritageStart = Lexer()->GetToken().Start();
383     lexer::SourcePosition heritageEnd = Lexer()->GetToken().End();
384     ir::Expression *expr = ParseQualifiedName();
385 
386     if (Lexer()->Lookahead() == lexer::LEX_CHAR_LESS_THAN) {
387         Lexer()->ForwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
388     }
389 
390     ir::TSTypeParameterInstantiation *typeParamInst = nullptr;
391     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
392         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
393         typeParamInst = ParseTypeParameterInstantiation(&options);
394         heritageEnd = typeParamInst->End();
395     }
396 
397     auto *typeReference = AllocNode<ir::TSTypeReference>(expr, typeParamInst);
398     typeReference->SetRange({heritageStart, heritageEnd});
399     return typeReference;
400 }
401 
ParseInterfaceExtendsClause()402 ArenaVector<ir::TSInterfaceHeritage *> TypedParser::ParseInterfaceExtendsClause()
403 {
404     Lexer()->NextToken();  // eat extends keyword
405 
406     ArenaVector<ir::TSInterfaceHeritage *> extends(Allocator()->Adapter());
407 
408     while (true) {
409         auto *typeReference = ParseInterfaceExtendsElement();
410         auto *heritage = AllocNode<ir::TSInterfaceHeritage>(typeReference);
411         heritage->SetRange(typeReference->Range());
412         extends.push_back(heritage);
413 
414         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
415             break;
416         }
417 
418         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) {
419             ThrowSyntaxError("',' expected");
420         }
421 
422         Lexer()->NextToken();
423     }
424 
425     return extends;
426 }
427 
ParseFunctionTypeParameters()428 ir::TSTypeParameterDeclaration *TypedParser::ParseFunctionTypeParameters()
429 {
430     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
431         auto options = TypeAnnotationParsingOptions::THROW_ERROR;
432         return ParseTypeParameterDeclaration(&options);
433     }
434 
435     return nullptr;
436 }
437 
ParseInterfaceDeclaration(bool isStatic)438 ir::Statement *TypedParser::ParseInterfaceDeclaration(bool isStatic)
439 {
440     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_INTERFACE);
441     GetContext().Status() |= ParserStatus::ALLOW_THIS_TYPE;
442     lexer::SourcePosition interfaceStart = Lexer()->GetToken().Start();
443     Lexer()->NextToken();  // eat interface keyword
444 
445     auto id = ExpectIdentifier(true);
446 
447     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
448     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
449         auto options = TypeAnnotationParsingOptions::THROW_ERROR;
450         typeParamDecl = ParseTypeParameterDeclaration(&options);
451     }
452 
453     ArenaVector<ir::TSInterfaceHeritage *> extends(Allocator()->Adapter());
454     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
455         extends = ParseInterfaceExtendsClause();
456     }
457 
458     lexer::SourcePosition bodyStart = Lexer()->GetToken().Start();
459     auto members = ParseTypeLiteralOrInterface();
460 
461     auto *body = AllocNode<ir::TSInterfaceBody>(std::move(members));
462     body->SetRange({bodyStart, Lexer()->GetToken().End()});
463 
464     const auto isExternal = IsExternal();
465     auto *interfaceDecl = AllocNode<ir::TSInterfaceDeclaration>(
466         Allocator(), std::move(extends),
467         ir::TSInterfaceDeclaration::ConstructorData {id, typeParamDecl, body, isStatic, isExternal,
468                                                      GetContext().GetLanguage()});
469     interfaceDecl->SetRange({interfaceStart, Lexer()->GetToken().End()});
470 
471     Lexer()->NextToken();
472     GetContext().Status() &= ~ParserStatus::ALLOW_THIS_TYPE;
473 
474     return interfaceDecl;
475 }
476 
GetTSPropertyName(ir::Expression * key)477 static util::StringView GetTSPropertyName(ir::Expression *key)
478 {
479     switch (key->Type()) {
480         case ir::AstNodeType::IDENTIFIER: {
481             return key->AsIdentifier()->Name();
482         }
483         case ir::AstNodeType::NUMBER_LITERAL: {
484             return key->AsNumberLiteral()->Str();
485         }
486         case ir::AstNodeType::STRING_LITERAL: {
487             return key->AsStringLiteral()->Str();
488         }
489         default: {
490             UNREACHABLE();
491         }
492     }
493 }
494 
CheckObjectTypeForDuplicatedProperties(ir::Expression * key,ArenaVector<ir::AstNode * > & members)495 void TypedParser::CheckObjectTypeForDuplicatedProperties(ir::Expression *key, ArenaVector<ir::AstNode *> &members)
496 {
497     if (!key->IsIdentifier() && !key->IsNumberLiteral() && !key->IsStringLiteral()) {
498         return;
499     }
500 
501     for (auto *it : members) {
502         ir::Expression *compare = nullptr;
503 
504         switch (it->Type()) {
505             case ir::AstNodeType::TS_PROPERTY_SIGNATURE: {
506                 compare = it->AsTSPropertySignature()->Key();
507                 break;
508             }
509             case ir::AstNodeType::TS_METHOD_SIGNATURE: {
510                 compare = it->AsTSMethodSignature()->Key();
511                 break;
512             }
513             default: {
514                 continue;
515             }
516         }
517 
518         if (!compare->IsIdentifier() && !compare->IsNumberLiteral() && !compare->IsStringLiteral()) {
519             continue;
520         }
521 
522         if (GetTSPropertyName(key) == GetTSPropertyName(compare)) {
523             ThrowSyntaxError("Duplicated identifier", key->Start());
524         }
525     }
526 }
527 
ParseTypeLiteralOrInterfaceBody()528 ArenaVector<ir::AstNode *> TypedParser::ParseTypeLiteralOrInterfaceBody()
529 {
530     ArenaVector<ir::AstNode *> members(Allocator()->Adapter());
531 
532     while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
533         ir::AstNode *member = ParseTypeLiteralOrInterfaceMember();
534         if (member->IsMethodDefinition() && member->AsMethodDefinition()->Function() != nullptr &&
535             member->AsMethodDefinition()->Function()->IsOverload() &&
536             member->AsMethodDefinition()->Function()->Body() != nullptr) {
537             continue;
538         }
539 
540         if (member->IsTSPropertySignature()) {
541             CheckObjectTypeForDuplicatedProperties(member->AsTSPropertySignature()->Key(), members);
542         } else if (member->IsTSMethodSignature()) {
543             CheckObjectTypeForDuplicatedProperties(member->AsTSMethodSignature()->Key(), members);
544         }
545 
546         members.push_back(member);
547 
548         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
549             break;
550         }
551 
552         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
553             Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
554             if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
555                 ThrowSyntaxError("Interface member initialization is prohibited");
556             }
557             if (!Lexer()->GetToken().NewLine()) {
558                 ThrowSyntaxError("',' expected");
559             }
560 
561             if (Lexer()->GetToken().IsKeyword() && ((Lexer()->GetToken().Type() != lexer::TokenType::KEYW_STATIC) &&
562                                                     (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_PRIVATE))) {
563                 Lexer()->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
564             }
565 
566             continue;
567         }
568 
569         Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
570     }
571 
572     return members;
573 }
574 
ParseTypeLiteralOrInterface()575 ArenaVector<ir::AstNode *> TypedParser::ParseTypeLiteralOrInterface()
576 {
577     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_IMPLEMENTS) {
578         ThrowSyntaxError("Interface declaration cannot have 'implements' clause.");
579     }
580 
581     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
582         ThrowSyntaxError("Unexpected token, expected '{'");
583     }
584 
585     Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat '{'
586 
587     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_OVERRIDE) {
588         ThrowSyntaxError("'override' modifier cannot appear in interfaces");
589     }
590 
591     bool const formattedParsing = Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
592                                   Lexer()->Lookahead() == static_cast<char32_t>(ARRAY_FORMAT_NODE);
593 
594     ArenaVector<ir::AstNode *> members =
595         !formattedParsing ? ParseTypeLiteralOrInterfaceBody() : std::move(ParseAstNodesArrayFormatPlaceholder());
596 
597     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
598         ThrowSyntaxError("Expected a '}'");
599     }
600 
601     return members;
602 }
603 
ParseEnumMembers(ir::Identifier * key,const lexer::SourcePosition & enumStart,bool isConst,bool isStatic)604 ir::TSEnumDeclaration *TypedParser::ParseEnumMembers(ir::Identifier *key, const lexer::SourcePosition &enumStart,
605                                                      bool isConst, [[maybe_unused]] bool isStatic)
606 {
607     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
608         ThrowSyntaxError("'{' expected");
609     }
610 
611     ArenaVector<ir::AstNode *> members(Allocator()->Adapter());
612     Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat '{'
613 
614     while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
615         ir::Expression *memberKey = nullptr;
616 
617         if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
618             memberKey = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
619             memberKey->SetRange(Lexer()->GetToken().Loc());
620             Lexer()->NextToken();
621         } else if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
622             memberKey = AllocNode<ir::StringLiteral>(Lexer()->GetToken().String());
623             memberKey->SetRange(Lexer()->GetToken().Loc());
624             Lexer()->NextToken();
625         } else {
626             ThrowSyntaxError("Unexpected token in enum member");
627         }
628 
629         ir::Expression *memberInit = nullptr;
630         lexer::SourcePosition initStart = Lexer()->GetToken().Start();
631 
632         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
633             Lexer()->NextToken();  // eat '='
634             initStart = Lexer()->GetToken().Start();
635             memberInit = ParseExpression();
636         }
637 
638         auto *member = AllocNode<ir::TSEnumMember>(memberKey, memberInit);
639         member->SetRange({initStart, Lexer()->GetToken().End()});
640         members.push_back(member);
641 
642         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
643             Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat ','
644         }
645     }
646 
647     auto *enumDeclaration = AllocNode<ir::TSEnumDeclaration>(Allocator(), key, std::move(members),
648                                                              ir::TSEnumDeclaration::ConstructorFlags {isConst});
649     enumDeclaration->SetRange({enumStart, Lexer()->GetToken().End()});
650     Lexer()->NextToken();  // eat '}'
651 
652     return enumDeclaration;
653 }
654 
655 // NOLINTNEXTLINE(google-default-arguments)
ParseEnumDeclaration(bool isConst,bool isStatic)656 ir::Statement *TypedParser::ParseEnumDeclaration(bool isConst, [[maybe_unused]] bool isStatic)
657 {
658     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_ENUM);
659     lexer::SourcePosition enumStart = Lexer()->GetToken().Start();
660     Lexer()->NextToken();  // eat enum keyword
661     auto *key = ExpectIdentifier(true);
662     auto *declNode = ParseEnumMembers(key, enumStart, isConst, false);
663     return declNode;
664 }
665 
ParseTypeParameter(TypeAnnotationParsingOptions * options)666 ir::TSTypeParameter *TypedParser::ParseTypeParameter(TypeAnnotationParsingOptions *options)
667 {
668     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
669     bool throwError = ((*options) & TypeAnnotationParsingOptions::THROW_ERROR) != 0;
670 
671     if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT || Lexer()->GetToken().IsDefinableTypeName()) {
672         if (!throwError) {
673             return nullptr;
674         }
675 
676         ThrowSyntaxError("Type parameter declaration expected");
677     }
678 
679     if (throwError) {
680         CheckIfTypeParameterNameIsReserved();
681     }
682 
683     const auto &ident = Lexer()->GetToken().Ident();
684     auto *paramIdent = AllocNode<ir::Identifier>(ident, Allocator());
685 
686     paramIdent->SetRange({Lexer()->GetToken().Start(), Lexer()->GetToken().End()});
687 
688     Lexer()->NextToken();
689 
690     TypeAnnotationParsingOptions newOptions = TypeAnnotationParsingOptions::NO_OPTS;
691 
692     if (throwError) {
693         newOptions |= TypeAnnotationParsingOptions::THROW_ERROR;
694     }
695 
696     ir::TypeNode *constraint = nullptr;
697     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
698         Lexer()->NextToken();
699         constraint = ParseTypeAnnotation(&newOptions);
700     }
701 
702     ir::TypeNode *defaultType = nullptr;
703     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
704         Lexer()->NextToken();
705         defaultType = ParseTypeAnnotation(&newOptions);
706     }
707 
708     auto *typeParam = AllocNode<ir::TSTypeParameter>(paramIdent, constraint, defaultType);
709 
710     typeParam->SetRange({startLoc, Lexer()->GetToken().End()});
711 
712     return typeParam;
713 }
714 
715 //  Auxiliary method to reduce the size of functions.
ParseTypeParameterDeclarationImpl(TypeAnnotationParsingOptions * options)716 ir::AstNode *TypedParser::ParseTypeParameterDeclarationImpl(TypeAnnotationParsingOptions *options)
717 {
718     ArenaVector<ir::TSTypeParameter *> params(Allocator()->Adapter());
719     bool seenDefault = false;
720     size_t requiredParams = 0U;
721 
722     while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
723         auto newOptions = *options | TypeAnnotationParsingOptions::ADD_TYPE_PARAMETER_BINDING;
724         ir::TSTypeParameter *currentParam = ParseTypeParameter(&newOptions);
725 
726         if (currentParam == nullptr) {
727             ASSERT((newOptions & TypeAnnotationParsingOptions::THROW_ERROR) == 0);
728             return nullptr;
729         }
730 
731         if (currentParam->DefaultType() != nullptr) {
732             seenDefault = true;
733         } else if (seenDefault) {
734             ThrowSyntaxError("Required type parameters may not follow optional type parameters.");
735         } else {
736             requiredParams++;
737         }
738 
739         params.push_back(currentParam);
740 
741         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) {
742             break;
743         }
744 
745         Lexer()->NextToken();
746     }
747 
748     if (params.empty()) {
749         ThrowSyntaxError("Type parameter list cannot be empty.");
750     }
751 
752     return AllocNode<ir::TSTypeParameterDeclaration>(std::move(params), requiredParams);
753 }
754 
ParseTypeParameterDeclaration(TypeAnnotationParsingOptions * options)755 ir::TSTypeParameterDeclaration *TypedParser::ParseTypeParameterDeclaration(TypeAnnotationParsingOptions *options)
756 {
757     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN);
758 
759     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
760     Lexer()->NextToken();  // eat '<'
761 
762     ir::AstNode *typeParamDecl;
763 
764     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
765         Lexer()->Lookahead() == static_cast<char32_t>(EXPRESSION_FORMAT_NODE)) {
766         typeParamDecl = ParseTypeParametersFormatPlaceholder();
767     } else {
768         typeParamDecl = ParseTypeParameterDeclarationImpl(options);
769     }
770 
771     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
772         if ((*options & TypeAnnotationParsingOptions::THROW_ERROR) == 0) {
773             return nullptr;
774         }
775         ThrowSyntaxError("Expected closing '>'.");
776     }
777 
778     lexer::SourcePosition endLoc = Lexer()->GetToken().End();
779     Lexer()->NextToken();  // eat '>'
780 
781     if (typeParamDecl != nullptr) {
782         typeParamDecl->SetRange({startLoc, endLoc});
783         return typeParamDecl->AsTSTypeParameterDeclaration();
784     }
785 
786     return nullptr;
787 }
788 
ParseSuperClassReference()789 ir::Expression *TypedParser::ParseSuperClassReference()
790 {
791     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
792         Lexer()->NextToken();
793 
794         return ParseLeftHandSideExpression();
795     }
796 
797     return nullptr;
798 }
799 
ParseSuperClass()800 std::tuple<ir::Expression *, ir::TSTypeParameterInstantiation *> TypedParser::ParseSuperClass()
801 {
802     ir::Expression *superClass = ParseSuperClassReference();
803 
804     ir::TSTypeParameterInstantiation *superTypeParams = nullptr;
805     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN ||
806         Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
807         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
808             Lexer()->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
809         }
810 
811         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
812         superTypeParams = ParseTypeParameterInstantiation(&options);
813     }
814 
815     return {superClass, superTypeParams};
816 }
817 
ParseClassImplementsElement()818 std::tuple<ir::Expression *, ir::TSTypeParameterInstantiation *> TypedParser::ParseClassImplementsElement()
819 {
820     ir::Expression *expr = ParseQualifiedName();
821 
822     ir::TSTypeParameterInstantiation *implTypeParams = nullptr;
823     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN ||
824         Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
825         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
826             Lexer()->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
827         }
828 
829         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
830         implTypeParams = ParseTypeParameterInstantiation(&options);
831     }
832 
833     return {expr, implTypeParams};
834 }
835 
ParseClassImplementClause()836 ArenaVector<ir::TSClassImplements *> TypedParser::ParseClassImplementClause()
837 {
838     ArenaVector<ir::TSClassImplements *> implements(Allocator()->Adapter());
839 
840     while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
841         lexer::SourcePosition implStart = Lexer()->GetToken().Start();
842         auto [expr, implTypeParams] = ParseClassImplementsElement();
843         auto *impl = AllocNode<ir::TSClassImplements>(expr, implTypeParams);
844         impl->SetRange({implStart, Lexer()->GetToken().End()});
845         implements.push_back(impl);
846 
847         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
848             Lexer()->NextToken();
849             continue;
850         }
851 
852         if (InAmbientContext()) {
853             break;
854         }
855 
856         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
857             ThrowSyntaxError("',' expected");
858         }
859     }
860 
861     if (implements.empty()) {
862         ThrowSyntaxError("Implements clause can not be empty");
863     }
864 
865     return implements;
866 }
867 
CheckClassElementInterfaceBody(ir::AstNode * property,ArenaVector<ir::AstNode * > & properties)868 bool TypedParser::CheckClassElementInterfaceBody(ir::AstNode *property, ArenaVector<ir::AstNode *> &properties)
869 {
870     for (auto *it : property->AsTSInterfaceBody()->Body()) {
871         properties.push_back(it);
872     }
873 
874     return true;
875 }
876 
CheckClassElement(ir::AstNode * property,ir::MethodDefinition * & ctor,ArenaVector<ir::AstNode * > & properties)877 bool TypedParser::CheckClassElement(ir::AstNode *property, ir::MethodDefinition *&ctor,
878                                     [[maybe_unused]] ArenaVector<ir::AstNode *> &properties)
879 {
880     if (property->IsTSInterfaceBody()) {
881         return CheckClassElementInterfaceBody(property, properties);
882     }
883 
884     return ParserImpl::CheckClassElement(property, ctor, properties);
885 }
886 
887 // NOLINTNEXTLINE(google-default-arguments)
ParseClassDefinition(ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)888 ir::ClassDefinition *TypedParser::ParseClassDefinition(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags)
889 {
890     Lexer()->NextToken();
891 
892     ir::Identifier *identNode = ParseClassIdent(modifiers);
893 
894     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
895     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
896         auto options = TypeAnnotationParsingOptions::THROW_ERROR;
897         typeParamDecl = ParseTypeParameterDeclaration(&options);
898     }
899 
900     varbinder::PrivateBinding privateBinding(Allocator(), ClassId()++);
901 
902     // Parse SuperClass
903     auto [superClass, superTypeParams] = ParseSuperClass();
904 
905     if (superClass != nullptr) {
906         modifiers |= ir::ClassDefinitionModifiers::HAS_SUPER;
907     }
908 
909     // Parse implements clause
910     ArenaVector<ir::TSClassImplements *> implements(Allocator()->Adapter());
911     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_IMPLEMENTS) {
912         Lexer()->NextToken();
913         implements = ParseClassImplementClause();
914     }
915 
916     ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE, false);
917 
918     // Parse ClassBody
919     auto [ctor, properties, bodyRange] = ParseClassBody(modifiers, flags);
920 
921     if (InAmbientContext()) {
922         flags |= ir::ModifierFlags::DECLARE;
923     }
924 
925     auto *classDefinition = AllocNode<ir::ClassDefinition>(
926         privateBinding.View(), identNode, typeParamDecl, superTypeParams, std::move(implements), ctor, superClass,
927         std::move(properties), modifiers, flags, GetContext().GetLanguage());
928 
929     classDefinition->SetRange(bodyRange);
930 
931     return classDefinition;
932 }
933 
ParseProperty(const ArenaVector<ir::AstNode * > & properties,ClassElementDescriptor & desc,ir::Expression * propName)934 ir::AstNode *TypedParser::ParseProperty(const ArenaVector<ir::AstNode *> &properties, ClassElementDescriptor &desc,
935                                         ir::Expression *propName)
936 {
937     ir::AstNode *property = nullptr;
938     ir::TypeNode *typeAnnotation = ParseClassKeyAnnotation();
939 
940     if (desc.isIndexSignature) {
941         if (!desc.decorators.empty()) {
942             ThrowSyntaxError("Decorators are not valid here.", desc.decorators.front()->Start());
943         }
944 
945         ValidateIndexSignatureTypeAnnotation(typeAnnotation);
946 
947         if (typeAnnotation == nullptr) {
948             ThrowSyntaxError("An index signature must have a type annotation");
949         }
950 
951         if ((desc.modifiers & ir::ModifierFlags::DECLARE) != 0) {
952             ThrowSyntaxError("'declare' modifier cannot appear on an index signature.");
953         }
954 
955         property =
956             AllocNode<ir::TSIndexSignature>(propName, typeAnnotation, desc.modifiers & ir::ModifierFlags::READONLY);
957 
958         property->SetRange({property->AsTSIndexSignature()->Param()->Start(),
959                             property->AsTSIndexSignature()->TypeAnnotation()->End()});
960     } else {
961         ValidateClassMethodStart(&desc, typeAnnotation);
962         property = ParseClassProperty(&desc, properties, propName, typeAnnotation);
963 
964         if (!desc.decorators.empty()) {
965             if (desc.isPrivateIdent) {
966                 ThrowSyntaxError("Decorators are not valid here");
967             }
968 
969             property->AddDecorators(std::move(desc.decorators));
970         }
971     }
972 
973     ASSERT(property != nullptr);
974     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
975         Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
976         ((Lexer()->GetToken().Flags() & lexer::TokenFlags::NEW_LINE) == 0) &&
977         !(property->IsMethodDefinition() &&
978           property->AsMethodDefinition()->Value()->AsFunctionExpression()->Function()->Body() != nullptr)) {
979         ThrowSyntaxError("';' expected.");
980     }
981 
982     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
983         Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
984     }
985 
986     GetContext().Status() &= ~ParserStatus::ALLOW_THIS_TYPE;
987 
988     if (desc.isPrivateIdent) {
989         AddPrivateElement(property->AsClassElement());
990     }
991 
992     return property;
993 }
994 
ParseClassElement(const ArenaVector<ir::AstNode * > & properties,ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)995 ir::AstNode *TypedParser::ParseClassElement(const ArenaVector<ir::AstNode *> &properties,
996                                             ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags)
997 {
998     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STATIC &&
999         Lexer()->Lookahead() == lexer::LEX_CHAR_LEFT_BRACE) {
1000         return ParseClassStaticBlock();
1001     }
1002 
1003     ClassElementDescriptor desc(Allocator());
1004 
1005     desc.methodKind = ir::MethodDefinitionKind::METHOD;
1006     desc.newStatus = ParserStatus::ALLOW_SUPER;
1007     desc.hasSuperClass = (modifiers & ir::ClassDefinitionModifiers::HAS_SUPER) != 0;
1008     desc.propStart = Lexer()->GetToken().Start();
1009 
1010     ParseDecorators(desc.decorators);
1011 
1012     desc.modifiers = ParseModifiers();
1013 
1014     if (((desc.modifiers & ir::ModifierFlags::ABSTRACT) != 0) && ((flags & ir::ModifierFlags::ABSTRACT) == 0)) {
1015         ThrowSyntaxError("Abstract methods can only appear within an abstract class.");
1016     }
1017 
1018     char32_t nextCp = Lexer()->Lookahead();
1019     CheckClassGeneratorMethod(&desc, &nextCp);
1020     ParseClassAccessor(&desc, &nextCp);
1021 
1022     if ((desc.modifiers & ir::ModifierFlags::STATIC) == 0) {
1023         GetContext().Status() |= ParserStatus::ALLOW_THIS_TYPE;
1024     }
1025 
1026     ir::Expression *propName = ParseClassKey(&desc);
1027 
1028     if (desc.methodKind == ir::MethodDefinitionKind::CONSTRUCTOR && !desc.decorators.empty()) {
1029         ThrowSyntaxError("Decorators are not valid here.", desc.decorators.front()->Start());
1030     }
1031 
1032     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
1033         ParseOptionalClassElement(&desc);
1034     } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) {
1035         if (desc.isIndexSignature || Lexer()->Lookahead() != lexer::LEX_CHAR_COLON) {
1036             ThrowSyntaxError("';' expected");
1037         }
1038 
1039         desc.modifiers |= ir::ModifierFlags::DEFINITE;
1040         Lexer()->NextToken();
1041     }
1042 
1043     return ParseProperty(properties, desc, propName);
1044 }
1045 
ParseOptionalClassElement(ClassElementDescriptor * desc)1046 void TypedParser::ParseOptionalClassElement(ClassElementDescriptor *desc)
1047 {
1048     if (desc->isIndexSignature) {
1049         ThrowSyntaxError("';' expected");
1050     }
1051 
1052     if (desc->methodKind == ir::MethodDefinitionKind::CONSTRUCTOR) {
1053         ThrowSyntaxError("'(' expected");
1054     }
1055 
1056     desc->modifiers |= ir::ModifierFlags::OPTIONAL;
1057     Lexer()->NextToken();
1058 }
1059 
ParseActualNextStatus(lexer::TokenType keywordType)1060 static std::pair<ir::ModifierFlags, ir::ModifierFlags> ParseActualNextStatus(lexer::TokenType keywordType)
1061 {
1062     constexpr auto ASYNC_STATIC_READONLY =
1063         ir::ModifierFlags::ASYNC | ir::ModifierFlags::STATIC | ir::ModifierFlags::READONLY;
1064     constexpr auto ASYNC_STATIC_READONLY_DECLARE_ABSTRACT =
1065         ASYNC_STATIC_READONLY | ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT;
1066 
1067     switch (keywordType) {
1068         case lexer::TokenType::KEYW_PUBLIC:
1069             return {ir::ModifierFlags::PUBLIC, ASYNC_STATIC_READONLY_DECLARE_ABSTRACT};
1070         case lexer::TokenType::KEYW_PRIVATE:
1071             return {ir::ModifierFlags::PRIVATE, ASYNC_STATIC_READONLY_DECLARE_ABSTRACT};
1072         case lexer::TokenType::KEYW_PROTECTED:
1073             return {ir::ModifierFlags::PROTECTED, ASYNC_STATIC_READONLY_DECLARE_ABSTRACT};
1074         case lexer::TokenType::KEYW_INTERNAL:
1075             return {ir::ModifierFlags::INTERNAL, ASYNC_STATIC_READONLY_DECLARE_ABSTRACT | ir::ModifierFlags::PROTECTED};
1076         case lexer::TokenType::KEYW_STATIC:
1077             return {ir::ModifierFlags::STATIC, ir::ModifierFlags::ASYNC | ir::ModifierFlags::READONLY |
1078                                                    ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT};
1079         case lexer::TokenType::KEYW_ASYNC:
1080             return {ir::ModifierFlags::ASYNC,
1081                     ir::ModifierFlags::READONLY | ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT};
1082         case lexer::TokenType::KEYW_ABSTRACT:
1083             return {ir::ModifierFlags::ABSTRACT,
1084                     ASYNC_STATIC_READONLY | ir::ModifierFlags::ACCESS | ir::ModifierFlags::DECLARE};
1085         case lexer::TokenType::KEYW_DECLARE:
1086             return {ir::ModifierFlags::DECLARE, ASYNC_STATIC_READONLY | ir::ModifierFlags::ACCESS};
1087         case lexer::TokenType::KEYW_READONLY:
1088             return {ir::ModifierFlags::READONLY,
1089                     ir::ModifierFlags::ASYNC | ir::ModifierFlags::DECLARE | ir::ModifierFlags::ABSTRACT};
1090         default:
1091             UNREACHABLE();
1092     }
1093 }
1094 
ParseModifiers()1095 ir::ModifierFlags TypedParser::ParseModifiers()
1096 {
1097     ir::ModifierFlags resultStatus = ir::ModifierFlags::NONE;
1098     ir::ModifierFlags prevStatus = ir::ModifierFlags::ALL;
1099 
1100     while (IsModifierKind(Lexer()->GetToken())) {
1101         char32_t nextCp = Lexer()->Lookahead();
1102         if (!(nextCp != lexer::LEX_CHAR_EQUALS && nextCp != lexer::LEX_CHAR_SEMICOLON &&
1103               nextCp != lexer::LEX_CHAR_COMMA && nextCp != lexer::LEX_CHAR_LEFT_PAREN)) {
1104             break;
1105         }
1106 
1107         lexer::TokenFlags tokenFlags = Lexer()->GetToken().Flags();
1108         if ((tokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) {
1109             ThrowSyntaxError("Keyword must not contain escaped characters");
1110         }
1111 
1112         auto [actualStatus, nextStatus] = ParseActualNextStatus(Lexer()->GetToken().KeywordType());
1113 
1114         nextCp = Lexer()->Lookahead();
1115         if (nextCp == lexer::LEX_CHAR_COLON || nextCp == lexer::LEX_CHAR_COMMA ||
1116             nextCp == lexer::LEX_CHAR_RIGHT_PAREN || nextCp == lexer::LEX_CHAR_QUESTION ||
1117             nextCp == lexer::LEX_CHAR_RIGHT_BRACE || nextCp == lexer::LEX_CHAR_LESS_THAN) {
1118             break;
1119         }
1120 
1121         auto pos = Lexer()->Save();
1122         Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
1123 
1124         if ((prevStatus & actualStatus) == 0) {
1125             Lexer()->Rewind(pos);
1126             ThrowSyntaxError("Unexpected modifier");
1127         }
1128 
1129         if ((resultStatus & actualStatus) != 0) {
1130             Lexer()->Rewind(pos);
1131             ThrowSyntaxError("Duplicated modifier is not allowed");
1132         }
1133 
1134         if ((GetContext().Status() & ParserStatus::CONSTRUCTOR_FUNCTION) != 0 &&
1135             (actualStatus & ~ir::ModifierFlags::ALLOWED_IN_CTOR_PARAMETER) != 0) {
1136             Lexer()->Rewind(pos);
1137             ThrowParameterModifierError(actualStatus);
1138         }
1139 
1140         resultStatus |= actualStatus;
1141         prevStatus = nextStatus;
1142     }
1143 
1144     return resultStatus;
1145 }
1146 
ParseQualifiedName(ExpressionParseFlags flags)1147 ir::Expression *TypedParser::ParseQualifiedName(ExpressionParseFlags flags)
1148 {
1149     ir::Expression *expr = nullptr;
1150 
1151     switch (Lexer()->GetToken().Type()) {
1152         case lexer::TokenType::PUNCTUATOR_FORMAT:
1153             expr = ParseIdentifierFormatPlaceholder(std::nullopt);
1154             break;
1155         case lexer::TokenType::LITERAL_IDENT:
1156             expr = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
1157             expr->SetRange(Lexer()->GetToken().Loc());
1158             Lexer()->NextToken();
1159             break;
1160         default:
1161             ThrowSyntaxError("Identifier expected");
1162             break;
1163     }
1164 
1165     expr->AsIdentifier()->SetReference();
1166 
1167     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
1168         expr = ParseQualifiedReference(expr, flags);
1169     }
1170 
1171     return expr;
1172 }
1173 
ParseLiteralIndent(ir::Expression * typeName,ExpressionParseFlags flags,const lexer::SourcePosition & startLoc)1174 ir::Expression *TypedParser::ParseLiteralIndent(ir::Expression *typeName, ExpressionParseFlags flags,
1175                                                 const lexer::SourcePosition &startLoc)
1176 {
1177     if ((flags & ExpressionParseFlags::POTENTIAL_CLASS_LITERAL) != 0) {
1178         if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS) {
1179             typeName->SetRange({startLoc, Lexer()->GetToken().End()});
1180             return typeName;
1181         }
1182         if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_THIS) {
1183             return static_cast<ir::Expression *>(nullptr);
1184         }
1185     }
1186 
1187     ThrowSyntaxError("Identifier expected");
1188 }
1189 
ParseQualifiedReference(ir::Expression * typeName,ExpressionParseFlags flags)1190 ir::Expression *TypedParser::ParseQualifiedReference(ir::Expression *typeName, ExpressionParseFlags flags)
1191 {
1192     lexer::SourcePosition startLoc = typeName->Start();
1193 
1194     do {
1195         Lexer()->NextToken();  // eat '.'
1196 
1197         ir::Identifier *propName {};
1198         if ((flags & ExpressionParseFlags::IMPORT) != 0 &&
1199             Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
1200             Lexer()->NextToken();  // eat '*'
1201             propName = AllocNode<ir::Identifier>(varbinder::VarBinder::STAR_IMPORT, Allocator());
1202         } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT) {
1203             propName = ParseIdentifierFormatPlaceholder(std::nullopt);
1204         } else if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1205             return ParseLiteralIndent(typeName, flags, startLoc);
1206         } else {
1207             propName = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
1208         }
1209 
1210         propName->SetReference();
1211         propName->SetRange(Lexer()->GetToken().Loc());
1212 
1213         typeName = AllocNode<ir::TSQualifiedName>(typeName, propName);
1214         typeName->SetRange({typeName->AsTSQualifiedName()->Left()->Start(), Lexer()->GetToken().End()});
1215 
1216         if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1217             Lexer()->NextToken();
1218         }
1219     } while (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD);
1220 
1221     typeName->SetRange({startLoc, Lexer()->GetToken().End()});
1222 
1223     return typeName;
1224 }
1225 
1226 //  Auxiliary method to reduce the size of functions.
ParseTypeParameterInstantiationImpl(TypeAnnotationParsingOptions * options)1227 ir::AstNode *TypedParser::ParseTypeParameterInstantiationImpl(TypeAnnotationParsingOptions *options)
1228 {
1229     ArenaVector<ir::TypeNode *> params(Allocator()->Adapter());
1230 
1231     while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
1232         TypeAnnotationParsingOptions tmpOptions = *options &= ~TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE;
1233         // Need to parse correctly the cases like `x: T|C<T|U>`
1234         tmpOptions &= ~TypeAnnotationParsingOptions::DISALLOW_UNION;
1235         ir::TypeNode *currentParam = ParseTypeAnnotation(&tmpOptions);
1236 
1237         if (currentParam == nullptr) {
1238             return nullptr;
1239         }
1240 
1241         params.push_back(currentParam);
1242 
1243         switch (Lexer()->GetToken().Type()) {
1244             case lexer::TokenType::PUNCTUATOR_COMMA: {
1245                 Lexer()->NextToken();
1246                 continue;
1247             }
1248             case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: {
1249                 Lexer()->BackwardToken(lexer::TokenType::PUNCTUATOR_GREATER_THAN, 1);
1250                 break;
1251             }
1252             case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: {
1253                 Lexer()->BackwardToken(lexer::TokenType::PUNCTUATOR_GREATER_THAN, 2U);
1254                 break;
1255             }
1256             case lexer::TokenType::PUNCTUATOR_GREATER_THAN: {
1257                 break;
1258             }
1259             default: {
1260                 return nullptr;
1261             }
1262         }
1263     }
1264 
1265     return AllocNode<ir::TSTypeParameterInstantiation>(std::move(params));
1266 }
1267 
ParseTypeParameterInstantiation(TypeAnnotationParsingOptions * options)1268 ir::TSTypeParameterInstantiation *TypedParser::ParseTypeParameterInstantiation(TypeAnnotationParsingOptions *options)
1269 {
1270     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN);
1271 
1272     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
1273     Lexer()->NextToken();  // eat '<'
1274 
1275     ir::AstNode *typeParamInst;
1276     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
1277         Lexer()->Lookahead() == static_cast<char32_t>(EXPRESSION_FORMAT_NODE)) {
1278         typeParamInst = ParseTypeParametersFormatPlaceholder();
1279     } else {
1280         typeParamInst = ParseTypeParameterInstantiationImpl(options);
1281     }
1282 
1283     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_GREATER_THAN) {
1284         if ((*options & TypeAnnotationParsingOptions::THROW_ERROR) == 0) {
1285             return nullptr;
1286         }
1287         ThrowSyntaxError("Expected closing '>'.");
1288     }
1289 
1290     lexer::SourcePosition endLoc = Lexer()->GetToken().End();
1291     Lexer()->NextToken();  // eat '>'
1292 
1293     if (typeParamInst != nullptr) {
1294         typeParamInst->SetRange({startLoc, endLoc});
1295         return typeParamInst->AsTSTypeParameterInstantiation();
1296     }
1297 
1298     return nullptr;
1299 }
1300 
ParseDeclareAndDecorators(StatementParsingFlags flags)1301 ir::Statement *TypedParser::ParseDeclareAndDecorators(StatementParsingFlags flags)
1302 {
1303     ArenaVector<ir::Decorator *> decorators(Allocator()->Adapter());
1304 
1305     ParseDecorators(decorators);
1306 
1307     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) {
1308         CheckDeclare();
1309     }
1310 
1311     ir::Statement *stmt = TypedParser::ParseStatement(flags);
1312 
1313     GetContext().Status() &= ~ParserStatus::IN_AMBIENT_CONTEXT;
1314     AddDecorators(stmt, decorators);
1315 
1316     return stmt;
1317 }
1318 
ConvertThisKeywordToIdentIfNecessary()1319 void TypedParser::ConvertThisKeywordToIdentIfNecessary()
1320 {
1321     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_THIS) {
1322         Lexer()->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
1323     }
1324 }
1325 
ParseVariableDeclarator(ir::Expression * init,lexer::SourcePosition startLoc,VariableParsingFlags flags)1326 ir::VariableDeclarator *TypedParser::ParseVariableDeclarator(ir::Expression *init, lexer::SourcePosition startLoc,
1327                                                              VariableParsingFlags flags)
1328 {
1329     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
1330         return ParseVariableDeclaratorInitializer(init, flags, startLoc);
1331     }
1332 
1333     if (((flags & VariableParsingFlags::CONST) != 0) && ((flags & VariableParsingFlags::ACCEPT_CONST_NO_INIT) == 0) &&
1334         !InAmbientContext()) {
1335         ThrowSyntaxError("Missing initializer in const declaration");
1336     }
1337 
1338     if (((flags & VariableParsingFlags::IN_FOR) == 0) && (init->IsArrayPattern() || init->IsObjectPattern())) {
1339         ThrowSyntaxError("Missing initializer in destructuring declaration");
1340     }
1341 
1342     lexer::SourcePosition endLoc = init->End();
1343     auto declarator = AllocNode<ir::VariableDeclarator>(GetFlag(flags), init);
1344     declarator->SetRange({startLoc, endLoc});
1345 
1346     return declarator;
1347 }
1348 
ParsePotentialOptionalFunctionParameter(ir::AnnotatedExpression * returnNode)1349 void TypedParser::ParsePotentialOptionalFunctionParameter(ir::AnnotatedExpression *returnNode)
1350 {
1351     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
1352         ASSERT(returnNode->IsIdentifier() || returnNode->IsObjectPattern() || returnNode->IsArrayPattern() ||
1353                returnNode->IsRestElement());
1354 
1355         switch (returnNode->Type()) {
1356             case ir::AstNodeType::IDENTIFIER: {
1357                 returnNode->AsIdentifier()->SetOptional(true);
1358                 break;
1359             }
1360             case ir::AstNodeType::OBJECT_PATTERN: {
1361                 returnNode->AsObjectPattern()->SetOptional(true);
1362                 break;
1363             }
1364             case ir::AstNodeType::ARRAY_PATTERN: {
1365                 returnNode->AsArrayPattern()->SetOptional(true);
1366                 break;
1367             }
1368             case ir::AstNodeType::REST_ELEMENT: {
1369                 returnNode->AsRestElement()->SetOptional(true);
1370                 break;
1371             }
1372             default: {
1373                 UNREACHABLE();
1374             }
1375         }
1376 
1377         Lexer()->NextToken();  // eat '?'
1378     }
1379 
1380     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1381         Lexer()->NextToken();  // eat ':'
1382         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1383         returnNode->SetTsTypeAnnotation(ParseTypeAnnotation(&options));
1384     }
1385 }
1386 
ValidateArrowParameterAssignment(ir::AssignmentExpression * assignmentExpr)1387 ParserStatus TypedParser::ValidateArrowParameterAssignment(ir::AssignmentExpression *assignmentExpr)
1388 {
1389     if (assignmentExpr->Right()->IsYieldExpression()) {
1390         ThrowSyntaxError("yield is not allowed in arrow function parameters");
1391     }
1392 
1393     if (assignmentExpr->Right()->IsAwaitExpression()) {
1394         ThrowSyntaxError("await is not allowed in arrow function parameters");
1395     }
1396 
1397     if (!assignmentExpr->ConvertibleToAssignmentPattern()) {
1398         ThrowSyntaxError("Invalid destructuring assignment target");
1399     }
1400 
1401     if (assignmentExpr->Left()->IsIdentifier() && assignmentExpr->Left()->AsIdentifier()->IsOptional()) {
1402         ThrowSyntaxError("Parameter cannot have question mark and initializer.", assignmentExpr->Start());
1403     }
1404 
1405     ValidateArrowParameterBindings(assignmentExpr);
1406     return ParserStatus::HAS_COMPLEX_PARAM;
1407 }
1408 
ValidateArrowParameterArray(ir::ArrayExpression * arrayPattern)1409 ParserStatus TypedParser::ValidateArrowParameterArray(ir::ArrayExpression *arrayPattern)
1410 {
1411     if (!arrayPattern->ConvertibleToArrayPattern()) {
1412         ThrowSyntaxError("Invalid destructuring assignment target");
1413     }
1414 
1415     if (!InAmbientContext() && ((GetContext().Status() & ParserStatus::FUNCTION) != 0) && arrayPattern->IsOptional()) {
1416         ThrowSyntaxError("A binding pattern parameter cannot be optional in an implementation signature.",
1417                          arrayPattern->Start());
1418     }
1419 
1420     ValidateArrowParameterBindings(arrayPattern);
1421     return ParserStatus::HAS_COMPLEX_PARAM;
1422 }
1423 
ValidateArrowParameterObject(ir::ObjectExpression * objectPattern)1424 ParserStatus TypedParser::ValidateArrowParameterObject(ir::ObjectExpression *objectPattern)
1425 {
1426     if (!objectPattern->ConvertibleToObjectPattern()) {
1427         ThrowSyntaxError("Invalid destructuring assignment target");
1428     }
1429 
1430     if (!InAmbientContext() && ((GetContext().Status() & ParserStatus::FUNCTION) != 0) && objectPattern->IsOptional()) {
1431         ThrowSyntaxError("A binding pattern parameter cannot be optional in an implementation signature.",
1432                          objectPattern->Start());
1433     }
1434 
1435     ValidateArrowParameterBindings(objectPattern);
1436     return ParserStatus::HAS_COMPLEX_PARAM;
1437 }
1438 
ValidateArrowParameter(ir::Expression * expr,bool * seenOptional)1439 ParserStatus TypedParser::ValidateArrowParameter(ir::Expression *expr, bool *seenOptional)
1440 {
1441     switch (expr->Type()) {
1442         case ir::AstNodeType::SPREAD_ELEMENT: {
1443             if (!expr->AsSpreadElement()->ConvertibleToRest(true)) {
1444                 ThrowSyntaxError("Invalid rest element.");
1445             }
1446 
1447             [[fallthrough]];
1448         }
1449         case ir::AstNodeType::REST_ELEMENT: {
1450             if (expr->AsRestElement()->IsOptional()) {
1451                 ThrowSyntaxError("A rest parameter cannot be optional.", expr->Start());
1452             }
1453 
1454             ValidateArrowParameterBindings(expr->AsRestElement()->Argument());
1455             return ParserStatus::HAS_COMPLEX_PARAM;
1456         }
1457         case ir::AstNodeType::IDENTIFIER: {
1458             const util::StringView &identifier = expr->AsIdentifier()->Name();
1459             bool isOptional = expr->AsIdentifier()->IsOptional();
1460             if ((*seenOptional) && !isOptional) {
1461                 ThrowSyntaxError("A required parameter cannot follow an optional parameter.", expr->Start());
1462             }
1463 
1464             (*seenOptional) |= isOptional;
1465 
1466             if (identifier.Is("arguments")) {
1467                 ThrowSyntaxError("Binding 'arguments' in strict mode is invalid");
1468             } else if (identifier.Is("eval")) {
1469                 ThrowSyntaxError("Binding 'eval' in strict mode is invalid");
1470             }
1471 
1472             ValidateArrowParameterBindings(expr);
1473             return ParserStatus::NO_OPTS;
1474         }
1475         case ir::AstNodeType::OBJECT_EXPRESSION:
1476             return ValidateArrowParameterObject(expr->AsObjectExpression());
1477         case ir::AstNodeType::ARRAY_EXPRESSION:
1478             return ValidateArrowParameterArray(expr->AsArrayExpression());
1479         case ir::AstNodeType::ASSIGNMENT_EXPRESSION:
1480             return ValidateArrowParameterAssignment(expr->AsAssignmentExpression());
1481         default:
1482             break;
1483     }
1484     ThrowSyntaxError("Insufficient formal parameter in arrow function.");
1485     return ParserStatus::NO_OPTS;
1486 }
1487 
1488 }  // namespace ark::es2panda::parser
1489