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