• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 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 "TSparser.h"
17 
18 #include "parserFlags.h"
19 #include "util/helpers.h"
20 #include "varbinder/privateBinding.h"
21 #include "varbinder/scope.h"
22 #include "varbinder/tsBinding.h"
23 #include "lexer/TSLexer.h"
24 #include "ir/base/spreadElement.h"
25 #include "ir/base/decorator.h"
26 #include "ir/base/classElement.h"
27 #include "ir/base/classDefinition.h"
28 #include "ir/base/methodDefinition.h"
29 #include "ir/base/scriptFunction.h"
30 #include "ir/module/importDefaultSpecifier.h"
31 #include "ir/module/exportDefaultDeclaration.h"
32 #include "ir/module/exportAllDeclaration.h"
33 #include "ir/module/exportNamedDeclaration.h"
34 #include "ir/module/importDeclaration.h"
35 #include "ir/expressions/memberExpression.h"
36 #include "ir/expressions/sequenceExpression.h"
37 #include "ir/expressions/templateLiteral.h"
38 #include "ir/expressions/taggedTemplateExpression.h"
39 #include "ir/expressions/callExpression.h"
40 #include "ir/expressions/functionExpression.h"
41 #include "ir/expressions/arrowFunctionExpression.h"
42 #include "ir/expressions/yieldExpression.h"
43 #include "ir/expressions/assignmentExpression.h"
44 #include "ir/expressions/identifier.h"
45 #include "ir/expressions/objectExpression.h"
46 #include "ir/expressions/arrayExpression.h"
47 #include "ir/expressions/literals/bigIntLiteral.h"
48 #include "ir/expressions/literals/booleanLiteral.h"
49 #include "ir/expressions/literals/nullLiteral.h"
50 #include "ir/expressions/literals/numberLiteral.h"
51 #include "ir/expressions/literals/stringLiteral.h"
52 #include "ir/statements/emptyStatement.h"
53 #include "ir/statements/blockStatement.h"
54 #include "ir/statements/ifStatement.h"
55 #include "ir/statements/doWhileStatement.h"
56 #include "ir/statements/whileStatement.h"
57 #include "ir/statements/tryStatement.h"
58 #include "ir/statements/breakStatement.h"
59 #include "ir/statements/continueStatement.h"
60 #include "ir/statements/throwStatement.h"
61 #include "ir/statements/switchStatement.h"
62 #include "ir/statements/returnStatement.h"
63 #include "ir/statements/debuggerStatement.h"
64 #include "ir/statements/classDeclaration.h"
65 #include "ir/statements/labelledStatement.h"
66 #include "ir/statements/variableDeclarator.h"
67 #include "ir/statements/functionDeclaration.h"
68 #include "ir/ts/tsLiteralType.h"
69 #include "ir/ts/tsMappedType.h"
70 #include "ir/ts/tsImportType.h"
71 #include "ir/ts/tsThisType.h"
72 #include "ir/ts/tsConditionalType.h"
73 #include "ir/ts/tsTypeOperator.h"
74 #include "ir/ts/tsInferType.h"
75 #include "ir/ts/tsTupleType.h"
76 #include "ir/ts/tsNamedTupleMember.h"
77 #include "ir/ts/tsQualifiedName.h"
78 #include "ir/ts/tsIndexedAccessType.h"
79 #include "ir/ts/tsTypeQuery.h"
80 #include "ir/ts/tsTypeReference.h"
81 #include "ir/ts/tsTypePredicate.h"
82 #include "ir/ts/tsTypeLiteral.h"
83 #include "ir/ts/tsArrayType.h"
84 #include "ir/ts/tsUnionType.h"
85 #include "ir/ts/tsIntersectionType.h"
86 #include "ir/ts/tsAnyKeyword.h"
87 #include "ir/ts/tsUndefinedKeyword.h"
88 #include "ir/ts/tsVoidKeyword.h"
89 #include "ir/ts/tsNumberKeyword.h"
90 #include "ir/ts/tsStringKeyword.h"
91 #include "ir/ts/tsBooleanKeyword.h"
92 #include "ir/ts/tsBigintKeyword.h"
93 #include "ir/ts/tsUnknownKeyword.h"
94 #include "ir/ts/tsNullKeyword.h"
95 #include "ir/ts/tsNeverKeyword.h"
96 #include "ir/ts/tsObjectKeyword.h"
97 #include "ir/ts/tsFunctionType.h"
98 #include "ir/ts/tsConstructorType.h"
99 #include "ir/ts/tsParenthesizedType.h"
100 #include "ir/ts/tsTypeAssertion.h"
101 #include "ir/ts/tsAsExpression.h"
102 #include "ir/ts/tsNonNullExpression.h"
103 #include "ir/ts/tsEnumDeclaration.h"
104 #include "ir/ts/tsInterfaceDeclaration.h"
105 #include "ir/ts/tsTypeAliasDeclaration.h"
106 #include "ir/ts/tsModuleDeclaration.h"
107 #include "ir/ts/tsTypeParameterInstantiation.h"
108 #include "ir/ts/tsInterfaceHeritage.h"
109 #include "ir/base/tsSignatureDeclaration.h"
110 #include "ir/base/tsIndexSignature.h"
111 #include "ir/base/tsMethodSignature.h"
112 #include "ir/base/tsPropertySignature.h"
113 #include "ir/ts/tsParameterProperty.h"
114 #include "ir/ts/tsClassImplements.h"
115 #include "ir/ts/tsImportEqualsDeclaration.h"
116 #include "ir/ts/tsExternalModuleReference.h"
117 
118 namespace ark::es2panda::parser {
ParsePotentialAsExpression(ir::Expression * expr)119 ir::Expression *TSParser::ParsePotentialAsExpression(ir::Expression *expr)
120 {
121     if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_AS) {
122         return nullptr;
123     }
124 
125     Lexer()->NextToken();  // eat 'as'
126     TypeAnnotationParsingOptions options =
127         TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::ALLOW_CONST;
128     ir::TypeNode *typeAnnotation = ParseTypeAnnotation(&options);
129 
130     bool isConst = false;
131     if (typeAnnotation->IsTSTypeReference() && typeAnnotation->AsTSTypeReference()->TypeName()->IsIdentifier()) {
132         const util::StringView &refName = typeAnnotation->AsTSTypeReference()->TypeName()->AsIdentifier()->Name();
133         if (refName.Is("const")) {
134             isConst = true;
135         }
136     }
137 
138     lexer::SourcePosition startLoc = expr->Start();
139     auto *asExpr = AllocNode<ir::TSAsExpression>(expr, typeAnnotation, isConst);
140     asExpr->SetRange({startLoc, Lexer()->GetToken().End()});
141 
142     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
143         return ParsePotentialAsExpression(asExpr);
144     }
145 
146     return asExpr;
147 }
148 
ParsePatternElementGetReturnNode(ExpressionParseFlags & flags,bool & isOptional)149 ir::AnnotatedExpression *TSParser::ParsePatternElementGetReturnNode(ExpressionParseFlags &flags, bool &isOptional)
150 {
151     switch (Lexer()->GetToken().Type()) {
152         case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
153             ir::AnnotatedExpression *returnNode = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
154             isOptional = returnNode->AsArrayPattern()->IsOptional();
155             return returnNode;
156         }
157         case lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD: {
158             if ((flags & ExpressionParseFlags::IN_REST) != 0) {
159                 ThrowSyntaxError("Unexpected token");
160             }
161 
162             return ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN);
163         }
164         case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
165             ir::AnnotatedExpression *returnNode =
166                 ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN | ExpressionParseFlags::OBJECT_PATTERN);
167             isOptional = returnNode->AsObjectPattern()->IsOptional();
168             return returnNode;
169         }
170         case lexer::TokenType::LITERAL_IDENT: {
171             ir::AnnotatedExpression *returnNode = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
172             returnNode->AsIdentifier()->SetReference();
173 
174             if (returnNode->AsIdentifier()->Decorators().empty()) {
175                 returnNode->SetRange(Lexer()->GetToken().Loc());
176             } else {
177                 returnNode->SetRange(
178                     {returnNode->AsIdentifier()->Decorators().front()->Start(), Lexer()->GetToken().End()});
179             }
180 
181             Lexer()->NextToken();
182 
183             if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
184                 isOptional = true;
185 
186                 if ((flags & ExpressionParseFlags::IN_REST) != 0) {
187                     ThrowSyntaxError("A rest parameter cannot be optional");
188                 }
189 
190                 returnNode->AsIdentifier()->SetOptional(true);
191                 Lexer()->NextToken();
192             }
193 
194             if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
195                 Lexer()->NextToken();  // eat ':'
196                 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
197                 returnNode->SetTsTypeAnnotation(ParseTypeAnnotation(&options));
198             }
199             return returnNode;
200         }
201         default: {
202             ThrowSyntaxError("Unexpected token, expected an identifier.");
203         }
204     }
205 }
206 // NOLINTNEXTLINE(google-default-arguments)
ParsePatternElement(ExpressionParseFlags flags,bool allowDefault)207 ir::Expression *TSParser::ParsePatternElement(ExpressionParseFlags flags, bool allowDefault)
208 {
209     bool isOptional = false;
210     ir::AnnotatedExpression *returnNode = ParsePatternElementGetReturnNode(flags, isOptional);
211 
212     if ((returnNode->IsObjectPattern() || returnNode->IsArrayPattern()) && !InAmbientContext() &&
213         ((GetContext().Status() & ParserStatus::FUNCTION) != 0) && isOptional) {
214         ThrowSyntaxError("A binding pattern parameter cannot be optional in an implementation signature.");
215     }
216 
217     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
218         return returnNode;
219     }
220 
221     if ((flags & ExpressionParseFlags::IN_REST) != 0) {
222         ThrowSyntaxError("A rest parameter cannot have an initializer.");
223     }
224 
225     if (!allowDefault) {
226         ThrowSyntaxError("Invalid destructuring assignment target");
227     }
228 
229     if (isOptional) {
230         ThrowSyntaxError("Parameter cannot have question mark and initializer");
231     }
232 
233     Lexer()->NextToken();
234 
235     if (((GetContext().Status() & ParserStatus::GENERATOR_FUNCTION) != 0) &&
236         Lexer()->GetToken().Type() == lexer::TokenType::KEYW_YIELD) {
237         ThrowSyntaxError("Yield is not allowed in generator parameters");
238     }
239 
240     ir::Expression *rightNode = ParseExpression();
241 
242     auto *assignmentExpression = AllocNode<ir::AssignmentExpression>(
243         ir::AstNodeType::ASSIGNMENT_PATTERN, returnNode, rightNode, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
244     assignmentExpression->SetRange({returnNode->Start(), rightNode->End()});
245 
246     return assignmentExpression;
247 }
248 
CreateParameterProperty(ir::Expression * parameter,ir::ModifierFlags modifiers)249 ir::TSParameterProperty *TSParser::CreateParameterProperty(ir::Expression *parameter, ir::ModifierFlags modifiers)
250 {
251     auto accessibilityOption = ir::AccessibilityOption::NO_OPTS;
252     bool readonly = false;
253     bool isStatic = false;
254     bool isExport = false;
255 
256     if ((modifiers & ir::ModifierFlags::PRIVATE) != 0) {
257         accessibilityOption = ir::AccessibilityOption::PRIVATE;
258     } else if ((modifiers & ir::ModifierFlags::PUBLIC) != 0) {
259         accessibilityOption = ir::AccessibilityOption::PUBLIC;
260     } else if ((modifiers & ir::ModifierFlags::PROTECTED) != 0) {
261         accessibilityOption = ir::AccessibilityOption::PROTECTED;
262     }
263 
264     if ((modifiers & ir::ModifierFlags::READONLY) != 0) {
265         readonly = true;
266     }
267 
268     if ((modifiers & ir::ModifierFlags::STATIC) != 0) {
269         isStatic = true;
270     }
271 
272     // NOTE(Csaba Repasi): Handle export property of TSParameterProperty
273 
274     return AllocNode<ir::TSParameterProperty>(accessibilityOption, parameter, readonly, isStatic, isExport);
275 }
276 
ParseFunctionParameter()277 ir::Expression *TSParser::ParseFunctionParameter()
278 {
279     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_THIS) {
280         Lexer()->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
281     }
282 
283     lexer::SourcePosition parameterStart = Lexer()->GetToken().Start();
284     ir::ModifierFlags modifiers = ParseModifiers();
285     // NOTE(Csaba Repasi): throw error if using strick mode reserved keyword here
286     if (((GetContext().Status() & ParserStatus::CONSTRUCTOR_FUNCTION) == 0) && modifiers != ir::ModifierFlags::NONE) {
287         ThrowSyntaxError("A parameter property is only allowed in a constructor implementation.", parameterStart);
288     }
289 
290     if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
291         CheckRestrictedBinding();
292     }
293 
294     ir::Expression *functionParameter = ParsePatternElement(ExpressionParseFlags::NO_OPTS, true);
295 
296     if (modifiers != ir::ModifierFlags::NONE && functionParameter->IsRestElement()) {
297         ThrowSyntaxError("A parameter property cannot be declared using a rest parameter.", parameterStart);
298     }
299 
300     if (modifiers != ir::ModifierFlags::NONE &&
301         (functionParameter->IsArrayPattern() || functionParameter->IsObjectPattern() ||
302          (functionParameter->IsAssignmentPattern() &&
303           (functionParameter->AsAssignmentPattern()->Left()->IsArrayPattern() ||
304            functionParameter->AsAssignmentPattern()->Left()->IsObjectPattern())))) {
305         ThrowSyntaxError("A parameter property may not be declared using a binding pattern.", parameterStart);
306     }
307 
308     if (modifiers != ir::ModifierFlags::NONE) {
309         functionParameter = CreateParameterProperty(functionParameter, modifiers);
310         functionParameter->SetRange({parameterStart, functionParameter->AsTSParameterProperty()->Parameter()->End()});
311     }
312 
313     return functionParameter;
314 }
315 
ParseModuleReference()316 ir::Expression *TSParser::ParseModuleReference()
317 {
318     ir::Expression *result = nullptr;
319 
320     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_REQUIRE &&
321         Lexer()->Lookahead() == lexer::LEX_CHAR_LEFT_PAREN) {
322         lexer::SourcePosition start = Lexer()->GetToken().Start();
323         Lexer()->NextToken();  // eat 'require'
324         Lexer()->NextToken();  // eat '('
325 
326         if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
327             ThrowSyntaxError("String literal expected.");
328         }
329 
330         result = AllocNode<ir::StringLiteral>(Lexer()->GetToken().String());
331         result->SetRange(Lexer()->GetToken().Loc());
332         Lexer()->NextToken();
333 
334         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
335             ThrowSyntaxError("')' expected.");
336         }
337 
338         result = AllocNode<ir::TSExternalModuleReference>(result);
339         result->SetRange({start, Lexer()->GetToken().End()});
340         Lexer()->NextToken();  // eat ')'
341     } else {
342         result = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
343         result->SetRange(Lexer()->GetToken().Loc());
344         Lexer()->NextToken();
345 
346         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
347             result = ParseQualifiedReference(result);
348         }
349     }
350 
351     return result;
352 }
353 
ParseConstExpression()354 ir::TSTypeReference *TSParser::ParseConstExpression()
355 {
356     auto *identRef = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
357     identRef->SetReference();
358     identRef->SetRange(Lexer()->GetToken().Loc());
359 
360     auto *typeReference = AllocNode<ir::TSTypeReference>(identRef, nullptr);
361     typeReference->SetRange(Lexer()->GetToken().Loc());
362 
363     Lexer()->NextToken();
364 
365     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
366         Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
367         Lexer()->GetToken().Type() != lexer::TokenType::EOS &&
368         Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET &&
369         ((Lexer()->GetToken().Flags() & lexer::TokenFlags::NEW_LINE) == 0)) {
370         ThrowSyntaxError("Unexpected token.");
371     }
372 
373     return typeReference;
374 }
375 
ParsePotentialNonNullExpression(ir::Expression ** returnExpression,lexer::SourcePosition startLoc)376 bool TSParser::ParsePotentialNonNullExpression(ir::Expression **returnExpression, lexer::SourcePosition startLoc)
377 {
378     if (returnExpression == nullptr || Lexer()->GetToken().NewLine()) {
379         return true;
380     }
381 
382     *returnExpression = AllocNode<ir::TSNonNullExpression>(*returnExpression);
383     (*returnExpression)->SetRange({startLoc, Lexer()->GetToken().End()});
384     Lexer()->NextToken();
385     return false;
386 }
387 
388 // NOLINTNEXTLINE(google-default-arguments)
ParseObjectExpression(ExpressionParseFlags flags)389 ir::ObjectExpression *TSParser::ParseObjectExpression(ExpressionParseFlags flags)
390 {
391     ir::ObjectExpression *objExpression = ParserImpl::ParseObjectExpression(flags);
392     ParsePotentialOptionalFunctionParameter(objExpression);
393     return objExpression;
394 }
395 
396 // NOLINTNEXTLINE(google-default-arguments)
ParseArrayExpression(ExpressionParseFlags flags)397 ir::ArrayExpression *TSParser::ParseArrayExpression(ExpressionParseFlags flags)
398 {
399     ir::ArrayExpression *arrayExpression = ParserImpl::ParseArrayExpression(flags);
400     ParsePotentialOptionalFunctionParameter(arrayExpression);
401     return arrayExpression;
402 }
403 class TSParser::ParsePotentialArrowExpressionHelper {
404     friend ir::ArrowFunctionExpression *TSParser::ParsePotentialArrowExpression(ir::Expression **returnExpression,
405                                                                                 const lexer::SourcePosition &startLoc);
406 
407 private:
CreateCallExpression(TSParser * parser,lexer::Lexer * lexer,ir::Expression ** returnExpression,ir::TSTypeParameterDeclaration * typeParamDecl,const lexer::SourcePosition & startLoc)408     static ir::ArrowFunctionExpression *CreateCallExpression(TSParser *parser, lexer::Lexer *lexer,
409                                                              ir::Expression **returnExpression,
410                                                              ir::TSTypeParameterDeclaration *typeParamDecl,
411                                                              const lexer::SourcePosition &startLoc)
412     {
413         ir::CallExpression *callExpression = parser->ParseCallExpression(*returnExpression, false);
414 
415         ir::TypeNode *returnTypeAnnotation = nullptr;
416         if (lexer->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
417             lexer->NextToken();  // eat ':'
418             TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
419             returnTypeAnnotation = parser->ParseTypeAnnotation(&options);
420         }
421 
422         if (lexer->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW) {
423             ir::ArrowFunctionExpression *arrowFuncExpr =
424                 parser->ParseArrowFunctionExpression(callExpression, typeParamDecl, returnTypeAnnotation, true);
425             arrowFuncExpr->SetStart(startLoc);
426 
427             return arrowFuncExpr;
428         }
429 
430         if (returnTypeAnnotation != nullptr || typeParamDecl != nullptr) {
431             parser->ThrowSyntaxError("'=>' expected");
432         }
433 
434         *returnExpression = callExpression;
435         return nullptr;
436     }
437 };
438 
ParsePotentialArrowExpression(ir::Expression ** returnExpression,const lexer::SourcePosition & startLoc)439 ir::ArrowFunctionExpression *TSParser::ParsePotentialArrowExpression(ir::Expression **returnExpression,
440                                                                      const lexer::SourcePosition &startLoc)
441 {
442     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
443 
444     switch (Lexer()->GetToken().Type()) {
445         case lexer::TokenType::KEYW_FUNCTION: {
446             *returnExpression = ParseFunctionExpression(ParserStatus::ASYNC_FUNCTION);
447             (*returnExpression)->SetStart(startLoc);
448             break;
449         }
450         case lexer::TokenType::LITERAL_IDENT: {
451             ir::Expression *identRef = ParsePrimaryExpression();
452             ASSERT(identRef->IsIdentifier());
453 
454             if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
455                 ThrowSyntaxError("Unexpected token, expected '=>'");
456             }
457 
458             ir::ArrowFunctionExpression *arrowFuncExpr = ParseArrowFunctionExpression(identRef, nullptr, nullptr, true);
459             arrowFuncExpr->SetStart(startLoc);
460 
461             return arrowFuncExpr;
462         }
463         case lexer::TokenType::PUNCTUATOR_ARROW: {
464             ir::ArrowFunctionExpression *arrowFuncExpr =
465                 ParseArrowFunctionExpression(*returnExpression, nullptr, nullptr, true);
466             arrowFuncExpr->SetStart(startLoc);
467             return arrowFuncExpr;
468         }
469         case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
470             const auto savedPos = Lexer()->Save();
471 
472             auto options = TypeAnnotationParsingOptions::NO_OPTS;
473             typeParamDecl = ParseTypeParameterDeclaration(&options);
474             if (typeParamDecl == nullptr) {
475                 Lexer()->Rewind(savedPos);
476                 return nullptr;
477             }
478 
479             if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
480                 ThrowSyntaxError("'(' expected");
481             }
482 
483             [[fallthrough]];
484         }
485         case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
486             return ParsePotentialArrowExpressionHelper::CreateCallExpression(this, Lexer(), returnExpression,
487                                                                              typeParamDecl, startLoc);
488         }
489         default: {
490             break;
491         }
492     }
493 
494     return nullptr;
495 }
496 
ParseVariableDeclaratorKey(VariableParsingFlags flags)497 ir::AnnotatedExpression *TSParser::ParseVariableDeclaratorKey(VariableParsingFlags flags)
498 {
499     ir::AnnotatedExpression *init = ParserImpl::ParseVariableDeclaratorKey(flags);
500 
501     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
502         Lexer()->NextToken();  // eat ':'
503         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
504         init->SetTsTypeAnnotation(ParseTypeAnnotation(&options));
505     }
506 
507     return init;
508 }
509 
ParseOptionalFunctionParameter(ir::AnnotatedExpression * returnNode,bool isRest)510 void TSParser::ParseOptionalFunctionParameter(ir::AnnotatedExpression *returnNode, bool isRest)
511 {
512     bool isOptional = false;
513 
514     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
515         if (isRest) {
516             ThrowSyntaxError("A rest parameter cannot be optional");
517         }
518 
519         switch (returnNode->Type()) {
520             case ir::AstNodeType::IDENTIFIER: {
521                 returnNode->AsIdentifier()->SetOptional(true);
522                 break;
523             }
524             case ir::AstNodeType::OBJECT_PATTERN:
525             case ir::AstNodeType::ARRAY_PATTERN: {
526                 if (!InAmbientContext() && ((GetContext().Status() & ParserStatus::FUNCTION) != 0)) {
527                     ThrowSyntaxError("A binding pattern parameter cannot be optional in an implementation signature.");
528                 }
529 
530                 if (returnNode->IsObjectPattern()) {
531                     returnNode->AsObjectPattern()->SetOptional(true);
532                     break;
533                 }
534 
535                 returnNode->AsArrayPattern()->SetOptional(true);
536                 break;
537             }
538             case ir::AstNodeType::REST_ELEMENT: {
539                 returnNode->AsRestElement()->SetOptional(true);
540                 break;
541             }
542             default: {
543                 UNREACHABLE();
544             }
545         }
546 
547         isOptional = true;
548         Lexer()->NextToken();  // eat '?'
549     }
550 
551     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
552         Lexer()->NextToken();  // eat ':'
553         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
554         returnNode->SetTsTypeAnnotation(ParseTypeAnnotation(&options));
555     }
556 
557     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
558         return;
559     }
560 
561     if (isRest) {
562         ThrowSyntaxError("A rest parameter cannot have an initializer");
563     }
564 
565     if (returnNode->IsIdentifier() && isOptional) {
566         ThrowSyntaxError("Parameter cannot have question mark and initializer");
567     }
568 }
569 
ValidateArrowFunctionRestParameter(ir::SpreadElement * restElement)570 void TSParser::ValidateArrowFunctionRestParameter(ir::SpreadElement *restElement)
571 {
572     ParseOptionalFunctionParameter(restElement, true);
573 
574     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
575         ThrowSyntaxError("')' expected");
576     }
577 }
578 
ParseArrowFunctionRestParameter(lexer::SourcePosition start)579 ir::Expression *TSParser::ParseArrowFunctionRestParameter(lexer::SourcePosition start)
580 {
581     ir::SpreadElement *restElement = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN);
582 
583     restElement->SetGrouped();
584     restElement->SetStart(start);
585 
586     ValidateArrowFunctionRestParameter(restElement);
587 
588     Lexer()->NextToken();
589 
590     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
591     ir::TypeNode *returnTypeAnnotation = nullptr;
592     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
593         Lexer()->NextToken();  // eat ':'
594         returnTypeAnnotation = ParseTypeAnnotation(&options);
595     }
596 
597     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
598         ThrowSyntaxError("Unexpected token");
599     }
600 
601     return ParseArrowFunctionExpression(restElement, nullptr, returnTypeAnnotation, false);
602 }
603 
ParseArrowFunctionNoParameter(lexer::SourcePosition start)604 ir::Expression *TSParser::ParseArrowFunctionNoParameter(lexer::SourcePosition start)
605 {
606     Lexer()->NextToken();
607 
608     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
609     ir::TypeNode *returnTypeAnnotation = nullptr;
610     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
611         Lexer()->NextToken();  // eat ':'
612         returnTypeAnnotation = ParseTypeAnnotation(&options);
613     }
614 
615     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
616         ThrowSyntaxError("Unexpected token");
617     }
618 
619     auto *arrowExpr = ParseArrowFunctionExpression(nullptr, nullptr, returnTypeAnnotation, false);
620     arrowExpr->SetStart(start);
621     arrowExpr->AsArrowFunctionExpression()->Function()->SetStart(start);
622 
623     return arrowExpr;
624 }
625 
626 // NOLINTNEXTLINE(google-default-arguments)
ParseCoverParenthesizedExpressionAndArrowParameterList(ExpressionParseFlags flags)627 ir::Expression *TSParser::ParseCoverParenthesizedExpressionAndArrowParameterList(
628     [[maybe_unused]] ExpressionParseFlags flags)
629 {
630     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
631     lexer::SourcePosition start = Lexer()->GetToken().Start();
632     Lexer()->NextToken();
633     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
634 
635     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
636         return ParseArrowFunctionRestParameter(start);
637     }
638 
639     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
640         return ParseArrowFunctionNoParameter(start);
641     }
642 
643     ir::Expression *expr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::ACCEPT_REST |
644                                            ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
645 
646     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
647         ThrowSyntaxError("Unexpected token, expected ')'");
648     }
649 
650     expr->SetGrouped();
651     expr->SetRange({start, Lexer()->GetToken().End()});
652     Lexer()->NextToken();
653 
654     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
655         auto savedPos = Lexer()->Save();
656         Lexer()->NextToken();  // eat ':'
657         options = TypeAnnotationParsingOptions::NO_OPTS;
658         ir::TypeNode *returnTypeAnnotation = ParseTypeAnnotation(&options);
659 
660         if (returnTypeAnnotation == nullptr) {
661             Lexer()->Rewind(savedPos);
662             return expr;
663         }
664 
665         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
666             Lexer()->Rewind(savedPos);
667             return expr;
668         }
669 
670         return ParseArrowFunctionExpression(expr, nullptr, returnTypeAnnotation, false);
671     }
672 
673     return expr;
674 }
675 
676 }  // namespace ark::es2panda::parser