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