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