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