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