• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2025 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 "ETSparser.h"
17 
18 #include "generated/tokenType.h"
19 #include "lexer/lexer.h"
20 #include "ir/expressions/literals/undefinedLiteral.h"
21 #include "ir/ets/etsTuple.h"
22 #include "macros.h"
23 #include "parserFlags.h"
24 #include "util/errorRecovery.h"
25 #include "generated/diagnostic.h"
26 #include "parserImpl.h"
27 #include "util/recursiveGuard.h"
28 
29 namespace ark::es2panda::parser {
30 class FunctionContext;
31 
32 using namespace std::literals::string_literals;
33 
GetArgumentsSourceView(lexer::Lexer * lexer,const util::StringView::Iterator & lexerPos)34 static std::string GetArgumentsSourceView(lexer::Lexer *lexer, const util::StringView::Iterator &lexerPos)
35 {
36     std::string value = lexer->SourceView(lexerPos.Index(), lexer->Save().Iterator().Index()).Mutf8();
37     while (!value.empty() && value.back() == ' ') {
38         value.pop_back();
39     }
40 
41     if (!value.empty() && (value.back() == ')' || value.back() == ',')) {
42         value.pop_back();
43     }
44 
45     return value;
46 }
47 
ParseFunctionParameterExpression(ir::AnnotatedExpression * const paramIdent,bool isOptional)48 ir::Expression *ETSParser::ParseFunctionParameterExpression(ir::AnnotatedExpression *const paramIdent, bool isOptional)
49 {
50     ir::ETSParameterExpression *paramExpression;
51     ES2PANDA_ASSERT(paramIdent != nullptr);
52     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
53         auto const lexerPos = Lexer()->Save().Iterator();
54         Lexer()->NextToken();  // eat '='
55 
56         if (paramIdent->IsRestElement()) {
57             LogError(diagnostic::NO_DEFAULT_FOR_REST);
58         }
59 
60         if ((GetContext().Status() & ParserStatus::ALLOW_DEFAULT_VALUE) != 0) {
61             LogError(diagnostic::DEFAULT_ONLY_FOR_OPTIONAL);
62         }
63 
64         if (isOptional) {
65             LogError(diagnostic::DEFAULT_UNDEF_NOT_ALLOWED);
66         }
67         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS ||
68             Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
69             LogError(diagnostic::VALUE_IS_NOT_SET);
70         }
71 
72         auto defaultValue = ParseExpression();
73         if (!paramIdent->IsIdentifier()) {
74             LogError(diagnostic::IDENTIFIER_EXPECTED);
75             return nullptr;
76         }
77 
78         paramExpression = AllocNode<ir::ETSParameterExpression>(paramIdent->AsIdentifier(), defaultValue, Allocator());
79         ES2PANDA_ASSERT(paramExpression != nullptr);
80 
81         std::string value = GetArgumentsSourceView(Lexer(), lexerPos);
82         paramExpression->SetLexerSaved(util::UString(value, Allocator()).View());
83         paramExpression->SetRange({paramIdent->Start(), paramExpression->Initializer()->End()});
84     } else if (paramIdent->IsIdentifier()) {
85         paramExpression = AllocNode<ir::ETSParameterExpression>(paramIdent->AsIdentifier(), isOptional, Allocator());
86         ES2PANDA_ASSERT(paramExpression != nullptr);
87         paramExpression->SetRange({paramIdent->Start(), paramIdent->End()});
88     } else {
89         paramExpression = AllocNode<ir::ETSParameterExpression>(paramIdent->AsRestElement(), false, Allocator());
90         ES2PANDA_ASSERT(paramExpression != nullptr);
91         paramExpression->SetRange({paramIdent->Start(), paramIdent->End()});
92     }
93     return paramExpression;
94 }
95 
ResolveArgumentUnaryExpr(ExpressionParseFlags flags)96 ir::Expression *ETSParser::ResolveArgumentUnaryExpr(ExpressionParseFlags flags)
97 {
98     switch (Lexer()->GetToken().Type()) {
99         case lexer::TokenType::PUNCTUATOR_PLUS:
100         case lexer::TokenType::PUNCTUATOR_MINUS:
101         case lexer::TokenType::PUNCTUATOR_TILDE:
102         case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK:
103         case lexer::TokenType::PUNCTUATOR_PLUS_PLUS:
104         case lexer::TokenType::PUNCTUATOR_MINUS_MINUS:
105         case lexer::TokenType::KEYW_TYPEOF: {
106             return ParseUnaryOrPrefixUpdateExpression();
107         }
108         default: {
109             return ParseLeftHandSideExpression(flags);
110         }
111     }
112 }
113 
CreateUnaryExpressionFromArgument(ir::Expression * argument,lexer::TokenType operatorType,char32_t beginningChar)114 ir::Expression *ETSParser::CreateUnaryExpressionFromArgument(ir::Expression *argument, lexer::TokenType operatorType,
115                                                              char32_t beginningChar)
116 {
117     ir::Expression *returnExpr = nullptr;
118     if (lexer::Token::IsUpdateToken(operatorType)) {
119         returnExpr = AllocNode<ir::UpdateExpression>(argument, operatorType, true);
120     } else if (operatorType == lexer::TokenType::KEYW_TYPEOF) {
121         returnExpr = AllocNode<ir::TypeofExpression>(argument);
122     } else if (operatorType == lexer::TokenType::PUNCTUATOR_MINUS && argument->IsNumberLiteral()) {
123         bool argBeginWithDigitOrDot = (beginningChar >= '0' && beginningChar <= '9') || (beginningChar == '.');
124         returnExpr = argBeginWithDigitOrDot ? argument : AllocNode<ir::UnaryExpression>(argument, operatorType);
125     } else {
126         returnExpr = AllocNode<ir::UnaryExpression>(argument, operatorType);
127     }
128 
129     return returnExpr;
130 }
131 
IsLeftHandSideExpression(lexer::TokenType & operatorType,lexer::NextTokenFlags & tokenFlags,lexer::TokenType keywordType)132 static bool IsLeftHandSideExpression(lexer::TokenType &operatorType, lexer::NextTokenFlags &tokenFlags,
133                                      lexer::TokenType keywordType)
134 {
135     if (operatorType == lexer::TokenType::LITERAL_IDENT && keywordType == lexer::TokenType::KEYW_TYPEOF) {
136         operatorType = lexer::TokenType::KEYW_TYPEOF;
137     }
138 
139     switch (operatorType) {
140         case lexer::TokenType::PUNCTUATOR_MINUS:
141             tokenFlags = lexer::NextTokenFlags::UNARY_MINUS;
142             [[fallthrough]];
143         case lexer::TokenType::PUNCTUATOR_PLUS_PLUS:
144         case lexer::TokenType::PUNCTUATOR_MINUS_MINUS:
145         case lexer::TokenType::PUNCTUATOR_PLUS:
146         case lexer::TokenType::PUNCTUATOR_TILDE:
147         case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK:
148         case lexer::TokenType::KEYW_TYPEOF:
149         case lexer::TokenType::KEYW_AWAIT:
150             return false;
151         default:
152             return true;
153     }
154 }
155 
156 // NOLINTNEXTLINE(google-default-arguments)
ParseUnaryOrPrefixUpdateExpression(ExpressionParseFlags flags)157 ir::Expression *ETSParser::ParseUnaryOrPrefixUpdateExpression(ExpressionParseFlags flags)
158 {
159     TrackRecursive trackRecursive(RecursiveCtx());
160     if (!trackRecursive) {
161         LogError(diagnostic::DEEP_NESTING);
162         while (Lexer()->GetToken().Type() != lexer::TokenType::EOS) {
163             Lexer()->NextToken();
164         }
165         return AllocBrokenExpression(Lexer()->GetToken().Loc());
166     }
167     auto tokenFlags = lexer::NextTokenFlags::NONE;
168     lexer::TokenType operatorType = Lexer()->GetToken().Type();
169     if (IsLeftHandSideExpression(operatorType, tokenFlags, Lexer()->GetToken().KeywordType())) {
170         return ParseLeftHandSideExpression(flags);
171     }
172 
173     char32_t beginningChar = Lexer()->Lookahead();
174     auto start = Lexer()->GetToken().Start();
175     Lexer()->NextToken(tokenFlags);
176 
177     ir::Expression *argument = ResolveArgumentUnaryExpr(flags);
178     if (operatorType == lexer::TokenType::KEYW_AWAIT) {
179         auto *awaitExpr = AllocNode<ir::AwaitExpression>(argument);
180         ES2PANDA_ASSERT(awaitExpr != nullptr);
181         awaitExpr->SetRange({start, argument->End()});
182         return awaitExpr;
183     }
184 
185     if (argument == nullptr) {
186         return nullptr;
187     }
188 
189     if (lexer::Token::IsUpdateToken(operatorType)) {
190         if (!argument->IsIdentifier() && !argument->IsMemberExpression()) {
191             LogError(diagnostic::INVALID_LEFT_IN_PREFIX);
192         }
193     }
194 
195     ir::Expression *returnExpr = CreateUnaryExpressionFromArgument(argument, operatorType, beginningChar);
196     ES2PANDA_ASSERT(returnExpr != nullptr);
197     returnExpr->SetRange({start, argument->End()});
198     return returnExpr;
199 }
200 
201 // NOLINTNEXTLINE(google-default-arguments)
ParsePropertyDefinition(ExpressionParseFlags flags)202 ir::Expression *ETSParser::ParsePropertyDefinition(ExpressionParseFlags flags)
203 {
204     ir::PropertyKind propertyKind = ir::PropertyKind::INIT;
205     ParserStatus methodStatus = ParserStatus::NO_OPTS;
206 
207     const auto startPos = Lexer()->Save();
208     Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
209     lexer::SourcePosition start = Lexer()->GetToken().Start();
210 
211     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
212         return ParseSpreadElement(flags);
213     }
214 
215     if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
216         if (ParsePropertyModifiers(flags, &propertyKind, &methodStatus)) {
217             return ParseShorthandProperty(&startPos);
218         }
219     } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
220         ParseGeneratorPropertyModifier(flags, &methodStatus);
221     }
222 
223     bool isComputed = Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET;
224     ir::Expression *key = ParsePropertyKey(flags);
225 
226     ir::Expression *value = ParsePropertyValue(&propertyKind, &methodStatus, flags);
227     ES2PANDA_ASSERT(value != nullptr);
228     lexer::SourcePosition end = value->End();
229 
230     ir::Expression *returnProperty = nullptr;
231     if (propertyKind == ir::PropertyKind::INIT) {
232         returnProperty =
233             AllocNode<ir::Property>(propertyKind, key, value, methodStatus != ParserStatus::NO_OPTS, isComputed);
234         ES2PANDA_ASSERT(returnProperty != nullptr);
235         returnProperty->SetRange({start, end});
236     } else {
237         returnProperty = AllocBrokenExpression(key->Start());
238         LogError(diagnostic::OBJECT_PATTER_CONTAIN_METHODS, {}, returnProperty->Start());
239     }
240 
241     return returnProperty;
242 }
243 
CheckNextTokenOfTypeof(const lexer::Token & token)244 bool CheckNextTokenOfTypeof(const lexer::Token &token)
245 {
246     bool pretendTypeof = token.KeywordType() == lexer::TokenType::KEYW_TYPEOF;
247     bool pretendIdent = token.IsLiteral();
248     bool pretendOperator = token.IsUpdate();
249     bool pretendUnary = token.IsUnary();
250     bool pretendPuctuator = token.IsTsParamToken(token.Type());
251     return (pretendTypeof || pretendIdent || pretendOperator || pretendUnary || pretendPuctuator);
252 }
253 
ParsePropertyKey(ExpressionParseFlags flags)254 ir::Expression *ETSParser::ParsePropertyKey([[maybe_unused]] ExpressionParseFlags flags)
255 {
256     ir::Expression *key = nullptr;
257 
258     switch (Lexer()->GetToken().Type()) {
259         case lexer::TokenType::LITERAL_IDENT: {
260             const util::StringView &ident = Lexer()->GetToken().Ident();
261             key = AllocNode<ir::Identifier>(ident, Allocator());
262             ES2PANDA_ASSERT(key != nullptr);
263             key->SetRange(Lexer()->GetToken().Loc());
264             Lexer()->NextToken();
265             return key;
266         }
267         case lexer::TokenType::LITERAL_STRING: {
268             const util::StringView &string = Lexer()->GetToken().String();
269             key = AllocNode<ir::StringLiteral>(string);
270             ES2PANDA_ASSERT(key != nullptr);
271             key->SetRange(Lexer()->GetToken().Loc());
272             Lexer()->NextToken();
273             return key;
274         }
275         case lexer::TokenType::LITERAL_NUMBER: {
276             if ((Lexer()->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) != 0) {
277                 key = AllocNode<ir::BigIntLiteral>(Lexer()->GetToken().BigInt());
278             } else {
279                 key = AllocNode<ir::NumberLiteral>(Lexer()->GetToken().GetNumber());
280             }
281             ES2PANDA_ASSERT(key != nullptr);
282             key->SetRange(Lexer()->GetToken().Loc());
283             Lexer()->NextToken();
284             return key;
285         }
286         default: {
287             const auto &rangeToken = Lexer()->GetToken().Loc();
288             LogError(diagnostic::UNEXPECTED_TOKEN);
289             Lexer()->NextToken();
290             return AllocBrokenExpression(rangeToken);
291         }
292     }
293 }
294 
295 // NOLINTNEXTLINE(google-default-arguments)
ParseDefaultPrimaryExpression(ExpressionParseFlags flags)296 ir::Expression *ETSParser::ParseDefaultPrimaryExpression(ExpressionParseFlags flags)
297 {
298     auto startLoc = Lexer()->GetToken().Start();
299     auto savedPos = Lexer()->Save();
300     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL |
301                                            TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE |
302                                            TypeAnnotationParsingOptions::DISALLOW_UNION;
303     ir::TypeNode *potentialType = ParseTypeAnnotation(&options);
304 
305     if (potentialType != nullptr) {
306         if (potentialType->IsTSArrayType()) {
307             return potentialType;
308         }
309 
310         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
311             Lexer()->NextToken();  // eat '.'
312         }
313 
314         if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS || IsStructKeyword()) {
315             Lexer()->NextToken();  // eat 'class' and 'struct'
316             auto *classLiteral = AllocNode<ir::ETSClassLiteral>(potentialType);
317             ES2PANDA_ASSERT(classLiteral != nullptr);
318             classLiteral->SetRange({startLoc, Lexer()->GetToken().End()});
319             return classLiteral;
320         }
321     }
322 
323     Lexer()->Rewind(savedPos);
324 
325     Lexer()->NextToken();
326     bool pretendArrow = Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW;
327     bool checkNextTokenOfTypeof = CheckNextTokenOfTypeof(Lexer()->GetToken());
328     Lexer()->Rewind(savedPos);
329 
330     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPEOF && checkNextTokenOfTypeof) {
331         return ParseUnaryOrPrefixUpdateExpression();
332     }
333 
334     if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
335         if (pretendArrow) {
336             return ParseArrowFunctionExpression();
337         }
338         return ParsePrimaryExpressionIdent(flags);
339     }
340 
341     const auto tokenNow = Lexer()->GetToken();
342     LogUnexpectedToken(tokenNow);
343     Lexer()->NextToken();  // eat an unexpected token
344     return AllocBrokenExpression(tokenNow.Loc());
345 }
346 
ParsePrimaryExpressionWithLiterals(ExpressionParseFlags flags)347 ir::Expression *ETSParser::ParsePrimaryExpressionWithLiterals(ExpressionParseFlags flags)
348 {
349     switch (Lexer()->GetToken().Type()) {
350         case lexer::TokenType::LITERAL_TRUE:
351         case lexer::TokenType::LITERAL_FALSE: {
352             return ParseBooleanLiteral();
353         }
354         case lexer::TokenType::LITERAL_NULL: {
355             return ParseNullLiteral();
356         }
357         case lexer::TokenType::KEYW_UNDEFINED: {
358             return ParseUndefinedLiteral();
359         }
360         case lexer::TokenType::LITERAL_NUMBER: {
361             return ParseNumberLiteral();
362         }
363         case lexer::TokenType::LITERAL_STRING: {
364             return ParseStringLiteral();
365         }
366         case lexer::TokenType::LITERAL_CHAR: {
367             return ParseCharLiteral();
368         }
369         default: {
370             return ParseDefaultPrimaryExpression(flags);
371         }
372     }
373 }
374 
375 // NOLINTNEXTLINE(google-default-arguments)
ParsePrimaryExpression(ExpressionParseFlags flags)376 ir::Expression *ETSParser::ParsePrimaryExpression(ExpressionParseFlags flags)
377 {
378     switch (Lexer()->GetToken().Type()) {
379         case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
380             return ParseCoverParenthesizedExpressionAndArrowParameterList(flags);
381         }
382         case lexer::TokenType::KEYW_THIS: {
383             return ParseThisExpression();
384         }
385         case lexer::TokenType::KEYW_SUPER: {
386             return ParseSuperExpression();
387         }
388         case lexer::TokenType::KEYW_NEW: {
389             return ParseNewExpression();
390         }
391         case lexer::TokenType::KEYW_ASYNC: {
392             return ParseAsyncExpression();
393         }
394         case lexer::TokenType::KEYW_AWAIT: {
395             return ParseAwaitExpression();
396         }
397         case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
398             return ParseArrayExpression(CarryPatternFlags(flags));
399         }
400         case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
401             return ParseObjectExpression(CarryPatternFlags(flags));
402         }
403         case lexer::TokenType::PUNCTUATOR_BACK_TICK: {
404             return ParseTemplateLiteral();
405         }
406         case lexer::TokenType::KEYW_TYPE: {
407             LogError(diagnostic::TYPE_ALIAS_ONLY_TOP_LEVEL);
408             const auto &rangeToken = Lexer()->GetToken().Loc();
409             ParseTypeAliasDeclaration();  // Try to parse type alias and drop the result.
410             return AllocBrokenExpression(rangeToken);
411         }
412         case lexer::TokenType::KEYW_FUNCTION: {
413             LogError(diagnostic::FUNC_EXPR);
414             ParseFunctionDeclaration(true, ir::ModifierFlags::NONE);
415             return AllocBrokenExpression(Lexer()->GetToken().Loc());
416         }
417         case lexer::TokenType::PUNCTUATOR_FORMAT: {
418             return ParseExpressionFormatPlaceholder();
419         }
420         case lexer::TokenType::KEYW_TYPEOF: {
421             return ParseUnaryOrPrefixUpdateExpression();
422         }
423         default: {
424             return ParsePrimaryExpressionWithLiterals(flags);
425         }
426     }
427 }
428 
IsPunctuartorSpecialCharacter(lexer::TokenType tokenType)429 bool IsPunctuartorSpecialCharacter(lexer::TokenType tokenType)
430 {
431     switch (tokenType) {
432         case lexer::TokenType::PUNCTUATOR_COLON:
433         case lexer::TokenType::PUNCTUATOR_COMMA:
434         case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT:
435         case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT:
436         case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET:
437         case lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET:
438         case lexer::TokenType::PUNCTUATOR_LESS_THAN:
439         case lexer::TokenType::PUNCTUATOR_GREATER_THAN:
440         case lexer::TokenType::PUNCTUATOR_BITWISE_OR:
441             return true;
442         default:
443             return false;
444     }
445 }
446 
447 // This function was created to reduce the size of `EatArrowFunctionParams`.
IsValidTokenTypeOfArrowFunctionStart(lexer::TokenType tokenType)448 bool TypedParser::IsValidTokenTypeOfArrowFunctionStart(lexer::TokenType tokenType)
449 {
450     return (tokenType == lexer::TokenType::LITERAL_IDENT || IsPrimitiveType(tokenType) ||
451             tokenType == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD || tokenType == lexer::TokenType::KEYW_THIS);
452 }
453 
EatArrowFunctionParams(lexer::Lexer * lexer)454 bool TypedParser::EatArrowFunctionParams(lexer::Lexer *lexer)
455 {
456     ES2PANDA_ASSERT(lexer->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
457     lexer->NextToken();
458     auto tokenType = lexer->GetToken().Type();
459 
460     size_t openBrackets = 1;
461     bool expectIdentifier = true;
462     while (tokenType != lexer::TokenType::EOS && openBrackets > 0) {
463         lexer::NextTokenFlags flag = lexer::NextTokenFlags::NONE;
464         switch (tokenType) {
465             case lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS:
466                 --openBrackets;
467                 break;
468             case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS:
469                 ++openBrackets;
470                 break;
471             case lexer::TokenType::PUNCTUATOR_COMMA:
472                 expectIdentifier = true;
473                 break;
474             // (DZ) need for correct processing of possible number literals
475             case lexer::TokenType::PUNCTUATOR_MINUS:
476                 flag = lexer::NextTokenFlags::UNARY_MINUS;
477                 break;
478             case lexer::TokenType::PUNCTUATOR_SEMI_COLON:
479             case lexer::TokenType::PUNCTUATOR_BACK_TICK:
480                 return false;
481             default:
482                 if (!expectIdentifier) {
483                     break;
484                 }
485                 if (!IsValidTokenTypeOfArrowFunctionStart(tokenType)) {
486                     return false;
487                 }
488                 expectIdentifier = false;
489         }
490         lexer->NextToken(flag);
491         tokenType = lexer->GetToken().Type();
492     }
493     return true;
494 }
495 
IsArrowFunctionExpressionStart()496 bool ETSParser::IsArrowFunctionExpressionStart()
497 {
498     auto finalizer = [this, savedPos = Lexer()->Save()]([[maybe_unused]] void *ptr) { Lexer()->Rewind(savedPos); };
499     std::unique_ptr<void, decltype(finalizer)> defer(&finalizer, finalizer);
500     if (!EatArrowFunctionParams(Lexer())) {
501         return false;
502     }
503 
504     if (Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_COLON)) {
505         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::RETURN_TYPE;
506         if (ParseTypeAnnotation(&options) == nullptr) {
507             return false;
508         }
509     }
510 
511     auto tokenType = Lexer()->GetToken().Type();
512     while (tokenType != lexer::TokenType::EOS && tokenType != lexer::TokenType::PUNCTUATOR_ARROW) {
513         if (lexer::Token::IsPunctuatorToken(tokenType) && !IsPunctuartorSpecialCharacter(tokenType)) {
514             break;
515         }
516         Lexer()->NextToken();
517         tokenType = Lexer()->GetToken().Type();
518     }
519     return Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW;
520 }
521 
ParseArrowFunctionExpression()522 ir::ArrowFunctionExpression *ETSParser::ParseArrowFunctionExpression()
523 {
524     auto newStatus = ParserStatus::ARROW_FUNCTION | ParserStatus::ALLOW_RECEIVER;
525     auto *func = ParseFunction(newStatus);
526     auto *arrowFuncNode = AllocNode<ir::ArrowFunctionExpression>(func, Allocator());
527     ES2PANDA_ASSERT(arrowFuncNode != nullptr);
528     arrowFuncNode->SetRange(func->Range());
529     return arrowFuncNode;
530 }
531 
532 // NOLINTNEXTLINE(google-default-arguments)
ParseCoverParenthesizedExpressionAndArrowParameterList(ExpressionParseFlags flags)533 ir::Expression *ETSParser::ParseCoverParenthesizedExpressionAndArrowParameterList(ExpressionParseFlags flags)
534 {
535     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
536     if (IsArrowFunctionExpressionStart()) {
537         return ParseArrowFunctionExpression();
538     }
539 
540     lexer::SourcePosition start = Lexer()->GetToken().Start();
541     Lexer()->NextToken();
542 
543     ExpressionParseFlags newFlags = ExpressionParseFlags::ACCEPT_COMMA;
544     if ((flags & ExpressionParseFlags::INSTANCEOF) != 0) {
545         newFlags |= ExpressionParseFlags::INSTANCEOF;
546     };
547 
548     ir::Expression *expr = ParseExpression(newFlags);
549 
550     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
551         LogExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
552     }
553 
554     expr->SetGrouped();
555     expr->SetRange({start, Lexer()->GetToken().End()});
556     Lexer()->NextToken();
557 
558     return expr;
559 }
560 
GetPostPrimaryExpression(ir::Expression * returnExpression,lexer::SourcePosition startLoc,bool ignoreCallExpression,bool * isChainExpression)561 std::optional<ir::Expression *> ETSParser::GetPostPrimaryExpression(ir::Expression *returnExpression,
562                                                                     lexer::SourcePosition startLoc,
563                                                                     bool ignoreCallExpression,
564                                                                     [[maybe_unused]] bool *isChainExpression)
565 {
566     switch (Lexer()->GetToken().Type()) {
567         case lexer::TokenType::PUNCTUATOR_QUESTION_DOT:
568             if (*isChainExpression) {
569                 return std::nullopt;  // terminate current chain
570             }
571             *isChainExpression = true;
572             Lexer()->NextToken();  // eat ?.
573 
574             if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
575                 return ParseElementAccess(returnExpression, true);
576             }
577 
578             if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
579                 return ParseCallExpression(returnExpression, true, false);
580             }
581 
582             return ParsePropertyAccess(returnExpression, true);
583         case lexer::TokenType::PUNCTUATOR_PERIOD:
584             Lexer()->NextToken();  // eat period
585 
586             return ParsePropertyAccess(returnExpression);
587         case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET:
588             return ParseElementAccess(returnExpression);
589         case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT:
590         case lexer::TokenType::PUNCTUATOR_LESS_THAN:
591             if (ParsePotentialGenericFunctionCall(returnExpression, &returnExpression, startLoc,
592                                                   ignoreCallExpression)) {
593                 return std::nullopt;
594             }
595 
596             return returnExpression;
597         case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS:
598             if (ignoreCallExpression) {
599                 return std::nullopt;
600             }
601             return ParseCallExpression(returnExpression, false, false);
602         case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: {
603             const bool shouldBreak = ParsePotentialNonNullExpression(&returnExpression, startLoc);
604             if (shouldBreak) {
605                 return std::nullopt;
606             }
607 
608             return returnExpression;
609         }
610         case lexer::TokenType::PUNCTUATOR_FORMAT:
611         case lexer::TokenType::PUNCTUATOR_ARROW:
612             LogUnexpectedToken(Lexer()->GetToken());
613             [[fallthrough]];
614         default:
615             return std::nullopt;
616     }
617 }
618 
ParsePostPrimaryExpression(ir::Expression * primaryExpr,lexer::SourcePosition startLoc,bool ignoreCallExpression,bool * isChainExpression)619 ir::Expression *ETSParser::ParsePostPrimaryExpression(ir::Expression *primaryExpr, lexer::SourcePosition startLoc,
620                                                       bool ignoreCallExpression,
621                                                       [[maybe_unused]] bool *isChainExpression)
622 {
623     ir::Expression *returnExpression = primaryExpr;
624 
625     while (true) {
626         auto expr = GetPostPrimaryExpression(returnExpression, startLoc, ignoreCallExpression, isChainExpression);
627         if (expr.has_value()) {
628             returnExpression = expr.value();
629             continue;
630         }
631 
632         break;
633     }
634 
635     return returnExpression;
636 }
637 
ParsePotentialAsExpression(ir::Expression * primaryExpr)638 ir::Expression *ETSParser::ParsePotentialAsExpression(ir::Expression *primaryExpr)
639 {
640     ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_AS);
641     Lexer()->NextToken();
642 
643     TypeAnnotationParsingOptions options =
644         TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::ANNOTATION_NOT_ALLOW;
645     ir::TypeNode *type = ParseTypeAnnotation(&options);
646     if (type == nullptr) {
647         // Error processing
648         // Failed to parse type annotation for AsExpression
649         return nullptr;
650     }
651 
652     auto *asExpression = AllocNode<ir::TSAsExpression>(primaryExpr, type, false);
653     ES2PANDA_ASSERT(asExpression != nullptr);
654     asExpression->SetRange(primaryExpr->Range());
655     return asExpression;
656 }
657 
658 //  Extracted from 'ParseNewExpression()' to reduce function's size
ParseArgumentsNewExpression(ArenaVector<ir::Expression * > & arguments,ir::TypeNode * typeReference)659 void ETSParser::ParseArgumentsNewExpression(ArenaVector<ir::Expression *> &arguments, ir::TypeNode *typeReference)
660 {
661     lexer::SourcePosition endLoc = typeReference->End();
662 
663     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
664         Lexer()->NextToken();
665 
666         ParseList(
667             lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS, lexer::NextTokenFlags::NONE,
668             [this, &arguments]() {
669                 ir::Expression *argument =
670                     Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD
671                         ? ParseSpreadElement(ExpressionParseFlags::POTENTIALLY_IN_PATTERN)
672                         : ParseExpression();
673 
674                 if (argument == nullptr) {
675                     return false;
676                 }
677                 arguments.push_back(argument);
678                 return true;
679             },
680             &endLoc, true);
681     }
682 }
683 
ParseNewExpression()684 ir::Expression *ETSParser::ParseNewExpression()
685 {
686     lexer::SourcePosition start = Lexer()->GetToken().Start();
687 
688     Lexer()->NextToken();  // eat new
689 
690     TypeAnnotationParsingOptions options =
691         TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE |
692         TypeAnnotationParsingOptions::ALLOW_WILDCARD | TypeAnnotationParsingOptions::POTENTIAL_NEW_ARRAY;
693     auto typeReference = ParseTypeAnnotation(&options);
694     ES2PANDA_ASSERT(typeReference != nullptr);
695 
696     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
697         Lexer()->NextToken();
698         ir::Expression *dimension = ParseExpression();
699 
700         auto endLoc = Lexer()->GetToken().End();
701         ExpectToken(lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET);
702 
703         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
704             auto *arrInstance = AllocNode<ir::ETSNewArrayInstanceExpression>(typeReference, dimension);
705             arrInstance->SetRange({start, endLoc});
706             return arrInstance;
707         }
708 
709         ArenaVector<ir::Expression *> dimensions(Allocator()->Adapter());
710         dimensions.push_back(dimension);
711 
712         do {
713             Lexer()->NextToken();
714             dimensions.push_back(ParseExpression());
715 
716             endLoc = Lexer()->GetToken().End();
717             ExpectToken(lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET);
718         } while (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
719 
720         auto *multiArray = AllocNode<ir::ETSNewMultiDimArrayInstanceExpression>(typeReference, std::move(dimensions));
721         ES2PANDA_ASSERT(multiArray != nullptr);
722         multiArray->SetRange({start, endLoc});
723         return multiArray;
724     }
725 
726     ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
727     ParseArgumentsNewExpression(arguments, typeReference);
728 
729     auto *newExprNode = AllocNode<ir::ETSNewClassInstanceExpression>(typeReference, std::move(arguments));
730     ES2PANDA_ASSERT(newExprNode != nullptr);
731     newExprNode->SetRange({start, Lexer()->GetToken().End()});
732 
733     return newExprNode;
734 }
735 
ParseAsyncExpression()736 ir::Expression *ETSParser::ParseAsyncExpression()
737 {
738     Lexer()->NextToken();  // eat 'async'
739     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION) {
740         LogError(diagnostic::FUNC_EXPR);
741         ParseFunctionDeclaration(true, ir::ModifierFlags::NONE);
742         return AllocBrokenExpression(Lexer()->GetToken().Loc());
743     }
744     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS ||
745         !IsArrowFunctionExpressionStart()) {
746         LogExpectedToken(lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
747     }
748 
749     auto newStatus = ParserStatus::NEED_RETURN_TYPE | ParserStatus::ARROW_FUNCTION | ParserStatus::ASYNC_FUNCTION;
750     auto *func = ParseFunction(newStatus);
751     if (func == nullptr) {  // Error processing.
752         return nullptr;
753     }
754     auto *arrowFuncNode = AllocNode<ir::ArrowFunctionExpression>(func, Allocator());
755     ES2PANDA_ASSERT(arrowFuncNode != nullptr);
756     arrowFuncNode->SetRange(func->Range());
757     return arrowFuncNode;
758 }
759 
ParseAwaitExpression()760 ir::Expression *ETSParser::ParseAwaitExpression()
761 {
762     lexer::SourcePosition start = Lexer()->GetToken().Start();
763     Lexer()->NextToken();
764     ir::Expression *argument = ParseExpression();
765     auto *awaitExpression = AllocNode<ir::AwaitExpression>(argument);
766     ES2PANDA_ASSERT(awaitExpression != nullptr);
767     awaitExpression->SetRange({start, Lexer()->GetToken().End()});
768     return awaitExpression;
769 }
770 
ParseArrayExpression(ExpressionParseFlags flags)771 ir::ArrayExpression *ETSParser::ParseArrayExpression(ExpressionParseFlags flags)
772 {
773     return ParserImpl::ParseArrayExpression(flags, false);
774 }
775 
ParsePotentialExpressionSequence(ir::Expression * expr,ExpressionParseFlags flags)776 ir::Expression *ETSParser::ParsePotentialExpressionSequence(ir::Expression *expr, ExpressionParseFlags flags)
777 {
778     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA &&
779         (flags & ExpressionParseFlags::ACCEPT_COMMA) != 0 && (flags & ExpressionParseFlags::IN_FOR) != 0U) {
780         return ParseSequenceExpression(expr, (flags & ExpressionParseFlags::ACCEPT_REST) != 0);
781     }
782 
783     return expr;
784 }
785 
ParsePotentialNonNullExpression(ir::Expression ** expression,const lexer::SourcePosition startLoc)786 bool ETSParser::ParsePotentialNonNullExpression(ir::Expression **expression, const lexer::SourcePosition startLoc)
787 {
788     if (expression == nullptr || Lexer()->GetToken().NewLine()) {
789         return true;
790     }
791 
792     const auto nonNullExpr = AllocNode<ir::TSNonNullExpression>(*expression);
793     ES2PANDA_ASSERT(nonNullExpr != nullptr);
794     nonNullExpr->SetRange({startLoc, Lexer()->GetToken().End()});
795 
796     *expression = nonNullExpr;
797 
798     Lexer()->NextToken();
799 
800     return false;
801 }
802 
ValidateInstanceOfExpression(ir::Expression * expr)803 void ETSParser::ValidateInstanceOfExpression(ir::Expression *expr)
804 {
805     ValidateGroupedExpression(expr);
806     lexer::TokenType tokenType = Lexer()->GetToken().Type();
807     if (tokenType == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
808         auto options = TypeAnnotationParsingOptions::NO_OPTS;
809 
810         // Run checks to validate type declarations
811         // Should provide helpful messages with incorrect declarations like the following:
812         // `instanceof A<String;`
813         ParseTypeParameterDeclaration(&options);
814 
815         // Display error message even when type declaration is correct
816         // `instanceof A<String>;`
817         LogError(diagnostic::INVALID_RIGHT_INSTANCEOF);
818     }
819 }
820 
821 // NOLINTNEXTLINE(google-default-arguments)
ParseExpression(ExpressionParseFlags flags)822 ir::Expression *ETSParser::ParseExpression(ExpressionParseFlags flags)
823 {
824     TrackRecursive trackRecursive(RecursiveCtx());
825     if (!trackRecursive) {
826         LogError(diagnostic::DEEP_NESTING);
827         while (Lexer()->GetToken().Type() != lexer::TokenType::EOS) {
828             Lexer()->NextToken();
829         }
830         return AllocBrokenExpression(Lexer()->GetToken().Loc());
831     }
832     ArenaVector<ir::AnnotationUsage *> annotations {Allocator()->Adapter()};
833     if (Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_AT)) {
834         annotations = ParseAnnotations(false);
835     }
836     auto savedPos = Lexer()->GetToken().Start();
837     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_YIELD &&
838         (flags & ExpressionParseFlags::DISALLOW_YIELD) == 0U) {
839         ir::YieldExpression *yieldExpr = ParseYieldExpression();
840 
841         return ParsePotentialExpressionSequence(yieldExpr, flags);
842     }
843 
844     ir::Expression *unaryExpressionNode = ParseUnaryOrPrefixUpdateExpression(flags);
845     if ((flags & ExpressionParseFlags::INSTANCEOF) != 0) {
846         ValidateInstanceOfExpression(unaryExpressionNode);
847     }
848 
849     ir::Expression *assignmentExpression = ParseAssignmentExpression(unaryExpressionNode, flags);
850     ApplyAnnotationsToNode(assignmentExpression, std::move(annotations), savedPos);
851 
852     if (Lexer()->GetToken().NewLine()) {
853         return assignmentExpression;
854     }
855 
856     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA &&
857         (flags & ExpressionParseFlags::ACCEPT_COMMA) != 0U && (flags & ExpressionParseFlags::IN_FOR) != 0U) {
858         return ParseSequenceExpression(assignmentExpression, (flags & ExpressionParseFlags::ACCEPT_REST) != 0U);
859     }
860 
861     return assignmentExpression;
862 }
863 
864 }  // namespace ark::es2panda::parser
865