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