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 "lexer/token/tokenType.h"
17#include "parser/parserFlags.h"
18#include "ir/astNode.h"
19#include "ir/base/classDefinition.h"
20#include "ir/base/decorator.h"
21#include "ir/base/metaProperty.h"
22#include "ir/base/methodDefinition.h"
23#include "ir/base/property.h"
24#include "ir/base/scriptFunction.h"
25#include "ir/base/spreadElement.h"
26#include "ir/base/templateElement.h"
27#include "ir/expression.h"
28#include "ir/expressions/arrayExpression.h"
29#include "ir/expressions/arrowFunctionExpression.h"
30#include "ir/expressions/assignmentExpression.h"
31#include "ir/expressions/awaitExpression.h"
32#include "ir/expressions/binaryExpression.h"
33#include "ir/expressions/callExpression.h"
34#include "ir/expressions/chainExpression.h"
35#include "ir/expressions/classExpression.h"
36#include "ir/expressions/conditionalExpression.h"
37#include "ir/expressions/directEvalExpression.h"
38#include "ir/expressions/functionExpression.h"
39#include "ir/expressions/identifier.h"
40#include "ir/expressions/importExpression.h"
41#include "ir/expressions/literals/bigIntLiteral.h"
42#include "ir/expressions/literals/booleanLiteral.h"
43#include "ir/expressions/literals/nullLiteral.h"
44#include "ir/expressions/literals/numberLiteral.h"
45#include "ir/expressions/literals/regExpLiteral.h"
46#include "ir/expressions/literals/charLiteral.h"
47#include "ir/expressions/literals/stringLiteral.h"
48#include "ir/expressions/literals/undefinedLiteral.h"
49#include "ir/expressions/memberExpression.h"
50#include "ir/expressions/newExpression.h"
51#include "ir/expressions/objectExpression.h"
52#include "ir/expressions/omittedExpression.h"
53#include "ir/expressions/sequenceExpression.h"
54#include "ir/expressions/superExpression.h"
55#include "ir/expressions/taggedTemplateExpression.h"
56#include "ir/expressions/templateLiteral.h"
57#include "ir/expressions/thisExpression.h"
58#include "ir/expressions/typeofExpression.h"
59#include "ir/expressions/unaryExpression.h"
60#include "ir/expressions/updateExpression.h"
61#include "ir/expressions/yieldExpression.h"
62#include "ir/statements/blockStatement.h"
63#include "ir/statements/classDeclaration.h"
64#include "ir/ts/tsAsExpression.h"
65#include "ir/ts/tsNonNullExpression.h"
66#include "ir/validationInfo.h"
67#include "lexer/lexer.h"
68#include "lexer/regexp/regexp.h"
69#include "lexer/token/letters.h"
70#include "lexer/token/sourceLocation.h"
71#include "lexer/token/token.h"
72#include "macros.h"
73
74#include <memory>
75
76#include "parser/parserStatusContext.h"
77#include "parserImpl.h"
78
79namespace ark::es2panda::parser {
80ir::YieldExpression *ParserImpl::ParseYieldExpression()
81{
82    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_YIELD);
83
84    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
85    lexer::SourcePosition endLoc = lexer_->GetToken().End();
86
87    if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0) {
88        ThrowSyntaxError("Unexpected identifier");
89    }
90
91    lexer_->NextToken();
92
93    bool isDelegate = false;
94    ir::Expression *argument = nullptr;
95
96    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY && !lexer_->GetToken().NewLine()) {
97        isDelegate = true;
98        lexer_->NextToken();
99
100        argument = ParseExpression();
101        endLoc = argument->End();
102    } else if (!lexer_->GetToken().NewLine() && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
103               lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS &&
104               lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET &&
105               lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
106               lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
107               lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON &&
108               lexer_->GetToken().Type() != lexer::TokenType::EOS) {
109        argument = ParseExpression();
110        endLoc = argument->End();
111    }
112
113    auto *yieldNode = AllocNode<ir::YieldExpression>(argument, isDelegate);
114    yieldNode->SetRange({startLoc, endLoc});
115
116    return yieldNode;
117}
118
119ir::Expression *ParserImpl::ParsePotentialExpressionSequence(ir::Expression *expr, ExpressionParseFlags flags)
120{
121    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA &&
122        (flags & ExpressionParseFlags::ACCEPT_COMMA) != 0) {
123        return ParseSequenceExpression(expr, (flags & ExpressionParseFlags::ACCEPT_REST) != 0);
124    }
125
126    return expr;
127}
128
129// NOLINTNEXTLINE(google-default-arguments)
130ir::Expression *ParserImpl::ParseExpression(ExpressionParseFlags flags)
131{
132    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_YIELD &&
133        (flags & ExpressionParseFlags::DISALLOW_YIELD) == 0U) {
134        ir::YieldExpression *yieldExpr = ParseYieldExpression();
135
136        return ParsePotentialExpressionSequence(yieldExpr, flags);
137    }
138
139    ir::Expression *unaryExpressionNode = ParseUnaryOrPrefixUpdateExpression(flags);
140    ir::Expression *assignmentExpression = ParseAssignmentExpression(unaryExpressionNode, flags);
141
142    if (lexer_->GetToken().NewLine()) {
143        return assignmentExpression;
144    }
145
146    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA &&
147        (flags & ExpressionParseFlags::ACCEPT_COMMA) != 0U) {
148        return ParseSequenceExpression(assignmentExpression, (flags & ExpressionParseFlags::ACCEPT_REST) != 0U);
149    }
150
151    return assignmentExpression;
152}
153
154// NOLINTNEXTLINE(google-default-arguments)
155ir::ArrayExpression *ParserImpl::ParseArrayExpression(ExpressionParseFlags flags)
156{
157    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
158
159    ArenaVector<ir::Expression *> elements(Allocator()->Adapter());
160
161    lexer_->NextToken();
162
163    bool trailingComma = false;
164    bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0;
165
166    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
167        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
168            auto *omitted = AllocNode<ir::OmittedExpression>();
169            omitted->SetRange(lexer_->GetToken().Loc());
170            elements.push_back(omitted);
171            lexer_->NextToken();
172            continue;
173        }
174
175        ir::Expression *element {};
176        if (inPattern) {
177            element = ParsePatternElement();
178        } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
179            element = ParseSpreadElement(ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
180        } else {
181            element = ParseExpression(ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
182        }
183
184        bool containsRest = element->IsRestElement();
185
186        elements.push_back(element);
187
188        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
189            if (containsRest) {
190                ThrowSyntaxError("Rest element must be last element", startLoc);
191            }
192
193            lexer_->NextToken();  // eat comma
194
195            if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
196                trailingComma = true;
197                break;
198            }
199
200            continue;
201        }
202
203        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
204            ThrowSyntaxError("Unexpected token, expected ',' or ']'");
205        }
206    }
207
208    auto nodeType = inPattern ? ir::AstNodeType::ARRAY_PATTERN : ir::AstNodeType::ARRAY_EXPRESSION;
209    auto *arrayExpressionNode =
210        AllocNode<ir::ArrayExpression>(nodeType, std::move(elements), Allocator(), trailingComma);
211    arrayExpressionNode->SetRange({startLoc, lexer_->GetToken().End()});
212    lexer_->NextToken();
213
214    if (inPattern) {
215        arrayExpressionNode->SetDeclaration();
216    }
217
218    ParseArrayExpressionErrorCheck(arrayExpressionNode, flags, inPattern);
219    return arrayExpressionNode;
220}
221
222void ParserImpl::ParseArrayExpressionErrorCheck(ir::ArrayExpression *arrayExpressionNode,
223                                                const ExpressionParseFlags flags, const bool inPattern)
224{
225    if ((flags & ExpressionParseFlags::POTENTIALLY_IN_PATTERN) == 0) {
226        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION &&
227            !arrayExpressionNode->ConvertibleToArrayPattern()) {
228            ThrowSyntaxError("Invalid left-hand side in array destructuring pattern", arrayExpressionNode->Start());
229        } else if (!inPattern && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
230            ir::ValidationInfo info = arrayExpressionNode->ValidateExpression();
231            if (info.Fail()) {
232                ThrowSyntaxError(info.msg.Utf8(), info.pos);
233            }
234        }
235    }
236}
237
238ParserStatus ParserImpl::ValidateArrowParameter(ir::Expression *expr, [[maybe_unused]] bool *seenOptional)
239{
240    switch (expr->Type()) {
241        case ir::AstNodeType::SPREAD_ELEMENT: {
242            if (!expr->AsSpreadElement()->ConvertibleToRest(true)) {
243                ThrowSyntaxError("Invalid rest element.");
244            }
245
246            [[fallthrough]];
247        }
248        case ir::AstNodeType::REST_ELEMENT: {
249            ValidateArrowParameterBindings(expr->AsRestElement()->Argument());
250            return ParserStatus::HAS_COMPLEX_PARAM;
251        }
252        case ir::AstNodeType::IDENTIFIER: {
253            ValidateArrowParameterBindings(expr);
254            return ParserStatus::NO_OPTS;
255        }
256        case ir::AstNodeType::OBJECT_EXPRESSION: {
257            if (ir::ObjectExpression *objectPattern = expr->AsObjectExpression();
258                !objectPattern->ConvertibleToObjectPattern()) {
259                ThrowSyntaxError("Invalid destructuring assignment target");
260            }
261
262            ValidateArrowParameterBindings(expr);
263            return ParserStatus::HAS_COMPLEX_PARAM;
264        }
265        case ir::AstNodeType::ARRAY_EXPRESSION: {
266            if (ir::ArrayExpression *arrayPattern = expr->AsArrayExpression();
267                !arrayPattern->ConvertibleToArrayPattern()) {
268                ThrowSyntaxError("Invalid destructuring assignment target");
269            }
270
271            ValidateArrowParameterBindings(expr);
272            return ParserStatus::HAS_COMPLEX_PARAM;
273        }
274        case ir::AstNodeType::ASSIGNMENT_EXPRESSION: {
275            ValidateArrowParameterAssignment(expr->AsAssignmentExpression());
276            ValidateArrowParameterBindings(expr);
277            return ParserStatus::HAS_COMPLEX_PARAM;
278        }
279        default: {
280            break;
281        }
282    }
283    ThrowSyntaxError("Insufficient formal parameter in arrow function.");
284    return ParserStatus::NO_OPTS;
285}
286
287void ParserImpl::ValidateArrowParameterAssignment(ir::AssignmentExpression *expr)
288{
289    if (expr->Right()->IsYieldExpression()) {
290        ThrowSyntaxError("yield is not allowed in arrow function parameters");
291    } else if (expr->Right()->IsAwaitExpression()) {
292        ThrowSyntaxError("await is not allowed in arrow function parameters");
293    } else if (!expr->ConvertibleToAssignmentPattern()) {
294        ThrowSyntaxError("Invalid destructuring assignment target");
295    }
296}
297
298ir::ArrowFunctionExpression *ParserImpl::ParseArrowFunctionExpressionBody(ArrowFunctionContext *arrowFunctionContext,
299                                                                          ArrowFunctionDescriptor *desc,
300                                                                          ir::TSTypeParameterDeclaration *typeParamDecl,
301                                                                          ir::TypeNode *returnTypeAnnotation)
302{
303    context_.Status() |= desc->newStatus;
304
305    lexer_->NextToken();  // eat '=>'
306    ir::ScriptFunction *funcNode {};
307
308    ir::AstNode *body = nullptr;
309    lexer::SourcePosition endLoc;
310    lexer::SourcePosition bodyStart = lexer_->GetToken().Start();
311
312    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
313        body = ParseExpression();
314        endLoc = body->AsExpression()->End();
315        arrowFunctionContext->AddFlag(ir::ScriptFunctionFlags::EXPRESSION);
316    } else {
317        lexer_->NextToken();
318        auto statements = ParseStatementList();
319        body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
320        body->SetRange({bodyStart, lexer_->GetToken().End()});
321
322        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
323            ThrowSyntaxError("Expected a '}'");
324        }
325
326        lexer_->NextToken();
327        endLoc = body->End();
328    }
329
330    // clang-format off
331    funcNode = AllocNode<ir::ScriptFunction>(
332        Allocator(), ir::ScriptFunction::ScriptFunctionData {
333                        body,
334                        ir::FunctionSignature(typeParamDecl, std::move(desc->params), returnTypeAnnotation),
335                        arrowFunctionContext->Flags(),
336                        {},
337                        false,
338                        context_.GetLanguage()});
339    // clang-format on
340    funcNode->SetRange({desc->startLoc, endLoc});
341
342    auto *arrowFuncNode = AllocNode<ir::ArrowFunctionExpression>(funcNode);
343    arrowFuncNode->SetRange(funcNode->Range());
344
345    return arrowFuncNode;
346}
347
348ArrowFunctionDescriptor ParserImpl::ConvertToArrowParameter(ir::Expression *expr, bool isAsync)
349{
350    auto arrowStatus = isAsync ? ParserStatus::ASYNC_FUNCTION : ParserStatus::NO_OPTS;
351    ArenaVector<ir::Expression *> params(Allocator()->Adapter());
352
353    if (expr == nullptr) {
354        return ArrowFunctionDescriptor {std::move(params), lexer_->GetToken().Start(), arrowStatus};
355    }
356
357    bool seenOptional = false;
358
359    switch (expr->Type()) {
360        case ir::AstNodeType::REST_ELEMENT:
361        case ir::AstNodeType::IDENTIFIER:
362        case ir::AstNodeType::OBJECT_EXPRESSION:
363        case ir::AstNodeType::ASSIGNMENT_EXPRESSION:
364        case ir::AstNodeType::ARRAY_EXPRESSION: {
365            arrowStatus |= ValidateArrowParameter(expr, &seenOptional);
366
367            params.push_back(expr);
368            break;
369        }
370        case ir::AstNodeType::SEQUENCE_EXPRESSION: {
371            auto &sequence = expr->AsSequenceExpression()->Sequence();
372
373            for (auto *it : sequence) {
374                arrowStatus |= ValidateArrowParameter(it, &seenOptional);
375            }
376
377            params.swap(sequence);
378            break;
379        }
380        case ir::AstNodeType::CALL_EXPRESSION: {
381            if (isAsync) {
382                auto *callExpression = expr->AsCallExpression();
383                auto &arguments = callExpression->Arguments();
384
385                if (callExpression->HasTrailingComma()) {
386                    ASSERT(!arguments.empty());
387                    ThrowSyntaxError("Rest parameter must be last formal parameter", arguments.back()->End());
388                }
389
390                for (auto *it : arguments) {
391                    arrowStatus |= ValidateArrowParameter(it, &seenOptional);
392                }
393
394                params.swap(arguments);
395                break;
396            }
397
398            [[fallthrough]];
399        }
400        default: {
401            ThrowSyntaxError("Unexpected token, arrow (=>)");
402        }
403    }
404
405    return ArrowFunctionDescriptor {std::move(params), expr->Start(), arrowStatus};
406}
407
408ir::ArrowFunctionExpression *ParserImpl::ParseArrowFunctionExpression(ir::Expression *expr,
409                                                                      ir::TSTypeParameterDeclaration *typeParamDecl,
410                                                                      ir::TypeNode *returnTypeAnnotation, bool isAsync)
411{
412    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW);
413
414    if (lexer_->GetToken().NewLine()) {
415        ThrowSyntaxError(
416            "expected '=>' on the same line after an argument list, "
417            "got line terminator");
418    }
419
420    ArrowFunctionContext arrowFunctionContext(this, isAsync);
421    FunctionParameterContext functionParamContext(&context_);
422    ArrowFunctionDescriptor desc = ConvertToArrowParameter(expr, isAsync);
423
424    return ParseArrowFunctionExpressionBody(&arrowFunctionContext, &desc, typeParamDecl, returnTypeAnnotation);
425}
426
427void ParserImpl::ValidateArrowFunctionRestParameter([[maybe_unused]] ir::SpreadElement *restElement)
428{
429    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
430        ThrowSyntaxError("Rest parameter must be last formal parameter");
431    }
432}
433
434// NOLINTNEXTLINE(google-default-arguments)
435ir::Expression *ParserImpl::ParseCoverParenthesizedExpressionAndArrowParameterList(
436    [[maybe_unused]] ExpressionParseFlags flags)
437{
438    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
439    lexer::SourcePosition start = lexer_->GetToken().Start();
440    lexer_->NextToken();
441
442    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
443        ir::SpreadElement *restElement = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN);
444
445        restElement->SetGrouped();
446        restElement->SetStart(start);
447
448        ValidateArrowFunctionRestParameter(restElement);
449
450        lexer_->NextToken();
451
452        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
453            ThrowSyntaxError("Unexpected token");
454        }
455
456        return ParseArrowFunctionExpression(restElement, nullptr, nullptr, false);
457    }
458
459    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
460        lexer_->NextToken();
461
462        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
463            ThrowSyntaxError("Unexpected token");
464        }
465
466        auto *arrowExpr = ParseArrowFunctionExpression(nullptr, nullptr, nullptr, false);
467        arrowExpr->SetStart(start);
468        arrowExpr->AsArrowFunctionExpression()->Function()->SetStart(start);
469
470        return arrowExpr;
471    }
472
473    ir::Expression *expr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::ACCEPT_REST |
474                                           ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
475
476    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
477        ThrowSyntaxError("Unexpected token, expected ')'");
478    }
479
480    expr->SetGrouped();
481    expr->SetRange({start, lexer_->GetToken().End()});
482    lexer_->NextToken();
483
484    return expr;
485}
486
487void ParserImpl::CheckInvalidDestructuring(const ir::AstNode *object) const
488{
489    object->Iterate([this](ir::AstNode *childNode) -> void {
490        switch (childNode->Type()) {
491            case ir::AstNodeType::ASSIGNMENT_PATTERN: {
492                ThrowSyntaxError("Invalid property initializer");
493                break;
494            }
495            case ir::AstNodeType::REST_ELEMENT:
496            case ir::AstNodeType::PROPERTY:
497            case ir::AstNodeType::OBJECT_EXPRESSION: {
498                CheckInvalidDestructuring(childNode);
499                break;
500            }
501            default: {
502                break;
503            }
504        }
505    });
506}
507
508void ParserImpl::ValidateGroupedExpression(ir::Expression *lhsExpression)
509{
510    lexer::TokenType tokenType = lexer_->GetToken().Type();
511    if (lhsExpression->IsGrouped() && tokenType != lexer::TokenType::PUNCTUATOR_ARROW) {
512        if (lhsExpression->IsSequenceExpression()) {
513            for (auto *seq : lhsExpression->AsSequenceExpression()->Sequence()) {
514                ValidateParenthesizedExpression(seq);
515            }
516        } else {
517            ValidateParenthesizedExpression(lhsExpression);
518        }
519    }
520}
521
522void ParserImpl::ValidateParenthesizedExpression(ir::Expression *lhsExpression)
523{
524    switch (lhsExpression->Type()) {
525        case ir::AstNodeType::IDENTIFIER: {
526            auto info = lhsExpression->AsIdentifier()->ValidateExpression();
527            if (info.Fail()) {
528                ThrowSyntaxError(info.msg.Utf8(), info.pos);
529            }
530            break;
531        }
532        case ir::AstNodeType::MEMBER_EXPRESSION: {
533            break;
534        }
535        case ir::AstNodeType::ARRAY_EXPRESSION: {
536            auto info = lhsExpression->AsArrayExpression()->ValidateExpression();
537            if (info.Fail()) {
538                ThrowSyntaxError(info.msg.Utf8(), info.pos);
539            }
540            break;
541        }
542        case ir::AstNodeType::OBJECT_EXPRESSION: {
543            auto info = lhsExpression->AsObjectExpression()->ValidateExpression();
544            if (info.Fail()) {
545                ThrowSyntaxError(info.msg.Utf8(), info.pos);
546            }
547            break;
548        }
549        case ir::AstNodeType::ASSIGNMENT_EXPRESSION: {
550            if (lhsExpression->AsAssignmentExpression()->ConvertibleToAssignmentPattern(false)) {
551                break;
552            }
553            [[fallthrough]];
554        }
555        case ir::AstNodeType::SPREAD_ELEMENT: {
556            ThrowSyntaxError("Invalid left-hand side in assignment expression");
557        }
558        default: {
559            break;
560        }
561    }
562}
563
564ir::Expression *ParserImpl::ParsePrefixAssertionExpression()
565{
566    ThrowSyntaxError({"Unexpected token '", lexer::TokenToString(lexer_->GetToken().Type()), "'."});
567    return nullptr;
568}
569
570ir::Expression *ParserImpl::ParseAssignmentExpression(ir::Expression *lhsExpression, ExpressionParseFlags flags)
571{
572    ValidateGroupedExpression(lhsExpression);
573
574    lexer::TokenType tokenType = lexer_->GetToken().Type();
575    switch (tokenType) {
576        case lexer::TokenType::PUNCTUATOR_QUESTION_MARK: {
577            lexer_->NextToken();
578            ir::Expression *consequent = ParseExpression();
579
580            if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
581                ThrowSyntaxError("Unexpected token, expected ':'");
582            }
583
584            lexer_->NextToken();
585            ir::Expression *alternate = ParseExpression();
586
587            auto *conditionalExpr = AllocNode<ir::ConditionalExpression>(lhsExpression, consequent, alternate);
588            conditionalExpr->SetRange({lhsExpression->Start(), alternate->End()});
589            return conditionalExpr;
590        }
591        case lexer::TokenType::PUNCTUATOR_ARROW: {
592            if (lexer_->GetToken().NewLine()) {
593                ThrowSyntaxError("Uncaught SyntaxError: expected expression, got '=>'");
594            }
595
596            return ParseArrowFunctionExpression(lhsExpression, nullptr, nullptr, false);
597        }
598        case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: {
599            ValidateAssignmentTarget(flags, lhsExpression);
600
601            lexer_->NextToken();
602            ir::Expression *assignmentExpression = ParseExpression(CarryPatternFlags(flags));
603
604            auto *binaryAssignmentExpression =
605                AllocNode<ir::AssignmentExpression>(lhsExpression, assignmentExpression, tokenType);
606
607            binaryAssignmentExpression->SetRange({lhsExpression->Start(), assignmentExpression->End()});
608            return binaryAssignmentExpression;
609        }
610        case lexer::TokenType::KEYW_AS: {
611            if (auto asExpression = ParsePotentialAsExpression(lhsExpression); asExpression != nullptr) {
612                return ParseAssignmentExpression(asExpression);
613            }
614            break;
615        }
616        default: {
617            auto expression = ParseAssignmentBinaryExpression(tokenType, lhsExpression, flags);
618            if (expression == nullptr) {
619                expression = ParseAssignmentEqualExpression(tokenType, lhsExpression, flags);
620            }
621
622            if (expression != nullptr) {
623                return expression;
624            }
625
626            break;
627        }
628    }
629
630    return lhsExpression;
631}
632
633ir::Expression *ParserImpl::ParseAssignmentBinaryExpression(const lexer::TokenType tokenType,
634                                                            ir::Expression *lhsExpression,
635                                                            const ExpressionParseFlags flags)
636{
637    switch (tokenType) {
638        case lexer::TokenType::KEYW_IN: {
639            if ((flags & ExpressionParseFlags::STOP_AT_IN) != 0) {
640                break;
641            }
642
643            [[fallthrough]];
644        }
645        case lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING:
646        case lexer::TokenType::PUNCTUATOR_LOGICAL_OR:
647        case lexer::TokenType::PUNCTUATOR_LOGICAL_AND:
648        case lexer::TokenType::PUNCTUATOR_BITWISE_OR:
649        case lexer::TokenType::PUNCTUATOR_BITWISE_XOR:
650        case lexer::TokenType::PUNCTUATOR_BITWISE_AND:
651        case lexer::TokenType::PUNCTUATOR_EQUAL:
652        case lexer::TokenType::PUNCTUATOR_NOT_EQUAL:
653        case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL:
654        case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL:
655        case lexer::TokenType::PUNCTUATOR_LESS_THAN:
656        case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL:
657        case lexer::TokenType::PUNCTUATOR_GREATER_THAN:
658        case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL:
659        case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT:
660        case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT:
661        case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT:
662        case lexer::TokenType::PUNCTUATOR_PLUS:
663        case lexer::TokenType::PUNCTUATOR_MINUS:
664        case lexer::TokenType::PUNCTUATOR_MULTIPLY:
665        case lexer::TokenType::PUNCTUATOR_DIVIDE:
666        case lexer::TokenType::PUNCTUATOR_MOD:
667        case lexer::TokenType::KEYW_INSTANCEOF:
668        case lexer::TokenType::PUNCTUATOR_EXPONENTIATION: {
669            return ParseAssignmentExpression(ParseBinaryExpression(lhsExpression));
670        }
671        default:
672            break;
673    }
674
675    return nullptr;
676}
677
678ir::Expression *ParserImpl::ParseAssignmentEqualExpression(const lexer::TokenType tokenType,
679                                                           ir::Expression *lhsExpression,
680                                                           const ExpressionParseFlags flags)
681{
682    switch (tokenType) {
683        case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL:
684        case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL:
685        case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL:
686        case lexer::TokenType::PUNCTUATOR_PLUS_EQUAL:
687        case lexer::TokenType::PUNCTUATOR_MINUS_EQUAL:
688        case lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL:
689        case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL:
690        case lexer::TokenType::PUNCTUATOR_MOD_EQUAL:
691        case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL:
692        case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL:
693        case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL:
694        case lexer::TokenType::PUNCTUATOR_EXPONENTIATION_EQUAL: {
695            ValidateLvalueAssignmentTarget(lhsExpression);
696
697            lexer_->NextToken();
698            ir::Expression *assignmentExpression = ParseExpression(CarryPatternFlags(flags));
699
700            auto *binaryAssignmentExpression =
701                AllocNode<ir::AssignmentExpression>(lhsExpression, assignmentExpression, tokenType);
702
703            binaryAssignmentExpression->SetRange({lhsExpression->Start(), assignmentExpression->End()});
704            return binaryAssignmentExpression;
705        }
706        case lexer::TokenType::PUNCTUATOR_LOGICAL_AND_EQUAL:
707        case lexer::TokenType::PUNCTUATOR_LOGICAL_OR_EQUAL:
708        case lexer::TokenType::PUNCTUATOR_LOGICAL_NULLISH_EQUAL: {
709            ThrowUnexpectedToken(tokenType);
710        }
711        default:
712            break;
713    }
714
715    return nullptr;
716}
717
718ir::TemplateLiteral *ParserImpl::ParseTemplateLiteral()
719{
720    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
721
722    ArenaVector<ir::TemplateElement *> quasis(Allocator()->Adapter());
723    ArenaVector<ir::Expression *> expressions(Allocator()->Adapter());
724
725    while (true) {
726        lexer_->ResetTokenEnd();
727        const auto startPos = lexer_->Save();
728
729        lexer_->ScanString<lexer::LEX_CHAR_BACK_TICK>();
730        util::StringView cooked = lexer_->GetToken().String();
731
732        lexer_->Rewind(startPos);
733        auto [raw, end, scanExpression] = lexer_->ScanTemplateString();
734
735        auto *element = AllocNode<ir::TemplateElement>(raw.View(), cooked);
736        element->SetRange({lexer::SourcePosition {startPos.Iterator().Index(), startPos.Line()},
737                           lexer::SourcePosition {end, lexer_->Line()}});
738        quasis.push_back(element);
739
740        if (!scanExpression) {
741            lexer_->ScanTemplateStringEnd();
742            break;
743        }
744
745        ir::Expression *expression = nullptr;
746
747        {
748            lexer::TemplateLiteralParserContext ctx(lexer_);
749            lexer_->PushTemplateContext(&ctx);
750            lexer_->NextToken();
751            expression = ParseExpression();
752        }
753
754        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
755            ThrowSyntaxError("Unexpected token, expected '}'.");
756        }
757
758        expressions.push_back(expression);
759    }
760
761    auto *templateNode = AllocNode<ir::TemplateLiteral>(std::move(quasis), std::move(expressions));
762    templateNode->SetRange({startLoc, lexer_->GetToken().End()});
763
764    lexer_->NextToken();
765
766    return templateNode;
767}
768
769ir::Expression *ParserImpl::ParseNewExpression()
770{
771    lexer::SourcePosition start = lexer_->GetToken().Start();
772
773    lexer_->NextToken();  // eat new
774
775    // parse callee part of NewExpression
776    ir::Expression *callee = ParseMemberExpression(true);
777    if (callee->IsImportExpression() && !callee->IsGrouped()) {
778        ThrowSyntaxError("Cannot use new with import(...)");
779    }
780
781    ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
782
783    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
784        lexer::SourcePosition endLoc = callee->End();
785        auto *newExprNode = AllocNode<ir::NewExpression>(callee, std::move(arguments));
786        newExprNode->SetRange({start, endLoc});
787
788        return newExprNode;
789    }
790
791    lexer_->NextToken();  // eat left parenthesis
792
793    // parse argument part of NewExpression
794    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
795        ir::Expression *argument = nullptr;
796
797        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
798            argument = ParseSpreadElement();
799        } else {
800            argument = ParseExpression();
801        }
802
803        arguments.push_back(argument);
804
805        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
806            lexer_->NextToken();  // eat comma
807        }
808
809        if (lexer_->GetToken().Type() == lexer::TokenType::EOS) {
810            ThrowSyntaxError("Unexpected token in argument parsing");
811        }
812    }
813
814    auto *newExprNode = AllocNode<ir::NewExpression>(callee, std::move(arguments));
815    newExprNode->SetRange({start, lexer_->GetToken().End()});
816
817    lexer_->NextToken();
818
819    return newExprNode;
820}
821
822ir::Expression *ParserImpl::ParseLeftHandSideExpression(ExpressionParseFlags flags)
823{
824    return ParseMemberExpression(false, flags);
825}
826
827ir::MetaProperty *ParserImpl::ParsePotentialNewTarget()
828{
829    lexer::SourceRange loc = lexer_->GetToken().Loc();
830
831    if (lexer_->Lookahead() == lexer::LEX_CHAR_DOT) {
832        lexer_->NextToken();
833        lexer_->NextToken();
834
835        if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TARGET) {
836            if ((context_.Status() & ParserStatus::ALLOW_NEW_TARGET) == 0) {
837                ThrowSyntaxError("'new.Target' is not allowed here");
838            }
839
840            if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0) {
841                ThrowSyntaxError("'new.Target' must not contain escaped characters");
842            }
843
844            auto *metaProperty = AllocNode<ir::MetaProperty>(ir::MetaProperty::MetaPropertyKind::NEW_TARGET);
845            metaProperty->SetRange(loc);
846            lexer_->NextToken();
847            return metaProperty;
848        }
849    }
850
851    return nullptr;
852}
853
854ir::Identifier *ParserImpl::ParsePrimaryExpressionIdent([[maybe_unused]] ExpressionParseFlags flags)
855{
856    auto *identNode = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
857    identNode->SetReference();
858    identNode->SetRange(lexer_->GetToken().Loc());
859
860    lexer_->NextToken();
861    return identNode;
862}
863
864ir::BooleanLiteral *ParserImpl::ParseBooleanLiteral()
865{
866    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_TRUE ||
867           lexer_->GetToken().Type() == lexer::TokenType::LITERAL_FALSE);
868
869    auto *booleanNode = AllocNode<ir::BooleanLiteral>(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_TRUE);
870    booleanNode->SetRange(lexer_->GetToken().Loc());
871
872    lexer_->NextToken();
873    return booleanNode;
874}
875
876ir::NullLiteral *ParserImpl::ParseNullLiteral()
877{
878    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_NULL);
879    auto *nullNode = AllocNode<ir::NullLiteral>();
880    nullNode->SetRange(lexer_->GetToken().Loc());
881
882    lexer_->NextToken();
883    return nullNode;
884}
885
886ir::Literal *ParserImpl::ParseNumberLiteral()
887{
888    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_NUMBER);
889
890    ir::Literal *numberNode {};
891
892    if ((lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) != 0U) {
893        numberNode = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
894    } else {
895        numberNode = AllocNode<ir::NumberLiteral>(lexer_->GetToken().GetNumber());
896    }
897
898    numberNode->SetRange(lexer_->GetToken().Loc());
899
900    lexer_->NextToken();
901    return numberNode;
902}
903
904ir::CharLiteral *ParserImpl::ParseCharLiteral()
905{
906    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_CHAR);
907
908    auto *charNode = AllocNode<ir::CharLiteral>(lexer_->GetToken().Utf16());
909    charNode->SetRange(lexer_->GetToken().Loc());
910
911    lexer_->NextToken();
912    return charNode;
913}
914
915ir::StringLiteral *ParserImpl::ParseStringLiteral()
916{
917    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
918
919    auto *stringNode = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
920    stringNode->SetRange(lexer_->GetToken().Loc());
921
922    lexer_->NextToken();
923    return stringNode;
924}
925
926ir::UndefinedLiteral *ParserImpl::ParseUndefinedLiteral()
927{
928    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_UNDEFINED);
929    auto *undefinedNode = AllocNode<ir::UndefinedLiteral>();
930    undefinedNode->SetRange(lexer_->GetToken().Loc());
931
932    lexer_->NextToken();
933    return undefinedNode;
934}
935
936ir::ThisExpression *ParserImpl::ParseThisExpression()
937{
938    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_THIS);
939
940    auto *thisExprNode = AllocNode<ir::ThisExpression>();
941    thisExprNode->SetRange(lexer_->GetToken().Loc());
942
943    lexer_->NextToken();
944    return thisExprNode;
945}
946
947ir::RegExpLiteral *ParserImpl::ParseRegularExpression()
948{
949    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_DIVIDE ||
950           lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL);
951
952    lexer_->ResetTokenEnd();
953    auto regexp = lexer_->ScanRegExp();
954
955    lexer::RegExpParser reParser(regexp, Allocator(), *this);
956
957    reParser.ParsePattern();
958
959    auto *regexpNode = AllocNode<ir::RegExpLiteral>(regexp.patternStr, regexp.flags, regexp.flagsStr);
960    regexpNode->SetRange(lexer_->GetToken().Loc());
961
962    lexer_->NextToken();
963    return regexpNode;
964}
965
966ir::SuperExpression *ParserImpl::ParseSuperExpression()
967{
968    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_SUPER);
969
970    auto *superExprNode = AllocNode<ir::SuperExpression>();
971    superExprNode->SetRange(lexer_->GetToken().Loc());
972
973    lexer_->NextToken();  // eat super
974
975    if ((lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD ||
976         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) &&
977        (context_.Status() & ParserStatus::ALLOW_SUPER) != 0U) {
978        return superExprNode;
979    }
980
981    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
982        (context_.Status() & ParserStatus::ALLOW_SUPER_CALL) != 0U) {
983        return superExprNode;
984    }
985
986    ThrowSyntaxError("Unexpected super keyword");
987}
988
989ir::Expression *ParserImpl::ParsePrimaryExpressionWithLiterals(ExpressionParseFlags flags)
990{
991    switch (lexer_->GetToken().Type()) {
992        case lexer::TokenType::LITERAL_IDENT: {
993            return ParsePrimaryExpressionIdent(flags);
994        }
995        case lexer::TokenType::LITERAL_TRUE:
996        case lexer::TokenType::LITERAL_FALSE: {
997            return ParseBooleanLiteral();
998        }
999        case lexer::TokenType::LITERAL_NULL: {
1000            return ParseNullLiteral();
1001        }
1002        case lexer::TokenType::KEYW_UNDEFINED: {
1003            return ParseUndefinedLiteral();
1004        }
1005        case lexer::TokenType::LITERAL_NUMBER: {
1006            return ParseNumberLiteral();
1007        }
1008        case lexer::TokenType::LITERAL_STRING: {
1009            return ParseStringLiteral();
1010        }
1011        default: {
1012            break;
1013        }
1014    }
1015
1016    ThrowSyntaxError({"Unexpected token '", lexer::TokenToString(lexer_->GetToken().Type()), "'."});
1017    return nullptr;
1018}
1019
1020ir::Expression *ParserImpl::ParseHashMaskOperator()
1021{
1022    ValidatePrivateIdentifier();
1023    auto *privateIdent = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
1024    privateIdent->SetPrivate(true);
1025    privateIdent->SetReference();
1026    lexer_->NextToken();
1027
1028    if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_IN) {
1029        ThrowSyntaxError("Unexpected private identifier");
1030    }
1031
1032    return privateIdent;
1033}
1034
1035ir::Expression *ParserImpl::ParseClassExpression()
1036{
1037    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1038    ir::ClassDefinition *classDefinition = ParseClassDefinition(ir::ClassDefinitionModifiers::ID_REQUIRED);
1039
1040    auto *classExpr = AllocNode<ir::ClassExpression>(classDefinition);
1041    classExpr->SetRange({startLoc, classDefinition->End()});
1042
1043    return classExpr;
1044}
1045
1046ir::Expression *ParserImpl::ParsePunctuators(ExpressionParseFlags flags)
1047{
1048    switch (lexer_->GetToken().Type()) {
1049        case lexer::TokenType::PUNCTUATOR_DIVIDE:
1050        case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL: {
1051            return ParseRegularExpression();
1052        }
1053        case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
1054            return ParseArrayExpression(CarryPatternFlags(flags));
1055        }
1056        case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
1057            return ParseCoverParenthesizedExpressionAndArrowParameterList();
1058        }
1059        case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
1060            return ParseObjectExpression(CarryPatternFlags(flags));
1061        }
1062        case lexer::TokenType::PUNCTUATOR_BACK_TICK: {
1063            return ParseTemplateLiteral();
1064        }
1065        case lexer::TokenType::PUNCTUATOR_HASH_MARK: {
1066            return ParseHashMaskOperator();
1067        }
1068        case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
1069            return ParsePrefixAssertionExpression();
1070        }
1071        default: {
1072            UNREACHABLE();
1073        }
1074    }
1075    return nullptr;
1076}
1077
1078// NOLINTNEXTLINE(google-default-arguments)
1079ir::Expression *ParserImpl::ParsePrimaryExpression(ExpressionParseFlags flags)
1080{
1081    switch (lexer_->GetToken().Type()) {
1082        case lexer::TokenType::KEYW_IMPORT: {
1083            return ParseImportExpression();
1084        }
1085        case lexer::TokenType::PUNCTUATOR_DIVIDE:
1086        case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL:
1087        case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET:
1088        case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS:
1089        case lexer::TokenType::PUNCTUATOR_LEFT_BRACE:
1090        case lexer::TokenType::PUNCTUATOR_BACK_TICK:
1091        case lexer::TokenType::PUNCTUATOR_HASH_MARK:
1092        case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
1093            return ParsePunctuators(flags);
1094        }
1095        case lexer::TokenType::KEYW_FUNCTION: {
1096            return ParseFunctionExpression();
1097        }
1098        case lexer::TokenType::KEYW_CLASS: {
1099            return ParseClassExpression();
1100        }
1101        case lexer::TokenType::KEYW_THIS: {
1102            return ParseThisExpression();
1103        }
1104        case lexer::TokenType::KEYW_TYPEOF: {
1105            return ParseUnaryOrPrefixUpdateExpression();
1106        }
1107        case lexer::TokenType::KEYW_SUPER: {
1108            return ParseSuperExpression();
1109        }
1110        case lexer::TokenType::KEYW_NEW: {
1111            ir::MetaProperty *newTarget = ParsePotentialNewTarget();
1112
1113            if (newTarget != nullptr) {
1114                return newTarget;
1115            }
1116
1117            return ParseNewExpression();
1118        }
1119        default: {
1120            break;
1121        }
1122    }
1123
1124    return ParsePrimaryExpressionWithLiterals(flags);
1125}
1126
1127static constexpr size_t GetOperatorPrecedenceArithmeticAndComparison(const lexer::TokenType operatorType)
1128{
1129    switch (operatorType) {
1130        case lexer::TokenType::PUNCTUATOR_EQUAL:
1131        case lexer::TokenType::PUNCTUATOR_NOT_EQUAL:
1132        case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL:
1133        case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: {
1134            constexpr auto PRECEDENCE = 8;
1135            return PRECEDENCE;
1136        }
1137        case lexer::TokenType::PUNCTUATOR_LESS_THAN:
1138        case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL:
1139        case lexer::TokenType::PUNCTUATOR_GREATER_THAN:
1140        case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL:
1141        case lexer::TokenType::KEYW_INSTANCEOF:
1142        case lexer::TokenType::KEYW_IN: {
1143            constexpr auto PRECEDENCE = 9;
1144            return PRECEDENCE;
1145        }
1146        case lexer::TokenType::PUNCTUATOR_PLUS:
1147        case lexer::TokenType::PUNCTUATOR_MINUS: {
1148            constexpr auto PRECEDENCE = 12;
1149            return PRECEDENCE;
1150        }
1151        case lexer::TokenType::PUNCTUATOR_MULTIPLY:
1152        case lexer::TokenType::PUNCTUATOR_DIVIDE:
1153        case lexer::TokenType::PUNCTUATOR_MOD: {
1154            constexpr auto PRECEDENCE = 13;
1155            return PRECEDENCE;
1156        }
1157        default: {
1158            UNREACHABLE();
1159        }
1160    }
1161}
1162
1163static constexpr size_t GetOperatorPrecedence(const lexer::TokenType operatorType)
1164{
1165    ASSERT(operatorType == lexer::TokenType::KEYW_AS || lexer::Token::IsBinaryToken(operatorType));
1166
1167    switch (operatorType) {
1168        case lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING: {
1169            constexpr auto PRECEDENCE = 1;
1170            return PRECEDENCE;
1171        }
1172        case lexer::TokenType::PUNCTUATOR_LOGICAL_OR: {
1173            constexpr auto PRECEDENCE = 2;
1174            return PRECEDENCE;
1175        }
1176        case lexer::TokenType::PUNCTUATOR_LOGICAL_AND: {
1177            constexpr auto PRECEDENCE = 4;
1178            return PRECEDENCE;
1179        }
1180        case lexer::TokenType::PUNCTUATOR_BITWISE_OR: {
1181            constexpr auto PRECEDENCE = 5;
1182            return PRECEDENCE;
1183        }
1184        case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: {
1185            constexpr auto PRECEDENCE = 6;
1186            return PRECEDENCE;
1187        }
1188        case lexer::TokenType::PUNCTUATOR_BITWISE_AND: {
1189            constexpr auto PRECEDENCE = 7;
1190            return PRECEDENCE;
1191        }
1192        case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT:
1193        case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT:
1194        case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: {
1195            constexpr auto PRECEDENCE = 10;
1196            return PRECEDENCE;
1197        }
1198        case lexer::TokenType::KEYW_AS: {
1199            constexpr auto PRECEDENCE = 11;
1200            return PRECEDENCE;
1201        }
1202        case lexer::TokenType::PUNCTUATOR_EXPONENTIATION: {
1203            constexpr auto PRECEDENCE = 14;
1204            return PRECEDENCE;
1205        }
1206        default: {
1207            return GetOperatorPrecedenceArithmeticAndComparison(operatorType);
1208        }
1209    }
1210}
1211
1212static inline bool ShouldBinaryExpressionBeAmended(const ir::BinaryExpression *const binaryExpression,
1213                                                   const lexer::TokenType operatorType)
1214{
1215    return GetOperatorPrecedence(binaryExpression->OperatorType()) <= GetOperatorPrecedence(operatorType) &&
1216           !binaryExpression->IsGrouped() &&
1217           (operatorType != lexer::TokenType::PUNCTUATOR_EXPONENTIATION ||
1218            binaryExpression->OperatorType() != lexer::TokenType::PUNCTUATOR_EXPONENTIATION);
1219}
1220
1221static inline bool ShouldAsExpressionBeAmended(const ir::TSAsExpression *const asExpression,
1222                                               const lexer::TokenType operatorType)
1223{
1224    return GetOperatorPrecedence(lexer::TokenType::KEYW_AS) <= GetOperatorPrecedence(operatorType) &&
1225           !asExpression->IsGrouped() && operatorType != lexer::TokenType::PUNCTUATOR_EXPONENTIATION;
1226}
1227
1228static inline bool ShouldExpressionBeAmended(const ir::Expression *const expression,
1229                                             const lexer::TokenType operatorType)
1230{
1231    bool shouldBeAmended = false;
1232
1233    if (expression->IsBinaryExpression()) {
1234        shouldBeAmended = ShouldBinaryExpressionBeAmended(expression->AsBinaryExpression(), operatorType);
1235    } else if (expression->IsTSAsExpression()) {
1236        shouldBeAmended = ShouldAsExpressionBeAmended(expression->AsTSAsExpression(), operatorType);
1237    }
1238
1239    return shouldBeAmended;
1240}
1241
1242static inline bool AreLogicalAndNullishMixedIncorrectly(const ir::Expression *const expression,
1243                                                        const lexer::TokenType operatorType)
1244{
1245    return ((operatorType == lexer::TokenType::PUNCTUATOR_LOGICAL_OR ||
1246             operatorType == lexer::TokenType::PUNCTUATOR_LOGICAL_AND) &&
1247            expression->IsBinaryExpression() &&
1248            expression->AsBinaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING &&
1249            !expression->IsGrouped()) ||
1250           (operatorType == lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING && expression->IsBinaryExpression() &&
1251            (expression->AsBinaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_LOGICAL_OR ||
1252             expression->AsBinaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_LOGICAL_AND) &&
1253            !expression->IsGrouped());
1254}
1255
1256static inline ir::Expression *GetAmendedChildExpression(ir::Expression *const expression)
1257{
1258    ir::Expression *amendedChild = nullptr;
1259
1260    if (expression->IsBinaryExpression()) {
1261        amendedChild = expression->AsBinaryExpression()->Left();
1262    } else if (expression->IsTSAsExpression()) {
1263        amendedChild = expression->AsTSAsExpression()->Expr();
1264    } else {
1265        UNREACHABLE();
1266    }
1267
1268    return amendedChild;
1269}
1270
1271static inline void SetAmendedChildExpression(ir::Expression *const parent, ir::Expression *const amended)
1272{
1273    if (parent->IsBinaryExpression()) {
1274        parent->AsBinaryExpression()->SetLeft(amended);
1275        amended->SetParent(parent);
1276    } else if (parent->IsTSAsExpression()) {
1277        parent->AsTSAsExpression()->SetExpr(amended);
1278        amended->SetParent(parent);
1279    } else {
1280        UNREACHABLE();
1281    }
1282}
1283
1284void ParserImpl::CreateAmendedBinaryExpression(ir::Expression *const left, ir::Expression *const right,
1285                                               const lexer::TokenType operatorType)
1286{
1287    auto *amended = GetAmendedChildExpression(right);
1288
1289    amended->SetParent(nullptr);  // Next line overwrite parent
1290    auto *binaryExpr = AllocNode<ir::BinaryExpression>(left, amended, operatorType);
1291
1292    binaryExpr->SetRange({left->Start(), amended->End()});
1293    SetAmendedChildExpression(right, binaryExpr);
1294}
1295
1296ir::Expression *ParserImpl::ParseExpressionOrTypeAnnotation([[maybe_unused]] lexer::TokenType type,
1297                                                            [[maybe_unused]] ExpressionParseFlags flags)
1298{
1299    return ParseExpression(ExpressionParseFlags::DISALLOW_YIELD);
1300}
1301
1302ir::Expression *ParserImpl::ParseBinaryExpression(ir::Expression *left, ExpressionParseFlags flags)
1303{
1304    lexer::TokenType operatorType = lexer_->GetToken().Type();
1305    ASSERT(lexer::Token::IsBinaryToken(operatorType));
1306
1307    if (operatorType == lexer::TokenType::PUNCTUATOR_EXPONENTIATION) {
1308        if ((left->IsUnaryExpression() || left->IsTypeofExpression()) && !left->IsGrouped()) {
1309            ThrowSyntaxError(
1310                "Illegal expression. Wrap left hand side or entire "
1311                "exponentiation in parentheses.");
1312        }
1313    }
1314
1315    lexer_->NextToken();
1316
1317    ExpressionParseFlags newFlags = ExpressionParseFlags::DISALLOW_YIELD;
1318    if ((operatorType == lexer::TokenType::KEYW_INSTANCEOF) || ((flags & ExpressionParseFlags::INSTANCEOF) != 0)) {
1319        newFlags |= ExpressionParseFlags::INSTANCEOF;
1320    }
1321
1322    ir::Expression *rightExpr = ParseExpressionOrTypeAnnotation(operatorType, ExpressionParseFlags::DISALLOW_YIELD);
1323    ir::ConditionalExpression *conditionalExpr = nullptr;
1324
1325    if (rightExpr->IsConditionalExpression() && !rightExpr->IsGrouped()) {
1326        conditionalExpr = rightExpr->AsConditionalExpression();
1327        rightExpr = conditionalExpr->Test();
1328    }
1329
1330    if (ShouldExpressionBeAmended(rightExpr, operatorType)) {
1331        if (AreLogicalAndNullishMixedIncorrectly(rightExpr, operatorType)) {
1332            ThrowSyntaxError("Nullish coalescing operator ?? requires parens when mixing with logical operators.");
1333        }
1334
1335        bool shouldBeAmended = true;
1336
1337        ir::Expression *expression = rightExpr;
1338        ir::Expression *parentExpression = nullptr;
1339
1340        while (shouldBeAmended && GetAmendedChildExpression(expression)->IsBinaryExpression()) {
1341            parentExpression = expression;
1342            parentExpression->SetStart(left->Start());
1343
1344            expression = GetAmendedChildExpression(expression);
1345
1346            shouldBeAmended = ShouldExpressionBeAmended(expression, operatorType);
1347        }
1348
1349        CreateAmendedBinaryExpression(left, shouldBeAmended ? expression : parentExpression, operatorType);
1350    } else {
1351        if (AreLogicalAndNullishMixedIncorrectly(rightExpr, operatorType)) {
1352            ThrowSyntaxError("Nullish coalescing operator ?? requires parens when mixing with logical operators.");
1353        }
1354        const lexer::SourcePosition &endPos = rightExpr->End();
1355        rightExpr = AllocNode<ir::BinaryExpression>(left, rightExpr, operatorType);
1356        rightExpr->SetRange({left->Start(), endPos});
1357    }
1358
1359    if (conditionalExpr != nullptr) {
1360        conditionalExpr->SetStart(rightExpr->Start());
1361        conditionalExpr->SetTest(rightExpr);
1362        return conditionalExpr;
1363    }
1364
1365    return rightExpr;
1366}
1367
1368ArenaVector<ir::Expression *> ParserImpl::ParseCallExpressionArguments(bool &trailingComma)
1369{
1370    ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
1371
1372    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
1373        lexer_->Lookahead() == static_cast<char32_t>(ARRAY_FORMAT_NODE)) {
1374        arguments = std::move(ParseExpressionsArrayFormatPlaceholder());
1375        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1376            ThrowSyntaxError("Expected a ')'");
1377        }
1378    } else {
1379        while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1380            trailingComma = false;
1381            ir::Expression *argument {};
1382            if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
1383                argument = ParseSpreadElement();
1384            } else {
1385                argument = ParseExpression();
1386            }
1387
1388            arguments.push_back(argument);
1389
1390            if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
1391                lexer_->NextToken();
1392                trailingComma = true;
1393            } else if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1394                ThrowSyntaxError("Expected a ')'");
1395            }
1396        }
1397    }
1398
1399    return arguments;
1400}
1401
1402ir::CallExpression *ParserImpl::ParseCallExpression(ir::Expression *callee, bool isOptionalChain, bool handleEval)
1403{
1404    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
1405    bool trailingComma {};
1406
1407    while (true) {
1408        lexer_->NextToken();
1409        ArenaVector<ir::Expression *> arguments = ParseCallExpressionArguments(trailingComma);
1410        ir::CallExpression *callExpr {};
1411
1412        if (!isOptionalChain && handleEval && callee->IsIdentifier() && callee->AsIdentifier()->Name().Is("eval")) {
1413            auto parserStatus = static_cast<uint32_t>(context_.Status() | ParserStatus::DIRECT_EVAL);
1414            callExpr = AllocNode<ir::DirectEvalExpression>(callee, std::move(arguments), nullptr, isOptionalChain,
1415                                                           parserStatus);
1416        } else {
1417            callExpr =
1418                AllocNode<ir::CallExpression>(callee, std::move(arguments), nullptr, isOptionalChain, trailingComma);
1419        }
1420
1421        callExpr->SetRange({callee->Start(), lexer_->GetToken().End()});
1422        isOptionalChain = false;
1423
1424        lexer_->NextToken();
1425
1426        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1427            ParseTrailingBlock(callExpr);
1428            return callExpr;
1429        }
1430
1431        callee = callExpr;
1432    }
1433
1434    UNREACHABLE();
1435}
1436
1437ir::Expression *ParserImpl::ParseOptionalChain(ir::Expression *leftSideExpr)
1438{
1439    ir::Expression *returnExpression = nullptr;
1440
1441    bool isPrivate = false;
1442
1443    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_HASH_MARK) {
1444        isPrivate = true;
1445        ValidatePrivateIdentifier();
1446    }
1447
1448    const auto tokenType = lexer_->GetToken().Type();
1449    if (tokenType == lexer::TokenType::LITERAL_IDENT) {
1450        auto *identNode = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
1451        identNode->SetReference();
1452        identNode->SetPrivate(isPrivate);
1453        identNode->SetRange(lexer_->GetToken().Loc());
1454
1455        returnExpression = AllocNode<ir::MemberExpression>(leftSideExpr, identNode,
1456                                                           ir::MemberExpressionKind::PROPERTY_ACCESS, false, true);
1457        returnExpression->SetRange({leftSideExpr->Start(), identNode->End()});
1458        lexer_->NextToken();
1459    }
1460
1461    if (tokenType == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1462        lexer_->NextToken();  // eat '['
1463        ir::Expression *propertyNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1464
1465        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1466            ThrowSyntaxError("Unexpected token");
1467        }
1468
1469        returnExpression = AllocNode<ir::MemberExpression>(leftSideExpr, propertyNode,
1470                                                           ir::MemberExpressionKind::ELEMENT_ACCESS, true, true);
1471        returnExpression->SetRange({leftSideExpr->Start(), lexer_->GetToken().End()});
1472        lexer_->NextToken();
1473    }
1474
1475    if (tokenType == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1476        returnExpression = ParseCallExpression(leftSideExpr, true);
1477    }
1478
1479    // Static semantic
1480    if (tokenType == lexer::TokenType::PUNCTUATOR_BACK_TICK ||
1481        lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BACK_TICK) {
1482        ThrowSyntaxError("Tagged Template Literals are not allowed in optionalChain");
1483    }
1484
1485    return returnExpression;
1486}
1487
1488ir::ArrowFunctionExpression *ParserImpl::ParsePotentialArrowExpression(ir::Expression **returnExpression,
1489                                                                       const lexer::SourcePosition &startLoc)
1490{
1491    switch (lexer_->GetToken().Type()) {
1492        case lexer::TokenType::KEYW_FUNCTION: {
1493            *returnExpression = ParseFunctionExpression(ParserStatus::ASYNC_FUNCTION);
1494            (*returnExpression)->SetStart(startLoc);
1495            break;
1496        }
1497        case lexer::TokenType::LITERAL_IDENT: {
1498            ir::Expression *identRef = ParsePrimaryExpression();
1499            ASSERT(identRef->IsIdentifier());
1500
1501            if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
1502                ThrowSyntaxError("Unexpected token, expected '=>'");
1503            }
1504
1505            ir::ArrowFunctionExpression *arrowFuncExpr = ParseArrowFunctionExpression(identRef, nullptr, nullptr, true);
1506            arrowFuncExpr->SetStart(startLoc);
1507
1508            return arrowFuncExpr;
1509        }
1510        case lexer::TokenType::PUNCTUATOR_ARROW: {
1511            ir::ArrowFunctionExpression *arrowFuncExpr =
1512                ParseArrowFunctionExpression(*returnExpression, nullptr, nullptr, true);
1513            arrowFuncExpr->SetStart(startLoc);
1514            return arrowFuncExpr;
1515        }
1516        case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
1517            ir::CallExpression *callExpression = ParseCallExpression(*returnExpression, false);
1518
1519            if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW) {
1520                ir::ArrowFunctionExpression *arrowFuncExpr =
1521                    ParseArrowFunctionExpression(callExpression, nullptr, nullptr, true);
1522                arrowFuncExpr->SetStart(startLoc);
1523
1524                return arrowFuncExpr;
1525            }
1526
1527            *returnExpression = callExpression;
1528            break;
1529        }
1530        default: {
1531            break;
1532        }
1533    }
1534
1535    return nullptr;
1536}
1537
1538bool ParserImpl::ParsePotentialGenericFunctionCall([[maybe_unused]] ir::Expression *primaryExpr,
1539                                                   [[maybe_unused]] ir::Expression **returnExpression,
1540                                                   [[maybe_unused]] const lexer::SourcePosition &startLoc,
1541                                                   [[maybe_unused]] bool ignoreCallExpression)
1542{
1543    return true;
1544}
1545
1546bool ParserImpl::ParsePotentialNonNullExpression([[maybe_unused]] ir::Expression **returnExpression,
1547                                                 [[maybe_unused]] lexer::SourcePosition startLoc)
1548{
1549    return true;
1550}
1551
1552ir::Expression *ParserImpl::ParsePotentialAsExpression([[maybe_unused]] ir::Expression *primaryExpression)
1553{
1554    return nullptr;
1555}
1556
1557ir::MemberExpression *ParserImpl::ParseElementAccess(ir::Expression *primaryExpr, bool isOptional)
1558{
1559    lexer_->NextToken();  // eat '['
1560    ir::Expression *propertyNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1561
1562    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1563        ThrowSyntaxError("Unexpected token");
1564    }
1565
1566    auto *memberExpr = AllocNode<ir::MemberExpression>(primaryExpr, propertyNode,
1567                                                       ir::MemberExpressionKind::ELEMENT_ACCESS, true, isOptional);
1568    memberExpr->SetRange({primaryExpr->Start(), lexer_->GetToken().End()});
1569    lexer_->NextToken();
1570    return memberExpr;
1571}
1572
1573ir::MemberExpression *ParserImpl::ParsePrivatePropertyAccess(ir::Expression *primaryExpr)
1574{
1575    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_HASH_MARK);
1576
1577    lexer::SourcePosition memberStart = lexer_->GetToken().Start();
1578    ValidatePrivateIdentifier();
1579
1580    auto *privateIdent = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
1581    privateIdent->SetRange({memberStart, lexer_->GetToken().End()});
1582    privateIdent->SetPrivate(true);
1583    privateIdent->SetReference();
1584    lexer_->NextToken();
1585
1586    auto *memberExpr = AllocNode<ir::MemberExpression>(primaryExpr, privateIdent,
1587                                                       ir::MemberExpressionKind::PROPERTY_ACCESS, false, false);
1588    memberExpr->SetRange({primaryExpr->Start(), privateIdent->End()});
1589    return memberExpr;
1590}
1591
1592ir::MemberExpression *ParserImpl::ParsePropertyAccess(ir::Expression *primaryExpr, bool isOptional)
1593{
1594    ir::Identifier *ident = ExpectIdentifier(true);
1595    if (ident == nullptr) {  // Error processing.
1596        return nullptr;
1597    }
1598
1599    auto *memberExpr = AllocNode<ir::MemberExpression>(primaryExpr, ident, ir::MemberExpressionKind::PROPERTY_ACCESS,
1600                                                       false, isOptional);
1601    memberExpr->SetRange({primaryExpr->Start(), ident->End()});
1602
1603    return memberExpr;
1604}
1605
1606ir::Expression *ParserImpl::ParsePostPrimaryExpression(ir::Expression *primaryExpr, lexer::SourcePosition startLoc,
1607                                                       bool ignoreCallExpression, bool *isChainExpression)
1608{
1609    ir::Expression *returnExpr = primaryExpr;
1610    while (true) {
1611        switch (lexer_->GetToken().Type()) {
1612            case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
1613                returnExpr = ParseElementAccess(returnExpr);
1614                continue;
1615            }
1616            case lexer::TokenType::LITERAL_IDENT: {
1617                if (auto *asExpression = ParsePotentialAsExpression(returnExpr); asExpression != nullptr) {
1618                    return asExpression;
1619                }
1620                break;
1621            }
1622            case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT:
1623            case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
1624                if (ParsePotentialGenericFunctionCall(primaryExpr, &returnExpr, startLoc, ignoreCallExpression)) {
1625                    break;
1626                }
1627                continue;
1628            }
1629            case lexer::TokenType::PUNCTUATOR_BACK_TICK: {
1630                returnExpr = ParsePostPrimaryExpressionBackTick(returnExpr, startLoc);
1631                continue;
1632            }
1633            case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
1634                if (ignoreCallExpression) {
1635                    break;
1636                }
1637                returnExpr = ParseCallExpression(returnExpr, false);
1638                continue;
1639            }
1640            case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: {
1641                if (ParsePotentialNonNullExpression(&returnExpr, startLoc)) {
1642                    break;
1643                }
1644                continue;
1645            }
1646            default: {
1647                auto tmp = ParsePostPrimaryExpressionDot(returnExpr, lexer_->GetToken().Type(), isChainExpression);
1648                if (tmp != nullptr) {
1649                    returnExpr = tmp;
1650                    continue;
1651                }
1652            }
1653        }
1654        break;
1655    }
1656    return returnExpr;
1657}
1658
1659ir::Expression *ParserImpl::ParsePostPrimaryExpressionBackTick(ir::Expression *returnExpression,
1660                                                               const lexer::SourcePosition startLoc)
1661{
1662    ir::TemplateLiteral *propertyNode = ParseTemplateLiteral();
1663    lexer::SourcePosition endLoc = propertyNode->End();
1664
1665    returnExpression = AllocNode<ir::TaggedTemplateExpression>(returnExpression, propertyNode, nullptr);
1666    returnExpression->SetRange({startLoc, endLoc});
1667
1668    return returnExpression;
1669}
1670
1671ir::Expression *ParserImpl::ParsePostPrimaryExpressionDot(ir::Expression *returnExpression,
1672                                                          const lexer::TokenType tokenType, bool *isChainExpression)
1673{
1674    switch (tokenType) {
1675        case lexer::TokenType::PUNCTUATOR_QUESTION_DOT: {
1676            *isChainExpression = true;
1677            lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat ?.
1678            return ParseOptionalChain(returnExpression);
1679        }
1680        case lexer::TokenType::PUNCTUATOR_PERIOD: {
1681            lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat period
1682
1683            if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_HASH_MARK) {
1684                return ParsePrivatePropertyAccess(returnExpression);
1685            }
1686
1687            return ParsePropertyAccess(returnExpression);
1688        }
1689        default: {
1690            break;
1691        }
1692    }
1693
1694    return nullptr;
1695}
1696
1697void ParserImpl::ValidateUpdateExpression(ir::Expression *returnExpression, bool isChainExpression)
1698{
1699    if ((!returnExpression->IsMemberExpression() && !returnExpression->IsIdentifier() &&
1700         !returnExpression->IsTSNonNullExpression()) ||
1701        isChainExpression) {
1702        ThrowSyntaxError("Invalid left-hand side operator.");
1703    }
1704
1705    if (returnExpression->IsIdentifier()) {
1706        const util::StringView &returnExpressionStr = returnExpression->AsIdentifier()->Name();
1707
1708        if (returnExpressionStr.Is("eval")) {
1709            ThrowSyntaxError("Assigning to 'eval' in strict mode is invalid");
1710        }
1711
1712        if (returnExpressionStr.Is("arguments")) {
1713            ThrowSyntaxError("Assigning to 'arguments' in strict mode is invalid");
1714        }
1715    }
1716}
1717
1718ir::Expression *ParserImpl::SetupChainExpr(ir::Expression *const top, lexer::SourcePosition startLoc)
1719{
1720    auto expr = top;
1721    while (expr->IsTSNonNullExpression()) {
1722        expr = expr->AsTSNonNullExpression()->Expr();
1723    }
1724    auto chainParent = expr->Parent();
1725
1726    lexer::SourcePosition endLoc = expr->End();
1727    auto chain = AllocNode<ir::ChainExpression>(expr);
1728    chain->SetRange({startLoc, endLoc});
1729
1730    if (expr == top) {
1731        return chain;
1732    }
1733    chainParent->AsTSNonNullExpression()->SetExpr(chain);
1734    chain->SetParent(chainParent);
1735    return top;
1736}
1737
1738ir::Expression *ParserImpl::ParseMemberExpression(bool ignoreCallExpression, ExpressionParseFlags flags)
1739{
1740    bool isAsync = lexer_->GetToken().IsAsyncModifier();
1741    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1742    ir::Expression *returnExpression = ParsePrimaryExpression(flags);
1743
1744    if (lexer_->GetToken().NewLine() && returnExpression->IsArrowFunctionExpression()) {
1745        return returnExpression;
1746    }
1747
1748    if (isAsync && !lexer_->GetToken().NewLine()) {
1749        context_.Status() |= ParserStatus::ASYNC_FUNCTION;
1750        ir::ArrowFunctionExpression *arrow = ParsePotentialArrowExpression(&returnExpression, startLoc);
1751
1752        if (arrow != nullptr) {
1753            return arrow;
1754        }
1755    }
1756
1757    bool isChainExpression;
1758    ir::Expression *prevExpression;
1759    do {
1760        isChainExpression = false;
1761        prevExpression = returnExpression;
1762        returnExpression =
1763            ParsePostPrimaryExpression(returnExpression, startLoc, ignoreCallExpression, &isChainExpression);
1764        if (isChainExpression) {
1765            returnExpression = SetupChainExpr(returnExpression, startLoc);
1766        }
1767    } while (prevExpression != returnExpression);
1768
1769    if (!lexer_->GetToken().NewLine() && lexer::Token::IsUpdateToken(lexer_->GetToken().Type())) {
1770        lexer::SourcePosition start = returnExpression->Start();
1771
1772        ValidateUpdateExpression(returnExpression, isChainExpression);
1773
1774        returnExpression = AllocNode<ir::UpdateExpression>(returnExpression, lexer_->GetToken().Type(), false);
1775
1776        returnExpression->SetRange({start, lexer_->GetToken().End()});
1777        lexer_->NextToken();
1778    }
1779
1780    return returnExpression;
1781}
1782
1783// NOLINTNEXTLINE(google-default-arguments)
1784ir::Expression *ParserImpl::ParsePatternElement(ExpressionParseFlags flags, bool allowDefault)
1785{
1786    ir::Expression *returnNode = nullptr;
1787
1788    switch (lexer_->GetToken().Type()) {
1789        case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
1790            returnNode = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1791            break;
1792        }
1793        case lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD: {
1794            if ((flags & ExpressionParseFlags::IN_REST) != 0) {
1795                ThrowSyntaxError("Unexpected token");
1796            }
1797            returnNode = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN);
1798            break;
1799        }
1800        case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
1801            returnNode =
1802                ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN | ExpressionParseFlags::OBJECT_PATTERN);
1803            break;
1804        }
1805        case lexer::TokenType::LITERAL_IDENT: {
1806            returnNode = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
1807            returnNode->AsIdentifier()->SetReference();
1808            returnNode->SetRange(lexer_->GetToken().Loc());
1809            lexer_->NextToken();
1810            break;
1811        }
1812        default: {
1813            ThrowSyntaxError("Unexpected token, expected an identifier.");
1814        }
1815    }
1816
1817    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
1818        return returnNode;
1819    }
1820
1821    ParsePatternElementErrorCheck(flags, allowDefault);
1822
1823    ir::Expression *rightNode = ParseExpression();
1824
1825    auto *assignmentExpression = AllocNode<ir::AssignmentExpression>(
1826        ir::AstNodeType::ASSIGNMENT_PATTERN, returnNode, rightNode, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
1827    assignmentExpression->SetRange({returnNode->Start(), rightNode->End()});
1828
1829    return assignmentExpression;
1830}
1831
1832void ParserImpl::ParsePatternElementErrorCheck(const ExpressionParseFlags flags, const bool allowDefault)
1833{
1834    if ((flags & ExpressionParseFlags::IN_REST) != 0) {
1835        ThrowSyntaxError("Unexpected token, expected ')'");
1836    }
1837
1838    if (!allowDefault) {
1839        ThrowSyntaxError("Invalid destructuring assignment target");
1840    }
1841
1842    lexer_->NextToken();
1843
1844    if (context_.IsGenerator() && lexer_->GetToken().Type() == lexer::TokenType::KEYW_YIELD) {
1845        ThrowSyntaxError("Yield is not allowed in generator parameters");
1846    }
1847
1848    if (context_.IsAsync() && lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) {
1849        ThrowSyntaxError("Illegal await-expression in formal parameters of async function");
1850    }
1851}
1852
1853void ParserImpl::CheckPropertyKeyAsyncModifier(ParserStatus *methodStatus)
1854{
1855    const auto asyncPos = lexer_->Save();
1856    lexer_->NextToken();
1857
1858    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
1859        lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON &&
1860        lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
1861        lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1862        if (lexer_->GetToken().NewLine()) {
1863            ThrowSyntaxError(
1864                "Async methods cannot have a line terminator between "
1865                "'async' and the property name");
1866        }
1867
1868        *methodStatus |= ParserStatus::ASYNC_FUNCTION;
1869    } else {
1870        lexer_->Rewind(asyncPos);
1871    }
1872}
1873
1874static bool IsAccessorDelimiter(char32_t cp)
1875{
1876    switch (cp) {
1877        case lexer::LEX_CHAR_LEFT_PAREN:
1878        case lexer::LEX_CHAR_COLON:
1879        case lexer::LEX_CHAR_COMMA:
1880        case lexer::LEX_CHAR_RIGHT_BRACE: {
1881            return true;
1882        }
1883        default: {
1884            return false;
1885        }
1886    }
1887}
1888
1889static bool IsShorthandDelimiter(char32_t cp)
1890{
1891    switch (cp) {
1892        case lexer::LEX_CHAR_EQUALS:
1893        case lexer::LEX_CHAR_COMMA:
1894        case lexer::LEX_CHAR_RIGHT_BRACE: {
1895            return true;
1896        }
1897        default: {
1898            return false;
1899        }
1900    }
1901}
1902
1903void ParserImpl::ValidateAccessor(ExpressionParseFlags flags, lexer::TokenFlags currentTokenFlags)
1904{
1905    if ((flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0) {
1906        ThrowSyntaxError("Unexpected token");
1907    }
1908
1909    if ((currentTokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) {
1910        ThrowSyntaxError("Keyword must not contain escaped characters");
1911    }
1912}
1913
1914ir::Property *ParserImpl::ParseShorthandProperty(const lexer::LexerPosition *startPos)
1915{
1916    char32_t nextCp = lexer_->Lookahead();
1917    lexer::TokenType keywordType = lexer_->GetToken().KeywordType();
1918
1919    /* Rewind the lexer to the beginning of the ident to reparse as common
1920     * identifier */
1921    lexer_->Rewind(*startPos);
1922    lexer_->NextToken();
1923    lexer::SourcePosition start = lexer_->GetToken().Start();
1924
1925    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1926        ThrowSyntaxError("Expected an identifier");
1927    }
1928
1929    const util::StringView &ident = lexer_->GetToken().Ident();
1930
1931    auto *key = AllocNode<ir::Identifier>(ident, Allocator());
1932    key->SetRange(lexer_->GetToken().Loc());
1933
1934    ir::Expression *value = AllocNode<ir::Identifier>(ident, Allocator());
1935    value->AsIdentifier()->SetReference();
1936    value->SetRange(lexer_->GetToken().Loc());
1937
1938    lexer::SourcePosition end;
1939
1940    if (nextCp == lexer::LEX_CHAR_EQUALS) {
1941        CheckRestrictedBinding(keywordType);
1942
1943        lexer_->NextToken();  // substitution
1944        lexer_->NextToken();  // eat substitution
1945
1946        ir::Expression *rightNode = ParseExpression();
1947
1948        auto *assignmentExpression = AllocNode<ir::AssignmentExpression>(
1949            ir::AstNodeType::ASSIGNMENT_PATTERN, value, rightNode, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
1950        assignmentExpression->SetRange({value->Start(), rightNode->End()});
1951        end = rightNode->End();
1952        value = assignmentExpression;
1953    } else {
1954        end = lexer_->GetToken().End();
1955        lexer_->NextToken();
1956    }
1957
1958    auto *returnProperty = AllocNode<ir::Property>(key, value);
1959    returnProperty->SetRange({start, end});
1960
1961    return returnProperty;
1962}
1963
1964bool ParserImpl::ParsePropertyModifiers(ExpressionParseFlags flags, ir::PropertyKind *propertyKind,
1965                                        ParserStatus *methodStatus)
1966{
1967    if (lexer_->GetToken().IsAsyncModifier()) {
1968        CheckPropertyKeyAsyncModifier(methodStatus);
1969    }
1970
1971    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
1972        if ((flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0) {
1973            ThrowSyntaxError("Unexpected token");
1974        }
1975
1976        lexer_->NextToken();
1977        *methodStatus |= ParserStatus::GENERATOR_FUNCTION;
1978    }
1979
1980    lexer::TokenFlags currentTokenFlags = lexer_->GetToken().Flags();
1981    char32_t nextCp = lexer_->Lookahead();
1982    lexer::TokenType keywordType = lexer_->GetToken().KeywordType();
1983    // Parse getter property
1984    if (keywordType == lexer::TokenType::KEYW_GET && !IsAccessorDelimiter(nextCp)) {
1985        ValidateAccessor(flags, currentTokenFlags);
1986
1987        *propertyKind = ir::PropertyKind::GET;
1988        lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
1989
1990        return false;
1991    }
1992
1993    // Parse setter property
1994    if (keywordType == lexer::TokenType::KEYW_SET && !IsAccessorDelimiter(nextCp)) {
1995        ValidateAccessor(flags, currentTokenFlags);
1996
1997        *propertyKind = ir::PropertyKind::SET;
1998        lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
1999
2000        return false;
2001    }
2002
2003    // Parse shorthand property or assignment pattern
2004    return (IsShorthandDelimiter(nextCp) && (*methodStatus & ParserStatus::ASYNC_FUNCTION) == 0);
2005}
2006
2007void ParserImpl::ParseGeneratorPropertyModifier(ExpressionParseFlags flags, ParserStatus *methodStatus)
2008{
2009    if ((flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0) {
2010        ThrowSyntaxError("Unexpected token");
2011    }
2012
2013    lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
2014    *methodStatus |= ParserStatus::GENERATOR_FUNCTION;
2015}
2016
2017ir::Expression *ParserImpl::ParsePropertyKey(ExpressionParseFlags flags)
2018{
2019    ir::Expression *key = nullptr;
2020
2021    switch (lexer_->GetToken().Type()) {
2022        case lexer::TokenType::LITERAL_IDENT: {
2023            const util::StringView &ident = lexer_->GetToken().Ident();
2024            key = AllocNode<ir::Identifier>(ident, Allocator());
2025            key->SetRange(lexer_->GetToken().Loc());
2026            break;
2027        }
2028        case lexer::TokenType::LITERAL_STRING: {
2029            const util::StringView &string = lexer_->GetToken().String();
2030            key = AllocNode<ir::StringLiteral>(string);
2031            key->SetRange(lexer_->GetToken().Loc());
2032            break;
2033        }
2034        case lexer::TokenType::LITERAL_NUMBER: {
2035            if ((lexer_->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) != 0) {
2036                key = AllocNode<ir::BigIntLiteral>(lexer_->GetToken().BigInt());
2037            } else {
2038                key = AllocNode<ir::NumberLiteral>(lexer_->GetToken().GetNumber());
2039            }
2040
2041            key->SetRange(lexer_->GetToken().Loc());
2042            break;
2043        }
2044        case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
2045            lexer_->NextToken();  // eat left square bracket
2046
2047            key = ParseExpression(flags | ExpressionParseFlags::ACCEPT_COMMA);
2048
2049            if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
2050                ThrowSyntaxError("Unexpected token, expected ']'");
2051            }
2052            break;
2053        }
2054        default: {
2055            ThrowSyntaxError("Unexpected token in property key");
2056        }
2057    }
2058
2059    lexer_->NextToken();
2060    return key;
2061}
2062
2063ir::Expression *ParserImpl::ParsePropertyValue(const ir::PropertyKind *propertyKind, const ParserStatus *methodStatus,
2064                                               ExpressionParseFlags flags)
2065{
2066    bool isMethod = (*methodStatus & ParserStatus::FUNCTION) != 0;
2067    bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0;
2068
2069    if (!isMethod && !ir::Property::IsAccessorKind(*propertyKind)) {
2070        // If the actual property is not getter/setter nor method, the following
2071        // token must be ':'
2072        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
2073            ThrowSyntaxError("Unexpected token, expected ':'");
2074        }
2075
2076        lexer_->NextToken();  // eat colon
2077
2078        if (!inPattern) {
2079            return ParseExpression(flags);
2080        }
2081
2082        return ParsePatternElement();
2083    }
2084
2085    if (inPattern) {
2086        ThrowSyntaxError("Object pattern can't contain methods");
2087    }
2088
2089    ParserStatus newStatus = *methodStatus | ParserStatus::FUNCTION | ParserStatus::ALLOW_SUPER;
2090
2091    if (*propertyKind != ir::PropertyKind::SET) {
2092        newStatus |= ParserStatus::NEED_RETURN_TYPE;
2093    }
2094
2095    ir::ScriptFunction *methodDefinitonNode = ParseFunction(newStatus);
2096    methodDefinitonNode->AddFlag(ir::ScriptFunctionFlags::METHOD);
2097
2098    size_t paramsSize = methodDefinitonNode->Params().size();
2099
2100    auto *value = AllocNode<ir::FunctionExpression>(methodDefinitonNode);
2101    value->SetRange(methodDefinitonNode->Range());
2102
2103    if (*propertyKind == ir::PropertyKind::SET && paramsSize != 1) {
2104        ThrowSyntaxError("Setter must have exactly one formal parameter");
2105    }
2106
2107    if (*propertyKind == ir::PropertyKind::GET && paramsSize != 0) {
2108        ThrowSyntaxError("Getter must not have formal parameters");
2109    }
2110
2111    return value;
2112}
2113
2114// NOLINTNEXTLINE(google-default-arguments)
2115ir::Expression *ParserImpl::ParsePropertyDefinition([[maybe_unused]] ExpressionParseFlags flags)
2116{
2117    ir::PropertyKind propertyKind = ir::PropertyKind::INIT;
2118    ParserStatus methodStatus = ParserStatus::NO_OPTS;
2119
2120    const auto startPos = lexer_->Save();
2121    lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
2122    lexer::SourcePosition start = lexer_->GetToken().Start();
2123
2124    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
2125        return ParseSpreadElement(flags);
2126    }
2127
2128    if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
2129        if (ParsePropertyModifiers(flags, &propertyKind, &methodStatus)) {
2130            return ParseShorthandProperty(&startPos);
2131        }
2132    } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
2133        ParseGeneratorPropertyModifier(flags, &methodStatus);
2134    }
2135
2136    bool isComputed = lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET;
2137    ir::Expression *key = ParsePropertyKey(flags);
2138
2139    // Parse method property
2140    if ((lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS ||
2141         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) &&
2142        !ir::Property::IsAccessorKind(propertyKind)) {
2143        methodStatus |= ParserStatus::FUNCTION | ParserStatus::ALLOW_SUPER;
2144        propertyKind = ir::PropertyKind::INIT;
2145    } else if ((methodStatus & (ParserStatus::GENERATOR_FUNCTION | ParserStatus::ASYNC_FUNCTION)) != 0) {
2146        ThrowSyntaxError("Unexpected identifier");
2147    }
2148
2149    ir::Expression *value = ParsePropertyValue(&propertyKind, &methodStatus, flags);
2150    lexer::SourcePosition end = value->End();
2151
2152    ASSERT(key);
2153    ASSERT(value);
2154
2155    auto *returnProperty =
2156        AllocNode<ir::Property>(propertyKind, key, value, methodStatus != ParserStatus::NO_OPTS, isComputed);
2157    returnProperty->SetRange({start, end});
2158
2159    return returnProperty;
2160}
2161
2162bool ParserImpl::ParsePropertyEnd()
2163{
2164    // Property definiton must end with ',' or '}' otherwise we throw SyntaxError
2165    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA &&
2166        lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
2167        ThrowSyntaxError("Unexpected token, expected ',' or '}'");
2168    }
2169
2170    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA &&
2171        lexer_->Lookahead() == lexer::LEX_CHAR_RIGHT_BRACE) {
2172        lexer_->NextToken();
2173        return true;
2174    }
2175
2176    return false;
2177}
2178
2179// NOLINTNEXTLINE(google-default-arguments)
2180ir::ObjectExpression *ParserImpl::ParseObjectExpression(ExpressionParseFlags flags)
2181{
2182    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
2183    lexer::SourcePosition start = lexer_->GetToken().Start();
2184    ArenaVector<ir::Expression *> properties(Allocator()->Adapter());
2185    bool trailingComma = false;
2186    bool inPattern = (flags & ExpressionParseFlags::MUST_BE_PATTERN) != 0;
2187
2188    if (lexer_->Lookahead() == lexer::LEX_CHAR_RIGHT_BRACE) {
2189        lexer_->NextToken();
2190    }
2191
2192    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
2193        ir::Expression *property = ParsePropertyDefinition(flags | ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
2194        properties.push_back(property);
2195        trailingComma = ParsePropertyEnd();
2196    }
2197
2198    auto nodeType = inPattern ? ir::AstNodeType::OBJECT_PATTERN : ir::AstNodeType::OBJECT_EXPRESSION;
2199    auto *objectExpression =
2200        AllocNode<ir::ObjectExpression>(nodeType, Allocator(), std::move(properties), trailingComma);
2201    objectExpression->SetRange({start, lexer_->GetToken().End()});
2202    lexer_->NextToken();
2203
2204    if (inPattern) {
2205        objectExpression->SetDeclaration();
2206    }
2207
2208    if ((flags & ExpressionParseFlags::POTENTIALLY_IN_PATTERN) == 0) {
2209        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION &&
2210            !objectExpression->ConvertibleToObjectPattern()) {
2211            ThrowSyntaxError("Invalid left-hand side in array destructuring pattern", objectExpression->Start());
2212        } else if (!inPattern && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
2213            ir::ValidationInfo info = objectExpression->ValidateExpression();
2214            if (info.Fail()) {
2215                ThrowSyntaxError(info.msg.Utf8(), info.pos);
2216            }
2217        }
2218    }
2219
2220    return objectExpression;
2221}
2222
2223ir::SequenceExpression *ParserImpl::ParseSequenceExpression(ir::Expression *startExpr, bool acceptRest)
2224{
2225    lexer::SourcePosition start = startExpr->Start();
2226
2227    ArenaVector<ir::Expression *> sequence(Allocator()->Adapter());
2228    sequence.push_back(startExpr);
2229
2230    while (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2231        lexer_->NextToken();
2232
2233        if (acceptRest && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
2234            ir::SpreadElement *expr = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN);
2235            sequence.push_back(expr);
2236            break;
2237        }
2238
2239        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS && lexer_->CheckArrow()) {
2240            break;
2241        }
2242
2243        sequence.push_back(ParseExpression());
2244    }
2245
2246    lexer::SourcePosition end = sequence.back()->End();
2247    auto *sequenceNode = AllocNode<ir::SequenceExpression>(std::move(sequence));
2248    sequenceNode->SetRange({start, end});
2249
2250    return sequenceNode;
2251}
2252
2253// NOLINTNEXTLINE(google-default-arguments)
2254ir::Expression *ParserImpl::ParseUnaryOrPrefixUpdateExpression(ExpressionParseFlags flags)
2255{
2256    if (!lexer_->GetToken().IsUnary()) {
2257        return ParseLeftHandSideExpression(flags);
2258    }
2259
2260    lexer::TokenType operatorType = lexer_->GetToken().Type();
2261    lexer::SourcePosition start = lexer_->GetToken().Start();
2262    lexer_->NextToken();
2263
2264    ir::Expression *argument =
2265        lexer_->GetToken().IsUnary() ? ParseUnaryOrPrefixUpdateExpression() : ParseLeftHandSideExpression();
2266
2267    if (lexer::Token::IsUpdateToken(operatorType)) {
2268        if (!argument->IsIdentifier() && !argument->IsMemberExpression() && !argument->IsTSNonNullExpression()) {
2269            ThrowSyntaxError("Invalid left-hand side in prefix operation");
2270        }
2271
2272        if (argument->IsIdentifier()) {
2273            const util::StringView &argumentStr = argument->AsIdentifier()->Name();
2274
2275            if (argumentStr.Is("eval")) {
2276                ThrowSyntaxError("Assigning to 'eval' in strict mode is invalid");
2277            } else if (argumentStr.Is("arguments")) {
2278                ThrowSyntaxError("Assigning to 'arguments' in strict mode is invalid");
2279            }
2280        }
2281    }
2282
2283    if (operatorType == lexer::TokenType::KEYW_DELETE) {
2284        if (argument->IsIdentifier()) {
2285            ThrowSyntaxError("Deleting local variable in strict mode");
2286        }
2287
2288        if (argument->IsMemberExpression() && argument->AsMemberExpression()->Property()->IsIdentifier() &&
2289            argument->AsMemberExpression()->Property()->AsIdentifier()->IsPrivateIdent()) {
2290            ThrowSyntaxError("Private fields can not be deleted");
2291        }
2292    }
2293
2294    lexer::SourcePosition end = argument->End();
2295
2296    ir::Expression *returnExpr = nullptr;
2297
2298    if (lexer::Token::IsUpdateToken(operatorType)) {
2299        returnExpr = AllocNode<ir::UpdateExpression>(argument, operatorType, true);
2300    } else if (operatorType == lexer::TokenType::KEYW_AWAIT) {
2301        returnExpr = AllocNode<ir::AwaitExpression>(argument);
2302    } else if (operatorType == lexer::TokenType::KEYW_TYPEOF) {
2303        returnExpr = AllocNode<ir::TypeofExpression>(argument);
2304    } else {
2305        returnExpr = AllocNode<ir::UnaryExpression>(argument, operatorType);
2306    }
2307
2308    returnExpr->SetRange({start, end});
2309
2310    return returnExpr;
2311}
2312
2313ir::Expression *ParserImpl::ParseImportExpression()
2314{
2315    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2316    lexer::SourcePosition endLoc = lexer_->GetToken().End();
2317    lexer_->NextToken();  // eat import
2318
2319    // parse import.Meta
2320    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
2321        if (!context_.IsModule()) {
2322            ThrowSyntaxError("'import.Meta' may appear only with 'sourceType: module'");
2323        } else if (GetOptions().isDirectEval) {
2324            ThrowSyntaxError("'import.Meta' is not allowed in direct eval in module code.");
2325        }
2326
2327        lexer_->NextToken();  // eat dot
2328
2329        if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT ||
2330            lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_META) {
2331            ThrowSyntaxError("The only valid meta property for import is import.Meta");
2332        }
2333
2334        auto *metaProperty = AllocNode<ir::MetaProperty>(ir::MetaProperty::MetaPropertyKind::IMPORT_META);
2335        metaProperty->SetRange({startLoc, endLoc});
2336
2337        lexer_->NextToken();
2338        return metaProperty;
2339    }
2340
2341    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
2342        ThrowSyntaxError("Unexpected token");
2343    }
2344
2345    lexer_->NextToken();  // eat left parentheses
2346
2347    ir::Expression *source = ParseExpression();
2348
2349    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
2350        ThrowSyntaxError("Unexpected token");
2351    }
2352
2353    auto *importExpression = AllocNode<ir::ImportExpression>(source);
2354    importExpression->SetRange({startLoc, lexer_->GetToken().End()});
2355
2356    lexer_->NextToken();  // eat right paren
2357    return importExpression;
2358}
2359
2360bool ParserImpl::IsNamedFunctionExpression()
2361{
2362    return lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS;
2363}
2364
2365ir::FunctionExpression *ParserImpl::ParseFunctionExpression(ParserStatus newStatus)
2366{
2367    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2368    ir::Identifier *ident = nullptr;
2369
2370    if ((newStatus & ParserStatus::ARROW_FUNCTION) == 0) {
2371        ParserStatus savedStatus = context_.Status();
2372        context_.Status() |= static_cast<ParserStatus>(newStatus & ParserStatus::ASYNC_FUNCTION);
2373
2374        lexer_->NextToken();
2375
2376        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
2377            newStatus |= ParserStatus::GENERATOR_FUNCTION;
2378            lexer_->NextToken();
2379        }
2380
2381        if (IsNamedFunctionExpression()) {
2382            CheckRestrictedBinding(lexer_->GetToken().KeywordType());
2383            ident = ExpectIdentifier(false, true);
2384        }
2385
2386        context_.Status() = savedStatus;
2387    }
2388
2389    ir::ScriptFunction *functionNode = ParseFunction(newStatus);
2390    functionNode->SetStart(startLoc);
2391
2392    auto *funcExpr = AllocNode<ir::FunctionExpression>(ident, functionNode);
2393    funcExpr->SetRange(functionNode->Range());
2394
2395    return funcExpr;
2396}
2397}  // namespace ark::es2panda::parser
2398