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