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