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