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