• 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         if (!allowBreak && Extension() == ScriptExtension::JS) {
969             ThrowSyntaxError("Illegal break statement");
970         }
971 
972         if (!allowBreak && Extension() == ScriptExtension::TS) {
973             if (context_.Status() & ParserStatus::FUNCTION) {
974                 ThrowSyntaxError("Jump target cannot cross function boundary");
975             } else {
976                 ThrowSyntaxError(
977                     "A 'break' statement can only be used within an "
978                     "enclosing iteration or switch statement");
979             }
980         }
981 
982         auto *breakStatement = AllocNode<ir::BreakStatement>();
983         breakStatement->SetRange({startLoc, lexer_->GetToken().End()});
984         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
985             lexer_->NextToken();
986         }
987 
988         return breakStatement;
989     }
990 
991     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
992         ThrowSyntaxError("Unexpected token.");
993     }
994 
995     const auto &label = lexer_->GetToken().Ident();
996 
997     if (!context_.FindLabel(label)) {
998         ThrowSyntaxError("Undefined label");
999     }
1000 
1001     auto *identNode = AllocNode<ir::Identifier>(label);
1002     identNode->SetRange(lexer_->GetToken().Loc());
1003 
1004     auto *breakStatement = AllocNode<ir::BreakStatement>(identNode);
1005     breakStatement->SetRange({startLoc, lexer_->GetToken().End()});
1006 
1007     lexer_->NextToken();
1008     ConsumeSemicolon(breakStatement);
1009 
1010     return breakStatement;
1011 }
1012 
ParseContinueStatement()1013 ir::ContinueStatement *ParserImpl::ParseContinueStatement()
1014 {
1015     if (Extension() == ScriptExtension::TS &&
1016         (static_cast<ParserStatus>(context_.Status() & (ParserStatus::FUNCTION | ParserStatus::IN_ITERATION |
1017                                                         ParserStatus::IN_SWITCH)) == ParserStatus::FUNCTION)) {
1018         ThrowSyntaxError("Jump target cannot cross function boundary");
1019     }
1020 
1021     if (!(context_.Status() & ParserStatus::IN_ITERATION)) {
1022         if (Extension() == ScriptExtension::JS) {
1023             ThrowSyntaxError("Illegal continue statement");
1024         }
1025         if (Extension() == ScriptExtension::TS) {
1026             ThrowSyntaxError(
1027                 "A 'continue' statement can only be used within an "
1028                 "enclosing iteration statement");
1029         }
1030     }
1031 
1032     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1033     lexer::SourcePosition endLoc = lexer_->GetToken().End();
1034     lexer_->NextToken();
1035 
1036     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1037         auto *continueStatement = AllocNode<ir::ContinueStatement>();
1038         continueStatement->SetRange({startLoc, lexer_->GetToken().End()});
1039         lexer_->NextToken();
1040         return continueStatement;
1041     }
1042 
1043     if (lexer_->GetToken().NewLine() || lexer_->GetToken().Type() == lexer::TokenType::EOS ||
1044         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1045         auto *continueStatement = AllocNode<ir::ContinueStatement>();
1046         continueStatement->SetRange({startLoc, endLoc});
1047         return continueStatement;
1048     }
1049 
1050     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1051         ThrowSyntaxError("Unexpected token.");
1052     }
1053 
1054     const auto &label = lexer_->GetToken().Ident();
1055     const ParserContext *labelCtx = context_.FindLabel(label);
1056 
1057     if (!labelCtx || !(labelCtx->Status() & (ParserStatus::IN_ITERATION | ParserStatus::IN_LABELED)) ||
1058        (labelCtx->Status() & ParserStatus::DISALLOW_CONTINUE)) {
1059         ThrowSyntaxError("Undefined label");
1060     }
1061 
1062     auto *identNode = AllocNode<ir::Identifier>(label);
1063     identNode->SetRange(lexer_->GetToken().Loc());
1064 
1065     auto *continueStatement = AllocNode<ir::ContinueStatement>(identNode);
1066     continueStatement->SetRange({startLoc, lexer_->GetToken().End()});
1067 
1068     lexer_->NextToken();
1069     ConsumeSemicolon(continueStatement);
1070 
1071     return continueStatement;
1072 }
1073 
ParseDoWhileStatement()1074 ir::DoWhileStatement *ParserImpl::ParseDoWhileStatement()
1075 {
1076     IterationContext<binder::LoopScope> iterCtx(&context_, Binder());
1077 
1078     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1079     lexer_->NextToken();
1080     ir::Statement *body = ParseStatement();
1081 
1082     if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_WHILE) {
1083         ThrowSyntaxError("Missing 'while' keyword in a 'DoWhileStatement'");
1084     }
1085 
1086     lexer_->NextToken();
1087     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1088         ThrowSyntaxError("Missing left parenthesis in a 'DoWhileStatement'");
1089     }
1090 
1091     lexer_->NextToken();
1092 
1093     ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1094 
1095     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1096         ThrowSyntaxError("Missing right parenthesis in a 'DoWhileStatement'");
1097     }
1098 
1099     auto *doWhileStatement = AllocNode<ir::DoWhileStatement>(iterCtx.LexicalScope().GetScope(), body, test);
1100     doWhileStatement->SetRange({startLoc, lexer_->GetToken().End()});
1101     iterCtx.LexicalScope().GetScope()->BindNode(doWhileStatement);
1102 
1103     lexer_->NextToken();
1104 
1105     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1106         doWhileStatement->SetEnd(lexer_->GetToken().End());
1107         lexer_->NextToken();
1108     }
1109 
1110     return doWhileStatement;
1111 }
1112 
ParseFunctionDeclaration(bool canBeAnonymous,ParserStatus newStatus,bool isDeclare)1113 ir::FunctionDeclaration *ParserImpl::ParseFunctionDeclaration(bool canBeAnonymous, ParserStatus newStatus,
1114                                                               bool isDeclare)
1115 {
1116     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1117 
1118     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION);
1119     ParserStatus savedStatus = context_.Status();
1120 
1121     lexer_->NextToken();
1122 
1123     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
1124         newStatus |= ParserStatus::GENERATOR_FUNCTION;
1125         lexer_->NextToken();
1126     }
1127 
1128     context_.Status() = savedStatus;
1129 
1130     // e.g. export default function () {}
1131     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT &&
1132         lexer_->GetToken().Type() != lexer::TokenType::KEYW_AWAIT) {
1133         if (canBeAnonymous) {
1134             ir::ScriptFunction *func = ParseFunction(newStatus, isDeclare);
1135             if (func->Body() != nullptr) {
1136                 lexer_->NextToken();
1137             }
1138             func->SetStart(startLoc);
1139             func->SetAsExportDefault();
1140 
1141             auto *funcDecl = AllocNode<ir::FunctionDeclaration>(func);
1142             funcDecl->SetRange(func->Range());
1143 
1144             binder::DeclarationFlags declflag = (newStatus & ParserStatus::EXPORT_REACHED) ?
1145                                                 binder::DeclarationFlags::EXPORT : binder::DeclarationFlags::NONE;
1146             Binder()->AddDecl<binder::FunctionDecl>(startLoc, declflag, isDeclare, Allocator(),
1147                                                     parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME, func);
1148 
1149             return funcDecl;
1150         }
1151 
1152         ThrowSyntaxError("Unexpected token, expected identifier after 'function' keyword");
1153     }
1154 
1155     if (!isDeclare) {
1156         CheckStrictReservedWord();
1157     }
1158 
1159     util::StringView ident = lexer_->GetToken().Ident();
1160 
1161     auto *identNode = AllocNode<ir::Identifier>(ident);
1162     identNode->SetRange(lexer_->GetToken().Loc());
1163     lexer_->NextToken();
1164 
1165     newStatus |= ParserStatus::FUNCTION_DECLARATION;
1166     ir::ScriptFunction *func = ParseFunction(newStatus, isDeclare);
1167     if (func->Body() != nullptr) {
1168         lexer_->NextToken();
1169     }
1170 
1171     func->SetIdent(identNode);
1172     func->SetStart(startLoc);
1173     auto *funcDecl = AllocNode<ir::FunctionDeclaration>(func);
1174     funcDecl->SetRange(func->Range());
1175 
1176     AddFunctionToBinder(func, newStatus);
1177 
1178     if (func->IsOverload() && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1179         lexer_->NextToken();
1180     }
1181 
1182     CheckOptionalBindingPatternParameter(func);
1183 
1184     return funcDecl;
1185 }
1186 
AddFunctionToBinder(ir::ScriptFunction * func,ParserStatus newStatus)1187 void ParserImpl::AddFunctionToBinder(ir::ScriptFunction *func, ParserStatus newStatus)
1188 {
1189     binder::DeclarationFlags declflag = (newStatus & ParserStatus::EXPORT_REACHED) ?
1190                                         binder::DeclarationFlags::EXPORT : binder::DeclarationFlags::NONE;
1191     const ir::Identifier *identNode = func->Id();
1192     const lexer::SourcePosition &startLoc = func->Start();
1193     const util::StringView ident = identNode->Name();
1194     if (Extension() == ScriptExtension::TS) {
1195         const auto &bindings = Binder()->GetScope()->Bindings();
1196         auto res = bindings.find(ident);
1197         binder::Decl *currentDecl = res == bindings.end() ? nullptr : res->second->Declaration();
1198         binder::FunctionDecl *decl {};
1199 
1200         if (res == bindings.end() ||
1201             (currentDecl->IsClassDecl() && currentDecl->AsClassDecl()->IsDeclare())) {
1202             decl = Binder()->AddDecl<binder::FunctionDecl>(identNode->Start(), declflag, func->Declare(),
1203                                                            Allocator(), ident, func);
1204         } else {
1205             if (!currentDecl->IsFunctionDecl()) {
1206                 Binder()->ThrowRedeclaration(startLoc, currentDecl->Name());
1207             }
1208 
1209             decl = currentDecl->AsFunctionDecl();
1210             if (!decl->Node()->AsScriptFunction()->IsOverload()) {
1211                 Binder()->ThrowRedeclaration(startLoc, currentDecl->Name());
1212             }
1213             if (!func->IsOverload()) {
1214                 decl->BindNode(func);
1215             }
1216         }
1217 
1218         decl->Add(func);
1219     } else {
1220         Binder()->AddDecl<binder::FunctionDecl>(identNode->Start(), declflag, func->Declare(),
1221                                                 Allocator(), ident, func);
1222     }
1223 }
1224 
CheckOptionalBindingPatternParameter(ir::ScriptFunction * func) const1225 void ParserImpl::CheckOptionalBindingPatternParameter(ir::ScriptFunction *func) const
1226 {
1227     if (func->Declare() || func->IsOverload()) {
1228         return;
1229     }
1230     for (auto *it : func->Params()) {
1231         if ((it->IsObjectPattern() && it->AsObjectPattern()->Optional()) ||
1232             (it->IsArrayPattern() && it->AsArrayPattern()->Optional())) {
1233             ThrowSyntaxError(
1234                 "A binding pattern parameter cannot be optional in an "
1235                 "implementation signature", it->Start());
1236         }
1237     }
1238 }
1239 
ParseExpressionStatement(StatementParsingFlags flags)1240 ir::Statement *ParserImpl::ParseExpressionStatement(StatementParsingFlags flags)
1241 {
1242     const auto startPos = lexer_->Save();
1243     ParserStatus savedStatus = context_.Status();
1244 
1245     if (lexer_->GetToken().IsAsyncModifier()) {
1246         context_.Status() |= ParserStatus::ASYNC_FUNCTION;
1247         lexer_->NextToken();
1248 
1249         if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION && !lexer_->GetToken().NewLine()) {
1250             if (!(flags & StatementParsingFlags::ALLOW_LEXICAL)) {
1251                 ThrowSyntaxError("Async functions can only be declared at the top level or inside a block.");
1252             }
1253 
1254             ir::FunctionDeclaration *functionDecl = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION);
1255             functionDecl->SetStart(startPos.token.Start());
1256 
1257             return functionDecl;
1258         }
1259 
1260         lexer_->Rewind(startPos);
1261     }
1262 
1263     ir::Expression *exprNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1264     context_.Status() = savedStatus;
1265     lexer::SourcePosition endPos = exprNode->End();
1266 
1267     auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(exprNode);
1268     exprStatementNode->SetRange({startPos.token.Start(), endPos});
1269     ConsumeSemicolon(exprStatementNode);
1270 
1271     return exprStatementNode;
1272 }
1273 
ParseForInOf(ir::AstNode * initNode,ExpressionParseFlags exprFlags,bool isAwait)1274 std::tuple<ForStatementKind, ir::Expression *, ir::Expression *> ParserImpl::ParseForInOf(
1275     ir::AstNode *initNode, ExpressionParseFlags exprFlags, bool isAwait)
1276 {
1277     ForStatementKind forKind = ForStatementKind::UPDATE;
1278     ir::Expression *updateNode = nullptr;
1279     ir::Expression *rightNode = nullptr;
1280 
1281     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN ||
1282         lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OF) {
1283         const ir::VariableDeclarator *varDecl = initNode->AsVariableDeclaration()->Declarators().front();
1284 
1285         if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN) {
1286             if (varDecl->Init()) {
1287                 ThrowSyntaxError("for-in loop variable declaration may not have an initializer");
1288             }
1289             forKind = ForStatementKind::IN;
1290             exprFlags = ExpressionParseFlags::ACCEPT_COMMA;
1291         } else {
1292             if (varDecl->Init()) {
1293                 ThrowSyntaxError("for-of loop variable declaration may not have an initializer");
1294             }
1295 
1296             forKind = ForStatementKind::OF;
1297         }
1298 
1299         lexer_->NextToken();
1300         rightNode = ParseExpression(exprFlags);
1301     } else {
1302         if (isAwait) {
1303             ThrowSyntaxError("Unexpected token");
1304         }
1305 
1306         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1307             ThrowSyntaxError("Invalid left-hand side in 'For[In/Of]Statement'");
1308         } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1309             lexer_->NextToken();
1310         } else {
1311             rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1312             if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1313                 ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
1314             }
1315             lexer_->NextToken();
1316         }
1317 
1318         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1319             updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1320         }
1321     }
1322 
1323     return {forKind, rightNode, updateNode};
1324 }
1325 
ParseForInOf(ir::Expression * leftNode,ExpressionParseFlags exprFlags,bool isAwait)1326 std::tuple<ForStatementKind, ir::AstNode *, ir::Expression *, ir::Expression *> ParserImpl::ParseForInOf(
1327     ir::Expression *leftNode, ExpressionParseFlags exprFlags, bool isAwait)
1328 {
1329     ForStatementKind forKind = ForStatementKind::UPDATE;
1330     ir::AstNode *initNode = nullptr;
1331     ir::Expression *updateNode = nullptr;
1332     ir::Expression *rightNode = nullptr;
1333 
1334     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN ||
1335         (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OF)) {
1336         if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN) {
1337             forKind = ForStatementKind::IN;
1338             exprFlags = ExpressionParseFlags::ACCEPT_COMMA;
1339         } else {
1340             forKind = ForStatementKind::OF;
1341         }
1342 
1343         bool isValid = true;
1344         switch (leftNode->Type()) {
1345             case ir::AstNodeType::IDENTIFIER:
1346             case ir::AstNodeType::MEMBER_EXPRESSION: {
1347                 break;
1348             }
1349             case ir::AstNodeType::ARRAY_EXPRESSION: {
1350                 isValid = leftNode->AsArrayExpression()->ConvertibleToArrayPattern();
1351                 break;
1352             }
1353             case ir::AstNodeType::OBJECT_EXPRESSION: {
1354                 isValid = leftNode->AsObjectExpression()->ConvertibleToObjectPattern();
1355                 break;
1356             }
1357             default: {
1358                 isValid = false;
1359             }
1360         }
1361 
1362         if (!isValid) {
1363             ValidateLvalueAssignmentTarget(leftNode);
1364         }
1365 
1366         initNode = leftNode;
1367         lexer_->NextToken();
1368         rightNode = ParseExpression(exprFlags);
1369 
1370         return {forKind, initNode, rightNode, updateNode};
1371     }
1372 
1373     if (isAwait) {
1374         ThrowSyntaxError("Unexpected token");
1375     }
1376 
1377     exprFlags &= ExpressionParseFlags::POTENTIALLY_IN_PATTERN;
1378     ir::Expression *expr = ParseAssignmentExpression(leftNode, exprFlags);
1379 
1380     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
1381         initNode = ParseSequenceExpression(expr);
1382     } else {
1383         initNode = expr;
1384     }
1385 
1386     if (initNode->IsConditionalExpression()) {
1387         ir::ConditionalExpression *condExpr = initNode->AsConditionalExpression();
1388         if (condExpr->Alternate()->IsBinaryExpression()) {
1389             const auto *binaryExpr = condExpr->Alternate()->AsBinaryExpression();
1390             if (binaryExpr->OperatorType() == lexer::TokenType::KEYW_IN) {
1391                 ThrowSyntaxError("Invalid left-hand side in for-in statement");
1392             }
1393         }
1394     }
1395 
1396     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1397         ThrowSyntaxError("Invalid left-hand side in 'For[In/Of]Statement'");
1398     }
1399 
1400     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1401         ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
1402     }
1403 
1404     lexer_->NextToken();
1405 
1406     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1407         lexer_->NextToken();
1408     } else {
1409         rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1410 
1411         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1412             ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
1413         }
1414         lexer_->NextToken();
1415     }
1416 
1417     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1418         updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1419     }
1420 
1421     return {forKind, initNode, rightNode, updateNode};
1422 }
1423 
ParseForUpdate(bool isAwait)1424 std::tuple<ir::Expression *, ir::Expression *> ParserImpl::ParseForUpdate(bool isAwait)
1425 {
1426     if (isAwait) {
1427         ThrowSyntaxError("Unexpected token");
1428     }
1429 
1430     ir::Expression *updateNode = nullptr;
1431     ir::Expression *rightNode = nullptr;
1432 
1433     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1434         lexer_->NextToken();
1435     } else {
1436         rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1437         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1438             ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
1439         }
1440         lexer_->NextToken();
1441     }
1442 
1443     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1444         updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1445     }
1446 
1447     return {rightNode, updateNode};
1448 }
1449 
ParseForStatement()1450 ir::Statement *ParserImpl::ParseForStatement()
1451 {
1452     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1453     ForStatementKind forKind = ForStatementKind::UPDATE;
1454     ir::AstNode *initNode = nullptr;
1455     ir::Expression *updateNode = nullptr;
1456     ir::Expression *leftNode = nullptr;
1457     ir::Expression *rightNode = nullptr;
1458     bool canBeForInOf = true;
1459     bool isAwait = false;
1460     lexer_->NextToken();
1461     VariableParsingFlags varFlags = VariableParsingFlags::STOP_AT_IN | VariableParsingFlags::IN_FOR;
1462     ExpressionParseFlags exprFlags = ExpressionParseFlags::NO_OPTS;
1463 
1464     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) {
1465         isAwait = true;
1466         varFlags |= VariableParsingFlags::DISALLOW_INIT;
1467         lexer_->NextToken();
1468     }
1469 
1470     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1471         ThrowSyntaxError("Missing left parenthesis in a 'ForStatement'");
1472     }
1473     lexer_->NextToken();
1474 
1475     IterationContext<binder::LoopScope> iterCtx(&context_, Binder());
1476 
1477     switch (lexer_->GetToken().Type()) {
1478         case lexer::TokenType::KEYW_VAR: {
1479             initNode = ParseVariableDeclaration(varFlags | VariableParsingFlags::VAR);
1480             break;
1481         }
1482         case lexer::TokenType::KEYW_LET: {
1483             initNode = ParseVariableDeclaration(varFlags | VariableParsingFlags::LET);
1484             break;
1485         }
1486         case lexer::TokenType::KEYW_CONST: {
1487             initNode = ParseVariableDeclaration(varFlags | VariableParsingFlags::CONST |
1488                                                 VariableParsingFlags::ACCEPT_CONST_NO_INIT);
1489             break;
1490         }
1491         case lexer::TokenType::PUNCTUATOR_SEMI_COLON: {
1492             if (isAwait) {
1493                 ThrowSyntaxError("Unexpected token");
1494             }
1495 
1496             canBeForInOf = false;
1497             lexer_->NextToken();
1498             break;
1499         }
1500         default: {
1501             leftNode = ParseUnaryOrPrefixUpdateExpression(ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
1502 
1503             break;
1504         }
1505     }
1506 
1507     if (initNode != nullptr) {
1508         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1509             lexer_->NextToken();
1510             canBeForInOf = false;
1511         } else {
1512             canBeForInOf = initNode->AsVariableDeclaration()->Declarators().size() == 1;
1513         }
1514     }
1515 
1516     // VariableDeclaration->DeclarationSize > 1 or seen semi_colon
1517     if (!canBeForInOf) {
1518         std::tie(rightNode, updateNode) = ParseForUpdate(isAwait);
1519     } else if (leftNode) {
1520         // initNode was parsed as LHS
1521         if (leftNode->IsArrayExpression() || leftNode->IsObjectExpression()) {
1522             exprFlags |= ExpressionParseFlags::POTENTIALLY_IN_PATTERN;
1523         }
1524         std::tie(forKind, initNode, rightNode, updateNode) = ParseForInOf(leftNode, exprFlags, isAwait);
1525     } else if (initNode) {
1526         // initNode was parsed as VariableDeclaration and declaration size = 1
1527         std::tie(forKind, rightNode, updateNode) = ParseForInOf(initNode, exprFlags, isAwait);
1528     }
1529 
1530     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1531         ThrowSyntaxError("Unexpected token, expected ')' in 'ForStatement'.");
1532     }
1533     lexer_->NextToken();
1534 
1535     ir::Statement *bodyNode = ParseStatement();
1536     lexer::SourcePosition endLoc = bodyNode->End();
1537 
1538     ir::Statement *forStatement = nullptr;
1539     auto *loopScope = iterCtx.LexicalScope().GetScope();
1540 
1541     if (forKind == ForStatementKind::UPDATE) {
1542         forStatement = AllocNode<ir::ForUpdateStatement>(loopScope, initNode, rightNode, updateNode, bodyNode);
1543     } else if (forKind == ForStatementKind::IN) {
1544         forStatement = AllocNode<ir::ForInStatement>(loopScope, initNode, rightNode, bodyNode);
1545     } else {
1546         forStatement = AllocNode<ir::ForOfStatement>(loopScope, initNode, rightNode, bodyNode, isAwait);
1547     }
1548 
1549     forStatement->SetRange({startLoc, endLoc});
1550     loopScope->BindNode(forStatement);
1551 
1552     return forStatement;
1553 }
1554 
ParseIfStatement()1555 ir::IfStatement *ParserImpl::ParseIfStatement()
1556 {
1557     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1558     lexer::SourcePosition endLoc = lexer_->GetToken().End();
1559     lexer_->NextToken();
1560 
1561     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1562         ThrowSyntaxError("Missing left parenthesis in an 'IfStatement'");
1563     }
1564 
1565     lexer_->NextToken();
1566     ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1567 
1568     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1569         ThrowSyntaxError("Missing right parenthesis in an 'IfStatement'");
1570     }
1571 
1572     lexer_->NextToken();
1573     ir::Statement *consequent = ParseStatement(StatementParsingFlags::IF_ELSE);
1574 
1575     if (Extension() == ScriptExtension::TS && consequent->IsEmptyStatement()) {
1576         ThrowSyntaxError("The body of an if statement cannot be the empty statement");
1577     }
1578 
1579     endLoc = consequent->End();
1580     ir::Statement *alternate = nullptr;
1581 
1582     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_ELSE) {
1583         lexer_->NextToken();  // eat ELSE keyword
1584         alternate = ParseStatement(StatementParsingFlags::IF_ELSE);
1585         endLoc = alternate->End();
1586     }
1587 
1588     auto *ifStatement = AllocNode<ir::IfStatement>(test, consequent, alternate);
1589     ifStatement->SetRange({startLoc, endLoc});
1590     return ifStatement;
1591 }
1592 
ParseLabelledStatement(const lexer::LexerPosition & pos)1593 ir::LabelledStatement *ParserImpl::ParseLabelledStatement(const lexer::LexerPosition &pos)
1594 {
1595     const auto savedPos = lexer_->Save();
1596     bool isLabelFollowedByIterationStatement = IsLabelFollowedByIterationStatement();
1597     lexer_->Rewind(savedPos);
1598 
1599     const util::StringView &actualLabel = pos.token.Ident();
1600 
1601     // TODO(frobert) : check correctness
1602     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AWAIT && context_.IsModule()) {
1603         ThrowSyntaxError("'await' is a reserved identifier in module code", pos.token.Start());
1604     }
1605 
1606     if (context_.FindLabel(actualLabel)) {
1607         ThrowSyntaxError("Label already declared", pos.token.Start());
1608     }
1609 
1610     SavedParserContext newCtx(this, ParserStatus::IN_LABELED | context_.Status(), actualLabel);
1611     if (isLabelFollowedByIterationStatement) {
1612         context_.Status() &= ~ParserStatus::DISALLOW_CONTINUE;
1613     } else {
1614         context_.Status() |= ParserStatus::DISALLOW_CONTINUE;
1615     }
1616 
1617     auto *identNode = AllocNode<ir::Identifier>(actualLabel);
1618     identNode->SetRange(pos.token.Loc());
1619 
1620     lexer_->NextToken();
1621 
1622     ir::Statement *body = ParseStatement(StatementParsingFlags::LABELLED);
1623 
1624     auto *labeledStatement = AllocNode<ir::LabelledStatement>(identNode, body);
1625     labeledStatement->SetRange({pos.token.Start(), body->End()});
1626 
1627     return labeledStatement;
1628 }
1629 
ParseReturnStatement()1630 ir::ReturnStatement *ParserImpl::ParseReturnStatement()
1631 {
1632     if (!(context_.Status() & ParserStatus::FUNCTION)) {
1633         ThrowSyntaxError("return keyword should be used in function body");
1634     }
1635 
1636     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1637     lexer::SourcePosition endLoc = lexer_->GetToken().End();
1638     lexer_->NextToken();
1639 
1640     bool hasArgument = (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
1641                         lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
1642                         lexer_->GetToken().Type() != lexer::TokenType::EOS && !lexer_->GetToken().NewLine());
1643 
1644     ir::ReturnStatement *returnStatement = nullptr;
1645 
1646     if (hasArgument) {
1647         ir::Expression *expression = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1648         endLoc = expression->End();
1649         returnStatement = AllocNode<ir::ReturnStatement>(expression);
1650     } else {
1651         returnStatement = AllocNode<ir::ReturnStatement>();
1652     }
1653 
1654     returnStatement->SetRange({startLoc, endLoc});
1655     ConsumeSemicolon(returnStatement);
1656 
1657     return returnStatement;
1658 }
1659 
ParseSwitchCaseStatement(bool * seenDefault)1660 ir::SwitchCaseStatement *ParserImpl::ParseSwitchCaseStatement(bool *seenDefault)
1661 {
1662     lexer::SourcePosition caseStartLoc = lexer_->GetToken().Start();
1663     ir::Expression *testExpr = nullptr;
1664 
1665     switch (lexer_->GetToken().Type()) {
1666         case lexer::TokenType::KEYW_CASE: {
1667             lexer_->NextToken();
1668             testExpr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1669             break;
1670         }
1671         case lexer::TokenType::KEYW_DEFAULT: {
1672             if (*seenDefault) {
1673                 if (Extension() == ScriptExtension::TS) {
1674                     ThrowSyntaxError(
1675                         "A 'default' clause cannot appear more than once in a "
1676                         "'switch' statement");
1677                 } else {
1678                     ThrowSyntaxError("Multiple default clauses.");
1679                 }
1680             }
1681             *seenDefault = true;
1682             lexer_->NextToken();
1683             break;
1684         }
1685         default: {
1686             ThrowSyntaxError("Unexpected token, expected 'case' or 'default'.");
1687         }
1688     }
1689 
1690     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
1691         ThrowSyntaxError("Unexpected token, expected ':'");
1692     }
1693 
1694     ArenaVector<ir::Statement *> consequents(Allocator()->Adapter());
1695     lexer::SourcePosition caseEndLoc = lexer_->GetToken().End();
1696 
1697     lexer_->NextToken();
1698 
1699     while (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CASE &&
1700            lexer_->GetToken().Type() != lexer::TokenType::KEYW_DEFAULT &&
1701            lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1702         ir::Statement *consequent = ParseStatement(StatementParsingFlags::ALLOW_LEXICAL);
1703         caseEndLoc = consequent->End();
1704         consequents.push_back(consequent);
1705     }
1706 
1707     auto *caseNode = AllocNode<ir::SwitchCaseStatement>(testExpr, std::move(consequents));
1708     caseNode->SetRange({caseStartLoc, caseEndLoc});
1709     return caseNode;
1710 }
1711 
ParseSwitchStatement()1712 ir::SwitchStatement *ParserImpl::ParseSwitchStatement()
1713 {
1714     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1715     lexer_->NextToken();
1716     if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS)) {
1717         ThrowSyntaxError("Unexpected token, expected '('");
1718     }
1719 
1720     lexer_->NextToken();
1721     ir::Expression *discriminant = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1722 
1723     if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS)) {
1724         ThrowSyntaxError("Unexpected token, expected ')'");
1725     }
1726 
1727     lexer_->NextToken();
1728     SwitchContext switchContext(&context_);
1729 
1730     if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE)) {
1731         ThrowSyntaxError("Unexpected token, expected '{'");
1732     }
1733 
1734     lexer_->NextToken();
1735     bool seenDefault = false;
1736     auto localCtx = binder::LexicalScope<binder::LocalScope>(Binder());
1737     ArenaVector<ir::SwitchCaseStatement *> cases(Allocator()->Adapter());
1738 
1739     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1740         cases.push_back(ParseSwitchCaseStatement(&seenDefault));
1741     }
1742 
1743     auto *switchStatement = AllocNode<ir::SwitchStatement>(localCtx.GetScope(), discriminant, std::move(cases));
1744     switchStatement->SetRange({startLoc, lexer_->GetToken().End()});
1745     localCtx.GetScope()->BindNode(switchStatement);
1746 
1747     lexer_->NextToken();
1748 
1749     return switchStatement;
1750 }
1751 
ParseThrowStatement()1752 ir::ThrowStatement *ParserImpl::ParseThrowStatement()
1753 {
1754     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1755     lexer_->NextToken();
1756 
1757     if (lexer_->GetToken().NewLine()) {
1758         if (Extension() == ScriptExtension::JS) {
1759             ThrowSyntaxError("Illegal newline after throw");
1760         }
1761 
1762         if (Extension() == ScriptExtension::TS) {
1763             ThrowSyntaxError("Line break not permitted here");
1764         }
1765     }
1766 
1767     ir::Expression *expression = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1768     lexer::SourcePosition endLoc = expression->End();
1769 
1770     auto *throwStatement = AllocNode<ir::ThrowStatement>(expression);
1771     throwStatement->SetRange({startLoc, endLoc});
1772     ConsumeSemicolon(throwStatement);
1773 
1774     return throwStatement;
1775 }
1776 
ParseCatchParam()1777 ir::Expression *ParserImpl::ParseCatchParam()
1778 {
1779     ir::Expression *param = nullptr;
1780 
1781     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1782         return param;
1783     }
1784 
1785     lexer_->NextToken();  // eat left paren
1786 
1787     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1788         switch (lexer_->GetToken().KeywordType()) {
1789             case lexer::TokenType::KEYW_EVAL: {
1790                 ThrowSyntaxError("Binding 'eval' in strict mode is invalid");
1791             }
1792             case lexer::TokenType::KEYW_ARGUMENTS: {
1793                 ThrowSyntaxError("Binding 'arguments' in strict mode is invalid");
1794             }
1795             default: {
1796                 break;
1797             }
1798         }
1799 
1800         param = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1801         param->SetRange(lexer_->GetToken().Loc());
1802 
1803         lexer_->NextToken();
1804     } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1805         param = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1806     } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1807         param = ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1808     } else {
1809         ThrowSyntaxError("Unexpected token in catch parameter");
1810     }
1811 
1812     Binder()->AddParamDecl(param);
1813 
1814     if (Extension() == ScriptExtension::TS) {
1815         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1816             lexer_->NextToken();  // eat ':'
1817 
1818             TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1819             param->SetTsTypeAnnotation(ParseTsTypeAnnotation(&options));
1820         }
1821 
1822         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
1823             ThrowSyntaxError("Catch clause variable cannot have an initializer");
1824         }
1825     }
1826 
1827     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1828         ThrowSyntaxError("Unexpected token, expected ')'");
1829     }
1830 
1831     lexer_->NextToken();
1832 
1833     return param;
1834 }
1835 
ParseCatchClause()1836 ir::CatchClause *ParserImpl::ParseCatchClause()
1837 {
1838     lexer::SourcePosition catchStartLoc = lexer_->GetToken().Start();
1839     lexer_->NextToken();  // eat 'catch' keyword
1840 
1841     auto catchParamCtx = binder::LexicalScope<binder::CatchParamScope>(Binder());
1842     auto *catchParamScope = catchParamCtx.GetScope();
1843 
1844     ir::Expression *param = ParseCatchParam();
1845     catchParamScope->BindNode(param);
1846 
1847     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1848         ThrowSyntaxError("Unexpected token, expected '{'");
1849     }
1850 
1851     auto catchCtx = binder::LexicalScope<binder::CatchScope>(Binder());
1852     auto *catchScope = catchCtx.GetScope();
1853     catchScope->AssignParamScope(catchParamScope);
1854 
1855     ir::BlockStatement *catchBlock = ParseBlockStatement(catchScope);
1856     lexer_->NextToken();
1857     lexer::SourcePosition endLoc = catchBlock->End();
1858 
1859     auto *catchClause = AllocNode<ir::CatchClause>(catchScope, param, catchBlock);
1860     catchClause->SetRange({catchStartLoc, endLoc});
1861     catchScope->BindNode(catchClause);
1862 
1863     return catchClause;
1864 }
1865 
ParseTryStatement()1866 ir::TryStatement *ParserImpl::ParseTryStatement()
1867 {
1868     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1869     lexer::SourcePosition endLoc = lexer_->GetToken().End();
1870 
1871     lexer_->NextToken();
1872 
1873     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1874         ThrowSyntaxError("Unexpected token, expected '{'");
1875     }
1876 
1877     ir::BlockStatement *body = ParseBlockStatement();
1878 
1879     if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CATCH &&
1880         lexer_->GetToken().Type() != lexer::TokenType::KEYW_FINALLY) {
1881         ThrowSyntaxError("Missing catch or finally clause");
1882     }
1883 
1884     ir::CatchClause *catchClause = nullptr;
1885     ir::BlockStatement *finnalyClause = nullptr;
1886 
1887     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_CATCH) {
1888         catchClause = ParseCatchClause();
1889         endLoc = catchClause->End();
1890     }
1891 
1892     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FINALLY) {
1893         lexer_->NextToken();  // eat 'finally' keyword
1894 
1895         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1896             ThrowSyntaxError("Unexpected token, expected '{'");
1897         }
1898 
1899         finnalyClause = ParseBlockStatement();
1900         endLoc = finnalyClause->End();
1901     }
1902 
1903     auto *tryStatement = AllocNode<ir::TryStatement>(body, catchClause, finnalyClause);
1904     tryStatement->SetRange({startLoc, endLoc});
1905     return tryStatement;
1906 }
1907 
1908 // TODO(frobert) : merge into lexer::LexerNextTokenFlags
ValidateDeclaratorId()1909 void ParserImpl::ValidateDeclaratorId()
1910 {
1911     if (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT) {
1912         return;
1913     }
1914 
1915     switch (lexer_->GetToken().KeywordType()) {
1916         case lexer::TokenType::KEYW_AWAIT: {
1917             if (context_.IsModule()) {
1918                 ThrowSyntaxError("'await' is not permitted as an identifier in module code");
1919             }
1920             break;
1921         }
1922         case lexer::TokenType::KEYW_EVAL: {
1923             ThrowSyntaxError("Binding 'eval' in strict mode is invalid");
1924         }
1925         case lexer::TokenType::KEYW_ARGUMENTS: {
1926             ThrowSyntaxError("Binding 'arguments' in strict mode is invalid");
1927         }
1928         case lexer::TokenType::KEYW_LET: {
1929             ThrowSyntaxError("let is disallowed as a lexically bound name");
1930             break;
1931         }
1932         case lexer::TokenType::KEYW_STATIC:
1933         case lexer::TokenType::KEYW_IMPLEMENTS:
1934         case lexer::TokenType::KEYW_INTERFACE:
1935         case lexer::TokenType::KEYW_PACKAGE:
1936         case lexer::TokenType::KEYW_PRIVATE:
1937         case lexer::TokenType::KEYW_PROTECTED:
1938         case lexer::TokenType::KEYW_PUBLIC:
1939         case lexer::TokenType::KEYW_YIELD: {
1940             ThrowSyntaxError("Unexpected reserved word");
1941         }
1942         default: {
1943             break;
1944         }
1945     }
1946 }
1947 
ParseVariableDeclaratorInitializer(ir::Expression * init,VariableParsingFlags flags,const lexer::SourcePosition & startLoc,bool isDeclare)1948 ir::VariableDeclarator *ParserImpl::ParseVariableDeclaratorInitializer(ir::Expression *init, VariableParsingFlags flags,
1949                                                                        const lexer::SourcePosition &startLoc,
1950                                                                        bool isDeclare)
1951 {
1952     if (flags & VariableParsingFlags::DISALLOW_INIT) {
1953         ThrowSyntaxError("for-await-of loop variable declaration may not have an initializer");
1954     }
1955 
1956     lexer_->NextToken();
1957 
1958     if (isDeclare && !(flags & VariableParsingFlags::CONST)) {
1959         ThrowSyntaxError("Initializers are not allowed in ambient contexts.");
1960     }
1961 
1962     auto exprFlags =
1963         ((flags & VariableParsingFlags::STOP_AT_IN) ? ExpressionParseFlags::STOP_AT_IN : ExpressionParseFlags::NO_OPTS);
1964 
1965     ir::Expression *initializer = ParseExpression(exprFlags);
1966     lexer::SourcePosition endLoc = initializer->End();
1967 
1968     auto *declarator = AllocNode<ir::VariableDeclarator>(init, initializer);
1969     declarator->SetRange({startLoc, endLoc});
1970 
1971     return declarator;
1972 }
1973 
ParseVariableDeclarator(VariableParsingFlags flags,bool isDeclare)1974 ir::VariableDeclarator *ParserImpl::ParseVariableDeclarator(VariableParsingFlags flags, bool isDeclare)
1975 {
1976     ir::Expression *init = nullptr;
1977     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1978     switch (lexer_->GetToken().Type()) {
1979         case lexer::TokenType::LITERAL_IDENT: {
1980             ValidateDeclaratorId();
1981 
1982             if (!(flags & VariableParsingFlags::VAR) &&
1983                 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_LET) {
1984                 ThrowSyntaxError("let is disallowed as a lexically bound name");
1985             }
1986 
1987             const util::StringView &identStr = lexer_->GetToken().Ident();
1988             init = AllocNode<ir::Identifier>(identStr);
1989             init->SetRange(lexer_->GetToken().Loc());
1990 
1991             if (Extension() == ScriptExtension::TS) {
1992                 init->AsIdentifier()->SetReference();
1993             }
1994 
1995             lexer_->NextToken();
1996             break;
1997         }
1998         case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
1999             init = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
2000             break;
2001         }
2002         case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
2003             init = ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN);
2004             break;
2005         }
2006         default: {
2007             ThrowSyntaxError("Unexpected token in variable declaration");
2008         }
2009     }
2010 
2011     bool isDefinite = false;
2012     if (Extension() == ScriptExtension::TS) {
2013         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) {
2014             lexer_->NextToken();  // eat '!'
2015             isDefinite = true;
2016         }
2017         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
2018             lexer_->NextToken();  // eat ':'
2019             TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
2020             init->SetTsTypeAnnotation(ParseTsTypeAnnotation(&options));
2021         }
2022     }
2023 
2024     ir::VariableDeclarator *declarator {};
2025 
2026     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
2027         declarator = ParseVariableDeclaratorInitializer(init, flags, startLoc, isDeclare);
2028     } else {
2029         if (!isDeclare && (flags & VariableParsingFlags::CONST) &&
2030             !(flags & VariableParsingFlags::ACCEPT_CONST_NO_INIT) &&
2031             !(context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT)) {
2032             ThrowSyntaxError("Missing initializer in const declaration");
2033         }
2034 
2035         if (!isDeclare && !(flags & VariableParsingFlags::IN_FOR) &&
2036             (init->IsArrayPattern() || init->IsObjectPattern())) {
2037             ThrowSyntaxError("Missing initializer in destructuring declaration");
2038         }
2039 
2040         lexer::SourcePosition endLoc = init->End();
2041         declarator = AllocNode<ir::VariableDeclarator>(init);
2042         declarator->SetRange({startLoc, endLoc});
2043     }
2044 
2045     declarator->SetDefinite(isDefinite);
2046 
2047     std::vector<const ir::Identifier *> bindings = util::Helpers::CollectBindingNames(init);
2048 
2049     for (const auto *binding : bindings) {
2050         binder::Decl *decl = nullptr;
2051         binder::DeclarationFlags declflag = (flags & VariableParsingFlags::EXPORTED) ?
2052                                             binder::DeclarationFlags::EXPORT : binder::DeclarationFlags::NONE;
2053         if (flags & VariableParsingFlags::EXPORTED_IN_TSMODULE) {
2054             declflag |= binder::DeclarationFlags::EXPORT_IN_TSMODULE;
2055         }
2056 
2057         if (flags & VariableParsingFlags::VAR) {
2058             decl = Binder()->AddDecl<binder::VarDecl>(startLoc, declflag, isDeclare, binding->Name());
2059         } else if (flags & VariableParsingFlags::LET) {
2060             decl = Binder()->AddDecl<binder::LetDecl>(startLoc, declflag, isDeclare, binding->Name());
2061         } else {
2062             decl = Binder()->AddDecl<binder::ConstDecl>(startLoc, declflag, isDeclare, binding->Name());
2063         }
2064 
2065         decl->BindNode(init);
2066     }
2067 
2068     return declarator;
2069 }
2070 
ParseVariableDeclaration(VariableParsingFlags flags,bool isDeclare,bool isExport)2071 ir::Statement *ParserImpl::ParseVariableDeclaration(VariableParsingFlags flags, bool isDeclare, bool isExport)
2072 {
2073     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2074 
2075     if (!(flags & VariableParsingFlags::NO_SKIP_VAR_KIND)) {
2076         lexer_->NextToken();
2077     }
2078 
2079     if ((flags & VariableParsingFlags::LET) && util::Helpers::IsGlobalIdentifier(lexer_->GetToken().Ident())) {
2080         ThrowSyntaxError("Declaration name conflicts with built-in global identifier '"
2081                         + lexer_->GetToken().Ident().Mutf8() + "'.");
2082     }
2083 
2084     if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ENUM) {
2085         if (!(flags & VariableParsingFlags::CONST)) {
2086             ThrowSyntaxError("Variable declaration expected.");
2087         }
2088         return ParseEnumDeclaration(isExport, isDeclare, true);
2089     }
2090 
2091     ArenaVector<ir::VariableDeclarator *> declarators(Allocator()->Adapter());
2092 
2093     while (true) {
2094         ir::VariableDeclarator *declarator = ParseVariableDeclarator(flags, isDeclare);
2095 
2096         declarators.push_back(declarator);
2097 
2098         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) {
2099             break;
2100         }
2101         lexer_->NextToken();
2102     }
2103 
2104     auto varKind = ir::VariableDeclaration::VariableDeclarationKind::VAR;
2105 
2106     if (flags & VariableParsingFlags::LET) {
2107         varKind = ir::VariableDeclaration::VariableDeclarationKind::LET;
2108     } else if (flags & VariableParsingFlags::CONST) {
2109         varKind = ir::VariableDeclaration::VariableDeclarationKind::CONST;
2110     }
2111 
2112     lexer::SourcePosition endLoc = declarators.back()->End();
2113     auto *declaration = AllocNode<ir::VariableDeclaration>(varKind, std::move(declarators), isDeclare);
2114     declaration->SetRange({startLoc, endLoc});
2115 
2116     return declaration;
2117 }
2118 
ParseWhileStatement()2119 ir::WhileStatement *ParserImpl::ParseWhileStatement()
2120 {
2121     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2122     lexer_->NextToken();
2123     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
2124         ThrowSyntaxError("Unexpected token, expected '('");
2125     }
2126 
2127     lexer_->NextToken();
2128     ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
2129 
2130     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
2131         ThrowSyntaxError("Unexpected token, expected ')'");
2132     }
2133 
2134     lexer_->NextToken();
2135     IterationContext<binder::LoopScope> iterCtx(&context_, Binder());
2136     ir::Statement *body = ParseStatement();
2137 
2138     lexer::SourcePosition endLoc = body->End();
2139     auto *whileStatement = AllocNode<ir::WhileStatement>(iterCtx.LexicalScope().GetScope(), test, body);
2140     whileStatement->SetRange({startLoc, endLoc});
2141     iterCtx.LexicalScope().GetScope()->BindNode(whileStatement);
2142 
2143     return whileStatement;
2144 }
2145 
AddImportEntryItem(const ir::StringLiteral * source,const ArenaVector<ir::AstNode * > * specifiers,bool isType)2146 void ParserImpl::AddImportEntryItem(const ir::StringLiteral *source,
2147                                     const ArenaVector<ir::AstNode *> *specifiers, bool isType)
2148 {
2149     if (context_.IsTsModule()) {
2150         return;
2151     }
2152 
2153     ASSERT(source != nullptr);
2154     auto *moduleRecord = isType ? GetSourceTextTypeModuleRecord() : GetSourceTextModuleRecord();
2155     ASSERT(moduleRecord != nullptr);
2156     auto moduleRequestIdx = moduleRecord->AddModuleRequest(source->Str());
2157 
2158     if (specifiers == nullptr) {
2159         if (isType) {
2160             ThrowSyntaxError("Unexpected import type syntax", source->Start());
2161         }
2162         return;
2163     }
2164 
2165     for (auto *it : *specifiers) {
2166         switch (it->Type()) {
2167             case ir::AstNodeType::IMPORT_DEFAULT_SPECIFIER: {
2168                 auto localName = it->AsImportDefaultSpecifier()->Local()->Name();
2169                 auto importName = parser::SourceTextModuleRecord::DEFAULT_EXTERNAL_NAME;
2170                 auto localId = it->AsImportDefaultSpecifier()->Local();
2171                 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ImportEntry>(
2172                     localName, importName, moduleRequestIdx, localId, nullptr);
2173                 moduleRecord->AddImportEntry(entry);
2174                 break;
2175             }
2176             case ir::AstNodeType::IMPORT_NAMESPACE_SPECIFIER: {
2177                 auto localName = it->AsImportNamespaceSpecifier()->Local()->Name();
2178                 auto localId = it->AsImportNamespaceSpecifier()->Local();
2179                 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ImportEntry>(
2180                     localName, moduleRequestIdx, localId);
2181                 moduleRecord->AddStarImportEntry(entry);
2182                 break;
2183             }
2184             case ir::AstNodeType::IMPORT_SPECIFIER: {
2185                 auto localName = it->AsImportSpecifier()->Local()->Name();
2186                 auto importName = it->AsImportSpecifier()->Imported()->Name();
2187                 auto localId = it->AsImportSpecifier()->Local();
2188                 auto importId = it->AsImportSpecifier()->Imported();
2189                 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ImportEntry>(
2190                     localName, importName, moduleRequestIdx, localId, importId);
2191                 moduleRecord->AddImportEntry(entry);
2192                 break;
2193             }
2194             default: {
2195                 ThrowSyntaxError("Unexpected astNode type", it->Start());
2196             }
2197         }
2198     }
2199 }
2200 
AddExportNamedEntryItem(const ArenaVector<ir::ExportSpecifier * > & specifiers,const ir::StringLiteral * source,bool isType)2201 void ParserImpl::AddExportNamedEntryItem(const ArenaVector<ir::ExportSpecifier *> &specifiers,
2202                                          const ir::StringLiteral *source, bool isType)
2203 {
2204     // The exported objects in the TSModuleScope do not need to be allocated index.
2205     if (context_.IsTsModule()) {
2206         ASSERT(Binder()->GetScope()->IsTSModuleScope());
2207         return;
2208     }
2209     auto moduleRecord = isType ? GetSourceTextTypeModuleRecord() : GetSourceTextModuleRecord();
2210     ASSERT(moduleRecord != nullptr);
2211     if (source) {
2212         auto moduleRequestIdx = moduleRecord->AddModuleRequest(source->Str());
2213 
2214         for (auto *it : specifiers) {
2215             auto exportSpecifier = it->AsExportSpecifier();
2216             auto importName = exportSpecifier->Local()->Name();
2217             auto exportName = exportSpecifier->Exported()->Name();
2218             auto importId = exportSpecifier->Local();
2219             auto exportId = exportSpecifier->Exported();
2220             auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2221                 exportName, importName, moduleRequestIdx, exportId, importId);
2222             if (!moduleRecord->AddIndirectExportEntry(entry)) {
2223                 ThrowSyntaxError("Duplicate export name of '" + exportName.Mutf8() + "'",
2224                                  exportSpecifier->Start());
2225             }
2226         }
2227     } else {
2228         for (auto *it : specifiers) {
2229             auto exportSpecifier = it->AsExportSpecifier();
2230             auto exportName = exportSpecifier->Exported()->Name();
2231             auto localName = exportSpecifier->Local()->Name();
2232             auto exportId = exportSpecifier->Exported();
2233             auto localId = exportSpecifier->Local();
2234             auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2235                 exportName, localName, exportId, localId);
2236             if (!moduleRecord->AddLocalExportEntry(entry)) {
2237                 ThrowSyntaxError("Duplicate export name of '" + exportName.Mutf8() + "'",
2238                                  exportSpecifier->Start());
2239             }
2240         }
2241     }
2242 }
2243 
AddExportStarEntryItem(const lexer::SourcePosition & startLoc,const ir::StringLiteral * source,const ir::Identifier * exported)2244 void ParserImpl::AddExportStarEntryItem(const lexer::SourcePosition &startLoc, const ir::StringLiteral *source,
2245                                         const ir::Identifier *exported)
2246 {
2247     auto moduleRecord = GetSourceTextModuleRecord();
2248     ASSERT(moduleRecord != nullptr);
2249     ASSERT(source != nullptr);
2250     auto moduleRequestIdx = moduleRecord->AddModuleRequest(source->Str());
2251 
2252     if (exported != nullptr) {
2253         /* Transform [NamespaceExport] into [NamespaceImport] & [LocalExport]
2254          * e.g. export * as ns from 'test.js'
2255          *      --->
2256          *      import * as [internalName] from 'test.js'
2257          *      export { [internalName] as ns }
2258          */
2259         auto namespaceExportInternalName = GetNamespaceExportInternalName();
2260         auto *decl = Binder()->AddDecl<binder::ConstDecl>(startLoc, binder::DeclarationFlags::EXPORT,
2261                                                           false, namespaceExportInternalName);
2262         decl->BindNode(exported);
2263 
2264         auto *importEntry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ImportEntry>(
2265             namespaceExportInternalName, moduleRequestIdx, nullptr);
2266         auto *exportEntry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2267             exported->Name(), namespaceExportInternalName, exported, nullptr);
2268         moduleRecord->AddStarImportEntry(importEntry);
2269         if (!moduleRecord->AddLocalExportEntry(exportEntry)) {
2270             ThrowSyntaxError("Duplicate export name of '" + exported->Name().Mutf8() + "'", exported->Start());
2271         }
2272         return;
2273     }
2274 
2275     auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(moduleRequestIdx);
2276     moduleRecord->AddStarExportEntry(entry);
2277 }
2278 
AddExportDefaultEntryItem(const ir::AstNode * declNode)2279 void ParserImpl::AddExportDefaultEntryItem(const ir::AstNode *declNode)
2280 {
2281     if (context_.IsTsModule()) {
2282         return;
2283     }
2284 
2285     ASSERT(declNode != nullptr);
2286     if (declNode->IsTSInterfaceDeclaration() ||
2287         (declNode->IsFunctionDeclaration() && declNode->AsFunctionDeclaration()->Function()->IsOverload())) {
2288         return;
2289     }
2290 
2291     auto moduleRecord = GetSourceTextModuleRecord();
2292     ASSERT(moduleRecord != nullptr);
2293     util::StringView exportName = parser::SourceTextModuleRecord::DEFAULT_EXTERNAL_NAME;
2294     util::StringView localName = parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME;
2295     if (declNode->IsFunctionDeclaration() || declNode->IsClassDeclaration()) {
2296         localName = declNode->IsFunctionDeclaration() ? declNode->AsFunctionDeclaration()->Function()->GetName() :
2297                                                         declNode->AsClassDeclaration()->Definition()->GetName();
2298     }
2299 
2300     ASSERT(!localName.Empty());
2301     auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2302         exportName, localName, nullptr, nullptr);
2303     if (!moduleRecord->AddLocalExportEntry(entry)) {
2304         ThrowSyntaxError("Duplicate export name of '" + exportName.Mutf8() + "'", declNode->Start());
2305     }
2306 }
2307 
AddExportLocalEntryItem(const ir::Statement * declNode,bool isTsModule)2308 void ParserImpl::AddExportLocalEntryItem(const ir::Statement *declNode, bool isTsModule)
2309 {
2310     ASSERT(declNode != nullptr);
2311     auto moduleRecord = GetSourceTextModuleRecord();
2312     ASSERT(isTsModule || moduleRecord != nullptr);
2313     binder::TSModuleScope *tsModuleScope = nullptr;
2314     if (isTsModule) {
2315         ASSERT(Binder()->GetScope()->IsTSModuleScope());
2316         tsModuleScope = Binder()->GetScope()->AsTSModuleScope();
2317     }
2318     if (declNode->IsVariableDeclaration()) {
2319         auto declarators = declNode->AsVariableDeclaration()->Declarators();
2320         for (auto *decl : declarators) {
2321             std::vector<const ir::Identifier *> bindings = util::Helpers::CollectBindingNames(decl->Id());
2322             for (const auto *binding : bindings) {
2323                 if (isTsModule) {
2324                     tsModuleScope->AddExportVariable(binding->Name());
2325                 } else {
2326                     auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2327                         binding->Name(), binding->Name(), binding, binding);
2328                     if (!moduleRecord->AddLocalExportEntry(entry)) {
2329                         ThrowSyntaxError("Duplicate export name of '" + binding->Name().Mutf8()
2330                                          + "'", binding->Start());
2331                     }
2332                 }
2333             }
2334         }
2335     }
2336     if (declNode->IsFunctionDeclaration() || declNode->IsClassDeclaration()) {
2337         auto name = declNode->IsFunctionDeclaration() ?
2338                     declNode->AsFunctionDeclaration()->Function()->Id() :
2339                     declNode->AsClassDeclaration()->Definition()->Ident();
2340         if (name == nullptr) {
2341             ThrowSyntaxError("A class or function declaration without the default modifier must have a name.",
2342                              declNode->Start());
2343         }
2344         if (declNode->IsFunctionDeclaration() && declNode->AsFunctionDeclaration()->Function()->IsOverload()) {
2345             return;
2346         }
2347         if (isTsModule) {
2348             tsModuleScope->AddExportVariable(name->Name());
2349         } else {
2350             auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2351                 name->Name(), name->Name(), name, name);
2352             if (!moduleRecord->AddLocalExportEntry(entry)) {
2353                 ThrowSyntaxError("Duplicate export name of '" + name->Name().Mutf8() + "'", name->Start());
2354             }
2355         }
2356     }
2357     AddTsTypeExportLocalEntryItem(declNode, isTsModule, tsModuleScope);
2358 }
2359 
AddTsTypeExportLocalEntryItem(const ir::Statement * declNode,bool isTsModule,binder::TSModuleScope * tsModuleScope)2360 void ParserImpl::AddTsTypeExportLocalEntryItem(const ir::Statement *declNode, bool isTsModule,
2361                                                binder::TSModuleScope *tsModuleScope)
2362 {
2363     if (!declNode->IsTSInterfaceDeclaration() && !declNode->IsTSTypeAliasDeclaration()) {
2364         return;
2365     }
2366     auto name = declNode->IsTSInterfaceDeclaration() ?
2367                 declNode->AsTSInterfaceDeclaration()->Id() : declNode->AsTSTypeAliasDeclaration()->Id();
2368     if (name == nullptr) {
2369         ThrowSyntaxError("An interface or type alias declaration must have a name.");
2370     }
2371     if (isTsModule) {
2372         binder::TSBinding tsBinding(Allocator(), name->Name());
2373         tsModuleScope->AddExportVariable(tsBinding.View());
2374     }
2375 }
2376 
ParseExportDefaultDeclaration(const lexer::SourcePosition & startLoc,ArenaVector<ir::Decorator * > decorators,bool isExportEquals)2377 ir::ExportDefaultDeclaration *ParserImpl::ParseExportDefaultDeclaration(const lexer::SourcePosition &startLoc,
2378                                                                         ArenaVector<ir::Decorator *> decorators,
2379                                                                         bool isExportEquals)
2380 {
2381     lexer_->NextToken();  // eat `default` keyword or `=`
2382 
2383     ir::AstNode *declNode = nullptr;
2384     bool eatSemicolon = false;
2385 
2386     if (!decorators.empty() && lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS &&
2387         (context_.Status() & ParserStatus::IN_CLASS_BODY) == 0) {
2388         ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2389     }
2390 
2391     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION) {
2392         declNode = ParseFunctionDeclaration(true, ParserStatus::EXPORT_REACHED);
2393     } else if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_CLASS) {
2394         declNode = ParseClassDeclaration(false, std::move(decorators), false, false, true);
2395     } else if (lexer_->GetToken().IsAsyncModifier()) {
2396         lexer_->NextToken();  // eat `async` keyword
2397         declNode = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION | ParserStatus::EXPORT_REACHED);
2398     } else if (Extension() == ScriptExtension::TS &&
2399                lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_INTERFACE) {
2400         declNode = ParseTsInterfaceDeclaration(false);
2401     } else if (Extension() == ScriptExtension::TS &&
2402                lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT) {
2403         lexer_->NextToken();
2404         if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS) {
2405             ThrowSyntaxError("Unexpected token, expected 'class'.");
2406         }
2407         declNode = ParseClassDeclaration(false, std::move(decorators), false, true, true);
2408     } else {
2409         declNode = ParseExpression();
2410         Binder()->AddDecl<binder::LetDecl>(declNode->Start(), binder::DeclarationFlags::EXPORT,
2411                                            false, parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME);
2412         eatSemicolon = true;
2413     }
2414 
2415     // record default export entry
2416     if (!isExportEquals) {
2417         AddExportDefaultEntryItem(declNode);
2418     }
2419 
2420     lexer::SourcePosition endLoc = declNode->End();
2421     auto *exportDeclaration = AllocNode<ir::ExportDefaultDeclaration>(declNode, isExportEquals);
2422     exportDeclaration->SetRange({startLoc, endLoc});
2423 
2424     if (eatSemicolon) {
2425         ConsumeSemicolon(exportDeclaration);
2426     }
2427 
2428     return exportDeclaration;
2429 }
2430 
ParseNamedExport(const lexer::Token & exportedToken)2431 ir::Identifier *ParserImpl::ParseNamedExport(const lexer::Token &exportedToken)
2432 {
2433     if (exportedToken.Type() != lexer::TokenType::LITERAL_IDENT) {
2434         ThrowSyntaxError("Unexpected token, expected an identifier.");
2435     }
2436 
2437     const util::StringView &exportedString = exportedToken.Ident();
2438 
2439     auto *exported = AllocNode<ir::Identifier>(exportedString);
2440     exported->SetRange(exportedToken.Loc());
2441 
2442     return exported;
2443 }
2444 
ParseExportAllDeclaration(const lexer::SourcePosition & startLoc)2445 ir::ExportAllDeclaration *ParserImpl::ParseExportAllDeclaration(const lexer::SourcePosition &startLoc)
2446 {
2447     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat `*` character
2448 
2449     ir::Identifier *exported = nullptr;
2450 
2451     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
2452         lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2453         exported = ParseNamedExport(lexer_->GetToken());
2454         lexer_->NextToken();  // eat exported name
2455     }
2456 
2457     ir::StringLiteral *source = ParseFromClause();
2458     lexer::SourcePosition endLoc = source->End();
2459 
2460     // record export star entry
2461     AddExportStarEntryItem(startLoc, source, exported);
2462 
2463     auto *exportDeclaration = AllocNode<ir::ExportAllDeclaration>(source, exported);
2464     exportDeclaration->SetRange({startLoc, endLoc});
2465 
2466     ConsumeSemicolon(exportDeclaration);
2467 
2468     return exportDeclaration;
2469 }
2470 
ParseExportNamedSpecifiers(const lexer::SourcePosition & startLoc,bool isType)2471 ir::ExportNamedDeclaration *ParserImpl::ParseExportNamedSpecifiers(const lexer::SourcePosition &startLoc,
2472                                                                    bool isType)
2473 {
2474     if (Extension() == ScriptExtension::TS && context_.IsTsModule() &&
2475         !(context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT)) {
2476         ThrowSyntaxError("Export declarations are not permitted in a namespace.");
2477     }
2478 
2479     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat `{` character
2480 
2481     ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter());
2482 
2483     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
2484         if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2485             ThrowSyntaxError("Unexpected token");
2486         }
2487 
2488         lexer::Token localToken = lexer_->GetToken();
2489         auto *local = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
2490         local->SetRange(lexer_->GetToken().Loc());
2491 
2492         if (Extension() == ScriptExtension::TS) {
2493             local->SetReference();
2494         }
2495 
2496         lexer_->NextToken();  // eat local name
2497 
2498         ir::Identifier *exported = nullptr;
2499 
2500         if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
2501             lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat `as` literal
2502             exported = ParseNamedExport(lexer_->GetToken());
2503             lexer_->NextToken();  // eat exported name
2504         } else {
2505             exported = ParseNamedExport(localToken);
2506         }
2507 
2508         auto *specifier = AllocNode<ir::ExportSpecifier>(local, exported);
2509         specifier->SetRange({local->Start(), exported->End()});
2510 
2511         specifiers.push_back(specifier);
2512 
2513         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2514             lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat comma
2515         }
2516     }
2517 
2518     lexer::SourcePosition endPos = lexer_->GetToken().End();
2519     lexer_->NextToken();  // eat right brace
2520 
2521     ir::StringLiteral *source = nullptr;
2522 
2523     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_FROM) {
2524         source = ParseFromClause();
2525     }
2526 
2527     // record ExportEntry
2528     AddExportNamedEntryItem(specifiers, source, isType);
2529 
2530     auto *exportDeclaration = AllocNode<ir::ExportNamedDeclaration>(source, std::move(specifiers), isType);
2531     exportDeclaration->SetRange({startLoc, endPos});
2532     ConsumeSemicolon(exportDeclaration);
2533 
2534     return exportDeclaration;
2535 }
2536 
ParseNamedExportDeclaration(const lexer::SourcePosition & startLoc,ArenaVector<ir::Decorator * > && decorators)2537 ir::ExportNamedDeclaration *ParserImpl::ParseNamedExportDeclaration(const lexer::SourcePosition &startLoc,
2538                                                                     ArenaVector<ir::Decorator *> &&decorators)
2539 {
2540     ir::Statement *decl = nullptr;
2541 
2542     bool isDeclare = false;
2543     bool isTsModule = context_.IsTsModule();
2544 
2545     if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) {
2546         isDeclare = CheckDeclare();
2547     }
2548 
2549     if (!decorators.empty() && lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS &&
2550         (context_.Status() & ParserStatus::IN_CLASS_BODY) == 0 &&
2551         !(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2552           (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT))) {
2553         ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2554     }
2555 
2556     VariableParsingFlags flag = isTsModule ?
2557         VariableParsingFlags::EXPORTED_IN_TSMODULE : VariableParsingFlags::EXPORTED;
2558     ParserStatus status = isTsModule ? ParserStatus::NO_OPTS : ParserStatus::EXPORT_REACHED;
2559 
2560     switch (lexer_->GetToken().Type()) {
2561         case lexer::TokenType::KEYW_VAR: {
2562             decl = ParseVariableDeclaration(flag | VariableParsingFlags::VAR, isDeclare, true);
2563             break;
2564         }
2565         case lexer::TokenType::KEYW_CONST: {
2566             decl = ParseVariableDeclaration(flag | VariableParsingFlags::CONST, isDeclare, true);
2567             break;
2568         }
2569         case lexer::TokenType::KEYW_LET: {
2570             decl = ParseVariableDeclaration(flag | VariableParsingFlags::LET, isDeclare, true);
2571             break;
2572         }
2573         case lexer::TokenType::KEYW_FUNCTION: {
2574             decl = ParseFunctionDeclaration(false, status, isDeclare);
2575             break;
2576         }
2577         case lexer::TokenType::KEYW_CLASS: {
2578             decl = ParseClassDeclaration(true, std::move(decorators), isDeclare || IsDtsFile(), false, !isTsModule);
2579             break;
2580         }
2581         case lexer::TokenType::LITERAL_IDENT: {
2582             if (Extension() == ScriptExtension::TS) {
2583                 switch (lexer_->GetToken().KeywordType()) {
2584                     case lexer::TokenType::KEYW_LET: {
2585                         decl = ParseVariableDeclaration(VariableParsingFlags::LET, isDeclare);
2586                         break;
2587                     }
2588                     case lexer::TokenType::KEYW_ENUM: {
2589                         decl = ParseEnumDeclaration(true, isDeclare, false);
2590                         break;
2591                     }
2592                     case lexer::TokenType::KEYW_INTERFACE: {
2593                         decl = ParseTsInterfaceDeclaration(isDeclare);
2594                         break;
2595                     }
2596                     case lexer::TokenType::KEYW_TYPE: {
2597                         decl = ParseTsTypeAliasDeclaration(isDeclare);
2598                         break;
2599                     }
2600                     case lexer::TokenType::KEYW_GLOBAL:
2601                     case lexer::TokenType::KEYW_MODULE:
2602                     case lexer::TokenType::KEYW_NAMESPACE: {
2603                         auto savedStatus = context_.Status();
2604                         if (isDeclare) {
2605                             context_.Status() |= ParserStatus::IN_AMBIENT_CONTEXT;
2606                         }
2607                         decl = ParseTsModuleDeclaration(isDeclare, true);
2608                         context_.Status() = savedStatus;
2609                         break;
2610                     }
2611                     case lexer::TokenType::KEYW_ABSTRACT: {
2612                         lexer_->NextToken();  // eat abstract keyword
2613 
2614                         if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) {
2615                             if (isDeclare) {
2616                                 ThrowSyntaxError("'declare' modifier already seen.");
2617                             }
2618                             lexer_->NextToken();
2619                             isDeclare = true;
2620                         }
2621 
2622                         if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS) {
2623                             ThrowSyntaxError("Unexpected token, expected 'class'.");
2624                         }
2625                         decl = ParseClassDeclaration(true, std::move(decorators),
2626                                                      isDeclare || IsDtsFile(), true, !isTsModule);
2627                         break;
2628                     }
2629                     default: {
2630                         break;
2631                     }
2632                 }
2633 
2634                 if (decl) {
2635                     break;
2636                 }
2637             }
2638 
2639             [[fallthrough]];
2640         }
2641         default: {
2642             if (!lexer_->GetToken().IsAsyncModifier()) {
2643                 ThrowSyntaxError("Unexpected token");
2644             }
2645 
2646             lexer_->NextToken();  // eat `async` keyword
2647             decl = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION | status);
2648         }
2649     }
2650 
2651     if (decl->IsVariableDeclaration()) {
2652         ConsumeSemicolon(decl);
2653     }
2654 
2655     AddExportLocalEntryItem(decl, isTsModule);
2656 
2657     lexer::SourcePosition endLoc = decl->End();
2658     ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter());
2659     auto *exportDeclaration = AllocNode<ir::ExportNamedDeclaration>(decl, std::move(specifiers));
2660     exportDeclaration->SetRange({startLoc, endLoc});
2661 
2662     return exportDeclaration;
2663 }
2664 
ParseExportDeclaration(StatementParsingFlags flags,ArenaVector<ir::Decorator * > && decorators)2665 ir::Statement *ParserImpl::ParseExportDeclaration(StatementParsingFlags flags,
2666                                                   ArenaVector<ir::Decorator *> &&decorators)
2667 {
2668     if (Extension() == ScriptExtension::JS || !context_.IsTsModule()) {
2669         if (!(flags & StatementParsingFlags::GLOBAL)) {
2670             ThrowSyntaxError("'import' and 'export' may only appear at the top level");
2671         }
2672 
2673         if (!context_.IsModule()) {
2674             ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'");
2675         }
2676     }
2677 
2678     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2679     lexer_->NextToken();  // eat `export` keyword
2680 
2681     // won't set `isType` for type alias
2682     bool isType = false;
2683     if (Extension() == ScriptExtension::TS &&
2684         lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE) {
2685         const auto savedPos = lexer_->Save();
2686         lexer_->NextToken();  // eat type
2687         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2688             isType = true;
2689         } else {
2690             lexer_->Rewind(savedPos);
2691         }
2692     }
2693 
2694     switch (lexer_->GetToken().Type()) {
2695         case lexer::TokenType::KEYW_DEFAULT: { // export default Id
2696             return ParseExportDefaultDeclaration(startLoc, std::move(decorators));
2697         }
2698         case lexer::TokenType::PUNCTUATOR_MULTIPLY: { // export * ...
2699             return ParseExportAllDeclaration(startLoc);
2700         }
2701         case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { // export { ... } ...
2702             return ParseExportNamedSpecifiers(startLoc, isType);
2703         }
2704         case lexer::TokenType::KEYW_IMPORT: {
2705             return ParseTsImportEqualsDeclaration(startLoc, true);
2706         }
2707         case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: {
2708             if (Extension() == ScriptExtension::TS) {
2709                 return ParseExportDefaultDeclaration(startLoc, std::move(decorators), true);
2710             }
2711 
2712             [[fallthrough]];
2713         }
2714         case lexer::TokenType::LITERAL_IDENT: {
2715             if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
2716                 return ParseTsNamespaceExportDeclaration(startLoc);
2717             }
2718 
2719             [[fallthrough]];
2720         }
2721         default: { // export [var] id
2722             ir::ExportNamedDeclaration *exportDecl = ParseNamedExportDeclaration(startLoc, std::move(decorators));
2723 
2724             if (Extension() == ScriptExtension::TS && exportDecl->Decl()->IsVariableDeclaration() &&
2725                 !(flags & StatementParsingFlags::GLOBAL) && exportDecl->Parent() &&
2726                 !exportDecl->Parent()->IsTSModuleBlock() && !context_.IsModule()) {
2727                 ThrowSyntaxError("Modifiers cannot appear here'");
2728             }
2729 
2730             return exportDecl;
2731         }
2732     }
2733 }
2734 
ParseNameSpaceImport(ArenaVector<ir::AstNode * > * specifiers,bool isType)2735 void ParserImpl::ParseNameSpaceImport(ArenaVector<ir::AstNode *> *specifiers, bool isType)
2736 {
2737     lexer::SourcePosition namespaceStart = lexer_->GetToken().Start();
2738     lexer_->NextToken();  // eat `*` character
2739 
2740     if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_AS) {
2741         ThrowSyntaxError("Unexpected token.");
2742     }
2743 
2744     lexer_->NextToken();  // eat `as` literal
2745 
2746     ir::Identifier *local = ParseNamedImport(lexer_->GetToken());
2747 
2748     auto *specifier = AllocNode<ir::ImportNamespaceSpecifier>(local);
2749     specifier->SetRange({namespaceStart, lexer_->GetToken().End()});
2750     specifiers->push_back(specifier);
2751 
2752     binder::Decl *decl = AddImportDecl(isType, local->Name(), namespaceStart,
2753         binder::DeclarationFlags::NAMESPACE_IMPORT);
2754     decl->BindNode(specifier);
2755 
2756     lexer_->NextToken();  // eat local name
2757 }
2758 
AddImportDecl(bool isType,util::StringView name,lexer::SourcePosition startPos,binder::DeclarationFlags flag)2759 binder::Decl *ParserImpl::AddImportDecl(bool isType,
2760                                         util::StringView name,
2761                                         lexer::SourcePosition startPos,
2762                                         binder::DeclarationFlags flag)
2763 {
2764     if (isType) {
2765         binder::TSBinding tsBinding(Allocator(), name);
2766         return Binder()->AddTsDecl<binder::TypeAliasDecl>(startPos, flag, false, tsBinding.View());
2767     }
2768     return Binder()->AddDecl<binder::ConstDecl>(startPos, flag, false, name);
2769 }
2770 
ParseNamedImport(const lexer::Token & importedToken)2771 ir::Identifier *ParserImpl::ParseNamedImport(const lexer::Token &importedToken)
2772 {
2773     if (importedToken.Type() != lexer::TokenType::LITERAL_IDENT) {
2774         ThrowSyntaxError("Unexpected token");
2775     }
2776 
2777     switch (importedToken.KeywordType()) {
2778         case lexer::TokenType::KEYW_EVAL: {
2779             ThrowSyntaxError("Binding 'eval' in strict mode is invalid");
2780         }
2781         case lexer::TokenType::KEYW_ARGUMENTS: {
2782             ThrowSyntaxError("Binding 'arguments' in strict mode is invalid");
2783         }
2784         default: {
2785             break;
2786         }
2787     }
2788 
2789     auto *local = AllocNode<ir::Identifier>(importedToken.Ident());
2790     local->SetRange(importedToken.Loc());
2791 
2792     return local;
2793 }
2794 
ParseNamedImportSpecifiers(ArenaVector<ir::AstNode * > * specifiers,bool isType)2795 void ParserImpl::ParseNamedImportSpecifiers(ArenaVector<ir::AstNode *> *specifiers, bool isType)
2796 {
2797     lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat `{` character
2798 
2799     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
2800         if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2801             ThrowSyntaxError("Unexpected token");
2802         }
2803 
2804         lexer::Token importedToken = lexer_->GetToken();
2805         auto *imported = AllocNode<ir::Identifier>(importedToken.Ident());
2806         ir::Identifier *local = nullptr;
2807         imported->SetRange(lexer_->GetToken().Loc());
2808 
2809         lexer_->NextToken();  // eat import name
2810 
2811         if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
2812             lexer_->NextToken();  // eat `as` literal
2813             local = ParseNamedImport(lexer_->GetToken());
2814             lexer_->NextToken();  // eat local name
2815         } else {
2816             local = ParseNamedImport(importedToken);
2817         }
2818 
2819         auto *specifier = AllocNode<ir::ImportSpecifier>(imported, local);
2820         specifier->SetRange({imported->Start(), local->End()});
2821         specifiers->push_back(specifier);
2822 
2823         binder::Decl *decl = AddImportDecl(isType, local->Name(), local->Start(), binder::DeclarationFlags::IMPORT);
2824         decl->BindNode(specifier);
2825 
2826         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2827             lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);  // eat comma
2828         }
2829     }
2830 
2831     lexer_->NextToken();  // eat right brace
2832 }
2833 
ParseModuleReference()2834 ir::Expression *ParserImpl::ParseModuleReference()
2835 {
2836     ir::Expression *result = nullptr;
2837 
2838     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2839         lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_REQUIRE &&
2840         lexer_->Lookahead() == LEX_CHAR_LEFT_PAREN) {
2841         lexer::SourcePosition start = lexer_->GetToken().Start();
2842         lexer_->NextToken();  // eat 'require'
2843         lexer_->NextToken();  // eat '('
2844 
2845         if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
2846             ThrowSyntaxError("String literal expected.");
2847         }
2848 
2849         result = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
2850         result->SetRange(lexer_->GetToken().Loc());
2851         lexer_->NextToken();
2852 
2853         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
2854             ThrowSyntaxError("')' expected.");
2855         }
2856 
2857         result = AllocNode<ir::TSExternalModuleReference>(result);
2858         result->SetRange({start, lexer_->GetToken().End()});
2859         lexer_->NextToken();  // eat ')'
2860     } else {
2861         result = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
2862         result->SetRange(lexer_->GetToken().Loc());
2863         lexer_->NextToken();
2864 
2865         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
2866             result = ParseTsQualifiedReference(result);
2867         }
2868     }
2869 
2870     return result;
2871 }
2872 
ParseImportDefaultSpecifier(ArenaVector<ir::AstNode * > * specifiers,bool isType)2873 ir::AstNode *ParserImpl::ParseImportDefaultSpecifier(ArenaVector<ir::AstNode *> *specifiers, bool isType)
2874 {
2875     ir::Identifier *local = ParseNamedImport(lexer_->GetToken());
2876     lexer_->NextToken();  // eat local name
2877 
2878     if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
2879         lexer_->NextToken();  // eat substitution
2880         if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2881             ThrowSyntaxError("identifier expected");
2882         }
2883         if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_REQUIRE ||
2884             lexer_->Lookahead() != LEX_CHAR_LEFT_PAREN) {
2885             auto *decl = Binder()->AddDecl<binder::ImportEqualsDecl>(local->Start(), binder::DeclarationFlags::NONE,
2886                                                                      false, local->Name());
2887             decl->BindNode(local);
2888             auto *scope = Binder()->GetScope();
2889             auto *var = scope->FindLocalTSVariable<binder::TSBindingType::IMPORT_EQUALS>(local->Name());
2890             ASSERT(var != nullptr);
2891             var->AsImportEqualsVariable()->SetScope(scope);
2892         }
2893 
2894         auto *importEqualsDecl = AllocNode<ir::TSImportEqualsDeclaration>(local, ParseModuleReference(), false);
2895 
2896         return importEqualsDecl;
2897     }
2898 
2899     auto *specifier = AllocNode<ir::ImportDefaultSpecifier>(local);
2900     specifier->SetRange(specifier->Local()->Range());
2901     specifiers->push_back(specifier);
2902 
2903     binder::Decl *decl = AddImportDecl(isType, local->Name(), local->Start(), binder::DeclarationFlags::IMPORT);
2904     decl->BindNode(specifier);
2905 
2906     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2907         lexer_->NextToken();  // eat comma
2908     }
2909 
2910     return nullptr;
2911 }
2912 
ParseFromClause(bool requireFrom)2913 ir::StringLiteral *ParserImpl::ParseFromClause(bool requireFrom)
2914 {
2915     if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) {
2916         if (requireFrom) {
2917             ThrowSyntaxError("Unexpected token.");
2918         }
2919     } else {
2920         lexer_->NextToken();  // eat `from` literal
2921     }
2922 
2923     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
2924         ThrowSyntaxError("Unexpected token.");
2925     }
2926 
2927     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
2928 
2929     auto *source = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
2930     source->SetRange(lexer_->GetToken().Loc());
2931 
2932     lexer_->NextToken();
2933 
2934     return source;
2935 }
2936 
ParseImportSpecifiers(ArenaVector<ir::AstNode * > * specifiers,bool isType)2937 ir::AstNode *ParserImpl::ParseImportSpecifiers(ArenaVector<ir::AstNode *> *specifiers, bool isType)
2938 {
2939     ASSERT(specifiers->empty());
2940 
2941     // import [default] from 'source'
2942     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
2943         ir::AstNode *astNode = ParseImportDefaultSpecifier(specifiers, isType);
2944         if (astNode != nullptr) {
2945             return astNode;
2946         }
2947     }
2948 
2949     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
2950         ParseNameSpaceImport(specifiers, isType);
2951     } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2952         ParseNamedImportSpecifiers(specifiers, isType);
2953     }
2954     return nullptr;
2955 }
2956 
ParseImportDeclaration(StatementParsingFlags flags)2957 ir::Statement *ParserImpl::ParseImportDeclaration(StatementParsingFlags flags)
2958 {
2959     char32_t nextChar = lexer_->Lookahead();
2960     // dynamic import || import.meta
2961     if (nextChar == LEX_CHAR_LEFT_PAREN || nextChar == LEX_CHAR_DOT) {
2962         return ParseExpressionStatement();
2963     }
2964 
2965     if (Extension() == ScriptExtension::JS) {
2966         if (!(flags & StatementParsingFlags::GLOBAL)) {
2967             ThrowSyntaxError("'import' and 'export' may only appear at the top level");
2968         }
2969 
2970         if (!context_.IsModule()) {
2971             ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'");
2972         }
2973     }
2974 
2975     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2976     lexer_->NextToken();  // eat import
2977 
2978     bool isType = false;
2979     if (Extension() == ScriptExtension::TS &&
2980         lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE) {
2981         const auto savedPos = lexer_->Save();
2982         lexer_->NextToken();  // eat type
2983         if ((lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2984             lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) ||
2985             lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE ||
2986             lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
2987             isType = true;
2988         } else {
2989             lexer_->Rewind(savedPos);
2990         }
2991     }
2992 
2993     ArenaVector<ir::AstNode *> specifiers(Allocator()->Adapter());
2994 
2995     ir::StringLiteral *source = nullptr;
2996 
2997     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
2998         ir::AstNode *astNode = ParseImportSpecifiers(&specifiers, isType);
2999         if (astNode != nullptr) {
3000             ASSERT(astNode->IsTSImportEqualsDeclaration());
3001             astNode->SetRange({startLoc, lexer_->GetToken().End()});
3002             ConsumeSemicolon(astNode->AsTSImportEqualsDeclaration());
3003             return astNode->AsTSImportEqualsDeclaration();
3004         }
3005         if (Extension() == ScriptExtension::TS && !context_.IsModule()) {
3006             ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'");
3007         }
3008         source = ParseFromClause(true);
3009         AddImportEntryItem(source, &specifiers, isType);
3010     } else {
3011         if (Extension() == ScriptExtension::TS && !context_.IsModule()) {
3012             ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'");
3013         }
3014         // import 'source'
3015         source = ParseFromClause(false);
3016         AddImportEntryItem(source, nullptr, isType);
3017     }
3018 
3019     lexer::SourcePosition endLoc = source->End();
3020     auto *importDeclaration = AllocNode<ir::ImportDeclaration>(source, std::move(specifiers), isType);
3021     importDeclaration->SetRange({startLoc, endLoc});
3022 
3023     ConsumeSemicolon(importDeclaration);
3024 
3025     return importDeclaration;
3026 }
3027 
3028 }  // namespace panda::es2panda::parser
3029