1/**
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "parser/parserFlags.h"
17#include "parser/parserStatusContext.h"
18#include "util/helpers.h"
19#include "ir/astNode.h"
20#include "ir/base/catchClause.h"
21#include "ir/base/classDefinition.h"
22#include "ir/base/scriptFunction.h"
23#include "ir/expression.h"
24#include "ir/expressions/arrayExpression.h"
25#include "ir/expressions/binaryExpression.h"
26#include "ir/expressions/conditionalExpression.h"
27#include "ir/expressions/literals/stringLiteral.h"
28#include "ir/expressions/objectExpression.h"
29#include "ir/expressions/sequenceExpression.h"
30#include "ir/module/exportAllDeclaration.h"
31#include "ir/module/exportDefaultDeclaration.h"
32#include "ir/module/exportNamedDeclaration.h"
33#include "ir/module/exportSpecifier.h"
34#include "ir/module/importDeclaration.h"
35#include "ir/module/importDefaultSpecifier.h"
36#include "ir/module/importNamespaceSpecifier.h"
37#include "ir/module/importSpecifier.h"
38#include "ir/statements/assertStatement.h"
39#include "ir/statements/blockStatement.h"
40#include "ir/statements/breakStatement.h"
41#include "ir/statements/classDeclaration.h"
42#include "ir/statements/continueStatement.h"
43#include "ir/statements/debuggerStatement.h"
44#include "ir/statements/doWhileStatement.h"
45#include "ir/statements/emptyStatement.h"
46#include "ir/statements/expressionStatement.h"
47#include "ir/statements/forInStatement.h"
48#include "ir/statements/forOfStatement.h"
49#include "ir/statements/forUpdateStatement.h"
50#include "ir/statements/functionDeclaration.h"
51#include "ir/statements/ifStatement.h"
52#include "ir/statements/labelledStatement.h"
53#include "ir/statements/returnStatement.h"
54#include "ir/statements/switchCaseStatement.h"
55#include "ir/statements/switchStatement.h"
56#include "ir/statements/throwStatement.h"
57#include "ir/statements/tryStatement.h"
58#include "ir/statements/variableDeclaration.h"
59#include "ir/statements/variableDeclarator.h"
60#include "ir/statements/whileStatement.h"
61#include "ir/ets/etsStructDeclaration.h"
62#include "lexer/lexer.h"
63#include "lexer/token/letters.h"
64#include "lexer/token/sourceLocation.h"
65#include "util/ustring.h"
66
67#include "parserImpl.h"
68
69namespace ark::es2panda::parser {
70
71using namespace std::literals::string_literals;
72
73// NOLINTNEXTLINE(google-default-arguments)
74ir::Statement *ParserImpl::ParseStatement(StatementParsingFlags flags)
75{
76    switch (lexer_->GetToken().Type()) {
77        case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
78            return ParseBlockStatement();
79        }
80        case lexer::TokenType::PUNCTUATOR_SEMI_COLON: {
81            return ParseEmptyStatement();
82        }
83        case lexer::TokenType::KEYW_ASSERT: {
84            return ParseAssertStatement();
85        }
86        case lexer::TokenType::KEYW_EXPORT: {
87            return ParseExportDeclaration(flags);
88        }
89        case lexer::TokenType::KEYW_IMPORT: {
90            return ParseImportDeclaration(flags);
91        }
92        case lexer::TokenType::KEYW_FUNCTION: {
93            return ParseFunctionStatement(flags);
94        }
95        case lexer::TokenType::KEYW_CLASS: {
96            return ParseClassStatement(flags, ir::ClassDefinitionModifiers::NONE);
97        }
98        case lexer::TokenType::KEYW_VAR: {
99            return ParseVarStatement();
100        }
101        case lexer::TokenType::KEYW_LET: {
102            return ParseLetStatement(flags);
103        }
104        case lexer::TokenType::KEYW_CONST: {
105            return ParseConstStatement(flags);
106        }
107        case lexer::TokenType::KEYW_IF: {
108            return ParseIfStatement();
109        }
110        case lexer::TokenType::KEYW_DO: {
111            return ParseDoWhileStatement();
112        }
113        case lexer::TokenType::KEYW_FOR: {
114            return ParseForStatement();
115        }
116        case lexer::TokenType::KEYW_TRY: {
117            return ParseTryStatement();
118        }
119        case lexer::TokenType::KEYW_WHILE: {
120            return ParseWhileStatement();
121        }
122        case lexer::TokenType::KEYW_BREAK: {
123            return ParseBreakStatement();
124        }
125        case lexer::TokenType::KEYW_CONTINUE: {
126            return ParseContinueStatement();
127        }
128        case lexer::TokenType::KEYW_THROW: {
129            return ParseThrowStatement();
130        }
131        case lexer::TokenType::KEYW_RETURN: {
132            return ParseReturnStatement();
133        }
134        case lexer::TokenType::KEYW_SWITCH: {
135            return ParseSwitchStatement();
136        }
137        case lexer::TokenType::KEYW_DEBUGGER: {
138            return ParseDebuggerStatement();
139        }
140        case lexer::TokenType::LITERAL_IDENT: {
141            if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STRUCT) {
142                return ParseStructStatement(flags, ir::ClassDefinitionModifiers::NONE);
143            }
144
145            if (lexer_->Lookahead() == lexer::LEX_CHAR_COLON) {
146                const auto pos = lexer_->Save();
147                lexer_->NextToken();
148                return ParseLabelledStatement(pos);
149            }
150
151            return ParsePotentialExpressionStatement(flags);
152        }
153        case lexer::TokenType::KEYW_WITH: {
154            ThrowSyntaxError("'With' is deprecated and not supported any more.");
155        }
156        case lexer::TokenType::KEYW_ENUM: {
157            return ParseEnumDeclaration();
158        }
159        case lexer::TokenType::KEYW_INTERFACE: {
160            return ParseInterfaceDeclaration(false);
161        }
162        case lexer::TokenType::PUNCTUATOR_FORMAT: {
163            if (lexer_->Lookahead() == static_cast<char32_t>(STATEMENT_FORMAT_NODE)) {
164                return ParseStatementFormatPlaceholder();
165            }
166            [[fallthrough]];
167        }
168        default: {
169            return ParseExpressionStatement(flags);
170        }
171    }
172}
173
174ir::Statement *ParserImpl::ParseVarStatement()
175{
176    auto *variableDecl = ParseVariableDeclaration(VariableParsingFlags::VAR);
177    ConsumeSemicolon(variableDecl);
178    return variableDecl;
179}
180
181ir::Statement *ParserImpl::ParseLetStatement(StatementParsingFlags flags)
182{
183    if ((flags & StatementParsingFlags::ALLOW_LEXICAL) == 0) {
184        ThrowSyntaxError("Lexical declaration is not allowed in single statement context");
185    }
186
187    auto *variableDecl = ParseVariableDeclaration(VariableParsingFlags::LET);
188    ConsumeSemicolon(variableDecl);
189    return variableDecl;
190}
191
192ir::Statement *ParserImpl::ParseConstStatement(StatementParsingFlags flags)
193{
194    if ((flags & StatementParsingFlags::ALLOW_LEXICAL) == 0) {
195        ThrowSyntaxError("Lexical declaration is not allowed in single statement context");
196    }
197
198    lexer::SourcePosition constVarStar = lexer_->GetToken().Start();
199    lexer_->NextToken();
200
201    auto *variableDecl = ParseVariableDeclaration(VariableParsingFlags::CONST | VariableParsingFlags::NO_SKIP_VAR_KIND);
202    variableDecl->SetStart(constVarStar);
203    ConsumeSemicolon(variableDecl);
204
205    return variableDecl;
206}
207
208ir::EmptyStatement *ParserImpl::ParseEmptyStatement()
209{
210    auto *empty = AllocNode<ir::EmptyStatement>();
211    empty->SetRange(lexer_->GetToken().Loc());
212    lexer_->NextToken();
213    return empty;
214}
215
216ir::DebuggerStatement *ParserImpl::ParseDebuggerStatement()
217{
218    auto *debuggerNode = AllocNode<ir::DebuggerStatement>();
219    debuggerNode->SetRange(lexer_->GetToken().Loc());
220    lexer_->NextToken();
221    ConsumeSemicolon(debuggerNode);
222    return debuggerNode;
223}
224
225ir::Statement *ParserImpl::ParseFunctionStatement(StatementParsingFlags flags)
226{
227    CheckFunctionDeclaration(flags);
228
229    if ((flags & StatementParsingFlags::STMT_LEXICAL_SCOPE_NEEDED) == 0) {
230        return ParseFunctionDeclaration(false, ParserStatus::NO_OPTS);
231    }
232
233    auto *funcDecl = ParseFunctionDeclaration(false, ParserStatus::NO_OPTS);
234    if (funcDecl == nullptr) {  // Error processing.
235        return nullptr;
236    }
237
238    ArenaVector<ir::Statement *> stmts(Allocator()->Adapter());
239    stmts.push_back(funcDecl);
240
241    auto *localBlockStmt = AllocNode<ir::BlockStatement>(Allocator(), std::move(stmts));
242    localBlockStmt->SetRange(funcDecl->Range());
243
244    return funcDecl;
245}
246
247ir::Statement *ParserImpl::ParsePotentialExpressionStatement(StatementParsingFlags flags)
248{
249    return ParseExpressionStatement(flags);
250}
251
252// NOLINTNEXTLINE(google-default-arguments)
253ir::ETSStructDeclaration *ParserImpl::ParseStructStatement([[maybe_unused]] StatementParsingFlags flags,
254                                                           [[maybe_unused]] ir::ClassDefinitionModifiers modifiers,
255                                                           [[maybe_unused]] ir::ModifierFlags modFlags)
256{
257    ThrowSyntaxError("Illegal start of expression", Lexer()->GetToken().Start());
258}
259
260// NOLINTNEXTLINE(google-default-arguments)
261ir::ClassDeclaration *ParserImpl::ParseClassStatement(StatementParsingFlags flags,
262                                                      ir::ClassDefinitionModifiers modifiers,
263                                                      ir::ModifierFlags modFlags)
264{
265    if ((flags & StatementParsingFlags::ALLOW_LEXICAL) == 0) {
266        ThrowSyntaxError("Lexical declaration is not allowed in single statement context");
267    }
268
269    return ParseClassDeclaration(modifiers, modFlags);
270}
271
272ir::ETSStructDeclaration *ParserImpl::ParseStructDeclaration(ir::ClassDefinitionModifiers modifiers,
273                                                             ir::ModifierFlags flags)
274{
275    const lexer::SourcePosition startLoc = lexer_->GetToken().Start();
276    modifiers |= ir::ClassDefinitionModifiers::DECLARATION;
277    if (IsExternal()) {
278        modifiers |= ir::ClassDefinitionModifiers::FROM_EXTERNAL;
279    }
280
281    if ((flags & ir::ModifierFlags::ABSTRACT) != 0U) {
282        ThrowSyntaxError("struct declaration is not allowed to use 'abstract' modifiers.");
283    }
284
285    ir::ClassDefinition *classDefinition = ParseClassDefinition(modifiers, flags);
286
287    if ((classDefinition->Modifiers() & ir::ClassDefinitionModifiers::HAS_SUPER) != 0U) {
288        ThrowSyntaxError("struct declaration cannot extends form other class");
289    }
290
291    lexer::SourcePosition endLoc = classDefinition->End();
292    auto *structDecl = AllocNode<ir::ETSStructDeclaration>(classDefinition, Allocator());
293    structDecl->SetRange({startLoc, endLoc});
294    return structDecl;
295}
296
297ir::ClassDeclaration *ParserImpl::ParseClassDeclaration(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags)
298{
299    const lexer::SourcePosition startLoc = lexer_->GetToken().Start();
300    modifiers |= ir::ClassDefinitionModifiers::DECLARATION;
301    if (IsExternal()) {
302        modifiers |= ir::ClassDefinitionModifiers::FROM_EXTERNAL;
303    }
304
305    ir::ClassDefinition *classDefinition = ParseClassDefinition(modifiers, flags);
306
307    lexer::SourcePosition endLoc = classDefinition->End();
308    auto *classDecl = AllocNode<ir::ClassDeclaration>(classDefinition, Allocator());
309    classDecl->SetRange({startLoc, endLoc});
310    return classDecl;
311}
312
313void ParserImpl::CheckFunctionDeclaration(StatementParsingFlags flags)
314{
315    if ((flags & StatementParsingFlags::LABELLED) != 0) {
316        ThrowSyntaxError(
317            "In strict mode code, functions can only be "
318            "declared at top level, inside a block, "
319            "or "
320            "as the body of an if statement");
321    }
322
323    if ((flags & StatementParsingFlags::ALLOW_LEXICAL) == 0) {
324        if ((flags & (StatementParsingFlags::IF_ELSE | StatementParsingFlags::LABELLED)) == 0) {
325            ThrowSyntaxError("Lexical declaration is not allowed in single statement context");
326        }
327
328        if (lexer_->Lookahead() == lexer::LEX_CHAR_ASTERISK) {
329            ThrowSyntaxError("Generators can only be declared at the top level or inside a block");
330        }
331    }
332}
333
334void ParserImpl::ConsumeSemicolon(ir::Statement *statement)
335{
336    auto tokenType = lexer_->GetToken().Type();
337    if (tokenType == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
338        statement->SetEnd(lexer_->GetToken().End());
339        lexer_->NextToken();
340        return;
341    }
342
343    if (!lexer_->GetToken().NewLine() && tokenType != lexer::TokenType::EOS &&
344        tokenType != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
345        LogSyntaxError({"Unexpected token '", TokenToString(tokenType), "'."});
346    }
347}
348
349ArenaVector<ir::Statement *> ParserImpl::ParseStatementList(StatementParsingFlags flags)
350{
351    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT &&
352        lexer_->Lookahead() == static_cast<char32_t>(ARRAY_FORMAT_NODE)) {
353        return std::move(ParseStatementsArrayFormatPlaceholder());
354    }
355
356    ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
357    ParseDirectivePrologue(&statements);
358
359    auto endType =
360        (flags & StatementParsingFlags::GLOBAL) != 0 ? lexer::TokenType::EOS : lexer::TokenType::PUNCTUATOR_RIGHT_BRACE;
361
362    while (lexer_->GetToken().Type() != endType) {
363        if (auto statement = ParseStatement(flags); statement != nullptr) {  // Error processing.
364            statements.push_back(statement);
365        }
366    }
367
368    return statements;
369}
370
371bool ParserImpl::ParseDirective(ArenaVector<ir::Statement *> *statements)
372{
373    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
374
375    const util::StringView &str = lexer_->GetToken().String();
376
377    const auto status = static_cast<ParserStatus>(
378        context_.Status() & (ParserStatus::CONSTRUCTOR_FUNCTION | ParserStatus::HAS_COMPLEX_PARAM));
379    if (status == ParserStatus::HAS_COMPLEX_PARAM && str.Is("use strict")) {
380        ThrowSyntaxError(
381            "Illegal 'use strict' directive in function with "
382            "non-simple parameter list");
383    }
384
385    ir::Expression *exprNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
386    bool isDirective = exprNode->IsStringLiteral();
387
388    auto *exprStatement = AllocNode<ir::ExpressionStatement>(exprNode);
389    exprStatement->SetRange(exprNode->Range());
390
391    ConsumeSemicolon(exprStatement);
392    statements->push_back(exprStatement);
393
394    return isDirective;
395}
396
397void ParserImpl::ParseDirectivePrologue(ArenaVector<ir::Statement *> *statements)
398{
399    while (true) {
400        if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING || !ParseDirective(statements)) {
401            break;
402        }
403    }
404}
405
406ir::Statement *ParserImpl::ParseAssertStatement()
407{
408    return nullptr;
409}
410
411void ParserImpl::ValidateLabeledStatement([[maybe_unused]] lexer::TokenType type) {}
412
413ir::BlockStatement *ParserImpl::ParseBlockStatement()
414{
415    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
416
417    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
418    lexer_->NextToken();
419    auto statements = ParseStatementList();
420
421    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
422        ThrowSyntaxError("Expected a '}'");
423    }
424
425    auto *blockNode = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
426    blockNode->SetRange({startLoc, lexer_->GetToken().End()});
427
428    lexer_->NextToken();
429    return blockNode;
430}
431
432void ParserImpl::ThrowPossibleOutOfBoundaryJumpError([[maybe_unused]] bool allowBreak) {}
433
434void ParserImpl::ThrowIllegalBreakError()
435{
436    ThrowSyntaxError("Illegal break statement");
437}
438
439ir::BreakStatement *ParserImpl::ParseBreakStatement()
440{
441    bool allowBreak = (context_.Status() & (ParserStatus::IN_ITERATION | ParserStatus::IN_SWITCH)) != 0;
442
443    ThrowPossibleOutOfBoundaryJumpError(allowBreak);
444
445    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
446    lexer_->NextToken();
447
448    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON ||
449        lexer_->GetToken().Type() == lexer::TokenType::EOS || lexer_->GetToken().NewLine() ||
450        lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
451        if (!allowBreak) {
452            ThrowIllegalBreakError();
453        }
454
455        auto *breakStatement = AllocNode<ir::BreakStatement>();
456        breakStatement->SetRange({startLoc, lexer_->GetToken().End()});
457
458        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
459            lexer_->NextToken();
460        }
461
462        return breakStatement;
463    }
464
465    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
466        ThrowSyntaxError("Unexpected token.");
467    }
468
469    const auto &label = lexer_->GetToken().Ident();
470    if (!ValidateBreakLabel(label)) {
471        ThrowSyntaxError("Undefined label");
472    }
473
474    auto *identNode = AllocNode<ir::Identifier>(label, Allocator());
475    identNode->SetReference();
476    identNode->SetRange(lexer_->GetToken().Loc());
477
478    auto *breakStatement = AllocNode<ir::BreakStatement>(identNode);
479    breakStatement->SetRange({startLoc, lexer_->GetToken().End()});
480
481    lexer_->NextToken();
482    ConsumeSemicolon(breakStatement);
483
484    return breakStatement;
485}
486
487void ParserImpl::ThrowIllegalContinueError()
488{
489    ThrowSyntaxError("Illegal continue statement");
490}
491
492ir::ContinueStatement *ParserImpl::ParseContinueStatement()
493{
494    ThrowPossibleOutOfBoundaryJumpError((context_.Status() & (ParserStatus::IN_ITERATION | ParserStatus::IN_SWITCH)) !=
495                                        0U);
496
497    if ((context_.Status() & ParserStatus::IN_ITERATION) == 0) {
498        ThrowIllegalContinueError();
499    }
500
501    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
502    lexer::SourcePosition endLoc = lexer_->GetToken().End();
503    lexer_->NextToken();
504
505    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
506        auto *continueStatement = AllocNode<ir::ContinueStatement>();
507        continueStatement->SetRange({startLoc, lexer_->GetToken().End()});
508        lexer_->NextToken();
509        return continueStatement;
510    }
511
512    if (lexer_->GetToken().NewLine() || lexer_->GetToken().Type() == lexer::TokenType::EOS ||
513        lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
514        auto *continueStatement = AllocNode<ir::ContinueStatement>();
515        continueStatement->SetRange({startLoc, endLoc});
516        return continueStatement;
517    }
518
519    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
520        ThrowSyntaxError("Unexpected token.");
521    }
522
523    const auto &label = lexer_->GetToken().Ident();
524    if (!ValidateContinueLabel(label)) {
525        ThrowSyntaxError("Undefined label");
526    }
527
528    auto *identNode = AllocNode<ir::Identifier>(label, Allocator());
529    identNode->SetReference();
530    identNode->SetRange(lexer_->GetToken().Loc());
531
532    auto *continueStatement = AllocNode<ir::ContinueStatement>(identNode);
533    continueStatement->SetRange({startLoc, lexer_->GetToken().End()});
534
535    lexer_->NextToken();
536    ConsumeSemicolon(continueStatement);
537
538    return continueStatement;
539}
540
541ir::DoWhileStatement *ParserImpl::ParseDoWhileStatement()
542{
543    IterationContext iterCtx(&context_);
544
545    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
546    lexer_->NextToken();
547    ir::Statement *body = ParseStatement();
548
549    if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_WHILE) {
550        ThrowSyntaxError("Missing 'while' keyword in a 'DoWhileStatement'");
551    }
552
553    lexer_->NextToken();
554    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
555        ThrowSyntaxError("Missing left parenthesis in a 'DoWhileStatement'");
556    }
557
558    lexer_->NextToken();
559
560    ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
561
562    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
563        ThrowSyntaxError("Missing right parenthesis in a 'DoWhileStatement'");
564    }
565
566    auto *doWhileStatement = AllocNode<ir::DoWhileStatement>(body, test);
567    doWhileStatement->SetRange({startLoc, lexer_->GetToken().End()});
568
569    lexer_->NextToken();
570
571    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
572        doWhileStatement->SetEnd(lexer_->GetToken().End());
573        lexer_->NextToken();
574    }
575
576    return doWhileStatement;
577}
578
579ir::FunctionDeclaration *ParserImpl::ParseFunctionDeclaration(bool canBeAnonymous, ParserStatus newStatus)
580{
581    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
582
583    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION);
584    ParserStatus savedStatus = context_.Status();
585
586    lexer_->NextToken();
587
588    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
589        newStatus |= ParserStatus::GENERATOR_FUNCTION;
590        lexer_->NextToken();
591    }
592
593    context_.Status() = savedStatus;
594
595    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
596        if (canBeAnonymous) {
597            ir::ScriptFunction *func = ParseFunction(newStatus | ParserStatus::NEED_RETURN_TYPE);
598            func->SetStart(startLoc);
599
600            auto *funcDecl = AllocNode<ir::FunctionDeclaration>(Allocator(), func, true);
601            funcDecl->SetRange(func->Range());
602            return funcDecl;
603        }
604
605        ThrowSyntaxError("Unexpected token, expected identifier after 'function' keyword");
606    }
607
608    CheckRestrictedBinding();
609    auto *identNode = ExpectIdentifier();
610
611    newStatus |= ParserStatus::FUNCTION_DECLARATION;
612    ir::ScriptFunction *func = ParseFunction(newStatus | ParserStatus::NEED_RETURN_TYPE);
613
614    func->SetIdent(identNode);
615    func->SetStart(startLoc);
616    auto *funcDecl = AllocNode<ir::FunctionDeclaration>(Allocator(), func);
617    funcDecl->SetRange(func->Range());
618
619    if (func->IsOverload() && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
620        lexer_->NextToken();
621    }
622
623    return funcDecl;
624}
625
626ir::Statement *ParserImpl::ParseExpressionStatement(StatementParsingFlags flags)
627{
628    const auto startPos = lexer_->Save();
629    ParserStatus savedStatus = context_.Status();
630
631    auto tokenType = lexer_->GetToken().Type();
632    if (tokenType == lexer::TokenType::KEYW_PUBLIC || tokenType == lexer::TokenType::KEYW_PRIVATE ||
633        tokenType == lexer::TokenType::KEYW_PROTECTED) {
634        lexer_->NextToken();
635        if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_CLASS ||
636            lexer_->GetToken().Type() == lexer::TokenType::KEYW_INTERFACE) {
637            ThrowSyntaxError("A local class or interface declaration can not have access modifier",
638                             startPos.GetToken().Start());
639        }
640        lexer_->Rewind(startPos);
641    }
642
643    if (lexer_->GetToken().IsAsyncModifier()) {
644        lexer_->NextToken();
645
646        if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION && !lexer_->GetToken().NewLine()) {
647            if ((flags & StatementParsingFlags::ALLOW_LEXICAL) == 0) {
648                ThrowSyntaxError("Lexical declaration is not allowed in single statement context");
649            }
650
651            ir::FunctionDeclaration *functionDecl = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION);
652            functionDecl->SetStart(startPos.GetToken().Start());
653
654            return functionDecl;
655        }
656
657        lexer_->Rewind(startPos);
658    }
659
660    ir::Expression *exprNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
661    context_.Status() = savedStatus;
662    lexer::SourcePosition endPos = exprNode->End();
663
664    auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(exprNode);
665    exprStatementNode->SetRange({startPos.GetToken().Start(), endPos});
666    ConsumeSemicolon(exprStatementNode);
667
668    return exprStatementNode;
669}
670
671// NOLINTBEGIN(cert-err58-cpp)
672static std::string const INVALID_LEFT_HAND_IN_FOR_OF =
673    "Invalid left-hand side in 'for' statement: must have a single binding."s;
674static std::string const UNEXPECTED_TOKEN = "Unexpected token"s;
675static std::string const MISSING_LEFT_IN_FOR = "Missing left parenthesis in 'for' statement."s;
676static std::string const MISSING_RIGHT_IN_FOR = "Missing right parenthesis in 'for' statement."s;
677static std::string const INVALID_TYPE_ANNOTATION_IN_FOR =
678    "Type annotation is not allowed when existing variable is used as loop iterator in 'for' statement."s;
679// NOLINTEND(cert-err58-cpp)
680
681std::tuple<ForStatementKind, ir::Expression *, ir::Expression *> ParserImpl::ParseForInOf(
682    ir::AstNode *initNode, ExpressionParseFlags exprFlags, bool isAwait)
683{
684    ForStatementKind forKind = ForStatementKind::UPDATE;
685    ir::Expression *updateNode = nullptr;
686    ir::Expression *rightNode = nullptr;
687
688    if (lexer_->GetToken().IsForInOf()) {
689        const ir::VariableDeclarator *varDecl = initNode->AsVariableDeclaration()->Declarators().front();
690
691        if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN) {
692            if (varDecl->Init() != nullptr) {
693                ThrowSyntaxError("for-in loop variable declaration may not have an initializer");
694            }
695            forKind = ForStatementKind::IN;
696            exprFlags = ExpressionParseFlags::ACCEPT_COMMA;
697            ValidateForInStatement();
698        } else {
699            if (varDecl->Init() != nullptr) {
700                ThrowSyntaxError("for-of loop variable declaration may not have an initializer");
701            }
702
703            forKind = ForStatementKind::OF;
704        }
705
706        lexer_->NextToken();
707        rightNode = ParseExpression(exprFlags);
708    } else {
709        if (isAwait) {
710            ThrowSyntaxError("Unexpected token");
711        }
712
713        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
714            ThrowSyntaxError("Invalid left-hand side in 'For[In/Of]Statement'");
715        } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
716            lexer_->NextToken();
717        } else {
718            rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::IN_FOR);
719            if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
720                ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
721            }
722            lexer_->NextToken();
723        }
724
725        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
726            updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::IN_FOR);
727        }
728    }
729
730    return {forKind, rightNode, updateNode};
731}
732
733std::tuple<ForStatementKind, ir::AstNode *, ir::Expression *, ir::Expression *> ParserImpl::ParseIsForInOf(
734    ir::Expression *leftNode, ExpressionParseFlags exprFlags)
735{
736    ASSERT(lexer_->GetToken().IsForInOf());
737    ForStatementKind forKind = ForStatementKind::OF;
738
739    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN) {
740        forKind = ForStatementKind::IN;
741        exprFlags = ExpressionParseFlags::ACCEPT_COMMA;
742        ValidateForInStatement();
743    }
744
745    bool isValid = true;
746    switch (leftNode->Type()) {
747        case ir::AstNodeType::IDENTIFIER:
748        case ir::AstNodeType::MEMBER_EXPRESSION: {
749            break;
750        }
751        case ir::AstNodeType::ARRAY_EXPRESSION: {
752            isValid = leftNode->AsArrayExpression()->ConvertibleToArrayPattern();
753            break;
754        }
755        case ir::AstNodeType::OBJECT_EXPRESSION: {
756            isValid = leftNode->AsObjectExpression()->ConvertibleToObjectPattern();
757            break;
758        }
759        default: {
760            isValid = false;
761        }
762    }
763
764    if (!isValid) {
765        ValidateLvalueAssignmentTarget(leftNode);
766    }
767
768    lexer_->NextToken();
769
770    return {forKind, leftNode, ParseExpression(exprFlags), nullptr};
771}
772
773std::tuple<ForStatementKind, ir::AstNode *, ir::Expression *, ir::Expression *> ParserImpl::ParseForInOf(
774    ir::Expression *leftNode, ExpressionParseFlags exprFlags, bool isAwait)
775{
776    ir::Expression *updateNode = nullptr;
777    ir::Expression *rightNode = nullptr;
778    if (lexer_->GetToken().IsForInOf()) {
779        return ParseIsForInOf(leftNode, exprFlags);
780    }
781
782    if (isAwait) {
783        ThrowSyntaxError("Unexpected token");
784    }
785
786    ir::Expression *expr = ParseAssignmentExpression(leftNode);
787
788    ir::AstNode *initNode =
789        lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA ? ParseSequenceExpression(expr) : expr;
790
791    if (initNode->IsConditionalExpression()) {
792        ir::ConditionalExpression *condExpr = initNode->AsConditionalExpression();
793        if (condExpr->Alternate()->IsBinaryExpression() &&
794            condExpr->Alternate()->AsBinaryExpression()->OperatorType() == lexer::TokenType::KEYW_IN) {
795            ThrowSyntaxError("Invalid left-hand side in for-in statement");
796        }
797    }
798
799    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
800        ThrowSyntaxError("Invalid left-hand side in 'For[In/Of]Statement'");
801    }
802
803    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
804        ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
805    }
806
807    lexer_->NextToken();
808
809    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
810        lexer_->NextToken();
811    } else {
812        rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::IN_FOR);
813        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
814            ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
815        }
816        lexer_->NextToken();
817    }
818
819    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
820        updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::IN_FOR);
821    }
822
823    return {ForStatementKind::UPDATE, initNode, rightNode, updateNode};
824}
825
826std::tuple<ir::Expression *, ir::Expression *> ParserImpl::ParseForUpdate(bool isAwait)
827{
828    if (isAwait) {
829        ThrowSyntaxError("Unexpected token");
830    }
831
832    ir::Expression *updateNode = nullptr;
833    ir::Expression *rightNode = nullptr;
834
835    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
836        lexer_->NextToken();
837    } else {
838        rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::IN_FOR);
839        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
840            ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
841        }
842        lexer_->NextToken();
843    }
844
845    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
846        updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::IN_FOR);
847    }
848
849    return {rightNode, updateNode};
850}
851
852std::tuple<ir::Expression *, ir::AstNode *> ParserImpl::ParseForLoopInitializer()
853{
854    VariableParsingFlags varFlags = VariableParsingFlags::IN_FOR;
855
856    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) {
857        varFlags |= VariableParsingFlags::DISALLOW_INIT;
858        lexer_->NextToken();
859    }
860
861    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
862        ThrowSyntaxError(MISSING_LEFT_IN_FOR, lexer_->GetToken().Start());
863    }
864    lexer_->NextToken();
865
866    lexer::TokenType tokenType;
867    auto const currentPosition = lexer_->Save();
868    do {
869        tokenType = lexer_->GetToken().Type();
870        if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OF) {
871            varFlags |= VariableParsingFlags::FOR_OF;
872            break;
873        }
874        if (tokenType == lexer::TokenType::KEYW_IN) {
875            varFlags |= VariableParsingFlags::STOP_AT_IN;
876            break;
877        }
878        lexer_->NextToken();
879    } while (tokenType != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS &&
880             tokenType != lexer::TokenType::PUNCTUATOR_LEFT_BRACE &&
881             tokenType != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS && tokenType != lexer::TokenType::EOS);
882    lexer_->Rewind(currentPosition);
883
884    switch (lexer_->GetToken().Type()) {
885        case lexer::TokenType::KEYW_VAR: {
886            return {nullptr, ParseVariableDeclaration(varFlags | VariableParsingFlags::VAR)};
887        }
888        case lexer::TokenType::KEYW_LET: {
889            return {nullptr, ParseVariableDeclaration(varFlags | VariableParsingFlags::LET)};
890        }
891        case lexer::TokenType::KEYW_CONST: {
892            return {nullptr, ParseVariableDeclaration(varFlags | VariableParsingFlags::CONST |
893                                                      VariableParsingFlags::ACCEPT_CONST_NO_INIT)};
894        }
895        case lexer::TokenType::PUNCTUATOR_SEMI_COLON: {
896            if ((varFlags & VariableParsingFlags::DISALLOW_INIT) != 0 /*isAsync*/) {
897                ThrowSyntaxError(UNEXPECTED_TOKEN, lexer_->GetToken().Start());
898            }
899
900            lexer_->NextToken();
901            return {nullptr, nullptr};
902        }
903        default: {
904            return {ParseUnaryOrPrefixUpdateExpression(ExpressionParseFlags::POTENTIALLY_IN_PATTERN), nullptr};
905        }
906    }
907}
908
909ir::Statement *ParserImpl::ParseForStatement()
910{
911    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
912    ForStatementKind forKind = ForStatementKind::UPDATE;
913    ir::AstNode *initNode = nullptr;
914    ir::Expression *updateNode = nullptr;
915    ir::Expression *leftNode = nullptr;
916    ir::Expression *rightNode = nullptr;
917
918    lexer_->NextToken();
919    bool isAwait = lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT;
920    std::tie(leftNode, initNode) = ParseForLoopInitializer();
921    bool canBeForInOf = (leftNode != nullptr) || (initNode != nullptr);
922
923    IterationContext iterCtx(&context_);
924
925    if (initNode != nullptr) {
926        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
927            lexer_->NextToken();
928            canBeForInOf = false;
929        } else if (initNode->AsVariableDeclaration()->Declarators().size() > 1 && lexer_->GetToken().IsForInOf()) {
930            ThrowSyntaxError(INVALID_LEFT_HAND_IN_FOR_OF, initNode->AsVariableDeclaration()->Declarators()[1]->Start());
931        }
932    }
933
934    // VariableDeclaration->DeclarationSize > 1 or seen semi_colon
935    if (!canBeForInOf) {
936        std::tie(rightNode, updateNode) = ParseForUpdate(isAwait);
937    } else if (leftNode != nullptr) {
938        // initNode was parsed as LHS
939        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
940            ThrowSyntaxError(INVALID_TYPE_ANNOTATION_IN_FOR, lexer_->GetToken().Start());
941        }
942        std::tie(forKind, initNode, rightNode, updateNode) =
943            ParseForInOf(leftNode, ExpressionParseFlags::NO_OPTS, isAwait);
944    } else if (initNode != nullptr) {
945        // initNode was parsed as VariableDeclaration and declaration size = 1
946        std::tie(forKind, rightNode, updateNode) = ParseForInOf(initNode, ExpressionParseFlags::NO_OPTS, isAwait);
947    }
948
949    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) {
950        lexer_->NextToken();
951    }
952    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
953        ThrowSyntaxError(MISSING_RIGHT_IN_FOR, lexer_->GetToken().Start());
954    }
955    lexer_->NextToken();
956
957    ir::Statement *bodyNode = ParseStatement();
958    ir::Statement *forStatement = nullptr;
959
960    if (forKind == ForStatementKind::UPDATE) {
961        forStatement = AllocNode<ir::ForUpdateStatement>(initNode, rightNode, updateNode, bodyNode);
962    } else if (forKind == ForStatementKind::IN) {
963        forStatement = AllocNode<ir::ForInStatement>(initNode, rightNode, bodyNode);
964    } else {
965        forStatement = AllocNode<ir::ForOfStatement>(initNode, rightNode, bodyNode, isAwait);
966    }
967
968    forStatement->SetRange({startLoc, bodyNode->End()});
969
970    return forStatement;
971}
972
973void ParserImpl::ThrowIfBodyEmptyError([[maybe_unused]] ir::Statement *consequent) {}
974
975ir::IfStatement *ParserImpl::ParseIfStatement()
976{
977    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
978    lexer::SourcePosition endLoc;
979    lexer_->NextToken();
980
981    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
982        ThrowSyntaxError("Missing left parenthesis in an 'IfStatement'");
983    }
984
985    lexer_->NextToken();
986    ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
987
988    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
989        ThrowSyntaxError("Missing right parenthesis in an 'IfStatement'");
990    }
991
992    lexer_->NextToken();
993    ir::Statement *consequent = ParseStatement(StatementParsingFlags::IF_ELSE | StatementParsingFlags::ALLOW_LEXICAL);
994
995    ThrowIfBodyEmptyError(consequent);
996
997    endLoc = consequent->End();
998    ir::Statement *alternate = nullptr;
999
1000    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_ELSE) {
1001        lexer_->NextToken();  // eat ELSE keyword
1002        alternate = ParseStatement(StatementParsingFlags::IF_ELSE | StatementParsingFlags::ALLOW_LEXICAL);
1003        endLoc = alternate->End();
1004    }
1005
1006    auto *ifStatement = AllocNode<ir::IfStatement>(test, consequent, alternate);
1007    ifStatement->SetRange({startLoc, endLoc});
1008    return ifStatement;
1009}
1010
1011ir::LabelledStatement *ParserImpl::ParseLabelledStatement(const lexer::LexerPosition &pos)
1012{
1013    const util::StringView &actualLabel = pos.GetToken().Ident();
1014
1015    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AWAIT && context_.IsModule()) {
1016        ThrowSyntaxError("'await' is a reserved identifier in module code", pos.GetToken().Start());
1017    }
1018
1019    if (context_.FindLabel(actualLabel) != nullptr) {
1020        ThrowSyntaxError("Label already declared", pos.GetToken().Start());
1021    }
1022
1023    SavedParserContext newCtx(this, ParserStatus::IN_LABELED, actualLabel);
1024
1025    auto *identNode = AllocNode<ir::Identifier>(actualLabel, Allocator());
1026    identNode->SetReference();
1027    identNode->SetRange(pos.GetToken().Loc());
1028
1029    lexer_->NextToken();
1030
1031    ValidateLabeledStatement(Lexer()->GetToken().Type());
1032
1033    ir::Statement *body = ParseStatement(StatementParsingFlags::LABELLED);
1034
1035    auto *labeledStatement = AllocNode<ir::LabelledStatement>(identNode, body);
1036    labeledStatement->SetRange({pos.GetToken().Start(), body->End()});
1037
1038    return labeledStatement;
1039}
1040
1041ir::ReturnStatement *ParserImpl::ParseReturnStatement()
1042{
1043    if ((context_.Status() & ParserStatus::FUNCTION) == 0) {
1044        ThrowSyntaxError("return keyword should be used in function body");
1045    }
1046
1047    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1048    lexer::SourcePosition endLoc = lexer_->GetToken().End();
1049    lexer_->NextToken();
1050
1051    bool hasArgument = (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
1052                        lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
1053                        lexer_->GetToken().Type() != lexer::TokenType::EOS && !lexer_->GetToken().NewLine());
1054
1055    ir::ReturnStatement *returnStatement = nullptr;
1056
1057    if (hasArgument) {
1058        ir::Expression *expression = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1059        endLoc = expression->End();
1060        returnStatement = AllocNode<ir::ReturnStatement>(expression);
1061    } else {
1062        returnStatement = AllocNode<ir::ReturnStatement>();
1063    }
1064
1065    returnStatement->SetRange({startLoc, endLoc});
1066    ConsumeSemicolon(returnStatement);
1067
1068    context_.Status() |= ParserStatus::FUNCTION_HAS_RETURN_STATEMENT;
1069    return returnStatement;
1070}
1071
1072void ParserImpl::ThrowMultipleDefaultError()
1073{
1074    ThrowSyntaxError("Multiple default clauses.");
1075}
1076
1077ir::SwitchCaseStatement *ParserImpl::ParseSwitchCaseStatement(bool *seenDefault)
1078{
1079    lexer::SourcePosition caseStartLoc = lexer_->GetToken().Start();
1080    ir::Expression *testExpr = nullptr;
1081
1082    switch (lexer_->GetToken().KeywordType()) {
1083        case lexer::TokenType::KEYW_CASE: {
1084            lexer_->NextToken();
1085            testExpr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1086            break;
1087        }
1088        case lexer::TokenType::KEYW_DEFAULT: {
1089            if (*seenDefault) {
1090                ThrowMultipleDefaultError();
1091            }
1092            *seenDefault = true;
1093            lexer_->NextToken();
1094            break;
1095        }
1096        default: {
1097            ThrowSyntaxError("Unexpected token, expected 'case' or 'default'.");
1098        }
1099    }
1100
1101    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
1102        ThrowSyntaxError("Unexpected token, expected ':'");
1103    }
1104
1105    ArenaVector<ir::Statement *> consequents(Allocator()->Adapter());
1106    lexer::SourcePosition caseEndLoc = lexer_->GetToken().End();
1107
1108    lexer_->NextToken();
1109
1110    while (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CASE &&
1111           lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_DEFAULT &&
1112           lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1113        ir::Statement *consequent = ParseStatement(StatementParsingFlags::ALLOW_LEXICAL);
1114        caseEndLoc = consequent->End();
1115        consequents.push_back(consequent);
1116    }
1117
1118    auto *caseNode = AllocNode<ir::SwitchCaseStatement>(testExpr, std::move(consequents));
1119    caseNode->SetRange({caseStartLoc, caseEndLoc});
1120    return caseNode;
1121}
1122
1123ir::SwitchStatement *ParserImpl::ParseSwitchStatement()
1124{
1125    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1126    lexer_->NextToken();
1127    if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS)) {
1128        ThrowSyntaxError("Unexpected token, expected '('");
1129    }
1130
1131    lexer_->NextToken();
1132    ir::Expression *discriminant = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1133
1134    if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS)) {
1135        ThrowSyntaxError("Unexpected token, expected ')'");
1136    }
1137
1138    lexer_->NextToken();
1139    SwitchContext switchContext(&context_);
1140
1141    if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE)) {
1142        ThrowSyntaxError("Unexpected token, expected '{'");
1143    }
1144
1145    lexer_->NextToken();
1146    bool seenDefault = false;
1147    ArenaVector<ir::SwitchCaseStatement *> cases(Allocator()->Adapter());
1148
1149    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1150        cases.push_back(ParseSwitchCaseStatement(&seenDefault));
1151    }
1152
1153    auto *switchStatement = AllocNode<ir::SwitchStatement>(discriminant, std::move(cases));
1154    switchStatement->SetRange({startLoc, lexer_->GetToken().End()});
1155
1156    lexer_->NextToken();
1157
1158    return switchStatement;
1159}
1160
1161void ParserImpl::ThrowIllegalNewLineErrorAfterThrow()
1162{
1163    ThrowSyntaxError("Illegal newline after throw");
1164}
1165
1166ir::ThrowStatement *ParserImpl::ParseThrowStatement()
1167{
1168    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1169    lexer_->NextToken();
1170
1171    if (lexer_->GetToken().NewLine()) {
1172        ThrowIllegalNewLineErrorAfterThrow();
1173    }
1174
1175    ir::Expression *expression = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1176    lexer::SourcePosition endLoc = expression->End();
1177
1178    auto *throwStatement = AllocNode<ir::ThrowStatement>(expression);
1179    throwStatement->SetRange({startLoc, endLoc});
1180    ConsumeSemicolon(throwStatement);
1181
1182    return throwStatement;
1183}
1184
1185void ParserImpl::ParseCatchParamTypeAnnotation([[maybe_unused]] ir::AnnotatedExpression *param) {}
1186
1187ir::Expression *ParserImpl::ParseCatchParam()
1188{
1189    ir::AnnotatedExpression *param = nullptr;
1190
1191    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1192        return param;
1193    }
1194
1195    lexer_->NextToken();  // eat left paren
1196
1197    if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1198        CheckRestrictedBinding();
1199        param = ExpectIdentifier();
1200    } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1201        param = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1202    } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1203        param = ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1204    } else {
1205        ThrowSyntaxError("Unexpected token in catch parameter");
1206    }
1207
1208    ParseCatchParamTypeAnnotation(param);
1209
1210    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1211        ThrowSyntaxError("Unexpected token, expected ')'");
1212    }
1213
1214    lexer_->NextToken();
1215
1216    return param;
1217}
1218
1219ir::CatchClause *ParserImpl::ParseCatchClause()
1220{
1221    lexer::SourcePosition catchStartLoc = lexer_->GetToken().Start();
1222    lexer_->NextToken();  // eat 'catch' keyword
1223
1224    ir::Expression *param = ParseCatchParam();
1225
1226    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1227        ThrowSyntaxError("Unexpected token, expected '{'");
1228    }
1229
1230    ir::BlockStatement *catchBlock = ParseBlockStatement();
1231    lexer::SourcePosition endLoc = catchBlock->End();
1232
1233    auto *catchClause = AllocNode<ir::CatchClause>(param, catchBlock);
1234    catchClause->SetRange({catchStartLoc, endLoc});
1235
1236    return catchClause;
1237}
1238
1239ir::Statement *ParserImpl::ParseTryStatement()
1240{
1241    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1242    lexer::SourcePosition endLoc = lexer_->GetToken().End();
1243
1244    lexer_->NextToken();
1245
1246    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1247        ThrowSyntaxError("Unexpected token, expected '{'");
1248    }
1249
1250    ir::BlockStatement *body = ParseBlockStatement();
1251
1252    if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CATCH &&
1253        lexer_->GetToken().Type() != lexer::TokenType::KEYW_FINALLY) {
1254        ThrowSyntaxError("Missing catch or finally clause");
1255    }
1256
1257    ir::CatchClause *catchClause = nullptr;
1258    ir::BlockStatement *finallyClause = nullptr;
1259    ArenaVector<ir::CatchClause *> catchClauses(Allocator()->Adapter());
1260
1261    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_CATCH) {
1262        catchClause = ParseCatchClause();
1263        endLoc = catchClause->End();
1264        catchClauses.push_back(catchClause);
1265    }
1266
1267    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FINALLY) {
1268        lexer_->NextToken();  // eat 'finally' keyword
1269
1270        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1271            ThrowSyntaxError("Unexpected token, expected '{'");
1272        }
1273
1274        finallyClause = ParseBlockStatement();
1275        endLoc = finallyClause->End();
1276    }
1277
1278    ArenaVector<std::pair<compiler::LabelPair, const ir::Statement *>> finalizerInsertions(Allocator()->Adapter());
1279
1280    auto *tryStatement = AllocNode<ir::TryStatement>(body, std::move(catchClauses), finallyClause, finalizerInsertions);
1281    tryStatement->SetRange({startLoc, endLoc});
1282    return tryStatement;
1283}
1284
1285void ParserImpl::ValidateDeclaratorId()
1286{
1287    if (InAmbientContext()) {
1288        return;
1289    }
1290
1291    CheckRestrictedBinding();
1292}
1293
1294ir::VariableDeclarator *ParserImpl::ParseVariableDeclaratorInitializer(ir::Expression *init, VariableParsingFlags flags,
1295                                                                       const lexer::SourcePosition &startLoc)
1296{
1297    if ((flags & VariableParsingFlags::DISALLOW_INIT) != 0) {
1298        ThrowSyntaxError("for-await-of loop variable declaration may not have an initializer");
1299    }
1300
1301    lexer_->NextToken();
1302
1303    if (InAmbientContext() && (flags & VariableParsingFlags::CONST) == 0) {
1304        ThrowSyntaxError("Initializers are not allowed in ambient contexts.");
1305    }
1306
1307    auto exprFlags = ((flags & VariableParsingFlags::STOP_AT_IN) != 0 ? ExpressionParseFlags::STOP_AT_IN
1308                                                                      : ExpressionParseFlags::NO_OPTS);
1309
1310    ir::Expression *initializer = ParseExpression(exprFlags);
1311    lexer::SourcePosition endLoc = initializer->End();
1312
1313    auto *declarator = AllocNode<ir::VariableDeclarator>(GetFlag(flags), init, initializer);
1314    declarator->SetRange({startLoc, endLoc});
1315
1316    return declarator;
1317}
1318
1319ir::AnnotatedExpression *ParserImpl::ParseVariableDeclaratorKey([[maybe_unused]] VariableParsingFlags flags)
1320{
1321    switch (lexer_->GetToken().Type()) {
1322        case lexer::TokenType::LITERAL_IDENT: {
1323            ValidateDeclaratorId();
1324            return ExpectIdentifier(true);
1325        }
1326        case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
1327            return ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1328        }
1329        case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
1330            return ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1331        }
1332        default: {
1333            break;
1334        }
1335    }
1336
1337    ThrowSyntaxError("Unexpected token in variable declaration");
1338    return nullptr;
1339}
1340
1341ir::VariableDeclaratorFlag ParserImpl::GetFlag(VariableParsingFlags flags)
1342{
1343    constexpr auto VARIABLE_FLAGS =
1344        (VariableParsingFlags::VAR | VariableParsingFlags::LET | VariableParsingFlags::CONST);
1345    switch (static_cast<VariableParsingFlags>(flags & VARIABLE_FLAGS)) {
1346        case VariableParsingFlags::CONST:
1347            return ir::VariableDeclaratorFlag::CONST;
1348        case VariableParsingFlags::VAR:
1349            return ir::VariableDeclaratorFlag::VAR;
1350        case VariableParsingFlags::LET:
1351            return ir::VariableDeclaratorFlag::LET;
1352        default:
1353            UNREACHABLE();
1354    }
1355}
1356
1357ir::VariableDeclarator *ParserImpl::ParseVariableDeclarator(ir::Expression *init, lexer::SourcePosition startLoc,
1358                                                            VariableParsingFlags flags)
1359{
1360    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
1361        return ParseVariableDeclaratorInitializer(init, flags, startLoc);
1362    }
1363
1364    if ((flags & VariableParsingFlags::CONST) != 0U && (flags & VariableParsingFlags::ACCEPT_CONST_NO_INIT) == 0U) {
1365        ThrowSyntaxError("Missing initializer in const declaration");
1366    }
1367
1368    if ((flags & VariableParsingFlags::IN_FOR) == 0U && (init->IsArrayPattern() || init->IsObjectPattern())) {
1369        ThrowSyntaxError("Missing initializer in destructuring declaration");
1370    }
1371
1372    lexer::SourcePosition endLoc = init->End();
1373    auto declarator = AllocNode<ir::VariableDeclarator>(GetFlag(flags), init);
1374    declarator->SetRange({startLoc, endLoc});
1375
1376    return declarator;
1377}
1378
1379ir::VariableDeclarator *ParserImpl::ParseVariableDeclarator(VariableParsingFlags flags)
1380{
1381    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1382    ir::Expression *init = ParseVariableDeclaratorKey(flags);
1383    ir::VariableDeclarator *declarator = ParseVariableDeclarator(init, startLoc, flags);
1384
1385    return declarator;
1386}
1387
1388ir::Statement *ParserImpl::ParsePotentialConstEnum([[maybe_unused]] VariableParsingFlags flags)
1389{
1390    ThrowSyntaxError("Variable declaration expected.");
1391}
1392
1393void ParserImpl::ThrowIfVarDeclaration([[maybe_unused]] VariableParsingFlags flags) {}
1394
1395ir::Statement *ParserImpl::ParseVariableDeclaration(VariableParsingFlags flags)
1396{
1397    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1398
1399    if ((flags & VariableParsingFlags::NO_SKIP_VAR_KIND) == 0) {
1400        lexer_->NextToken();
1401    }
1402
1403    ThrowIfVarDeclaration(flags);
1404
1405    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_ENUM) {
1406        return ParsePotentialConstEnum(flags);
1407    }
1408
1409    ArenaVector<ir::VariableDeclarator *> declarators(Allocator()->Adapter());
1410
1411    while (true) {
1412        ir::VariableDeclarator *declarator = ParseVariableDeclarator(flags);
1413
1414        declarators.push_back(declarator);
1415
1416        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) {
1417            break;
1418        }
1419        lexer_->NextToken();
1420    }
1421
1422    auto varKind = ir::VariableDeclaration::VariableDeclarationKind::VAR;
1423
1424    if ((flags & VariableParsingFlags::LET) != 0) {
1425        varKind = ir::VariableDeclaration::VariableDeclarationKind::LET;
1426    } else if ((flags & VariableParsingFlags::CONST) != 0) {
1427        varKind = ir::VariableDeclaration::VariableDeclarationKind::CONST;
1428    }
1429
1430    lexer::SourcePosition endLoc = declarators.back()->End();
1431    auto *declaration =
1432        AllocNode<ir::VariableDeclaration>(varKind, Allocator(), std::move(declarators), InAmbientContext());
1433    declaration->SetRange({startLoc, endLoc});
1434
1435    return declaration;
1436}
1437
1438ir::WhileStatement *ParserImpl::ParseWhileStatement()
1439{
1440    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1441    lexer_->NextToken();
1442    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1443        ThrowSyntaxError("Unexpected token, expected '('");
1444    }
1445
1446    lexer_->NextToken();
1447    ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1448
1449    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1450        ThrowSyntaxError("Unexpected token, expected ')'");
1451    }
1452
1453    lexer_->NextToken();
1454    IterationContext iterCtx(&context_);
1455    ir::Statement *body = ParseStatement();
1456
1457    lexer::SourcePosition endLoc = body->End();
1458    auto *whileStatement = AllocNode<ir::WhileStatement>(test, body);
1459    whileStatement->SetRange({startLoc, endLoc});
1460
1461    return whileStatement;
1462}
1463
1464// NOLINTNEXTLINE(google-default-arguments)
1465ir::ExportDefaultDeclaration *ParserImpl::ParseExportDefaultDeclaration(const lexer::SourcePosition &startLoc,
1466                                                                        bool isExportEquals)
1467{
1468    lexer_->NextToken();  // eat `default` keyword or `=`
1469
1470    ir::AstNode *declNode = nullptr;
1471    bool eatSemicolon = false;
1472
1473    switch (lexer_->GetToken().Type()) {
1474        case lexer::TokenType::KEYW_FUNCTION: {
1475            declNode = ParseFunctionDeclaration(true);
1476            break;
1477        }
1478        case lexer::TokenType::KEYW_CLASS: {
1479            declNode = ParseClassDeclaration(ir::ClassDefinitionModifiers::NONE);
1480            break;
1481        }
1482        case lexer::TokenType::LITERAL_IDENT: {
1483            switch (lexer_->GetToken().KeywordType()) {
1484                case lexer::TokenType::KEYW_STRUCT: {
1485                    declNode = ParseStructDeclaration(ir::ClassDefinitionModifiers::NONE);
1486                    break;
1487                }
1488                case lexer::TokenType::KEYW_ASYNC: {
1489                    if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) == 0) {
1490                        lexer_->NextToken();  // eat `async`
1491                        declNode = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION);
1492                        break;
1493                    }
1494
1495                    [[fallthrough]];
1496                }
1497                default: {
1498                    declNode = ParseExpression();
1499                    eatSemicolon = true;
1500                    break;
1501                }
1502            }
1503
1504            break;
1505        }
1506        default: {
1507            declNode = ParseExpression();
1508            eatSemicolon = true;
1509            break;
1510        }
1511    }
1512
1513    lexer::SourcePosition endLoc = declNode->End();
1514    auto *exportDeclaration = AllocNode<ir::ExportDefaultDeclaration>(declNode, isExportEquals);
1515    exportDeclaration->SetRange({startLoc, endLoc});
1516
1517    if (eatSemicolon) {
1518        ConsumeSemicolon(exportDeclaration);
1519    }
1520
1521    return exportDeclaration;
1522}
1523
1524ir::Identifier *ParserImpl::ParseNamedExport(const lexer::Token &exportedToken)
1525{
1526    if (exportedToken.Type() != lexer::TokenType::LITERAL_IDENT) {
1527        ThrowSyntaxError("Unexpected token, expected an identifier.");
1528    }
1529
1530    CheckRestrictedBinding(exportedToken.KeywordType());
1531
1532    const util::StringView &exportedString = exportedToken.Ident();
1533
1534    auto *exported = AllocNode<ir::Identifier>(exportedString, Allocator());
1535    exported->SetRange(exportedToken.Loc());
1536
1537    return exported;
1538}
1539
1540ir::ExportAllDeclaration *ParserImpl::ParseExportAllDeclaration(const lexer::SourcePosition &startLoc)
1541{
1542    lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat `*` character
1543
1544    ir::Identifier *exported = nullptr;
1545
1546    if (CheckModuleAsModifier()) {
1547        lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
1548        exported = ParseNamedExport(lexer_->GetToken());
1549        lexer_->NextToken();  // eat exported name
1550    }
1551
1552    ir::StringLiteral *source = ParseFromClause();
1553    lexer::SourcePosition endLoc = source->End();
1554
1555    auto *exportDeclaration = AllocNode<ir::ExportAllDeclaration>(source, exported);
1556    exportDeclaration->SetRange({startLoc, endLoc});
1557
1558    ConsumeSemicolon(exportDeclaration);
1559
1560    return exportDeclaration;
1561}
1562
1563ir::ExportNamedDeclaration *ParserImpl::ParseExportNamedSpecifiers(const lexer::SourcePosition &startLoc)
1564{
1565    lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat `{` character
1566
1567    ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter());
1568
1569    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1570        if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1571            ThrowSyntaxError("Unexpected token");
1572        }
1573
1574        lexer::Token localToken = lexer_->GetToken();
1575        auto *local = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
1576        local->SetRange(lexer_->GetToken().Loc());
1577
1578        lexer_->NextToken();  // eat local name
1579
1580        ir::Identifier *exported = nullptr;
1581
1582        if (CheckModuleAsModifier()) {
1583            lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat `as` literal
1584            exported = ParseNamedExport(lexer_->GetToken());
1585            lexer_->NextToken();  // eat exported name
1586        } else {
1587            exported = ParseNamedExport(localToken);
1588        }
1589
1590        auto *specifier = AllocNode<ir::ExportSpecifier>(local, exported);
1591        specifier->SetRange({local->Start(), exported->End()});
1592
1593        specifiers.push_back(specifier);
1594
1595        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
1596            lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat comma
1597        }
1598    }
1599
1600    lexer::SourcePosition endPos = lexer_->GetToken().End();
1601    lexer_->NextToken();  // eat right brace
1602
1603    ir::StringLiteral *source = nullptr;
1604
1605    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_FROM) {
1606        source = ParseFromClause();
1607    }
1608
1609    auto *exportDeclaration = AllocNode<ir::ExportNamedDeclaration>(Allocator(), source, std::move(specifiers));
1610    exportDeclaration->SetRange({startLoc, endPos});
1611    ConsumeSemicolon(exportDeclaration);
1612
1613    return exportDeclaration;
1614}
1615
1616ir::ExportNamedDeclaration *ParserImpl::ParseNamedExportDeclaration(const lexer::SourcePosition &startLoc)
1617{
1618    ir::Statement *decl = nullptr;
1619
1620    switch (lexer_->GetToken().Type()) {
1621        case lexer::TokenType::KEYW_VAR: {
1622            decl = ParseVariableDeclaration(VariableParsingFlags::VAR);
1623            break;
1624        }
1625        case lexer::TokenType::KEYW_CONST: {
1626            decl = ParseVariableDeclaration(VariableParsingFlags::CONST);
1627            break;
1628        }
1629        case lexer::TokenType::KEYW_LET: {
1630            decl = ParseVariableDeclaration(VariableParsingFlags::LET);
1631            break;
1632        }
1633        case lexer::TokenType::KEYW_FUNCTION: {
1634            decl = ParseFunctionDeclaration(false, ParserStatus::NO_OPTS);
1635            break;
1636        }
1637        case lexer::TokenType::KEYW_CLASS: {
1638            decl = ParseClassDeclaration(ir::ClassDefinitionModifiers::ID_REQUIRED);
1639            break;
1640        }
1641        case lexer::TokenType::LITERAL_IDENT: {
1642            if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_STRUCT) {
1643                decl = ParseStructDeclaration(ir::ClassDefinitionModifiers::NONE);
1644                break;
1645            }
1646            [[fallthrough]];
1647        }
1648        default: {
1649            if (!lexer_->GetToken().IsAsyncModifier()) {
1650                ThrowSyntaxError("Unexpected token");
1651            }
1652
1653            lexer_->NextToken();  // eat `async` keyword
1654            decl = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION);
1655        }
1656    }
1657
1658    if (decl->IsVariableDeclaration()) {
1659        ConsumeSemicolon(decl);
1660    }
1661
1662    lexer::SourcePosition endLoc = decl->End();
1663    ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter());
1664    auto *exportDeclaration = AllocNode<ir::ExportNamedDeclaration>(Allocator(), decl, std::move(specifiers));
1665    exportDeclaration->SetRange({startLoc, endLoc});
1666
1667    return exportDeclaration;
1668}
1669
1670ir::Statement *ParserImpl::ParseExportDeclaration(StatementParsingFlags flags)
1671{
1672    if ((flags & StatementParsingFlags::GLOBAL) == 0) {
1673        ThrowSyntaxError("'import' and 'export' may only appear at the top level");
1674    }
1675
1676    if (!context_.IsModule()) {
1677        ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'");
1678    }
1679
1680    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1681    lexer_->NextToken();  // eat `export` keyword
1682
1683    switch (lexer_->GetToken().Type()) {
1684        case lexer::TokenType::PUNCTUATOR_MULTIPLY: {
1685            return ParseExportAllDeclaration(startLoc);
1686        }
1687        case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
1688            return ParseExportNamedSpecifiers(startLoc);
1689        }
1690        default: {
1691            if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DEFAULT) {
1692                return ParseExportDefaultDeclaration(startLoc);
1693            }
1694            return ParseNamedExportDeclaration(startLoc);
1695        }
1696    }
1697}
1698
1699void ParserImpl::ParseNameSpaceImport(ArenaVector<ir::AstNode *> *specifiers)
1700{
1701    lexer::SourcePosition namespaceStart = lexer_->GetToken().Start();
1702    lexer_->NextToken();  // eat `*` character
1703
1704    if (!CheckModuleAsModifier()) {
1705        ThrowSyntaxError("Unexpected token.");
1706    }
1707
1708    lexer_->NextToken();  // eat `as` literal
1709
1710    ir::Identifier *local = ParseNamedImport(lexer_->GetToken());
1711
1712    auto *specifier = AllocNode<ir::ImportNamespaceSpecifier>(local);
1713    specifier->SetRange({namespaceStart, lexer_->GetToken().End()});
1714    specifiers->push_back(specifier);
1715
1716    lexer_->NextToken();  // eat local name
1717}
1718
1719ir::Identifier *ParserImpl::ParseNamedImport(const lexer::Token &importedToken)
1720{
1721    if (importedToken.Type() != lexer::TokenType::LITERAL_IDENT) {
1722        ThrowSyntaxError("Unexpected token");
1723    }
1724
1725    CheckRestrictedBinding(importedToken.KeywordType());
1726
1727    auto *local = AllocNode<ir::Identifier>(importedToken.Ident(), Allocator());
1728    local->SetReference();
1729    local->SetRange(importedToken.Loc());
1730
1731    return local;
1732}
1733
1734void ParserImpl::ParseNamedImportSpecifiers(ArenaVector<ir::AstNode *> *specifiers)
1735{
1736    lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat `{` character
1737
1738    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1739        if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1740            ThrowSyntaxError("Unexpected token");
1741        }
1742
1743        lexer::Token importedToken = lexer_->GetToken();
1744        auto *imported = AllocNode<ir::Identifier>(importedToken.Ident(), Allocator());
1745        ir::Identifier *local = nullptr;
1746        imported->SetReference();
1747        imported->SetRange(lexer_->GetToken().Loc());
1748
1749        lexer_->NextToken();  // eat import name
1750
1751        if (CheckModuleAsModifier()) {
1752            lexer_->NextToken();  // eat `as` literal
1753            local = ParseNamedImport(lexer_->GetToken());
1754            lexer_->NextToken();  // eat local name
1755        } else {
1756            local = ParseNamedImport(importedToken);
1757        }
1758
1759        auto *specifier = AllocNode<ir::ImportSpecifier>(imported, local);
1760        specifier->SetRange({imported->Start(), local->End()});
1761        specifiers->push_back(specifier);
1762
1763        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
1764            lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat comma
1765        }
1766    }
1767
1768    lexer_->NextToken();  // eat right brace
1769}
1770
1771ir::AstNode *ParserImpl::ParseImportDefaultSpecifier(ArenaVector<ir::AstNode *> *specifiers)
1772{
1773    ir::Identifier *local = ParseNamedImport(lexer_->GetToken());
1774    lexer_->NextToken();  // eat local name
1775
1776    auto *specifier = AllocNode<ir::ImportDefaultSpecifier>(local);
1777    specifier->SetRange(specifier->Local()->Range());
1778    specifiers->push_back(specifier);
1779
1780    lexer_->NextToken();  // eat specifier name
1781
1782    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
1783        lexer_->NextToken();  // eat comma
1784    }
1785
1786    return nullptr;
1787}
1788
1789ir::StringLiteral *ParserImpl::ParseFromClause(bool requireFrom)
1790{
1791    if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) {
1792        if (requireFrom) {
1793            ThrowSyntaxError("Unexpected token.");
1794        }
1795    } else {
1796        lexer_->NextToken();  // eat `from` literal
1797    }
1798
1799    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
1800        ThrowSyntaxError("Unexpected token.");
1801    }
1802
1803    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
1804
1805    auto *source = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
1806    source->SetRange(lexer_->GetToken().Loc());
1807
1808    lexer_->NextToken();
1809
1810    return source;
1811}
1812
1813ir::AstNode *ParserImpl::ParseImportSpecifiers(ArenaVector<ir::AstNode *> *specifiers)
1814{
1815    ASSERT(specifiers->empty());
1816
1817    if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1818        ir::AstNode *astNode = ParseImportDefaultSpecifier(specifiers);
1819
1820        if (astNode != nullptr) {
1821            return astNode;
1822        }
1823    }
1824
1825    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
1826        ParseNameSpaceImport(specifiers);
1827    } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1828        ParseNamedImportSpecifiers(specifiers);
1829    }
1830    return nullptr;
1831}
1832
1833ir::Statement *ParserImpl::ParseImportDeclaration(StatementParsingFlags flags)
1834{
1835    if ((flags & StatementParsingFlags::GLOBAL) == 0) {
1836        ThrowSyntaxError("'import' and 'export' may only appear at the top level");
1837    }
1838
1839    if (!context_.IsModule()) {
1840        ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'");
1841    }
1842
1843    char32_t nextChar = lexer_->Lookahead();
1844    if (nextChar == lexer::LEX_CHAR_LEFT_PAREN || nextChar == lexer::LEX_CHAR_DOT) {
1845        return ParseExpressionStatement();
1846    }
1847
1848    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1849    lexer_->NextToken();  // eat import
1850
1851    ArenaVector<ir::AstNode *> specifiers(Allocator()->Adapter());
1852
1853    ir::StringLiteral *source = nullptr;
1854
1855    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
1856        ParseImportSpecifiers(&specifiers);
1857        source = ParseFromClause(true);
1858    } else {
1859        source = ParseFromClause(false);
1860    }
1861
1862    lexer::SourcePosition endLoc = source->End();
1863    auto *importDeclaration = AllocNode<ir::ImportDeclaration>(source, std::move(specifiers));
1864    importDeclaration->SetRange({startLoc, endLoc});
1865
1866    ConsumeSemicolon(importDeclaration);
1867
1868    return importDeclaration;
1869}
1870}  // namespace ark::es2panda::parser
1871