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