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