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