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 <util/helpers.h>
17#include <binder/tsBinding.h>
18#include <ir/astNode.h>
19#include <ir/base/annotation.h>
20#include <ir/base/catchClause.h>
21#include <ir/base/classDefinition.h>
22#include <ir/base/decorator.h>
23#include <ir/base/scriptFunction.h>
24#include <ir/expression.h>
25#include <ir/expressions/arrayExpression.h>
26#include <ir/expressions/assignmentExpression.h>
27#include <ir/expressions/binaryExpression.h>
28#include <ir/expressions/conditionalExpression.h>
29#include <ir/expressions/literals/stringLiteral.h>
30#include <ir/expressions/objectExpression.h>
31#include <ir/expressions/sequenceExpression.h>
32#include <ir/module/exportAllDeclaration.h>
33#include <ir/module/exportDefaultDeclaration.h>
34#include <ir/module/exportNamedDeclaration.h>
35#include <ir/module/exportSpecifier.h>
36#include <ir/module/importDeclaration.h>
37#include <ir/module/importDefaultSpecifier.h>
38#include <ir/module/importNamespaceSpecifier.h>
39#include <ir/module/importSpecifier.h>
40#include <ir/statements/blockStatement.h>
41#include <ir/statements/breakStatement.h>
42#include <ir/statements/classDeclaration.h>
43#include <ir/statements/continueStatement.h>
44#include <ir/statements/debuggerStatement.h>
45#include <ir/statements/doWhileStatement.h>
46#include <ir/statements/emptyStatement.h>
47#include <ir/statements/expressionStatement.h>
48#include <ir/statements/forInStatement.h>
49#include <ir/statements/forOfStatement.h>
50#include <ir/statements/forUpdateStatement.h>
51#include <ir/statements/functionDeclaration.h>
52#include <ir/statements/ifStatement.h>
53#include <ir/statements/labelledStatement.h>
54#include <ir/statements/returnStatement.h>
55#include <ir/statements/switchCaseStatement.h>
56#include <ir/statements/switchStatement.h>
57#include <ir/statements/throwStatement.h>
58#include <ir/statements/tryStatement.h>
59#include <ir/statements/variableDeclaration.h>
60#include <ir/statements/variableDeclarator.h>
61#include <ir/statements/whileStatement.h>
62#include <ir/ts/tsEnumDeclaration.h>
63#include <ir/ts/tsExternalModuleReference.h>
64#include <ir/ts/tsImportEqualsDeclaration.h>
65#include <ir/ts/tsInterfaceBody.h>
66#include <ir/ts/tsInterfaceDeclaration.h>
67#include <ir/ts/tsInterfaceHeritage.h>
68#include <ir/ts/tsModuleBlock.h>
69#include <ir/ts/tsModuleDeclaration.h>
70#include <ir/ts/tsNamespaceExportDeclaration.h>
71#include <ir/ts/tsTypeAliasDeclaration.h>
72#include <ir/ts/tsTypeParameter.h>
73#include <ir/ts/tsTypeParameterDeclaration.h>
74#include <ir/ts/tsTypeParameterInstantiation.h>
75#include <ir/ts/tsTypeReference.h>
76#include <lexer/lexer.h>
77#include <lexer/token/letters.h>
78#include <lexer/token/sourceLocation.h>
79#include <util/ustring.h>
80
81#include <tuple>
82
83#include "parserImpl.h"
84
85namespace panda::es2panda::parser {
86
87bool ParserImpl::CheckDeclare()
88{
89    ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE);
90
91    const auto startPos = lexer_->Save();
92    lexer_->NextToken();  // eat 'declare'
93    if (lexer_->GetToken().NewLine()) {
94        lexer_->Rewind(startPos);
95        return false;
96    }
97    switch (lexer_->GetToken().Type()) {
98        case lexer::TokenType::KEYW_VAR:
99        case lexer::TokenType::KEYW_LET:
100        case lexer::TokenType::KEYW_CONST:
101        case lexer::TokenType::KEYW_FUNCTION:
102        case lexer::TokenType::KEYW_CLASS: {
103            break;
104        }
105        case lexer::TokenType::LITERAL_IDENT: {
106            if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE ||
107                lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_MODULE ||
108                lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_GLOBAL ||
109                lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NAMESPACE ||
110                lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ENUM ||
111                lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT ||
112                lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_INTERFACE) {
113                break;
114            }
115
116            [[fallthrough]];
117        }
118        default: {
119            lexer_->Rewind(startPos);
120            return false;
121        }
122    }
123
124    if (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT) {
125        lexer_->Rewind(startPos);
126        ThrowSyntaxError("A 'declare' modifier cannot be used in an already ambient context.");
127    }
128
129    return true;
130}
131
132bool ParserImpl::IsLabelFollowedByIterationStatement()
133{
134    lexer_->NextToken();
135
136    switch (lexer_->GetToken().Type()) {
137        case lexer::TokenType::KEYW_DO:
138        case lexer::TokenType::KEYW_FOR:
139        case lexer::TokenType::KEYW_WHILE: {
140            return true;
141        }
142        case lexer::TokenType::LITERAL_IDENT: {
143            if (lexer_->Lookahead() == LEX_CHAR_COLON) {
144                lexer_->NextToken();
145                return IsLabelFollowedByIterationStatement();
146            }
147
148            [[fallthrough]];
149        }
150        default:
151            return false;
152    }
153    return false;
154}
155
156bool ParserImpl::IsTsDeclarationStatement() const
157{
158    const auto startPos = lexer_->Save();
159    bool isTsDeclarationStatement = false;
160
161    auto keywordType = lexer_->GetToken().KeywordType();
162    lexer_->NextToken();
163    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) {
164        lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
165    }
166    switch (keywordType) {
167        case lexer::TokenType::KEYW_MODULE:
168        case lexer::TokenType::KEYW_NAMESPACE: {
169            isTsDeclarationStatement = !lexer_->GetToken().NewLine() &&
170                (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
171                lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
172            break;
173        }
174        case lexer::TokenType::KEYW_GLOBAL: {
175            isTsDeclarationStatement = lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
176                lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE ||
177                lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXPORT;
178            break;
179        }
180        case lexer::TokenType::KEYW_INTERFACE:
181        case lexer::TokenType::KEYW_TYPE: {
182            isTsDeclarationStatement = !lexer_->GetToken().NewLine() &&
183                lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT;
184            break;
185        }
186        case lexer::TokenType::KEYW_ENUM: {
187            isTsDeclarationStatement = true;
188            break;
189        }
190        default: {
191            break;
192        }
193    }
194
195    lexer_->Rewind(startPos);
196    return isTsDeclarationStatement;
197}
198
199ir::Statement *ParserImpl::ParseStatement(StatementParsingFlags flags)
200{
201    bool isDeclare = false;
202    auto decoratorsAndAnnotations = ParseDecoratorsAndAnnotations();
203    auto decorators = decoratorsAndAnnotations.first;
204    auto annotations = decoratorsAndAnnotations.second;
205
206    if (Extension() == ScriptExtension::TS) {
207        if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) {
208            isDeclare = CheckDeclare();
209        }
210
211        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_AT) {
212            lexer_->NextToken(); // eat @ symbol
213            if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_INTERFACE) {
214                ThrowSyntaxError("'interface' keyword expected.");
215            }
216            if (!decorators.empty()) {
217                ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
218            }
219            if (!annotations.empty()) {
220                ThrowSyntaxError("Annotations can not be used with annotation declaration",
221                                 annotations.front()->Start());
222            }
223            return ParseClassDeclaration(true, std::move(decorators), std::move(annotations), isDeclare, false,
224                                         false, true);
225        }
226
227        if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT) {
228            const auto startPos = lexer_->Save();
229            lexer_->NextToken();  // eat abstract keyword
230
231            if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) {
232                if (isDeclare) {
233                    ThrowSyntaxError("'declare' modifier already seen.");
234                }
235                lexer_->NextToken();
236                isDeclare = true;
237            }
238
239            if (!annotations.empty()) {
240                ThrowSyntaxError("Annotations can not be used with abstract classes", annotations.front()->Start());
241            }
242
243            if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS) {
244                lexer_->Rewind(startPos);
245            } else {
246                return ParseClassStatement(flags, isDeclare, std::move(decorators), std::move(annotations), true);
247            }
248        }
249
250        if ((lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_GLOBAL ||
251             lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_MODULE ||
252             lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NAMESPACE) &&
253             IsTsDeclarationStatement()) {
254            auto savedStatus = context_.Status();
255            if (isDeclare) {
256                context_.Status() |= ParserStatus::IN_AMBIENT_CONTEXT;
257            }
258            ir::TSModuleDeclaration *decl = ParseTsModuleDeclaration(isDeclare);
259            context_.Status() = savedStatus;
260            return decl;
261        }
262    }
263
264    switch (lexer_->GetToken().Type()) {
265        case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
266            return ParseBlockStatement();
267        }
268        case lexer::TokenType::PUNCTUATOR_SEMI_COLON: {
269            return ParseEmptyStatement();
270        }
271        case lexer::TokenType::KEYW_EXPORT: {
272            return ParseExportDeclaration(flags, std::move(decorators), std::move(annotations));
273        }
274        case lexer::TokenType::KEYW_IMPORT: {
275            return ParseImportDeclaration(flags);
276        }
277        case lexer::TokenType::KEYW_FUNCTION: {
278            return ParseFunctionStatement(flags, isDeclare);
279        }
280        case lexer::TokenType::KEYW_CLASS: {
281            return ParseClassStatement(flags, isDeclare, std::move(decorators), std::move(annotations));
282        }
283        case lexer::TokenType::KEYW_VAR: {
284            return ParseVarStatement(isDeclare);
285        }
286        case lexer::TokenType::KEYW_LET: {
287            return ParseLetStatement(flags, isDeclare);
288        }
289        case lexer::TokenType::KEYW_CONST: {
290            return ParseConstStatement(flags, isDeclare);
291        }
292        case lexer::TokenType::KEYW_IF: {
293            return ParseIfStatement();
294        }
295        case lexer::TokenType::KEYW_DO: {
296            return ParseDoWhileStatement();
297        }
298        case lexer::TokenType::KEYW_FOR: {
299            return ParseForStatement();
300        }
301        case lexer::TokenType::KEYW_TRY: {
302            return ParseTryStatement();
303        }
304        case lexer::TokenType::KEYW_WHILE: {
305            return ParseWhileStatement();
306        }
307        case lexer::TokenType::KEYW_BREAK: {
308            return ParseBreakStatement();
309        }
310        case lexer::TokenType::KEYW_CONTINUE: {
311            return ParseContinueStatement();
312        }
313        case lexer::TokenType::KEYW_THROW: {
314            return ParseThrowStatement();
315        }
316        case lexer::TokenType::KEYW_RETURN: {
317            return ParseReturnStatement();
318        }
319        case lexer::TokenType::KEYW_SWITCH: {
320            return ParseSwitchStatement();
321        }
322        case lexer::TokenType::KEYW_DEBUGGER: {
323            return ParseDebuggerStatement();
324        }
325        case lexer::TokenType::LITERAL_IDENT: {
326            return ParsePotentialExpressionStatement(flags, isDeclare);
327        }
328        default: {
329            break;
330        }
331    }
332
333    return ParseExpressionStatement(flags);
334}
335
336ir::TSModuleDeclaration *ParserImpl::ParseTsModuleDeclaration(bool isDeclare, bool isExport)
337{
338    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
339    context_.Status() |= ParserStatus::TS_MODULE;
340
341    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_GLOBAL) {
342        return ParseTsAmbientExternalModuleDeclaration(startLoc, isDeclare);
343    }
344
345    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NAMESPACE) {
346        lexer_->NextToken();
347        if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) {
348            lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
349        }
350    } else {
351        ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_MODULE);
352        lexer_->NextToken();
353        if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) {
354            lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
355        }
356        if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
357            return ParseTsAmbientExternalModuleDeclaration(startLoc, isDeclare);
358        }
359    }
360
361    return ParseTsModuleOrNamespaceDelaration(startLoc, isDeclare, isExport);
362}
363
364ir::TSModuleDeclaration *ParserImpl::ParseTsAmbientExternalModuleDeclaration(const lexer::SourcePosition &startLoc,
365                                                                             bool isDeclare)
366{
367    bool isGlobal = false;
368    ir::Expression *name = nullptr;
369
370    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_GLOBAL) {
371        isGlobal = true;
372        name = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
373    } else {
374        ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
375
376        if (!isDeclare && !(context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT)) {
377            ThrowSyntaxError("Only ambient modules can use quoted names");
378        }
379
380        name = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
381    }
382
383    name->SetRange(lexer_->GetToken().Loc());
384
385    lexer_->NextToken();
386
387    binder::ExportBindings *exportBindings = Allocator()->New<binder::ExportBindings>(Allocator());
388    auto localCtx = binder::LexicalScope<binder::TSModuleScope>(Binder(), exportBindings);
389
390    ir::Statement *body = nullptr;
391    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
392        body = ParseTsModuleBlock();
393    } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
394        lexer_->NextToken();
395    } else if (!lexer_->GetToken().NewLine()) {
396        ThrowSyntaxError("';' expected");
397    }
398
399    auto *moduleDecl = AllocNode<ir::TSModuleDeclaration>(localCtx.GetScope(), name, body, isDeclare, isGlobal);
400    moduleDecl->SetRange({startLoc, lexer_->GetToken().End()});
401    localCtx.GetScope()->BindNode(moduleDecl);
402
403    return moduleDecl;
404}
405
406ir::TSModuleDeclaration *ParserImpl::ParseTsModuleOrNamespaceDelaration(const lexer::SourcePosition &startLoc,
407                                                                        bool isDeclare, bool isExport)
408{
409    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
410        ThrowSyntaxError("Identifier expected");
411    }
412
413    auto name = lexer_->GetToken().Ident();
414    auto *parentScope = Binder()->GetScope();
415    binder::Variable *res = parentScope->FindLocalTSVariable<binder::TSBindingType::NAMESPACE>(name);
416    if (!res && isExport && parentScope->IsTSModuleScope()) {
417        res = parentScope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::NAMESPACE>(name);
418        if (res != nullptr) {
419            parentScope->AddLocalTSVariable<binder::TSBindingType::NAMESPACE>(name, res);
420        }
421    }
422    if (res == nullptr) {
423        Binder()->AddTsDecl<binder::NamespaceDecl>(lexer_->GetToken().Start(), isDeclare, Allocator(), name);
424        res = parentScope->FindLocalTSVariable<binder::TSBindingType::NAMESPACE>(name);
425        if (isExport && parentScope->IsTSModuleScope()) {
426            parentScope->AsTSModuleScope()->AddExportTSVariable<binder::TSBindingType::NAMESPACE>(name, res);
427        }
428        res->AsNamespaceVariable()->SetExportBindings(Allocator()->New<binder::ExportBindings>(Allocator()));
429    }
430    binder::ExportBindings *exportBindings = res->AsNamespaceVariable()->GetExportBindings();
431
432    auto *identNode = AllocNode<ir::Identifier>(name);
433    identNode->SetRange(lexer_->GetToken().Loc());
434
435    lexer_->NextToken();
436
437    ir::Statement *body = nullptr;
438
439    auto savedStatus = context_.Status();
440    if (isDeclare) {
441        context_.Status() |= ParserStatus::IN_AMBIENT_CONTEXT;
442    }
443
444    auto localCtx = binder::LexicalScope<binder::TSModuleScope>(Binder(), exportBindings);
445
446    bool isInstantiated = IsInstantiatedInTsModuleBlock(&body);
447    if (isDeclare) {
448        isInstantiated = false;
449    }
450
451    context_.Status() = savedStatus;
452
453    auto *moduleDecl = AllocNode<ir::TSModuleDeclaration>(localCtx.GetScope(), identNode, body,
454                                                          isDeclare, false, isInstantiated);
455    moduleDecl->SetRange({startLoc, lexer_->GetToken().End()});
456    localCtx.GetScope()->BindNode(moduleDecl);
457    res->Declaration()->AsNamespaceDecl()->Add(moduleDecl);
458
459    return moduleDecl;
460}
461
462bool ParserImpl::IsInstantiatedInTsModuleBlock(ir::Statement **body)
463{
464    bool isInstantiated = false;
465    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
466        lexer_->NextToken();
467        lexer::SourcePosition moduleStart = lexer_->GetToken().Start();
468        *body = ParseTsModuleOrNamespaceDelaration(moduleStart, false, true);
469        isInstantiated = (*body)->AsTSModuleDeclaration()->IsInstantiated();
470    } else {
471        *body = ParseTsModuleBlock();
472        auto statements = (*body)->AsTSModuleBlock()->Statements();
473        for (auto *it : statements) {
474            auto statement = it;
475            if (LIKELY(statement != nullptr) && statement->IsExportNamedDeclaration()) {
476                statement = statement->AsExportNamedDeclaration()->Decl();
477            }
478            if (statement != nullptr && !statement->IsTSInterfaceDeclaration() &&
479                !statement->IsTSTypeAliasDeclaration() &&
480                (!statement->IsTSModuleDeclaration() || statement->AsTSModuleDeclaration()->IsInstantiated())) {
481                isInstantiated = true;
482                break;
483            }
484        }
485    }
486    return isInstantiated;
487}
488
489ir::TSImportEqualsDeclaration *ParserImpl::ParseTsImportEqualsDeclaration(const lexer::SourcePosition &startLoc,
490                                                                          bool isExport)
491{
492    ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_IMPORT);
493    lexer_->NextToken();
494    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
495        ThrowSyntaxError("Unexpected token");
496    }
497
498    auto *id = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
499    id->SetRange(lexer_->GetToken().Loc());
500    lexer_->NextToken();  // eat id name
501
502    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
503        ThrowSyntaxError("'=' expected");
504    }
505    lexer_->NextToken();  // eat substitution
506
507    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
508        ThrowSyntaxError("identifier expected");
509    }
510
511    if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_REQUIRE ||
512        lexer_->Lookahead() != LEX_CHAR_LEFT_PAREN) {
513        binder::DeclarationFlags declflag = binder::DeclarationFlags::NONE;
514        auto *decl = Binder()->AddDecl<binder::ImportEqualsDecl>(id->Start(), declflag, false, id->Name());
515        decl->BindNode(id);
516        auto *scope = Binder()->GetScope();
517        auto name = id->Name();
518        auto *var = scope->FindLocalTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name);
519        CHECK_NOT_NULL(var);
520        var->AsImportEqualsVariable()->SetScope(scope);
521        if (isExport && scope->IsTSModuleScope()) {
522            scope->AsTSModuleScope()->AddExportTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name, var);
523        }
524    }
525
526    auto *importEqualsDecl = AllocNode<ir::TSImportEqualsDeclaration>(id, ParseModuleReference(), isExport);
527    importEqualsDecl->SetRange({startLoc, lexer_->GetToken().End()});
528
529    ConsumeSemicolon(importEqualsDecl);
530
531    return importEqualsDecl;
532}
533
534ir::TSNamespaceExportDeclaration *ParserImpl::ParseTsNamespaceExportDeclaration(const lexer::SourcePosition &startLoc)
535{
536    if (!IsDtsFile()) {
537        ThrowSyntaxError("namespace export declaration is only supported in TypeScript '.d.ts'");
538    }
539    ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS);
540    lexer_->NextToken();  // eat as keyword
541    if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_NAMESPACE) {
542        ThrowSyntaxError("'namespace' expected");
543    }
544    lexer_->NextToken();  // eat namespace keyword
545    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
546        ThrowSyntaxError("identifier expected");
547    }
548
549    auto *id = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
550    id->SetRange(lexer_->GetToken().Loc());
551    lexer_->NextToken();  // eat identifier
552
553    auto *namespaceExportDecl = AllocNode<ir::TSNamespaceExportDeclaration>(id);
554    namespaceExportDecl->SetRange({startLoc, lexer_->GetToken().End()});
555
556    ConsumeSemicolon(namespaceExportDecl);
557
558    return namespaceExportDecl;
559}
560
561ir::TSModuleBlock *ParserImpl::ParseTsModuleBlock()
562{
563    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
564        ThrowSyntaxError("'{' expected.");
565    }
566
567    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
568    lexer_->NextToken();
569    auto statements = ParseStatementList();
570
571    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
572        ThrowSyntaxError("Expected a '}'");
573    }
574
575    auto *blockNode = AllocNode<ir::TSModuleBlock>(std::move(statements));
576    blockNode->SetRange({startLoc, lexer_->GetToken().End()});
577
578    lexer_->NextToken();
579    return blockNode;
580}
581
582ir::Statement *ParserImpl::ParseVarStatement(bool isDeclare)
583{
584    auto *variableDecl = ParseVariableDeclaration(VariableParsingFlags::VAR, isDeclare);
585    ConsumeSemicolon(variableDecl);
586    return variableDecl;
587}
588
589ir::Statement *ParserImpl::ParseLetStatement(StatementParsingFlags flags, bool isDeclare)
590{
591    if (!(flags & StatementParsingFlags::ALLOW_LEXICAL)) {
592        ThrowSyntaxError("The 'let' declarations can only be declared at the top level or inside a block.");
593    }
594
595    auto *variableDecl = ParseVariableDeclaration(VariableParsingFlags::LET, isDeclare);
596    ConsumeSemicolon(variableDecl);
597    return variableDecl;
598}
599
600ir::Statement *ParserImpl::ParseConstStatement(StatementParsingFlags flags, bool isDeclare)
601{
602    lexer::SourcePosition constVarStar = lexer_->GetToken().Start();
603    lexer_->NextToken();
604
605    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ENUM) {
606        if (Extension() == ScriptExtension::TS) {
607            return ParseEnumDeclaration(false, isDeclare, true);
608        }
609        ThrowSyntaxError("Unexpected token");
610    }
611
612    if (!(flags & StatementParsingFlags::ALLOW_LEXICAL)) {
613        ThrowSyntaxError("The 'const' declarations can only be declared at the top level or inside a block.");
614    }
615
616    auto *variableDecl =
617        ParseVariableDeclaration(VariableParsingFlags::CONST | VariableParsingFlags::NO_SKIP_VAR_KIND, isDeclare);
618    variableDecl->SetStart(constVarStar);
619    ConsumeSemicolon(variableDecl);
620
621    return variableDecl;
622}
623
624ir::EmptyStatement *ParserImpl::ParseEmptyStatement()
625{
626    auto *empty = AllocNode<ir::EmptyStatement>();
627    empty->SetRange(lexer_->GetToken().Loc());
628    lexer_->NextToken();
629    return empty;
630}
631
632ir::DebuggerStatement *ParserImpl::ParseDebuggerStatement()
633{
634    auto *debuggerNode = AllocNode<ir::DebuggerStatement>();
635    debuggerNode->SetRange(lexer_->GetToken().Loc());
636    lexer_->NextToken();
637    ConsumeSemicolon(debuggerNode);
638    return debuggerNode;
639}
640
641ir::Statement *ParserImpl::ParseFunctionStatement(StatementParsingFlags flags, bool isDeclare)
642{
643    CheckFunctionDeclaration(flags);
644
645    if (!(flags & StatementParsingFlags::STMT_LEXICAL_SCOPE_NEEDED)) {
646        return ParseFunctionDeclaration(false, ParserStatus::NO_OPTS, isDeclare);
647    }
648
649    auto localCtx = binder::LexicalScope<binder::LocalScope>(Binder());
650    ArenaVector<ir::Statement *> stmts(Allocator()->Adapter());
651    auto *funcDecl = ParseFunctionDeclaration(false, ParserStatus::NO_OPTS, isDeclare);
652    stmts.push_back(funcDecl);
653
654    auto *localBlockStmt = AllocNode<ir::BlockStatement>(localCtx.GetScope(), std::move(stmts));
655    localBlockStmt->SetRange(funcDecl->Range());
656    localCtx.GetScope()->BindNode(localBlockStmt);
657
658    return funcDecl;
659}
660
661ir::Statement *ParserImpl::ParsePotentialExpressionStatement(StatementParsingFlags flags, bool isDeclare)
662{
663    if (lexer_->Lookahead() == LEX_CHAR_COLON) {
664        const auto pos = lexer_->Save();
665        lexer_->NextToken();
666        return ParseLabelledStatement(pos);
667    }
668
669    if (Extension() == ScriptExtension::TS && IsTsDeclarationStatement()) {
670        switch (lexer_->GetToken().KeywordType()) {
671            case lexer::TokenType::KEYW_ENUM: {
672                return ParseEnumDeclaration(false, isDeclare, false);
673            }
674            case lexer::TokenType::KEYW_TYPE: {
675                return ParseTsTypeAliasDeclaration(isDeclare);
676            }
677            case lexer::TokenType::KEYW_INTERFACE: {
678                return ParseTsInterfaceDeclaration(isDeclare);
679            }
680            default:
681                break;
682        }
683    }
684
685    return ParseExpressionStatement(flags);
686}
687
688ir::ClassDeclaration *ParserImpl::ParseClassStatement(StatementParsingFlags flags, bool isDeclare,
689                                                      ArenaVector<ir::Decorator *> &&decorators,
690                                                      ArenaVector<ir::Annotation *> &&annotations, bool isAbstract)
691{
692    if (!(flags & StatementParsingFlags::ALLOW_LEXICAL)) {
693        ThrowSyntaxError("Lexical 'class' declaration is not allowed in single statement context");
694    }
695
696    return ParseClassDeclaration(true, std::move(decorators), std::move(annotations), isDeclare, isAbstract, false,
697                                 false);
698}
699
700ir::ClassDeclaration *ParserImpl::ParseClassDeclaration(bool idRequired, ArenaVector<ir::Decorator *> &&decorators,
701                                                        ArenaVector<ir::Annotation *> &&annotations, bool isDeclare,
702                                                        bool isAbstract, bool isExported, bool isAnnotation)
703{
704    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
705    ir::ClassDefinition *classDefinition = ParseClassDefinition(true, idRequired, isDeclare, isAbstract);
706    if (isExported && !idRequired) {
707        classDefinition->SetAsExportDefault();
708    }
709
710    if (!decorators.empty()) {
711        classDefinition->SetClassDecoratorPresent();
712    }
713
714    auto location = classDefinition->Ident() ? classDefinition->Ident()->Start() : startLoc;
715    auto className = classDefinition->GetName();
716    ASSERT(!className.Empty());
717
718    binder::DeclarationFlags flag = isExported ? binder::DeclarationFlags::EXPORT : binder::DeclarationFlags::NONE;
719    auto *decl = Binder()->AddDecl<binder::ClassDecl>(location, flag, classDefinition->Declare(), className);
720
721    decl->BindNode(classDefinition);
722
723    lexer::SourcePosition endLoc = classDefinition->End();
724    auto *classDecl = AllocNode<ir::ClassDeclaration>(classDefinition, std::move(decorators), std::move(annotations),
725                                                      isAnnotation);
726    classDecl->SetRange({startLoc, endLoc});
727    return classDecl;
728}
729
730ir::TSTypeAliasDeclaration *ParserImpl::ParseTsTypeAliasDeclaration(bool isDeclare)
731{
732    ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE);
733    lexer::SourcePosition typeStart = lexer_->GetToken().Start();
734    lexer_->NextToken();  // eat type keyword
735
736    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT &&
737        !(lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT && isDeclare)) {
738        ThrowSyntaxError("Identifier expected");
739    }
740
741    if (lexer_->GetToken().IsReservedTypeName()) {
742        std::string errMsg("Type alias name cannot be '");
743        errMsg.append(TokenToString(lexer_->GetToken().KeywordType()));
744        errMsg.append("'");
745        ThrowSyntaxError(errMsg.c_str());
746    }
747
748    const util::StringView &ident = lexer_->GetToken().Ident();
749    binder::TSBinding tsBinding(Allocator(), ident);
750    auto *decl = Binder()->AddTsDecl<binder::TypeAliasDecl>(lexer_->GetToken().Start(), isDeclare, tsBinding.View());
751
752    auto *id = AllocNode<ir::Identifier>(ident);
753    id->SetRange(lexer_->GetToken().Loc());
754    lexer_->NextToken();
755
756    ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
757    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
758        typeParamDecl = ParseTsTypeParameterDeclaration(true, true);
759    }
760
761    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
762        ThrowSyntaxError("'=' expected");
763    }
764
765    lexer_->NextToken();  // eat '='
766
767    TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
768    ir::Expression *typeAnnotation = ParseTsTypeAnnotation(&options);
769
770    auto *typeAliasDecl = AllocNode<ir::TSTypeAliasDeclaration>(id, typeParamDecl, typeAnnotation, isDeclare);
771    typeAliasDecl->SetRange({typeStart, lexer_->GetToken().End()});
772    decl->BindNode(typeAliasDecl);
773    ConsumeSemicolon(typeAliasDecl);
774
775    return typeAliasDecl;
776}
777
778ir::TSInterfaceDeclaration *ParserImpl::ParseTsInterfaceDeclaration(bool isDeclare)
779{
780    ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_INTERFACE);
781    context_.Status() |= ParserStatus::ALLOW_THIS_TYPE;
782    lexer::SourcePosition interfaceStart = lexer_->GetToken().Start();
783    lexer_->NextToken();  // eat interface keyword
784
785    ValidateTsInterfaceName(isDeclare);
786
787    const util::StringView &ident = lexer_->GetToken().Ident();
788    binder::TSBinding tsBinding(Allocator(), ident);
789
790    const auto &bindings = Binder()->GetScope()->Bindings();
791    auto res = bindings.find(tsBinding.View());
792    binder::InterfaceDecl *decl {};
793
794    if (res == bindings.end()) {
795        decl = Binder()->AddTsDecl<binder::InterfaceDecl>(lexer_->GetToken().Start(), isDeclare,
796                                                          Allocator(), tsBinding.View());
797    } else if (!res->second->Declaration()->IsInterfaceDecl()) {
798        Binder()->ThrowRedeclaration(lexer_->GetToken().Start(), ident);
799    } else {
800        decl = res->second->Declaration()->AsInterfaceDecl();
801    }
802
803    auto *id = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
804    id->SetRange(lexer_->GetToken().Loc());
805    id->SetReference();
806    lexer_->NextToken();
807
808    binder::LexicalScope<binder::LocalScope> localScope(Binder());
809
810    ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
811    if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
812        typeParamDecl = ParseTsTypeParameterDeclaration(true, true);
813    }
814
815    ArenaVector<ir::TSInterfaceHeritage *> extends = ParseTsInterfaceExtends();
816
817    lexer::SourcePosition bodyStart = lexer_->GetToken().Start();
818    auto members = ParseTsTypeLiteralOrInterface();
819
820    auto *body = AllocNode<ir::TSInterfaceBody>(std::move(members));
821    body->SetRange({bodyStart, lexer_->GetToken().End()});
822
823    auto *interfaceDecl =
824        AllocNode<ir::TSInterfaceDeclaration>(localScope.GetScope(), id, typeParamDecl, body, std::move(extends));
825    interfaceDecl->SetRange({interfaceStart, lexer_->GetToken().End()});
826
827    ASSERT(decl);
828
829    if (res == bindings.end()) {
830        decl->BindNode(interfaceDecl);
831    }
832    decl->AsInterfaceDecl()->Add(interfaceDecl);
833
834    lexer_->NextToken();
835    context_.Status() &= ~ParserStatus::ALLOW_THIS_TYPE;
836
837    return interfaceDecl;
838}
839
840void ParserImpl::ValidateTsInterfaceName(bool isDeclare)
841{
842    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT &&
843        !(lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT && isDeclare)) {
844        ThrowSyntaxError("Identifier expected");
845    }
846
847    if (lexer_->GetToken().IsReservedTypeName()) {
848        std::string errMsg("Interface name cannot be '");
849        errMsg.append(TokenToString(lexer_->GetToken().KeywordType()));
850        errMsg.append("'");
851        ThrowSyntaxError(errMsg.c_str());
852    }
853}
854
855ArenaVector<ir::TSInterfaceHeritage *> ParserImpl::ParseTsInterfaceExtends()
856{
857    ArenaVector<ir::TSInterfaceHeritage *> extends(Allocator()->Adapter());
858
859    if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_EXTENDS) {
860        return extends;
861    }
862
863    lexer_->NextToken();  // eat extends keyword
864    while (true) {
865        if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
866            ThrowSyntaxError("Identifier expected");
867        }
868        const lexer::SourcePosition &heritageStart = lexer_->GetToken().Start();
869        lexer::SourcePosition heritageEnd = lexer_->GetToken().End();
870        ir::Expression *expr = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
871        expr->AsIdentifier()->SetReference();
872        expr->SetRange(lexer_->GetToken().Loc());
873        if (lexer_->Lookahead() == LEX_CHAR_LESS_THAN) {
874            lexer_->ForwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
875        } else {
876            lexer_->NextToken();
877        }
878        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
879            expr = ParseTsQualifiedReference(expr);
880        }
881        ir::TSTypeParameterInstantiation *typeParamInst = nullptr;
882        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
883            typeParamInst = ParseTsTypeParameterInstantiation();
884            heritageEnd = typeParamInst->End();
885        }
886        auto *typeReference = AllocNode<ir::TSTypeReference>(expr, typeParamInst);
887        typeReference->SetRange({heritageStart, heritageEnd});
888        auto *heritage = AllocNode<ir::TSInterfaceHeritage>(typeReference);
889        heritage->SetRange(typeReference->Range());
890        extends.push_back(heritage);
891        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
892            break;
893        }
894        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) {
895            ThrowSyntaxError("',' expected");
896        }
897        lexer_->NextToken();
898    }
899
900    return extends;
901}
902
903void ParserImpl::CheckFunctionDeclaration(StatementParsingFlags flags)
904{
905    if (flags & StatementParsingFlags::ALLOW_LEXICAL) {
906        return;
907    }
908
909    if (lexer_->Lookahead() == LEX_CHAR_ASTERISK) {
910        ThrowSyntaxError("Generators can only be declared at the top level or inside a block.");
911    }
912
913    ThrowSyntaxError(
914        "In strict mode code, functions can only be "
915        "declared at top level, inside a block, "
916        "or "
917        "as the body of an if statement");
918}
919
920void ParserImpl::ConsumeSemicolon(ir::Statement *statement)
921{
922    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
923        statement->SetEnd(lexer_->GetToken().End());
924        lexer_->NextToken();
925        return;
926    }
927
928    if (!lexer_->GetToken().NewLine()) {
929        if (lexer_->GetToken().Type() != lexer::TokenType::EOS &&
930            lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
931            ThrowSyntaxError("Unexpected token");
932        }
933    }
934}
935
936ArenaVector<ir::Statement *> ParserImpl::ParseStatementList(StatementParsingFlags flags)
937{
938    ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
939    ParseDirectivePrologue(&statements);
940
941    auto endType =
942        (flags & StatementParsingFlags::GLOBAL) ? lexer::TokenType::EOS : lexer::TokenType::PUNCTUATOR_RIGHT_BRACE;
943
944    while (lexer_->GetToken().Type() != endType) {
945        statements.push_back(ParseStatement(flags));
946    }
947
948    return statements;
949}
950
951bool ParserImpl::ParseDirective(ArenaVector<ir::Statement *> *statements)
952{
953    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
954
955    const util::StringView &str = lexer_->GetToken().String();
956
957    const auto status = static_cast<ParserStatus>(
958        context_.Status() & (ParserStatus::CONSTRUCTOR_FUNCTION | ParserStatus::HAS_COMPLEX_PARAM));
959    if (status == ParserStatus::HAS_COMPLEX_PARAM && str.Is("use strict")) {
960        ThrowSyntaxError(
961            "Illegal 'use strict' directive in function with "
962            "non-simple parameter list");
963    }
964
965    ir::Expression *exprNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
966    bool isDirective = exprNode->IsStringLiteral();
967
968    auto *exprStatement = AllocNode<ir::ExpressionStatement>(exprNode);
969    exprStatement->SetRange(exprNode->Range());
970
971    ConsumeSemicolon(exprStatement);
972    statements->push_back(exprStatement);
973
974    return isDirective;
975}
976
977void ParserImpl::ParseDirectivePrologue(ArenaVector<ir::Statement *> *statements)
978{
979    while (true) {
980        if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING || !ParseDirective(statements)) {
981            break;
982        }
983    }
984}
985
986ir::BlockStatement *ParserImpl::ParseBlockStatement(binder::Scope *scope)
987{
988    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
989
990    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
991    lexer_->NextToken();
992    auto statements = ParseStatementList();
993
994    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
995        ThrowSyntaxError("Expected a '}'");
996    }
997
998    auto *blockNode = AllocNode<ir::BlockStatement>(scope, std::move(statements));
999    blockNode->SetRange({startLoc, lexer_->GetToken().End()});
1000    scope->BindNode(blockNode);
1001
1002    return blockNode;
1003}
1004
1005ir::BlockStatement *ParserImpl::ParseBlockStatement()
1006{
1007    auto localCtx = binder::LexicalScope<binder::LocalScope>(Binder());
1008    auto *blockNode = ParseBlockStatement(localCtx.GetScope());
1009    lexer_->NextToken();
1010    return blockNode;
1011}
1012
1013ir::BreakStatement *ParserImpl::ParseBreakStatement()
1014{
1015    bool allowBreak = (context_.Status() & (ParserStatus::IN_ITERATION | ParserStatus::IN_SWITCH));
1016
1017    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1018    lexer_->NextToken();
1019
1020    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON ||
1021        lexer_->GetToken().Type() == lexer::TokenType::EOS || lexer_->GetToken().NewLine() ||
1022        lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1023
1024        if (!allowBreak && Extension() == ScriptExtension::JS) {
1025            ThrowSyntaxError("Illegal break statement");
1026        }
1027
1028        if (!allowBreak && Extension() == ScriptExtension::TS) {
1029            if (context_.Status() & ParserStatus::FUNCTION) {
1030                ThrowSyntaxError("Jump target cannot cross function boundary");
1031            } else {
1032                ThrowSyntaxError(
1033                    "A 'break' statement can only be used within an "
1034                    "enclosing iteration or switch statement");
1035            }
1036        }
1037
1038        auto *breakStatement = AllocNode<ir::BreakStatement>();
1039        breakStatement->SetRange({startLoc, lexer_->GetToken().End()});
1040        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1041            lexer_->NextToken();
1042        }
1043
1044        return breakStatement;
1045    }
1046
1047    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1048        ThrowSyntaxError("Unexpected token.");
1049    }
1050
1051    const auto &label = lexer_->GetToken().Ident();
1052
1053    if (!context_.FindLabel(label)) {
1054        ThrowSyntaxError("Undefined label");
1055    }
1056
1057    auto *identNode = AllocNode<ir::Identifier>(label);
1058    identNode->SetRange(lexer_->GetToken().Loc());
1059
1060    auto *breakStatement = AllocNode<ir::BreakStatement>(identNode);
1061    breakStatement->SetRange({startLoc, lexer_->GetToken().End()});
1062
1063    lexer_->NextToken();
1064    ConsumeSemicolon(breakStatement);
1065
1066    return breakStatement;
1067}
1068
1069ir::ContinueStatement *ParserImpl::ParseContinueStatement()
1070{
1071    if (Extension() == ScriptExtension::TS &&
1072        (static_cast<ParserStatus>(context_.Status() & (ParserStatus::FUNCTION | ParserStatus::IN_ITERATION |
1073                                                        ParserStatus::IN_SWITCH)) == ParserStatus::FUNCTION)) {
1074        ThrowSyntaxError("Jump target cannot cross function boundary");
1075    }
1076
1077    if (!(context_.Status() & ParserStatus::IN_ITERATION)) {
1078        if (Extension() == ScriptExtension::JS) {
1079            ThrowSyntaxError("Illegal continue statement");
1080        }
1081        if (Extension() == ScriptExtension::TS) {
1082            ThrowSyntaxError(
1083                "A 'continue' statement can only be used within an "
1084                "enclosing iteration statement");
1085        }
1086    }
1087
1088    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1089    lexer::SourcePosition endLoc = lexer_->GetToken().End();
1090    lexer_->NextToken();
1091
1092    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1093        auto *continueStatement = AllocNode<ir::ContinueStatement>();
1094        continueStatement->SetRange({startLoc, lexer_->GetToken().End()});
1095        lexer_->NextToken();
1096        return continueStatement;
1097    }
1098
1099    if (lexer_->GetToken().NewLine() || lexer_->GetToken().Type() == lexer::TokenType::EOS ||
1100        lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1101        auto *continueStatement = AllocNode<ir::ContinueStatement>();
1102        continueStatement->SetRange({startLoc, endLoc});
1103        return continueStatement;
1104    }
1105
1106    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1107        ThrowSyntaxError("Unexpected token.");
1108    }
1109
1110    const auto &label = lexer_->GetToken().Ident();
1111    const ParserContext *labelCtx = context_.FindLabel(label);
1112
1113    if (!labelCtx || !(labelCtx->Status() & (ParserStatus::IN_ITERATION | ParserStatus::IN_LABELED)) ||
1114       (labelCtx->Status() & ParserStatus::DISALLOW_CONTINUE)) {
1115        ThrowSyntaxError("Undefined label");
1116    }
1117
1118    auto *identNode = AllocNode<ir::Identifier>(label);
1119    identNode->SetRange(lexer_->GetToken().Loc());
1120
1121    auto *continueStatement = AllocNode<ir::ContinueStatement>(identNode);
1122    continueStatement->SetRange({startLoc, lexer_->GetToken().End()});
1123
1124    lexer_->NextToken();
1125    ConsumeSemicolon(continueStatement);
1126
1127    return continueStatement;
1128}
1129
1130ir::DoWhileStatement *ParserImpl::ParseDoWhileStatement()
1131{
1132    auto *savedScope = Binder()->GetScope();
1133    IterationContext<binder::LoopScope> iterCtx(&context_, Binder());
1134
1135    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1136    lexer_->NextToken();
1137    ir::Statement *body = ParseStatement();
1138
1139    if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_WHILE) {
1140        ThrowSyntaxError("Missing 'while' keyword in a 'DoWhileStatement'");
1141    }
1142
1143    lexer_->NextToken();
1144    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1145        ThrowSyntaxError("Missing left parenthesis in a 'DoWhileStatement'");
1146    }
1147
1148    lexer_->NextToken();
1149    ir::Expression *test = nullptr;
1150
1151    // The while expression should be included in the outer scope
1152    {
1153        auto outerScope = binder::LexicalScope<binder::Scope>::Enter(Binder(), savedScope);
1154        test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1155    }
1156
1157    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1158        ThrowSyntaxError("Missing right parenthesis in a 'DoWhileStatement'");
1159    }
1160
1161    auto *doWhileStatement = AllocNode<ir::DoWhileStatement>(iterCtx.LexicalScope().GetScope(), body, test);
1162    doWhileStatement->SetRange({startLoc, lexer_->GetToken().End()});
1163    iterCtx.LexicalScope().GetScope()->BindNode(doWhileStatement);
1164
1165    lexer_->NextToken();
1166
1167    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1168        doWhileStatement->SetEnd(lexer_->GetToken().End());
1169        lexer_->NextToken();
1170    }
1171
1172    return doWhileStatement;
1173}
1174
1175ir::FunctionDeclaration *ParserImpl::ParseFunctionDeclaration(bool canBeAnonymous, ParserStatus newStatus,
1176                                                              bool isDeclare)
1177{
1178    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1179
1180    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION);
1181    ParserStatus savedStatus = context_.Status();
1182
1183    lexer_->NextToken();
1184
1185    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
1186        newStatus |= ParserStatus::GENERATOR_FUNCTION;
1187        lexer_->NextToken();
1188    }
1189
1190    context_.Status() = savedStatus;
1191
1192    // e.g. export default function () {}
1193    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT &&
1194        lexer_->GetToken().Type() != lexer::TokenType::KEYW_AWAIT) {
1195        if (canBeAnonymous) {
1196            ir::ScriptFunction *func = ParseFunction(newStatus, isDeclare);
1197            if (func->Body() != nullptr) {
1198                lexer_->NextToken();
1199            }
1200            func->SetStart(startLoc);
1201            func->SetAsExportDefault();
1202
1203            auto *funcDecl = AllocNode<ir::FunctionDeclaration>(func);
1204            funcDecl->SetRange(func->Range());
1205
1206            binder::DeclarationFlags declflag = (newStatus & ParserStatus::EXPORT_REACHED) ?
1207                                                binder::DeclarationFlags::EXPORT : binder::DeclarationFlags::NONE;
1208            Binder()->AddDecl<binder::FunctionDecl>(startLoc, declflag, isDeclare, Allocator(),
1209                                                    parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME, func);
1210
1211            return funcDecl;
1212        }
1213
1214        ThrowSyntaxError("Unexpected token, expected identifier after 'function' keyword");
1215    }
1216
1217    if (!isDeclare) {
1218        CheckStrictReservedWord();
1219    }
1220
1221    util::StringView ident = lexer_->GetToken().Ident();
1222
1223    auto *identNode = AllocNode<ir::Identifier>(ident);
1224    identNode->SetRange(lexer_->GetToken().Loc());
1225    lexer_->NextToken();
1226
1227    newStatus |= ParserStatus::FUNCTION_DECLARATION;
1228    ir::ScriptFunction *func = ParseFunction(newStatus, isDeclare);
1229    if (func->Body() != nullptr) {
1230        lexer_->NextToken();
1231    }
1232
1233    func->SetIdent(identNode);
1234    func->SetStart(startLoc);
1235    auto *funcDecl = AllocNode<ir::FunctionDeclaration>(func);
1236    funcDecl->SetRange(func->Range());
1237
1238    AddFunctionToBinder(func, newStatus);
1239
1240    if (func->IsOverload() && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1241        lexer_->NextToken();
1242    }
1243
1244    CheckOptionalBindingPatternParameter(func);
1245
1246    return funcDecl;
1247}
1248
1249void ParserImpl::AddFunctionToBinder(ir::ScriptFunction *func, ParserStatus newStatus)
1250{
1251    binder::DeclarationFlags declflag = (newStatus & ParserStatus::EXPORT_REACHED) ?
1252                                        binder::DeclarationFlags::EXPORT : binder::DeclarationFlags::NONE;
1253    const ir::Identifier *identNode = func->Id();
1254    const lexer::SourcePosition &startLoc = func->Start();
1255    const util::StringView ident = identNode->Name();
1256    if (Extension() == ScriptExtension::TS) {
1257        const auto &bindings = Binder()->GetScope()->Bindings();
1258        auto res = bindings.find(ident);
1259        binder::Decl *currentDecl = res == bindings.end() ? nullptr : res->second->Declaration();
1260        binder::FunctionDecl *decl {};
1261
1262        if (res == bindings.end() ||
1263            (currentDecl->IsClassDecl() && currentDecl->AsClassDecl()->IsDeclare())) {
1264            decl = Binder()->AddDecl<binder::FunctionDecl>(identNode->Start(), declflag, func->Declare(),
1265                                                           Allocator(), ident, func);
1266        } else {
1267            if (!currentDecl->IsFunctionDecl()) {
1268                Binder()->ThrowRedeclaration(startLoc, currentDecl->Name());
1269            }
1270
1271            decl = currentDecl->AsFunctionDecl();
1272
1273            if (!decl->Node()->AsScriptFunction()->IsOverload()) {
1274                Binder()->ThrowRedeclaration(startLoc, currentDecl->Name());
1275            }
1276            if (!func->IsOverload()) {
1277                decl->BindNode(func);
1278            }
1279        }
1280
1281        decl->Add(func);
1282    } else {
1283        Binder()->AddDecl<binder::FunctionDecl>(identNode->Start(), declflag, func->Declare(),
1284                                                Allocator(), ident, func);
1285    }
1286}
1287
1288void ParserImpl::CheckOptionalBindingPatternParameter(ir::ScriptFunction *func) const
1289{
1290    if (func->Declare() || func->IsOverload()) {
1291        return;
1292    }
1293    for (auto *it : func->Params()) {
1294        if ((it->IsObjectPattern() && it->AsObjectPattern()->Optional()) ||
1295            (it->IsArrayPattern() && it->AsArrayPattern()->Optional())) {
1296            ThrowSyntaxError(
1297                "A binding pattern parameter cannot be optional in an "
1298                "implementation signature", it->Start());
1299        }
1300    }
1301}
1302
1303ir::Statement *ParserImpl::ParseExpressionStatement(StatementParsingFlags flags)
1304{
1305    const auto startPos = lexer_->Save();
1306    ParserStatus savedStatus = context_.Status();
1307
1308    if (lexer_->GetToken().IsAsyncModifier()) {
1309        context_.Status() |= ParserStatus::ASYNC_FUNCTION;
1310        lexer_->NextToken();
1311
1312        if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION && !lexer_->GetToken().NewLine()) {
1313            if (!(flags & StatementParsingFlags::ALLOW_LEXICAL)) {
1314                ThrowSyntaxError("Async functions can only be declared at the top level or inside a block.");
1315            }
1316
1317            ir::FunctionDeclaration *functionDecl = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION);
1318            functionDecl->SetStart(startPos.token.Start());
1319
1320            return functionDecl;
1321        }
1322
1323        lexer_->Rewind(startPos);
1324    }
1325
1326    ir::Expression *exprNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1327    context_.Status() = savedStatus;
1328    lexer::SourcePosition endPos = exprNode->End();
1329
1330    auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(exprNode);
1331    exprStatementNode->SetRange({startPos.token.Start(), endPos});
1332    ConsumeSemicolon(exprStatementNode);
1333
1334    return exprStatementNode;
1335}
1336
1337std::tuple<ForStatementKind, ir::Expression *, ir::Expression *> ParserImpl::ParseForInOf(
1338    ir::AstNode *initNode, ExpressionParseFlags exprFlags, bool isAwait)
1339{
1340    ForStatementKind forKind = ForStatementKind::UPDATE;
1341    ir::Expression *updateNode = nullptr;
1342    ir::Expression *rightNode = nullptr;
1343
1344    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN ||
1345        lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OF) {
1346        const ir::VariableDeclarator *varDecl = initNode->AsVariableDeclaration()->Declarators().front();
1347
1348        if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN) {
1349            if (varDecl->Init()) {
1350                ThrowSyntaxError("for-in loop variable declaration may not have an initializer");
1351            }
1352            forKind = ForStatementKind::IN;
1353            exprFlags = ExpressionParseFlags::ACCEPT_COMMA;
1354        } else {
1355            if (varDecl->Init()) {
1356                ThrowSyntaxError("for-of loop variable declaration may not have an initializer");
1357            }
1358
1359            forKind = ForStatementKind::OF;
1360        }
1361
1362        lexer_->NextToken();
1363        rightNode = ParseExpression(exprFlags);
1364    } else {
1365        if (isAwait) {
1366            ThrowSyntaxError("Unexpected token");
1367        }
1368
1369        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1370            ThrowSyntaxError("Invalid left-hand side in 'For[In/Of]Statement'");
1371        } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1372            lexer_->NextToken();
1373        } else {
1374            rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1375            if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1376                ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
1377            }
1378            lexer_->NextToken();
1379        }
1380
1381        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1382            updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1383        }
1384    }
1385
1386    return {forKind, rightNode, updateNode};
1387}
1388
1389std::tuple<ForStatementKind, ir::AstNode *, ir::Expression *, ir::Expression *> ParserImpl::ParseForInOf(
1390    ir::Expression *leftNode, ExpressionParseFlags exprFlags, bool isAwait)
1391{
1392    ForStatementKind forKind = ForStatementKind::UPDATE;
1393    ir::AstNode *initNode = nullptr;
1394    ir::Expression *updateNode = nullptr;
1395    ir::Expression *rightNode = nullptr;
1396
1397    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN ||
1398        (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OF)) {
1399        if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN) {
1400            forKind = ForStatementKind::IN;
1401            exprFlags = ExpressionParseFlags::ACCEPT_COMMA;
1402        } else {
1403            forKind = ForStatementKind::OF;
1404        }
1405
1406        bool isValid = true;
1407        switch (leftNode->Type()) {
1408            case ir::AstNodeType::IDENTIFIER: {
1409                constexpr std::string_view ASYNC = "async";
1410                if (isAwait || !(forKind == ForStatementKind::OF && leftNode->AsIdentifier()->Name().Is(ASYNC) &&
1411                    leftNode->End().index - leftNode->Start().index == ASYNC.length())) {
1412                    break;
1413                }
1414                ThrowSyntaxError(" The left-hand side of a for-of loop may not be 'async'", leftNode->Start());
1415            }
1416            case ir::AstNodeType::MEMBER_EXPRESSION: {
1417                break;
1418            }
1419            case ir::AstNodeType::ARRAY_EXPRESSION: {
1420                isValid = leftNode->AsArrayExpression()->ConvertibleToArrayPattern();
1421                break;
1422            }
1423            case ir::AstNodeType::OBJECT_EXPRESSION: {
1424                isValid = leftNode->AsObjectExpression()->ConvertibleToObjectPattern();
1425                break;
1426            }
1427            default: {
1428                isValid = false;
1429            }
1430        }
1431
1432        if (!isValid) {
1433            ValidateLvalueAssignmentTarget(leftNode);
1434        }
1435
1436        initNode = leftNode;
1437        lexer_->NextToken();
1438        rightNode = ParseExpression(exprFlags);
1439
1440        return {forKind, initNode, rightNode, updateNode};
1441    }
1442
1443    if (isAwait) {
1444        ThrowSyntaxError("Unexpected token");
1445    }
1446
1447    exprFlags &= ExpressionParseFlags::POTENTIALLY_IN_PATTERN;
1448    ir::Expression *expr = ParseAssignmentExpression(leftNode, exprFlags);
1449
1450    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
1451        initNode = ParseSequenceExpression(expr);
1452    } else {
1453        initNode = expr;
1454    }
1455
1456    if (initNode->IsConditionalExpression()) {
1457        ir::ConditionalExpression *condExpr = initNode->AsConditionalExpression();
1458        if (condExpr->Alternate()->IsBinaryExpression()) {
1459            const auto *binaryExpr = condExpr->Alternate()->AsBinaryExpression();
1460            if (binaryExpr->OperatorType() == lexer::TokenType::KEYW_IN) {
1461                ThrowSyntaxError("Invalid left-hand side in for-in statement");
1462            }
1463        }
1464    }
1465
1466    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1467        ThrowSyntaxError("Invalid left-hand side in 'For[In/Of]Statement'");
1468    }
1469
1470    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1471        ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
1472    }
1473
1474    lexer_->NextToken();
1475
1476    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1477        lexer_->NextToken();
1478    } else {
1479        rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1480
1481        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1482            ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
1483        }
1484        lexer_->NextToken();
1485    }
1486
1487    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1488        updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1489    }
1490
1491    return {forKind, initNode, rightNode, updateNode};
1492}
1493
1494std::tuple<ir::Expression *, ir::Expression *> ParserImpl::ParseForUpdate(bool isAwait)
1495{
1496    if (isAwait) {
1497        ThrowSyntaxError("Unexpected token");
1498    }
1499
1500    ir::Expression *updateNode = nullptr;
1501    ir::Expression *rightNode = nullptr;
1502
1503    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1504        lexer_->NextToken();
1505    } else {
1506        rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1507        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1508            ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
1509        }
1510        lexer_->NextToken();
1511    }
1512
1513    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1514        updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1515    }
1516
1517    return {rightNode, updateNode};
1518}
1519
1520ir::Statement *ParserImpl::ParseForStatement()
1521{
1522    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1523    ForStatementKind forKind = ForStatementKind::UPDATE;
1524    ir::AstNode *initNode = nullptr;
1525    ir::Expression *updateNode = nullptr;
1526    ir::Expression *leftNode = nullptr;
1527    ir::Expression *rightNode = nullptr;
1528    bool canBeForInOf = true;
1529    bool isAwait = false;
1530    lexer_->NextToken();
1531    VariableParsingFlags varFlags = VariableParsingFlags::STOP_AT_IN | VariableParsingFlags::IN_FOR;
1532    ExpressionParseFlags exprFlags = ExpressionParseFlags::NO_OPTS;
1533
1534    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) {
1535        isAwait = true;
1536        varFlags |= VariableParsingFlags::DISALLOW_INIT;
1537        lexer_->NextToken();
1538    }
1539
1540    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1541        ThrowSyntaxError("Missing left parenthesis in a 'ForStatement'");
1542    }
1543    lexer_->NextToken();
1544
1545    IterationContext<binder::LoopScope> iterCtx(&context_, Binder());
1546
1547    switch (lexer_->GetToken().Type()) {
1548        case lexer::TokenType::KEYW_VAR: {
1549            initNode = ParseVariableDeclaration(varFlags | VariableParsingFlags::VAR);
1550            break;
1551        }
1552        case lexer::TokenType::KEYW_LET: {
1553            initNode = ParseVariableDeclaration(varFlags | VariableParsingFlags::LET);
1554            break;
1555        }
1556        case lexer::TokenType::KEYW_CONST: {
1557            initNode = ParseVariableDeclaration(varFlags | VariableParsingFlags::CONST |
1558                                                VariableParsingFlags::ACCEPT_CONST_NO_INIT);
1559            break;
1560        }
1561        case lexer::TokenType::PUNCTUATOR_SEMI_COLON: {
1562            if (isAwait) {
1563                ThrowSyntaxError("Unexpected token");
1564            }
1565
1566            canBeForInOf = false;
1567            lexer_->NextToken();
1568            break;
1569        }
1570        default: {
1571            leftNode = ParseUnaryOrPrefixUpdateExpression(ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
1572
1573            break;
1574        }
1575    }
1576
1577    if (initNode != nullptr) {
1578        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1579            lexer_->NextToken();
1580            canBeForInOf = false;
1581        } else {
1582            canBeForInOf = initNode->AsVariableDeclaration()->Declarators().size() == 1;
1583        }
1584    }
1585
1586    // VariableDeclaration->DeclarationSize > 1 or seen semi_colon
1587    if (!canBeForInOf) {
1588        std::tie(rightNode, updateNode) = ParseForUpdate(isAwait);
1589    } else if (leftNode) {
1590        // initNode was parsed as LHS
1591        if (leftNode->IsArrayExpression() || leftNode->IsObjectExpression()) {
1592            exprFlags |= ExpressionParseFlags::POTENTIALLY_IN_PATTERN;
1593        }
1594        std::tie(forKind, initNode, rightNode, updateNode) = ParseForInOf(leftNode, exprFlags, isAwait);
1595    } else if (initNode) {
1596        // initNode was parsed as VariableDeclaration and declaration size = 1
1597        std::tie(forKind, rightNode, updateNode) = ParseForInOf(initNode, exprFlags, isAwait);
1598    }
1599
1600    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1601        ThrowSyntaxError("Unexpected token, expected ')' in 'ForStatement'.");
1602    }
1603    lexer_->NextToken();
1604
1605    ir::Statement *bodyNode = ParseStatement();
1606    lexer::SourcePosition endLoc = bodyNode->End();
1607
1608    ir::Statement *forStatement = nullptr;
1609    auto *loopScope = iterCtx.LexicalScope().GetScope();
1610
1611    if (forKind == ForStatementKind::UPDATE) {
1612        forStatement = AllocNode<ir::ForUpdateStatement>(loopScope, initNode, rightNode, updateNode, bodyNode);
1613    } else if (forKind == ForStatementKind::IN) {
1614        forStatement = AllocNode<ir::ForInStatement>(loopScope, initNode, rightNode, bodyNode);
1615    } else {
1616        forStatement = AllocNode<ir::ForOfStatement>(loopScope, initNode, rightNode, bodyNode, isAwait);
1617    }
1618
1619    forStatement->SetRange({startLoc, endLoc});
1620    loopScope->BindNode(forStatement);
1621
1622    return forStatement;
1623}
1624
1625ir::IfStatement *ParserImpl::ParseIfStatement()
1626{
1627    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1628    lexer::SourcePosition endLoc = lexer_->GetToken().End();
1629    lexer_->NextToken();
1630
1631    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1632        ThrowSyntaxError("Missing left parenthesis in an 'IfStatement'");
1633    }
1634
1635    lexer_->NextToken();
1636    ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1637
1638    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1639        ThrowSyntaxError("Missing right parenthesis in an 'IfStatement'");
1640    }
1641
1642    lexer_->NextToken();
1643    ir::Statement *consequent = ParseStatement(StatementParsingFlags::IF_ELSE);
1644
1645    if (Extension() == ScriptExtension::TS && consequent->IsEmptyStatement()) {
1646        ThrowSyntaxError("The body of an if statement cannot be the empty statement");
1647    }
1648
1649    endLoc = consequent->End();
1650    ir::Statement *alternate = nullptr;
1651
1652    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_ELSE) {
1653        lexer_->NextToken();  // eat ELSE keyword
1654        alternate = ParseStatement(StatementParsingFlags::IF_ELSE);
1655        endLoc = alternate->End();
1656    }
1657
1658    auto *ifStatement = AllocNode<ir::IfStatement>(test, consequent, alternate);
1659    ifStatement->SetRange({startLoc, endLoc});
1660    return ifStatement;
1661}
1662
1663ir::LabelledStatement *ParserImpl::ParseLabelledStatement(const lexer::LexerPosition &pos)
1664{
1665    const auto savedPos = lexer_->Save();
1666    bool isLabelFollowedByIterationStatement = IsLabelFollowedByIterationStatement();
1667    lexer_->Rewind(savedPos);
1668
1669    const util::StringView &actualLabel = pos.token.Ident();
1670
1671    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AWAIT && context_.IsModule()) {
1672        ThrowSyntaxError("'await' is a reserved identifier in module code", pos.token.Start());
1673    }
1674
1675    if (context_.FindLabel(actualLabel)) {
1676        ThrowSyntaxError("Label already declared", pos.token.Start());
1677    }
1678
1679    SavedParserContext newCtx(this, ParserStatus::IN_LABELED | context_.Status(), actualLabel);
1680    if (isLabelFollowedByIterationStatement) {
1681        context_.Status() &= ~ParserStatus::DISALLOW_CONTINUE;
1682    } else {
1683        context_.Status() |= ParserStatus::DISALLOW_CONTINUE;
1684    }
1685
1686    auto *identNode = AllocNode<ir::Identifier>(actualLabel);
1687    identNode->SetRange(pos.token.Loc());
1688
1689    lexer_->NextToken();
1690
1691    ir::Statement *body = ParseStatement(StatementParsingFlags::LABELLED);
1692
1693    auto *labeledStatement = AllocNode<ir::LabelledStatement>(identNode, body);
1694    labeledStatement->SetRange({pos.token.Start(), body->End()});
1695
1696    return labeledStatement;
1697}
1698
1699ir::ReturnStatement *ParserImpl::ParseReturnStatement()
1700{
1701    if (!(context_.Status() & ParserStatus::FUNCTION)) {
1702        ThrowSyntaxError("return keyword should be used in function body");
1703    }
1704
1705    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1706    lexer::SourcePosition endLoc = lexer_->GetToken().End();
1707    lexer_->NextToken();
1708
1709    bool hasArgument = (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
1710                        lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
1711                        lexer_->GetToken().Type() != lexer::TokenType::EOS && !lexer_->GetToken().NewLine());
1712
1713    ir::ReturnStatement *returnStatement = nullptr;
1714
1715    if (hasArgument) {
1716        ir::Expression *expression = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1717        endLoc = expression->End();
1718        returnStatement = AllocNode<ir::ReturnStatement>(expression);
1719    } else {
1720        returnStatement = AllocNode<ir::ReturnStatement>();
1721    }
1722
1723    returnStatement->SetRange({startLoc, endLoc});
1724    ConsumeSemicolon(returnStatement);
1725
1726    return returnStatement;
1727}
1728
1729ir::SwitchCaseStatement *ParserImpl::ParseSwitchCaseStatement(bool *seenDefault)
1730{
1731    lexer::SourcePosition caseStartLoc = lexer_->GetToken().Start();
1732    ir::Expression *testExpr = nullptr;
1733
1734    switch (lexer_->GetToken().Type()) {
1735        case lexer::TokenType::KEYW_CASE: {
1736            lexer_->NextToken();
1737            testExpr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1738            break;
1739        }
1740        case lexer::TokenType::KEYW_DEFAULT: {
1741            if (*seenDefault) {
1742                if (Extension() == ScriptExtension::TS) {
1743                    ThrowSyntaxError(
1744                        "A 'default' clause cannot appear more than once in a "
1745                        "'switch' statement");
1746                } else {
1747                    ThrowSyntaxError("Multiple default clauses.");
1748                }
1749            }
1750            *seenDefault = true;
1751            lexer_->NextToken();
1752            break;
1753        }
1754        default: {
1755            ThrowSyntaxError("Unexpected token, expected 'case' or 'default'.");
1756        }
1757    }
1758
1759    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
1760        ThrowSyntaxError("Unexpected token, expected ':'");
1761    }
1762
1763    ArenaVector<ir::Statement *> consequents(Allocator()->Adapter());
1764    lexer::SourcePosition caseEndLoc = lexer_->GetToken().End();
1765
1766    lexer_->NextToken();
1767
1768    while (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CASE &&
1769           lexer_->GetToken().Type() != lexer::TokenType::KEYW_DEFAULT &&
1770           lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1771        ir::Statement *consequent = ParseStatement(StatementParsingFlags::ALLOW_LEXICAL);
1772        caseEndLoc = consequent->End();
1773        consequents.push_back(consequent);
1774    }
1775
1776    auto *caseNode = AllocNode<ir::SwitchCaseStatement>(testExpr, std::move(consequents));
1777    caseNode->SetRange({caseStartLoc, caseEndLoc});
1778    return caseNode;
1779}
1780
1781ir::SwitchStatement *ParserImpl::ParseSwitchStatement()
1782{
1783    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1784    lexer_->NextToken();
1785    if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS)) {
1786        ThrowSyntaxError("Unexpected token, expected '('");
1787    }
1788
1789    lexer_->NextToken();
1790    ir::Expression *discriminant = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1791
1792    if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS)) {
1793        ThrowSyntaxError("Unexpected token, expected ')'");
1794    }
1795
1796    lexer_->NextToken();
1797    SwitchContext switchContext(&context_);
1798
1799    if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE)) {
1800        ThrowSyntaxError("Unexpected token, expected '{'");
1801    }
1802
1803    lexer_->NextToken();
1804    bool seenDefault = false;
1805    auto localCtx = binder::LexicalScope<binder::LocalScope>(Binder());
1806    ArenaVector<ir::SwitchCaseStatement *> cases(Allocator()->Adapter());
1807
1808    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1809        cases.push_back(ParseSwitchCaseStatement(&seenDefault));
1810    }
1811
1812    auto *switchStatement = AllocNode<ir::SwitchStatement>(localCtx.GetScope(), discriminant, std::move(cases));
1813    switchStatement->SetRange({startLoc, lexer_->GetToken().End()});
1814    localCtx.GetScope()->BindNode(switchStatement);
1815
1816    lexer_->NextToken();
1817
1818    return switchStatement;
1819}
1820
1821ir::ThrowStatement *ParserImpl::ParseThrowStatement()
1822{
1823    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1824    lexer_->NextToken();
1825
1826    if (lexer_->GetToken().NewLine()) {
1827        if (Extension() == ScriptExtension::JS) {
1828            ThrowSyntaxError("Illegal newline after throw");
1829        }
1830
1831        if (Extension() == ScriptExtension::TS) {
1832            ThrowSyntaxError("Line break not permitted here");
1833        }
1834    }
1835
1836    ir::Expression *expression = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1837    lexer::SourcePosition endLoc = expression->End();
1838
1839    auto *throwStatement = AllocNode<ir::ThrowStatement>(expression);
1840    throwStatement->SetRange({startLoc, endLoc});
1841    ConsumeSemicolon(throwStatement);
1842
1843    return throwStatement;
1844}
1845
1846ir::Expression *ParserImpl::ParseCatchParam()
1847{
1848    ir::Expression *param = nullptr;
1849
1850    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1851        return param;
1852    }
1853
1854    lexer_->NextToken();  // eat left paren
1855
1856    if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1857        switch (lexer_->GetToken().KeywordType()) {
1858            case lexer::TokenType::KEYW_EVAL: {
1859                ThrowSyntaxError("Binding 'eval' in strict mode is invalid");
1860            }
1861            case lexer::TokenType::KEYW_ARGUMENTS: {
1862                ThrowSyntaxError("Binding 'arguments' in strict mode is invalid");
1863            }
1864            default: {
1865                break;
1866            }
1867        }
1868
1869        param = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1870        param->SetRange(lexer_->GetToken().Loc());
1871
1872        lexer_->NextToken();
1873    } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1874        param = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1875    } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1876        param = ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1877    } else {
1878        ThrowSyntaxError("Unexpected token in catch parameter");
1879    }
1880
1881    Binder()->AddParamDecl(param);
1882
1883    if (Extension() == ScriptExtension::TS) {
1884        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1885            lexer_->NextToken();  // eat ':'
1886
1887            TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1888            param->SetTsTypeAnnotation(ParseTsTypeAnnotation(&options));
1889        }
1890
1891        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
1892            ThrowSyntaxError("Catch clause variable cannot have an initializer");
1893        }
1894    }
1895
1896    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1897        ThrowSyntaxError("Unexpected token, expected ')'");
1898    }
1899
1900    lexer_->NextToken();
1901
1902    return param;
1903}
1904
1905ir::CatchClause *ParserImpl::ParseCatchClause()
1906{
1907    lexer::SourcePosition catchStartLoc = lexer_->GetToken().Start();
1908    lexer_->NextToken();  // eat 'catch' keyword
1909
1910    auto catchParamCtx = binder::LexicalScope<binder::CatchParamScope>(Binder());
1911    auto *catchParamScope = catchParamCtx.GetScope();
1912
1913    ir::Expression *param = ParseCatchParam();
1914    catchParamScope->BindNode(param);
1915
1916    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1917        ThrowSyntaxError("Unexpected token, expected '{'");
1918    }
1919
1920    auto catchCtx = binder::LexicalScope<binder::CatchScope>(Binder());
1921    auto *catchScope = catchCtx.GetScope();
1922    catchScope->AssignParamScope(catchParamScope);
1923
1924    ir::BlockStatement *catchBlock = ParseBlockStatement(catchScope);
1925    lexer_->NextToken();
1926    lexer::SourcePosition endLoc = catchBlock->End();
1927
1928    auto *catchClause = AllocNode<ir::CatchClause>(catchScope, param, catchBlock);
1929    catchClause->SetRange({catchStartLoc, endLoc});
1930    catchScope->BindNode(catchClause);
1931
1932    return catchClause;
1933}
1934
1935ir::TryStatement *ParserImpl::ParseTryStatement()
1936{
1937    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1938    lexer::SourcePosition endLoc = lexer_->GetToken().End();
1939
1940    lexer_->NextToken();
1941
1942    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1943        ThrowSyntaxError("Unexpected token, expected '{'");
1944    }
1945
1946    ir::BlockStatement *body = ParseBlockStatement();
1947
1948    if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CATCH &&
1949        lexer_->GetToken().Type() != lexer::TokenType::KEYW_FINALLY) {
1950        ThrowSyntaxError("Missing catch or finally clause");
1951    }
1952
1953    ir::CatchClause *catchClause = nullptr;
1954    ir::BlockStatement *finnalyClause = nullptr;
1955
1956    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_CATCH) {
1957        catchClause = ParseCatchClause();
1958        endLoc = catchClause->End();
1959    }
1960
1961    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FINALLY) {
1962        lexer_->NextToken();  // eat 'finally' keyword
1963
1964        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1965            ThrowSyntaxError("Unexpected token, expected '{'");
1966        }
1967
1968        finnalyClause = ParseBlockStatement();
1969        endLoc = finnalyClause->End();
1970    }
1971
1972    auto *tryStatement = AllocNode<ir::TryStatement>(body, catchClause, finnalyClause);
1973    tryStatement->SetRange({startLoc, endLoc});
1974    return tryStatement;
1975}
1976
1977void ParserImpl::ValidateDeclaratorId(bool isDeclare)
1978{
1979    if (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT) {
1980        return;
1981    }
1982
1983    switch (lexer_->GetToken().KeywordType()) {
1984        case lexer::TokenType::KEYW_AWAIT: {
1985            if (context_.IsModule() && !program_.IsDtsFile() && !context_.IsTsModule() && !isDeclare) {
1986                ThrowSyntaxError("'await' is not permitted as an identifier in module code");
1987            }
1988            break;
1989        }
1990        case lexer::TokenType::KEYW_EVAL: {
1991            ThrowSyntaxError("Binding 'eval' in strict mode is invalid");
1992        }
1993        case lexer::TokenType::KEYW_ARGUMENTS: {
1994            ThrowSyntaxError("Binding 'arguments' in strict mode is invalid");
1995        }
1996        case lexer::TokenType::KEYW_LET: {
1997            ThrowSyntaxError("let is disallowed as a lexically bound name");
1998            break;
1999        }
2000        case lexer::TokenType::KEYW_STATIC:
2001        case lexer::TokenType::KEYW_IMPLEMENTS:
2002        case lexer::TokenType::KEYW_INTERFACE:
2003        case lexer::TokenType::KEYW_PACKAGE:
2004        case lexer::TokenType::KEYW_PRIVATE:
2005        case lexer::TokenType::KEYW_PROTECTED:
2006        case lexer::TokenType::KEYW_PUBLIC:
2007        case lexer::TokenType::KEYW_YIELD: {
2008            ThrowSyntaxError("Unexpected reserved word");
2009        }
2010        default: {
2011            break;
2012        }
2013    }
2014}
2015
2016ir::VariableDeclarator *ParserImpl::ParseVariableDeclaratorInitializer(ir::Expression *init, VariableParsingFlags flags,
2017                                                                       const lexer::SourcePosition &startLoc,
2018                                                                       bool isDeclare)
2019{
2020    if (flags & VariableParsingFlags::DISALLOW_INIT) {
2021        ThrowSyntaxError("for-await-of loop variable declaration may not have an initializer");
2022    }
2023
2024    lexer_->NextToken();
2025
2026    if (isDeclare && !(flags & VariableParsingFlags::CONST)) {
2027        ThrowSyntaxError("Initializers are not allowed in ambient contexts.");
2028    }
2029
2030    auto exprFlags =
2031        ((flags & VariableParsingFlags::STOP_AT_IN) ? ExpressionParseFlags::STOP_AT_IN : ExpressionParseFlags::NO_OPTS);
2032
2033    ir::Expression *initializer = ParseExpression(exprFlags);
2034    lexer::SourcePosition endLoc = initializer->End();
2035
2036    auto *declarator = AllocNode<ir::VariableDeclarator>(init, initializer);
2037    declarator->SetRange({startLoc, endLoc});
2038
2039    return declarator;
2040}
2041
2042ir::VariableDeclarator *ParserImpl::ParseVariableDeclarator(VariableParsingFlags flags, bool isDeclare)
2043{
2044    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2045
2046    bool isDefinite = false;
2047    ir::Expression *init = ParseVariableDeclaratorKey(flags, isDeclare, &isDefinite);
2048
2049    ir::VariableDeclarator *declarator {};
2050
2051    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
2052        declarator = ParseVariableDeclaratorInitializer(init, flags, startLoc, isDeclare);
2053    } else {
2054        if (!isDeclare && (flags & VariableParsingFlags::CONST) &&
2055            !(flags & VariableParsingFlags::ACCEPT_CONST_NO_INIT) &&
2056            !(context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT)) {
2057            ThrowSyntaxError("Missing initializer in const declaration");
2058        }
2059
2060        if (!isDeclare && !(flags & VariableParsingFlags::IN_FOR) &&
2061            (init->IsArrayPattern() || init->IsObjectPattern())) {
2062            ThrowSyntaxError("Missing initializer in destructuring declaration");
2063        }
2064
2065        lexer::SourcePosition endLoc = init->End();
2066        declarator = AllocNode<ir::VariableDeclarator>(init);
2067        declarator->SetRange({startLoc, endLoc});
2068    }
2069
2070    declarator->SetDefinite(isDefinite);
2071
2072    std::vector<const ir::Identifier *> bindings = util::Helpers::CollectBindingNames(init);
2073
2074    for (const auto *binding : bindings) {
2075        binder::Decl *decl = nullptr;
2076        binder::DeclarationFlags declflag = (flags & VariableParsingFlags::EXPORTED) ?
2077                                            binder::DeclarationFlags::EXPORT : binder::DeclarationFlags::NONE;
2078        if (flags & VariableParsingFlags::EXPORTED_IN_TSMODULE) {
2079            declflag |= binder::DeclarationFlags::EXPORT_IN_TSMODULE;
2080        }
2081
2082        if (flags & VariableParsingFlags::VAR) {
2083            decl = Binder()->AddDecl<binder::VarDecl>(startLoc, declflag, isDeclare, binding->Name());
2084        } else if (flags & VariableParsingFlags::LET) {
2085            decl = Binder()->AddDecl<binder::LetDecl>(startLoc, declflag, isDeclare, binding->Name());
2086        } else {
2087            decl = Binder()->AddDecl<binder::ConstDecl>(startLoc, declflag, isDeclare, binding->Name());
2088        }
2089
2090        decl->BindNode(init);
2091    }
2092
2093    return declarator;
2094}
2095
2096ir::Expression *ParserImpl::ParseVariableDeclaratorKey(VariableParsingFlags flags, bool isDeclare, bool *isDefinite)
2097{
2098    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT && isDeclare) {
2099        lexer_->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT);
2100    }
2101
2102    ir::Expression *init = nullptr;
2103    switch (lexer_->GetToken().Type()) {
2104        case lexer::TokenType::LITERAL_IDENT: {
2105            ValidateDeclaratorId(isDeclare);
2106
2107            if (!(flags & VariableParsingFlags::VAR) &&
2108                lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_LET) {
2109                ThrowSyntaxError("let is disallowed as a lexically bound name");
2110            }
2111
2112            const util::StringView &identStr = lexer_->GetToken().Ident();
2113            init = AllocNode<ir::Identifier>(identStr);
2114            init->SetRange(lexer_->GetToken().Loc());
2115
2116            if (Extension() == ScriptExtension::TS) {
2117                init->AsIdentifier()->SetReference();
2118            }
2119
2120            lexer_->NextToken();
2121            break;
2122        }
2123        case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
2124            init = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
2125            break;
2126        }
2127        case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
2128            init = ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN);
2129            break;
2130        }
2131        default: {
2132            ThrowSyntaxError("Unexpected token in variable declaration");
2133        }
2134    }
2135
2136    if (Extension() == ScriptExtension::TS) {
2137        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) {
2138            lexer_->NextToken();  // eat '!'
2139            *isDefinite = true;
2140        }
2141        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
2142            lexer_->NextToken();  // eat ':'
2143            TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
2144            init->SetTsTypeAnnotation(ParseTsTypeAnnotation(&options));
2145        }
2146    }
2147
2148    return init;
2149}
2150
2151ir::Statement *ParserImpl::ParseVariableDeclaration(VariableParsingFlags flags, bool isDeclare, bool isExport)
2152{
2153    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2154    if (!(flags & VariableParsingFlags::NO_SKIP_VAR_KIND)) {
2155        lexer_->NextToken();
2156    }
2157
2158    if ((flags & VariableParsingFlags::LET) && util::Helpers::IsGlobalIdentifier(lexer_->GetToken().Ident())) {
2159        ThrowSyntaxError("Declaration name conflicts with built-in global identifier '"
2160                        + lexer_->GetToken().Ident().Mutf8() + "'.");
2161    }
2162
2163    if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ENUM) {
2164        if (!(flags & VariableParsingFlags::CONST)) {
2165            ThrowSyntaxError("Variable declaration expected.");
2166        }
2167        return ParseEnumDeclaration(isExport, isDeclare, true);
2168    }
2169
2170    ArenaVector<ir::VariableDeclarator *> declarators(Allocator()->Adapter());
2171
2172    while (true) {
2173        ir::VariableDeclarator *declarator = ParseVariableDeclarator(flags, isDeclare);
2174
2175        declarators.push_back(declarator);
2176
2177        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) {
2178            break;
2179        }
2180        lexer_->NextToken();
2181    }
2182
2183    auto varKind = ir::VariableDeclaration::VariableDeclarationKind::VAR;
2184
2185    if (flags & VariableParsingFlags::LET) {
2186        varKind = ir::VariableDeclaration::VariableDeclarationKind::LET;
2187    } else if (flags & VariableParsingFlags::CONST) {
2188        varKind = ir::VariableDeclaration::VariableDeclarationKind::CONST;
2189    }
2190
2191    lexer::SourcePosition endLoc = declarators.back()->End();
2192    auto *declaration = AllocNode<ir::VariableDeclaration>(varKind, std::move(declarators), isDeclare);
2193    declaration->SetRange({startLoc, endLoc});
2194
2195    return declaration;
2196}
2197
2198ir::WhileStatement *ParserImpl::ParseWhileStatement()
2199{
2200    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2201    lexer_->NextToken();
2202    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
2203        ThrowSyntaxError("Unexpected token, expected '('");
2204    }
2205
2206    lexer_->NextToken();
2207    ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
2208
2209    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
2210        ThrowSyntaxError("Unexpected token, expected ')'");
2211    }
2212
2213    lexer_->NextToken();
2214    IterationContext<binder::LoopScope> iterCtx(&context_, Binder());
2215    ir::Statement *body = ParseStatement();
2216
2217    lexer::SourcePosition endLoc = body->End();
2218    auto *whileStatement = AllocNode<ir::WhileStatement>(iterCtx.LexicalScope().GetScope(), test, body);
2219    whileStatement->SetRange({startLoc, endLoc});
2220    iterCtx.LexicalScope().GetScope()->BindNode(whileStatement);
2221
2222    return whileStatement;
2223}
2224
2225void ParserImpl::AddImportEntryItem(const ir::StringLiteral *source,
2226                                    const ArenaVector<ir::AstNode *> *specifiers, bool isType, bool isLazy)
2227{
2228    if (context_.IsTsModule()) {
2229        return;
2230    }
2231
2232    ASSERT(source != nullptr);
2233
2234    if (specifiers == nullptr) {
2235        if (isType) {
2236            ThrowSyntaxError("Unexpected import type syntax", source->Start());
2237        }
2238        auto *moduleRecord = GetSourceTextModuleRecord();
2239        ASSERT(moduleRecord != nullptr);
2240        moduleRecord->AddModuleRequest(source->Str());
2241        return;
2242    }
2243
2244    for (auto *it : *specifiers) {
2245        if (!it->IsImportDefaultSpecifier() && !it->IsImportNamespaceSpecifier() && !it->IsImportSpecifier()) {
2246            ThrowSyntaxError("Unexpected astNode type", it->Start());
2247        }
2248        if (it->IsImportSpecifier()) {
2249            AddImportEntryItemForImportSpecifier(source, it, isLazy);
2250        } else {
2251            AddImportEntryItemForImportDefaultOrNamespaceSpecifier(source, it, isType);
2252        }
2253    }
2254}
2255
2256void ParserImpl::AddImportEntryItemForImportSpecifier(const ir::StringLiteral *source, const ir::AstNode *specifier,
2257    bool isLazy)
2258{
2259    auto *moduleRecord = specifier->AsImportSpecifier()->IsType() ?
2260        GetSourceTextTypeModuleRecord() : GetSourceTextModuleRecord();
2261    ASSERT(moduleRecord != nullptr);
2262    int moduleRequestIdx = moduleRecord->AddModuleRequest(source->Str(), isLazy);
2263
2264    auto localName = specifier->AsImportSpecifier()->Local()->Name();
2265    auto importName = specifier->AsImportSpecifier()->Imported()->Name();
2266    auto localId = specifier->AsImportSpecifier()->Local();
2267    auto importId = specifier->AsImportSpecifier()->Imported();
2268    auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ImportEntry>(
2269        localName, importName, moduleRequestIdx, localId, importId);
2270    moduleRecord->AddImportEntry(entry);
2271}
2272
2273void ParserImpl::AddImportEntryItemForImportDefaultOrNamespaceSpecifier(const ir::StringLiteral *source,
2274                                                                        const ir::AstNode *specifier, bool isType)
2275{
2276    auto *moduleRecord = isType ? GetSourceTextTypeModuleRecord() : GetSourceTextModuleRecord();
2277    ASSERT(moduleRecord != nullptr);
2278    auto moduleRequestIdx = moduleRecord->AddModuleRequest(source->Str());
2279
2280    if (specifier->IsImportDefaultSpecifier()) {
2281        auto localName = specifier->AsImportDefaultSpecifier()->Local()->Name();
2282        auto importName = parser::SourceTextModuleRecord::DEFAULT_EXTERNAL_NAME;
2283        auto localId = specifier->AsImportDefaultSpecifier()->Local();
2284        auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ImportEntry>(
2285            localName, importName, moduleRequestIdx, localId, nullptr);
2286        moduleRecord->AddImportEntry(entry);
2287    } else if (specifier->IsImportNamespaceSpecifier()) {
2288        auto localName = specifier->AsImportNamespaceSpecifier()->Local()->Name();
2289        auto localId = specifier->AsImportNamespaceSpecifier()->Local();
2290        auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ImportEntry>(
2291            localName, moduleRequestIdx, localId);
2292        moduleRecord->AddStarImportEntry(entry);
2293    }
2294}
2295
2296void ParserImpl::AddExportNamedEntryItem(const ArenaVector<ir::ExportSpecifier *> &specifiers,
2297                                         const ir::StringLiteral *source, bool isType)
2298{
2299    // The exported objects in the TSModuleScope do not need to be allocated index.
2300    if (context_.IsTsModule()) {
2301        ASSERT(Binder()->GetScope()->IsTSModuleScope());
2302        return;
2303    }
2304
2305    if (source) {
2306        for (auto *it : specifiers) {
2307            auto exportSpecifier = it->AsExportSpecifier();
2308            auto moduleRecord =
2309                exportSpecifier->IsType() ? GetSourceTextTypeModuleRecord() : GetSourceTextModuleRecord();
2310            ASSERT(moduleRecord != nullptr);
2311            auto moduleRequestIdx = moduleRecord->AddModuleRequest(source->Str());
2312
2313            auto importName = exportSpecifier->Local()->Name();
2314            auto exportName = exportSpecifier->Exported()->Name();
2315            auto importId = exportSpecifier->Local();
2316            auto exportId = exportSpecifier->Exported();
2317            auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2318                exportName, importName, moduleRequestIdx, exportId, importId);
2319            if (!moduleRecord->AddIndirectExportEntry(entry)) {
2320                ThrowSyntaxError("Duplicate export name of '" + exportName.Mutf8() + "'",
2321                                 exportSpecifier->Start());
2322            }
2323        }
2324    } else {
2325        for (auto *it : specifiers) {
2326            auto exportSpecifier = it->AsExportSpecifier();
2327            auto moduleRecord =
2328                exportSpecifier->IsType() ? GetSourceTextTypeModuleRecord() : GetSourceTextModuleRecord();
2329            ASSERT(moduleRecord != nullptr);
2330
2331            auto exportName = exportSpecifier->Exported()->Name();
2332            auto localName = exportSpecifier->Local()->Name();
2333            auto exportId = exportSpecifier->Exported();
2334            auto localId = exportSpecifier->Local();
2335            auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2336                exportName, localName, exportId, localId);
2337            if (!moduleRecord->AddLocalExportEntry(entry)) {
2338                ThrowSyntaxError("Duplicate export name of '" + exportName.Mutf8() + "'",
2339                                 exportSpecifier->Start());
2340            }
2341        }
2342    }
2343}
2344
2345void ParserImpl::AddExportStarEntryItem(const lexer::SourcePosition &startLoc, const ir::StringLiteral *source,
2346                                        const ir::Identifier *exported)
2347{
2348    auto moduleRecord = GetSourceTextModuleRecord();
2349    ASSERT(moduleRecord != nullptr);
2350    ASSERT(source != nullptr);
2351    auto moduleRequestIdx = moduleRecord->AddModuleRequest(source->Str());
2352
2353    if (exported != nullptr) {
2354        /* Transform [NamespaceExport] into [NamespaceImport] & [LocalExport]
2355         * e.g. export * as ns from 'test.js'
2356         *      --->
2357         *      import * as [internalName] from 'test.js'
2358         *      export { [internalName] as ns }
2359         */
2360        auto namespaceExportInternalName = GetNamespaceExportInternalName();
2361        auto *decl = Binder()->AddDecl<binder::ConstDecl>(startLoc, binder::DeclarationFlags::EXPORT,
2362                                                          false, namespaceExportInternalName);
2363        decl->BindNode(exported);
2364
2365        auto *importEntry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ImportEntry>(
2366            namespaceExportInternalName, moduleRequestIdx, nullptr);
2367        auto *exportEntry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2368            exported->Name(), namespaceExportInternalName, exported, nullptr);
2369        moduleRecord->AddStarImportEntry(importEntry);
2370        if (!moduleRecord->AddLocalExportEntry(exportEntry)) {
2371            ThrowSyntaxError("Duplicate export name of '" + exported->Name().Mutf8() + "'", exported->Start());
2372        }
2373        return;
2374    }
2375
2376    auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(moduleRequestIdx);
2377    moduleRecord->AddStarExportEntry(entry);
2378}
2379
2380void ParserImpl::AddExportDefaultEntryItem(const ir::AstNode *declNode)
2381{
2382    if (context_.IsTsModule()) {
2383        return;
2384    }
2385
2386    ASSERT(declNode != nullptr);
2387    if (declNode->IsTSInterfaceDeclaration() ||
2388        (declNode->IsFunctionDeclaration() && declNode->AsFunctionDeclaration()->Function()->IsOverload())) {
2389        return;
2390    }
2391
2392    auto moduleRecord = GetSourceTextModuleRecord();
2393    ASSERT(moduleRecord != nullptr);
2394    util::StringView exportName = parser::SourceTextModuleRecord::DEFAULT_EXTERNAL_NAME;
2395    util::StringView localName = parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME;
2396    if (declNode->IsFunctionDeclaration() || declNode->IsClassDeclaration()) {
2397        localName = declNode->IsFunctionDeclaration() ? declNode->AsFunctionDeclaration()->Function()->GetName() :
2398                                                        declNode->AsClassDeclaration()->Definition()->GetName();
2399    }
2400
2401    ASSERT(!localName.Empty());
2402    auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2403        exportName, localName, nullptr, nullptr);
2404    if (!moduleRecord->AddLocalExportEntry(entry)) {
2405        ThrowSyntaxError("Duplicate export name of '" + exportName.Mutf8() + "'", declNode->Start());
2406    }
2407}
2408
2409void ParserImpl::AddExportLocalEntryItem(const ir::Statement *declNode, bool isTsModule)
2410{
2411    ASSERT(declNode != nullptr);
2412    auto moduleRecord = GetSourceTextModuleRecord();
2413    ASSERT(isTsModule || moduleRecord != nullptr);
2414    binder::TSModuleScope *tsModuleScope = nullptr;
2415    if (isTsModule) {
2416        ASSERT(Binder()->GetScope()->IsTSModuleScope());
2417        tsModuleScope = Binder()->GetScope()->AsTSModuleScope();
2418    }
2419    if (declNode->IsVariableDeclaration()) {
2420        auto declarators = declNode->AsVariableDeclaration()->Declarators();
2421        for (auto *decl : declarators) {
2422            std::vector<const ir::Identifier *> bindings = util::Helpers::CollectBindingNames(decl->Id());
2423            for (const auto *binding : bindings) {
2424                if (isTsModule) {
2425                    tsModuleScope->AddExportVariable(binding->Name());
2426                } else {
2427                    auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2428                        binding->Name(), binding->Name(), binding, binding);
2429                    if (!moduleRecord->AddLocalExportEntry(entry)) {
2430                        ThrowSyntaxError("Duplicate export name of '" + binding->Name().Mutf8()
2431                                         + "'", binding->Start());
2432                    }
2433                }
2434            }
2435        }
2436    }
2437    if (declNode->IsFunctionDeclaration() || declNode->IsClassDeclaration()) {
2438        auto name = declNode->IsFunctionDeclaration() ?
2439                    declNode->AsFunctionDeclaration()->Function()->Id() :
2440                    declNode->AsClassDeclaration()->Definition()->Ident();
2441        if (name == nullptr) {
2442            ThrowSyntaxError("A class or function declaration without the default modifier must have a name.",
2443                             declNode->Start());
2444        }
2445        if (declNode->IsFunctionDeclaration() && declNode->AsFunctionDeclaration()->Function()->IsOverload()) {
2446            return;
2447        }
2448        if (isTsModule) {
2449            tsModuleScope->AddExportVariable(name->Name());
2450        } else {
2451            auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2452                name->Name(), name->Name(), name, name);
2453            if (!moduleRecord->AddLocalExportEntry(entry)) {
2454                ThrowSyntaxError("Duplicate export name of '" + name->Name().Mutf8() + "'", name->Start());
2455            }
2456        }
2457    }
2458    AddTsTypeExportLocalEntryItem(declNode, isTsModule, tsModuleScope);
2459}
2460
2461void ParserImpl::AddTsTypeExportLocalEntryItem(const ir::Statement *declNode, bool isTsModule,
2462                                               binder::TSModuleScope *tsModuleScope)
2463{
2464    if (!declNode->IsTSInterfaceDeclaration() && !declNode->IsTSTypeAliasDeclaration()) {
2465        return;
2466    }
2467    auto name = declNode->IsTSInterfaceDeclaration() ?
2468                declNode->AsTSInterfaceDeclaration()->Id() : declNode->AsTSTypeAliasDeclaration()->Id();
2469    if (name == nullptr) {
2470        ThrowSyntaxError("An interface or type alias declaration must have a name.");
2471    }
2472    if (isTsModule) {
2473        binder::TSBinding tsBinding(Allocator(), name->Name());
2474        tsModuleScope->AddExportVariable(tsBinding.View());
2475    }
2476}
2477
2478ir::ExportDefaultDeclaration *ParserImpl::ParseExportDefaultDeclaration(const lexer::SourcePosition &startLoc,
2479                                                                        ArenaVector<ir::Decorator *> decorators,
2480                                                                        ArenaVector<ir::Annotation *> annotations,
2481                                                                        bool isExportEquals)
2482{
2483    lexer_->NextToken();  // eat `default` keyword or `=`
2484
2485    ir::AstNode *declNode = nullptr;
2486    bool eatSemicolon = false;
2487
2488    if (!decorators.empty() && lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS &&
2489        (context_.Status() & ParserStatus::IN_CLASS_BODY) == 0) {
2490        ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2491    }
2492
2493    if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION) {
2494        declNode = ParseFunctionDeclaration(true, ParserStatus::EXPORT_REACHED);
2495    } else if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_CLASS) {
2496        declNode = ParseClassDeclaration(false, std::move(decorators), std::move(annotations), false, false, true);
2497    } else if (lexer_->GetToken().IsAsyncModifier()) {
2498        lexer_->NextToken();  // eat `async` keyword
2499        declNode = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION | ParserStatus::EXPORT_REACHED);
2500    } else if (Extension() == ScriptExtension::TS &&
2501               lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_INTERFACE) {
2502        declNode = ParseTsInterfaceDeclaration(false);
2503    } else if (Extension() == ScriptExtension::TS &&
2504               lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT) {
2505        lexer_->NextToken();
2506        if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS) {
2507            ThrowSyntaxError("Unexpected token, expected 'class'.");
2508        }
2509
2510        if (!annotations.empty()) {
2511            ThrowSyntaxError("Annotations can not be used with abstract classes", annotations.front()->Start());
2512        }
2513
2514        declNode = ParseClassDeclaration(false, std::move(decorators), std::move(annotations), false, true, true);
2515    } else {
2516        declNode = ParseExpression();
2517        Binder()->AddDecl<binder::LetDecl>(declNode->Start(), binder::DeclarationFlags::EXPORT,
2518                                           false, parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME);
2519        eatSemicolon = true;
2520    }
2521
2522    // record default export entry
2523    if (!isExportEquals) {
2524        AddExportDefaultEntryItem(declNode);
2525    }
2526
2527    lexer::SourcePosition endLoc = declNode->End();
2528    auto *exportDeclaration = AllocNode<ir::ExportDefaultDeclaration>(declNode, isExportEquals);
2529    exportDeclaration->SetRange({startLoc, endLoc});
2530
2531    if (eatSemicolon) {
2532        ConsumeSemicolon(exportDeclaration);
2533    }
2534
2535    return exportDeclaration;
2536}
2537
2538ir::Identifier *ParserImpl::ParseNamedExport(const lexer::Token &exportedToken)
2539{
2540    if (exportedToken.Type() != lexer::TokenType::LITERAL_IDENT) {
2541        ThrowSyntaxError("Unexpected token, expected an identifier.");
2542    }
2543
2544    const util::StringView &exportedString = exportedToken.Ident();
2545
2546    auto *exported = AllocNode<ir::Identifier>(exportedString);
2547    exported->SetRange(exportedToken.Loc());
2548
2549    return exported;
2550}
2551
2552ir::ExportAllDeclaration *ParserImpl::ParseExportAllDeclaration(const lexer::SourcePosition &startLoc)
2553{
2554    lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat `*` character
2555
2556    ir::Identifier *exported = nullptr;
2557
2558    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
2559        lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2560        exported = ParseNamedExport(lexer_->GetToken());
2561        lexer_->NextToken();  // eat exported name
2562    }
2563
2564    ir::StringLiteral *source = ParseFromClause();
2565    lexer::SourcePosition endLoc = source->End();
2566
2567    // record export star entry
2568    AddExportStarEntryItem(startLoc, source, exported);
2569
2570    ir::AssertClause *assertClause = nullptr;
2571    if (Extension() == ScriptExtension::TS && !lexer_->GetToken().NewLine() &&
2572        lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2573        lexer_->GetToken().Ident().Is("assert")) {
2574        assertClause = ParseAssertClause();
2575    }
2576
2577    auto *exportDeclaration = AllocNode<ir::ExportAllDeclaration>(source, exported, assertClause);
2578    exportDeclaration->SetRange({startLoc, endLoc});
2579
2580    ConsumeSemicolon(exportDeclaration);
2581
2582    return exportDeclaration;
2583}
2584
2585ir::ExportNamedDeclaration *ParserImpl::ParseExportNamedSpecifiers(const lexer::SourcePosition &startLoc,
2586                                                                   bool isType)
2587{
2588    if (Extension() == ScriptExtension::TS && context_.IsTsModule() &&
2589        !(context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT)) {
2590        ThrowSyntaxError("Export declarations are not permitted in a namespace.");
2591    }
2592
2593    lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat `{` character
2594
2595    ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter());
2596
2597    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
2598        bool isTypeOfExportSpecifier = isType;
2599        if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE) {
2600            auto isTypeUsedAsKeyword = HandleTypeImportOrExportSpecifier();
2601            if (isTypeUsedAsKeyword) {
2602                lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat type
2603                if (isType) {
2604                    ThrowSyntaxError("The type modifier cannot be used on a named export "
2605                                     "when 'export type' is used on its export statement.");
2606                }
2607                isTypeOfExportSpecifier = true;
2608            }
2609        }
2610
2611        if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2612            ThrowSyntaxError("Unexpected token");
2613        }
2614
2615        lexer::Token localToken = lexer_->GetToken();
2616        auto *local = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
2617        local->SetRange(lexer_->GetToken().Loc());
2618
2619        if (Extension() == ScriptExtension::TS) {
2620            local->SetReference();
2621        }
2622
2623        lexer_->NextToken();  // eat local name
2624
2625        ir::Identifier *exported = nullptr;
2626
2627        if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
2628            lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat `as` literal
2629            exported = ParseNamedExport(lexer_->GetToken());
2630            lexer_->NextToken();  // eat exported name
2631        } else {
2632            exported = ParseNamedExport(localToken);
2633        }
2634
2635        auto *specifier = AllocNode<ir::ExportSpecifier>(local, exported, isTypeOfExportSpecifier);
2636        specifier->SetRange({local->Start(), exported->End()});
2637
2638        specifiers.push_back(specifier);
2639
2640        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2641            lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat comma
2642        }
2643    }
2644
2645    lexer::SourcePosition endPos = lexer_->GetToken().End();
2646    lexer_->NextToken();  // eat right brace
2647
2648    ir::StringLiteral *source = nullptr;
2649
2650    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_FROM) {
2651        source = ParseFromClause();
2652    }
2653
2654    // record ExportEntry
2655    AddExportNamedEntryItem(specifiers, source, isType);
2656
2657    ir::AssertClause *assertClause = nullptr;
2658    if (Extension() == ScriptExtension::TS && !lexer_->GetToken().NewLine() &&
2659        lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2660        lexer_->GetToken().Ident().Is("assert")) {
2661        if (source == nullptr) {
2662            ThrowSyntaxError("';' expected.");
2663        }
2664        if (isType) {
2665            ThrowSyntaxError("Import assertions cannot be used with type-only imports or exports.");
2666        }
2667        assertClause = ParseAssertClause();
2668    }
2669
2670    auto *exportDeclaration = AllocNode<ir::ExportNamedDeclaration>(source, std::move(specifiers),
2671                                                                    assertClause, isType);
2672    exportDeclaration->SetRange({startLoc, endPos});
2673    ConsumeSemicolon(exportDeclaration);
2674
2675    return exportDeclaration;
2676}
2677
2678ir::ExportNamedDeclaration *ParserImpl::ParseNamedExportDeclaration(const lexer::SourcePosition &startLoc,
2679                                                                    ArenaVector<ir::Decorator *> &&decorators,
2680                                                                    ArenaVector<ir::Annotation *> &&annotations)
2681{
2682    ir::Statement *decl = nullptr;
2683
2684    bool isDeclare = false;
2685    bool isTsModule = context_.IsTsModule();
2686
2687    if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) {
2688        isDeclare = CheckDeclare();
2689    }
2690
2691    if (!decorators.empty() && lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS &&
2692        (context_.Status() & ParserStatus::IN_CLASS_BODY) == 0 &&
2693        !(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2694          (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT))) {
2695        ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2696    }
2697
2698    if (!annotations.empty() && lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS &&
2699        (context_.Status() & ParserStatus::IN_CLASS_BODY) == 0) {
2700        ThrowSyntaxError("Annotations can be used only with classes and class methods", annotations.front()->Start());
2701    }
2702
2703    VariableParsingFlags flag = isTsModule ?
2704        VariableParsingFlags::EXPORTED_IN_TSMODULE : VariableParsingFlags::EXPORTED;
2705    ParserStatus status = isTsModule ? ParserStatus::NO_OPTS : ParserStatus::EXPORT_REACHED;
2706
2707    switch (lexer_->GetToken().Type()) {
2708        case lexer::TokenType::KEYW_VAR: {
2709            decl = ParseVariableDeclaration(flag | VariableParsingFlags::VAR, isDeclare, true);
2710            break;
2711        }
2712        case lexer::TokenType::KEYW_CONST: {
2713            decl = ParseVariableDeclaration(flag | VariableParsingFlags::CONST, isDeclare, true);
2714            break;
2715        }
2716        case lexer::TokenType::KEYW_LET: {
2717            decl = ParseVariableDeclaration(flag | VariableParsingFlags::LET, isDeclare, true);
2718            break;
2719        }
2720        case lexer::TokenType::KEYW_FUNCTION: {
2721            decl = ParseFunctionDeclaration(false, status, isDeclare);
2722            break;
2723        }
2724        case lexer::TokenType::KEYW_CLASS: {
2725            decl = ParseClassDeclaration(true, std::move(decorators), std::move(annotations), isDeclare || IsDtsFile(),
2726                                         false, !isTsModule);
2727            break;
2728        }
2729        case lexer::TokenType::PUNCTUATOR_AT: {
2730            lexer_->NextToken(); // eat @ symbol
2731            if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_INTERFACE) {
2732                ThrowSyntaxError("'interface' keyword expected.");
2733            }
2734
2735            if (!decorators.empty()) {
2736                ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2737            }
2738
2739            if (!annotations.empty()) {
2740                ThrowSyntaxError("Annotations can not be used with annotation declaration",
2741                                 annotations.front()->Start());
2742            }
2743            decl = ParseClassDeclaration(true, std::move(decorators), std::move(annotations), isDeclare || IsDtsFile(),
2744                                         false, !isTsModule, true);
2745            break;
2746        }
2747        case lexer::TokenType::LITERAL_IDENT: {
2748            if (Extension() == ScriptExtension::TS) {
2749                switch (lexer_->GetToken().KeywordType()) {
2750                    case lexer::TokenType::KEYW_LET: {
2751                        decl = ParseVariableDeclaration(VariableParsingFlags::LET, isDeclare);
2752                        break;
2753                    }
2754                    case lexer::TokenType::KEYW_ENUM: {
2755                        decl = ParseEnumDeclaration(true, isDeclare, false);
2756                        break;
2757                    }
2758                    case lexer::TokenType::KEYW_INTERFACE: {
2759                        decl = ParseTsInterfaceDeclaration(isDeclare);
2760                        break;
2761                    }
2762                    case lexer::TokenType::KEYW_TYPE: {
2763                        decl = ParseTsTypeAliasDeclaration(isDeclare);
2764                        break;
2765                    }
2766                    case lexer::TokenType::KEYW_GLOBAL:
2767                    case lexer::TokenType::KEYW_MODULE:
2768                    case lexer::TokenType::KEYW_NAMESPACE: {
2769                        auto savedStatus = context_.Status();
2770                        if (isDeclare) {
2771                            context_.Status() |= ParserStatus::IN_AMBIENT_CONTEXT;
2772                        }
2773                        decl = ParseTsModuleDeclaration(isDeclare, true);
2774                        context_.Status() = savedStatus;
2775                        break;
2776                    }
2777                    case lexer::TokenType::KEYW_ABSTRACT: {
2778                        lexer_->NextToken();  // eat abstract keyword
2779
2780                        if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) {
2781                            if (isDeclare) {
2782                                ThrowSyntaxError("'declare' modifier already seen.");
2783                            }
2784                            lexer_->NextToken();
2785                            isDeclare = true;
2786                        }
2787
2788                        if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS) {
2789                            ThrowSyntaxError("Unexpected token, expected 'class'.");
2790                        }
2791                        if (!annotations.empty()) {
2792                            ThrowSyntaxError("Annotations can not be used with abstract classes",
2793                                             annotations.front()->Start());
2794                        }
2795                        decl = ParseClassDeclaration(true, std::move(decorators), std::move(annotations),
2796                                                     isDeclare || IsDtsFile(), true, !isTsModule);
2797                        break;
2798                    }
2799                    default: {
2800                        break;
2801                    }
2802                }
2803
2804                if (decl) {
2805                    break;
2806                }
2807            }
2808
2809            [[fallthrough]];
2810        }
2811        default: {
2812            if (!lexer_->GetToken().IsAsyncModifier()) {
2813                ThrowSyntaxError("Unexpected token");
2814            }
2815
2816            lexer_->NextToken();  // eat `async` keyword
2817            decl = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION | status);
2818        }
2819    }
2820
2821    if (decl->IsVariableDeclaration()) {
2822        ConsumeSemicolon(decl);
2823    }
2824
2825    AddExportLocalEntryItem(decl, isTsModule);
2826
2827    lexer::SourcePosition endLoc = decl->End();
2828    ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter());
2829    auto *exportDeclaration = AllocNode<ir::ExportNamedDeclaration>(decl, std::move(specifiers));
2830    exportDeclaration->SetRange({startLoc, endLoc});
2831
2832    return exportDeclaration;
2833}
2834
2835ir::Statement *ParserImpl::ParseExportDeclaration(StatementParsingFlags flags,
2836                                                  ArenaVector<ir::Decorator *> &&decorators,
2837                                                  ArenaVector<ir::Annotation *> &&annotations)
2838{
2839    if (Extension() == ScriptExtension::JS || !context_.IsTsModule()) {
2840        if (!(flags & StatementParsingFlags::GLOBAL)) {
2841            ThrowSyntaxError("'import' and 'export' may only appear at the top level");
2842        }
2843
2844        if (!context_.IsModule()) {
2845            ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'");
2846        }
2847    }
2848
2849    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2850    lexer_->NextToken();  // eat `export` keyword
2851
2852    // won't set `isType` for type alias
2853    bool isType = false;
2854    if (Extension() == ScriptExtension::TS &&
2855        lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE) {
2856        const auto savedPos = lexer_->Save();
2857        lexer_->NextToken();  // eat type
2858        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2859            isType = true;
2860        } else {
2861            lexer_->Rewind(savedPos);
2862        }
2863    }
2864
2865    switch (lexer_->GetToken().Type()) {
2866        case lexer::TokenType::KEYW_DEFAULT: { // export default Id
2867            return ParseExportDefaultDeclaration(startLoc, std::move(decorators), std::move(annotations));
2868        }
2869        case lexer::TokenType::PUNCTUATOR_MULTIPLY: { // export * ...
2870            return ParseExportAllDeclaration(startLoc);
2871        }
2872        case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { // export { ... } ...
2873            return ParseExportNamedSpecifiers(startLoc, isType);
2874        }
2875        case lexer::TokenType::KEYW_IMPORT: {
2876            return ParseTsImportEqualsDeclaration(startLoc, true);
2877        }
2878        case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: {
2879            if (!annotations.empty()) {
2880                ThrowSyntaxError("Annotations can not be used with assignment expression",
2881                                 annotations.front()->Start());
2882            }
2883
2884            if (Extension() == ScriptExtension::TS) {
2885                return ParseExportDefaultDeclaration(startLoc, std::move(decorators), std::move(annotations), true);
2886            }
2887
2888            [[fallthrough]];
2889        }
2890        case lexer::TokenType::LITERAL_IDENT: {
2891            if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
2892                return ParseTsNamespaceExportDeclaration(startLoc);
2893            }
2894
2895            [[fallthrough]];
2896        }
2897        default: { // export [var] id
2898            ir::ExportNamedDeclaration *exportDecl = ParseNamedExportDeclaration(startLoc, std::move(decorators),
2899                                                                                 std::move(annotations));
2900
2901            if (Extension() == ScriptExtension::TS && exportDecl->Decl()->IsVariableDeclaration() &&
2902                !(flags & StatementParsingFlags::GLOBAL) && exportDecl->Parent() &&
2903                !exportDecl->Parent()->IsTSModuleBlock() && !context_.IsModule()) {
2904                ThrowSyntaxError("Modifiers cannot appear here'");
2905            }
2906
2907            return exportDecl;
2908        }
2909    }
2910}
2911
2912void ParserImpl::ParseNameSpaceImport(ArenaVector<ir::AstNode *> *specifiers, bool isType)
2913{
2914    lexer::SourcePosition namespaceStart = lexer_->GetToken().Start();
2915    lexer_->NextToken();  // eat `*` character
2916
2917    if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_AS) {
2918        ThrowSyntaxError("Unexpected token.");
2919    }
2920
2921    lexer_->NextToken();  // eat `as` literal
2922
2923    ir::Identifier *local = ParseNamedImport(lexer_->GetToken());
2924
2925    auto *specifier = AllocNode<ir::ImportNamespaceSpecifier>(local);
2926    specifier->SetRange({namespaceStart, lexer_->GetToken().End()});
2927    specifiers->push_back(specifier);
2928
2929    binder::Decl *decl = AddImportDecl(isType, local->Name(), namespaceStart,
2930        binder::DeclarationFlags::NAMESPACE_IMPORT);
2931    decl->BindNode(specifier);
2932
2933    lexer_->NextToken();  // eat local name
2934}
2935
2936binder::Decl *ParserImpl::AddImportDecl(bool isType,
2937                                        util::StringView name,
2938                                        lexer::SourcePosition startPos,
2939                                        binder::DeclarationFlags flag)
2940{
2941    if (isType) {
2942        binder::TSBinding tsBinding(Allocator(), name);
2943        return Binder()->AddTsDecl<binder::TypeAliasDecl>(startPos, flag, false, tsBinding.View());
2944    }
2945    return Binder()->AddDecl<binder::ConstDecl>(startPos, flag, false, name);
2946}
2947
2948ir::Identifier *ParserImpl::ParseNamedImport(const lexer::Token &importedToken)
2949{
2950    if (importedToken.Type() != lexer::TokenType::LITERAL_IDENT) {
2951        ThrowSyntaxError("Unexpected token");
2952    }
2953
2954    switch (importedToken.KeywordType()) {
2955        case lexer::TokenType::KEYW_EVAL: {
2956            ThrowSyntaxError("Binding 'eval' in strict mode is invalid");
2957        }
2958        case lexer::TokenType::KEYW_ARGUMENTS: {
2959            ThrowSyntaxError("Binding 'arguments' in strict mode is invalid");
2960        }
2961        default: {
2962            break;
2963        }
2964    }
2965
2966    auto *local = AllocNode<ir::Identifier>(importedToken.Ident());
2967    local->SetRange(importedToken.Loc());
2968
2969    return local;
2970}
2971
2972void ParserImpl::ParseNamedImportSpecifiers(ArenaVector<ir::AstNode *> *specifiers, bool isType, bool isLazy)
2973{
2974    lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat `{` character
2975
2976    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
2977        bool isTypeOfImportSpecifier = isType;
2978        if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE) {
2979            auto isTypeUsedAsKeyword = HandleTypeImportOrExportSpecifier();
2980            if (isTypeUsedAsKeyword) {
2981                lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat type
2982                isTypeOfImportSpecifier = true;
2983            }
2984            if (isTypeUsedAsKeyword && isType) {
2985                ThrowSyntaxError("The type modifier cannot be used on a named import "
2986                                 "when 'import type' is used on its import statement.");
2987            }
2988        }
2989
2990        if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT ||
2991            (Extension() == ScriptExtension::TS && lexer_->GetToken().Ident().Is("await"))) {
2992            ThrowSyntaxError("Unexpected token");
2993        }
2994
2995        lexer::Token importedToken = lexer_->GetToken();
2996        auto *imported = AllocNode<ir::Identifier>(importedToken.Ident());
2997        ir::Identifier *local = nullptr;
2998        imported->SetRange(lexer_->GetToken().Loc());
2999
3000        lexer_->NextToken();  // eat import name
3001
3002        if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
3003            lexer_->NextToken();  // eat `as` literal
3004            local = ParseNamedImport(lexer_->GetToken());
3005            lexer_->NextToken();  // eat local name
3006        } else {
3007            local = ParseNamedImport(importedToken);
3008        }
3009
3010        auto *specifier = AllocNode<ir::ImportSpecifier>(imported, local, isTypeOfImportSpecifier, isLazy);
3011        specifier->SetRange({imported->Start(), local->End()});
3012        specifiers->push_back(specifier);
3013
3014        binder::Decl *decl = AddImportDecl(isTypeOfImportSpecifier, local->Name(), local->Start(),
3015                                           binder::DeclarationFlags::IMPORT);
3016        decl->BindNode(specifier);
3017
3018        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3019            lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat comma
3020        } else if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
3021            ThrowSyntaxError("Unexpected token");
3022        }
3023    }
3024
3025    lexer_->NextToken();  // eat right brace
3026}
3027
3028bool ParserImpl::HandleTypeImportOrExportSpecifier()
3029{
3030    bool isTypeUsedAsKeyword = false;
3031    const auto savedPos = lexer_->Save();
3032
3033    lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat type
3034
3035    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
3036        // {type as ...? }
3037        lexer_->NextToken(); // eat first as
3038        if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
3039            // { type as as ...? }
3040            lexer_->NextToken(); // eat second as
3041            if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
3042                // { type as as something }
3043                isTypeUsedAsKeyword = true;
3044            } else {
3045                // { type as as }
3046                isTypeUsedAsKeyword = false;
3047            }
3048        } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
3049            // { type as something }
3050            isTypeUsedAsKeyword = false;
3051        } else {
3052            // { type as }
3053            isTypeUsedAsKeyword = true;
3054        }
3055    } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
3056        // { type something ...? }
3057        isTypeUsedAsKeyword = true;
3058    } else {
3059        // { type }
3060        isTypeUsedAsKeyword = false;
3061    }
3062
3063    lexer_->Rewind(savedPos);
3064    return isTypeUsedAsKeyword;
3065}
3066
3067ir::Expression *ParserImpl::ParseModuleReference()
3068{
3069    ir::Expression *result = nullptr;
3070
3071    if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
3072        lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_REQUIRE &&
3073        lexer_->Lookahead() == LEX_CHAR_LEFT_PAREN) {
3074        lexer::SourcePosition start = lexer_->GetToken().Start();
3075        lexer_->NextToken();  // eat 'require'
3076        lexer_->NextToken();  // eat '('
3077
3078        if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
3079            ThrowSyntaxError("String literal expected.");
3080        }
3081
3082        result = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
3083        result->SetRange(lexer_->GetToken().Loc());
3084        lexer_->NextToken();
3085
3086        if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
3087            ThrowSyntaxError("')' expected.");
3088        }
3089
3090        result = AllocNode<ir::TSExternalModuleReference>(result);
3091        result->SetRange({start, lexer_->GetToken().End()});
3092        lexer_->NextToken();  // eat ')'
3093    } else {
3094        result = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
3095        result->SetRange(lexer_->GetToken().Loc());
3096        lexer_->NextToken();
3097
3098        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
3099            result = ParseTsQualifiedReference(result);
3100        }
3101    }
3102
3103    return result;
3104}
3105
3106ir::AstNode *ParserImpl::ParseImportDefaultSpecifier(ArenaVector<ir::AstNode *> *specifiers, bool isType)
3107{
3108    ir::Identifier *local = ParseNamedImport(lexer_->GetToken());
3109    lexer_->NextToken();  // eat local name
3110
3111    if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
3112        lexer_->NextToken();  // eat substitution
3113        if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
3114            ThrowSyntaxError("identifier expected");
3115        }
3116        if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_REQUIRE ||
3117            lexer_->Lookahead() != LEX_CHAR_LEFT_PAREN) {
3118            auto *decl = Binder()->AddDecl<binder::ImportEqualsDecl>(local->Start(), binder::DeclarationFlags::NONE,
3119                                                                     false, local->Name());
3120            decl->BindNode(local);
3121            auto *scope = Binder()->GetScope();
3122            auto *var = scope->FindLocalTSVariable<binder::TSBindingType::IMPORT_EQUALS>(local->Name());
3123            CHECK_NOT_NULL(var);
3124            var->AsImportEqualsVariable()->SetScope(scope);
3125        }
3126
3127        auto *importEqualsDecl = AllocNode<ir::TSImportEqualsDeclaration>(local, ParseModuleReference(), false);
3128
3129        return importEqualsDecl;
3130    }
3131
3132    auto *specifier = AllocNode<ir::ImportDefaultSpecifier>(local);
3133    specifier->SetRange(specifier->Local()->Range());
3134    specifiers->push_back(specifier);
3135
3136    binder::Decl *decl = AddImportDecl(isType, local->Name(), local->Start(), binder::DeclarationFlags::IMPORT);
3137    decl->BindNode(specifier);
3138
3139    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3140        lexer_->NextToken();  // eat comma
3141    } else if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) {
3142        ThrowSyntaxError("Unexpected token.");
3143    }
3144
3145    return nullptr;
3146}
3147
3148ir::StringLiteral *ParserImpl::ParseFromClause(bool requireFrom)
3149{
3150    if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) {
3151        if (requireFrom) {
3152            ThrowSyntaxError("Unexpected token.");
3153        }
3154    } else {
3155        lexer_->NextToken();  // eat `from` literal
3156    }
3157
3158    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
3159        ThrowSyntaxError("Unexpected token.");
3160    }
3161
3162    ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
3163
3164    auto *source = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
3165    source->SetRange(lexer_->GetToken().Loc());
3166
3167    lexer_->NextToken();
3168
3169    return source;
3170}
3171
3172ir::AstNode *ParserImpl::ParseImportSpecifiers(ArenaVector<ir::AstNode *> *specifiers, bool isType, bool isLazy)
3173{
3174    ASSERT(specifiers->empty());
3175
3176    // import [default] from 'source'
3177    if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
3178        ir::AstNode *astNode = ParseImportDefaultSpecifier(specifiers, isType);
3179        if (astNode != nullptr) {
3180            return astNode;
3181        }
3182    }
3183
3184    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
3185        ParseNameSpaceImport(specifiers, isType);
3186    } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
3187        ParseNamedImportSpecifiers(specifiers, isType, isLazy);
3188    }
3189    return nullptr;
3190}
3191
3192void ParserImpl::VerifySupportLazyImportVersion()
3193{
3194    if (!util::Helpers::IsSupportLazyImportVersion(program_.TargetApiVersion(), program_.GetTargetApiSubVersion())) {
3195        std::string errMessage = "Current configuration does not support using lazy import. Lazy import can be "
3196            "used in the beta3 version of API 12 or higher versions.\n"
3197            "Solutions: > Check the compatibleSdkVersion and compatibleSdkVersionStage in build-profile.json5."
3198            "> If compatibleSdkVersion is set to API 12, then compatibleSdkVersionStage needs to be configured "
3199            "as beta3."
3200            "> If you're running es2abc in commandline without IDE, please check whether target-api-version and "
3201            "target-api-sub-version options are correctly configured.";
3202        ThrowSyntaxError(errMessage);
3203    }
3204}
3205
3206ir::Statement *ParserImpl::ParseImportDeclaration(StatementParsingFlags flags)
3207{
3208    char32_t nextChar = lexer_->Lookahead();
3209    // dynamic import || import.meta
3210    if (nextChar == LEX_CHAR_LEFT_PAREN || nextChar == LEX_CHAR_DOT) {
3211        return ParseExpressionStatement();
3212    }
3213
3214    if (Extension() == ScriptExtension::JS) {
3215        if (!(flags & StatementParsingFlags::GLOBAL)) {
3216            ThrowSyntaxError("'import' and 'export' may only appear at the top level");
3217        }
3218
3219        if (!context_.IsModule()) {
3220            ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'");
3221        }
3222    }
3223
3224    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3225    lexer_->NextToken();  // eat import
3226
3227    bool isLazy = false;
3228    if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_LAZY) {
3229        const auto savedPos = lexer_->Save();
3230        lexer_->NextToken();  // eat lazy
3231        // only support import lazy {xxx} from '...'
3232        if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
3233            VerifySupportLazyImportVersion();
3234            isLazy = true;
3235        } else {
3236            lexer_->Rewind(savedPos);
3237        }
3238    }
3239
3240    bool isType = false;
3241    if (Extension() == ScriptExtension::TS &&
3242        lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE) {
3243        const auto savedPos = lexer_->Save();
3244        lexer_->NextToken();  // eat type
3245        if ((lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
3246            lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) ||
3247            lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE ||
3248            lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
3249            isType = true;
3250        } else {
3251            lexer_->Rewind(savedPos);
3252        }
3253    }
3254
3255    ArenaVector<ir::AstNode *> specifiers(Allocator()->Adapter());
3256
3257    ir::StringLiteral *source = nullptr;
3258
3259    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
3260        ir::AstNode *astNode = ParseImportSpecifiers(&specifiers, isType, isLazy);
3261        if (astNode != nullptr) {
3262            ASSERT(astNode->IsTSImportEqualsDeclaration());
3263            astNode->SetRange({startLoc, lexer_->GetToken().End()});
3264            ConsumeSemicolon(astNode->AsTSImportEqualsDeclaration());
3265            return astNode->AsTSImportEqualsDeclaration();
3266        }
3267        if (Extension() == ScriptExtension::TS && !context_.IsModule()) {
3268            ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'");
3269        }
3270        source = ParseFromClause(true);
3271        AddImportEntryItem(source, &specifiers, isType, isLazy);
3272    } else {
3273        if (Extension() == ScriptExtension::TS && !context_.IsModule()) {
3274            ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'");
3275        }
3276        // import 'source'
3277        source = ParseFromClause(false);
3278        AddImportEntryItem(source, nullptr, isType, isLazy);
3279    }
3280
3281    ir::AssertClause *assertClause = nullptr;
3282    if (Extension() == ScriptExtension::TS && !lexer_->GetToken().NewLine() &&
3283        lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
3284        lexer_->GetToken().Ident().Is("assert")) {
3285        if (isType) {
3286            ThrowSyntaxError("Import assertions cannot be used with type-only imports or exports.");
3287        }
3288        assertClause = ParseAssertClause();
3289    }
3290
3291    lexer::SourcePosition endLoc = source->End();
3292    auto *importDeclaration = AllocNode<ir::ImportDeclaration>(source, std::move(specifiers),
3293        assertClause, isType, isLazy);
3294    if (importDeclaration->Specifiers().empty() && program_.IsShared()) {
3295        ThrowSyntaxError("Arkts-no-side-effects-import is not allowed in shared module.");
3296    }
3297    importDeclaration->SetRange({startLoc, endLoc});
3298
3299    ConsumeSemicolon(importDeclaration);
3300
3301    return importDeclaration;
3302}
3303
3304ir::AssertClause *ParserImpl::ParseAssertClause()
3305{
3306    lexer::SourcePosition startLoc = lexer_->GetToken().Start();
3307    lexer_->NextToken();  // eat assert
3308
3309    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
3310        ThrowSyntaxError("expected left brace.");
3311    }
3312    lexer_->NextToken();  // eat '{'
3313
3314    ArenaVector<ir::AssertEntry *> elements(Allocator()->Adapter());
3315    while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
3316        elements.push_back(ParseAssertEntry());
3317    }
3318
3319    lexer_->NextToken();  // eat '}'
3320
3321    auto *assertClause = AllocNode<ir::AssertClause>(std::move(elements));
3322    assertClause->SetRange({startLoc, lexer_->GetToken().End()});
3323
3324    return assertClause;
3325}
3326
3327ir::AssertEntry *ParserImpl::ParseAssertEntry()
3328{
3329    ir::Expression *key = nullptr;
3330    if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
3331        key = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
3332        key->SetRange(lexer_->GetToken().Loc());
3333    } else if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
3334        key = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
3335        key->SetRange(lexer_->GetToken().Loc());
3336    } else {
3337        ThrowSyntaxError("Identifier or string literal expected.");
3338    }
3339
3340    lexer_->NextToken();
3341
3342    if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
3343        ThrowSyntaxError("':' expected.");
3344    }
3345    lexer_->NextToken();  // eat :
3346
3347    if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
3348        ThrowSyntaxError("Import assertion values must be string literal expressions.");
3349    }
3350
3351    ir::StringLiteral *value = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
3352    value->SetRange(lexer_->GetToken().Loc());
3353    lexer_->NextToken();
3354
3355    ASSERT(key);
3356    ASSERT(value);
3357
3358    auto *assertEntry = AllocNode<ir::AssertEntry>(key, value);
3359    assertEntry->SetRange({key->Start(), value->End()});
3360
3361    if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3362        lexer_->NextToken();  // eat comma
3363    }
3364
3365    return assertEntry;
3366}
3367
3368}  // namespace panda::es2panda::parser
3369