• 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 "parser/parserFlags.h"
17 #include "util/helpers.h"
18 #include "varbinder/tsBinding.h"
19 #include "ir/astNode.h"
20 #include "ir/base/catchClause.h"
21 #include "ir/base/classDefinition.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/assertStatement.h"
40 #include "ir/statements/blockStatement.h"
41 #include "ir/statements/breakStatement.h"
42 #include "ir/statements/classDeclaration.h"
43 #include "ir/statements/continueStatement.h"
44 #include "ir/statements/debuggerStatement.h"
45 #include "ir/statements/doWhileStatement.h"
46 #include "ir/statements/emptyStatement.h"
47 #include "ir/statements/expressionStatement.h"
48 #include "ir/statements/forInStatement.h"
49 #include "ir/statements/forOfStatement.h"
50 #include "ir/statements/forUpdateStatement.h"
51 #include "ir/statements/functionDeclaration.h"
52 #include "ir/statements/ifStatement.h"
53 #include "ir/statements/labelledStatement.h"
54 #include "ir/statements/returnStatement.h"
55 #include "ir/statements/switchCaseStatement.h"
56 #include "ir/statements/switchStatement.h"
57 #include "ir/statements/throwStatement.h"
58 #include "ir/statements/tryStatement.h"
59 #include "ir/statements/variableDeclaration.h"
60 #include "ir/statements/variableDeclarator.h"
61 #include "ir/statements/whileStatement.h"
62 #include "ir/ets/etsStructDeclaration.h"
63 #include "lexer/keywordsBase.h"
64 #include "lexer/lexer.h"
65 #include "lexer/token/letters.h"
66 #include "lexer/token/sourceLocation.h"
67 #include "util/ustring.h"
68 
69 #include <tuple>
70 
71 #include "parserImpl.h"
72 
73 namespace panda::es2panda::parser {
74 
75 using namespace std::literals::string_literals;
76 
77 // NOLINTNEXTLINE(google-default-arguments)
ParseStatement(StatementParsingFlags flags)78 ir::Statement *ParserImpl::ParseStatement(StatementParsingFlags flags)
79 {
80     switch (lexer_->GetToken().Type()) {
81         case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
82             return ParseBlockStatement();
83         }
84         case lexer::TokenType::PUNCTUATOR_SEMI_COLON: {
85             return ParseEmptyStatement();
86         }
87         case lexer::TokenType::KEYW_ASSERT: {
88             return ParseAssertStatement();
89         }
90         case lexer::TokenType::KEYW_EXPORT: {
91             return ParseExportDeclaration(flags);
92         }
93         case lexer::TokenType::KEYW_IMPORT: {
94             return ParseImportDeclaration(flags);
95         }
96         case lexer::TokenType::KEYW_FUNCTION: {
97             return ParseFunctionStatement(flags);
98         }
99         case lexer::TokenType::KEYW_CLASS: {
100             return ParseClassStatement(flags, ir::ClassDefinitionModifiers::NONE);
101         }
102         case lexer::TokenType::KEYW_VAR: {
103             return ParseVarStatement();
104         }
105         case lexer::TokenType::KEYW_LET: {
106             return ParseLetStatement(flags);
107         }
108         case lexer::TokenType::KEYW_CONST: {
109             return ParseConstStatement(flags);
110         }
111         case lexer::TokenType::KEYW_IF: {
112             return ParseIfStatement();
113         }
114         case lexer::TokenType::KEYW_DO: {
115             return ParseDoWhileStatement();
116         }
117         case lexer::TokenType::KEYW_FOR: {
118             return ParseForStatement();
119         }
120         case lexer::TokenType::KEYW_TRY: {
121             return ParseTryStatement();
122         }
123         case lexer::TokenType::KEYW_WHILE: {
124             return ParseWhileStatement();
125         }
126         case lexer::TokenType::KEYW_BREAK: {
127             return ParseBreakStatement();
128         }
129         case lexer::TokenType::KEYW_CONTINUE: {
130             return ParseContinueStatement();
131         }
132         case lexer::TokenType::KEYW_THROW: {
133             return ParseThrowStatement();
134         }
135         case lexer::TokenType::KEYW_RETURN: {
136             return ParseReturnStatement();
137         }
138         case lexer::TokenType::KEYW_SWITCH: {
139             return ParseSwitchStatement();
140         }
141         case lexer::TokenType::KEYW_DEBUGGER: {
142             return ParseDebuggerStatement();
143         }
144         case lexer::TokenType::LITERAL_IDENT: {
145             if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STRUCT) {
146                 return ParseStructStatement(flags, ir::ClassDefinitionModifiers::NONE);
147             }
148 
149             if (lexer_->Lookahead() == lexer::LEX_CHAR_COLON) {
150                 const auto pos = lexer_->Save();
151                 lexer_->NextToken();
152                 return ParseLabelledStatement(pos);
153             }
154 
155             return ParsePotentialExpressionStatement(flags);
156         }
157         case lexer::TokenType::KEYW_WITH: {
158             ThrowSyntaxError("'With' is deprecated and not supported any more.");
159         }
160         case lexer::TokenType::KEYW_ENUM: {
161             return ParseEnumDeclaration();
162         }
163         case lexer::TokenType::KEYW_INTERFACE: {
164             return ParseInterfaceDeclaration(false);
165         }
166         default: {
167             return ParseExpressionStatement(flags);
168         }
169     }
170 }
171 
ParseVarStatement()172 ir::Statement *ParserImpl::ParseVarStatement()
173 {
174     auto *variableDecl = ParseVariableDeclaration(VariableParsingFlags::VAR);
175     ConsumeSemicolon(variableDecl);
176     return variableDecl;
177 }
178 
ParseLetStatement(StatementParsingFlags flags)179 ir::Statement *ParserImpl::ParseLetStatement(StatementParsingFlags flags)
180 {
181     if ((flags & StatementParsingFlags::ALLOW_LEXICAL) == 0) {
182         ThrowSyntaxError("Lexical declaration is not allowed in single statement context");
183     }
184 
185     auto *variableDecl = ParseVariableDeclaration(VariableParsingFlags::LET);
186     ConsumeSemicolon(variableDecl);
187     return variableDecl;
188 }
189 
ParseConstStatement(StatementParsingFlags flags)190 ir::Statement *ParserImpl::ParseConstStatement(StatementParsingFlags flags)
191 {
192     if ((flags & StatementParsingFlags::ALLOW_LEXICAL) == 0) {
193         ThrowSyntaxError("Lexical declaration is not allowed in single statement context");
194     }
195 
196     lexer::SourcePosition constVarStar = lexer_->GetToken().Start();
197     lexer_->NextToken();
198 
199     auto *variableDecl = ParseVariableDeclaration(VariableParsingFlags::CONST | VariableParsingFlags::NO_SKIP_VAR_KIND);
200     variableDecl->SetStart(constVarStar);
201     ConsumeSemicolon(variableDecl);
202 
203     return variableDecl;
204 }
205 
ParseEmptyStatement()206 ir::EmptyStatement *ParserImpl::ParseEmptyStatement()
207 {
208     auto *empty = AllocNode<ir::EmptyStatement>();
209     empty->SetRange(lexer_->GetToken().Loc());
210     lexer_->NextToken();
211     return empty;
212 }
213 
ParseDebuggerStatement()214 ir::DebuggerStatement *ParserImpl::ParseDebuggerStatement()
215 {
216     auto *debuggerNode = AllocNode<ir::DebuggerStatement>();
217     debuggerNode->SetRange(lexer_->GetToken().Loc());
218     lexer_->NextToken();
219     ConsumeSemicolon(debuggerNode);
220     return debuggerNode;
221 }
222 
ParseFunctionStatement(StatementParsingFlags flags)223 ir::Statement *ParserImpl::ParseFunctionStatement(StatementParsingFlags flags)
224 {
225     CheckFunctionDeclaration(flags);
226 
227     if ((flags & StatementParsingFlags::STMT_LEXICAL_SCOPE_NEEDED) == 0) {
228         return ParseFunctionDeclaration(false, ParserStatus::NO_OPTS);
229     }
230 
231     ArenaVector<ir::Statement *> stmts(Allocator()->Adapter());
232     auto *funcDecl = ParseFunctionDeclaration(false, ParserStatus::NO_OPTS);
233     stmts.push_back(funcDecl);
234 
235     auto *localBlockStmt = AllocNode<ir::BlockStatement>(Allocator(), std::move(stmts));
236     localBlockStmt->SetRange(funcDecl->Range());
237 
238     return funcDecl;
239 }
240 
ParsePotentialExpressionStatement(StatementParsingFlags flags)241 ir::Statement *ParserImpl::ParsePotentialExpressionStatement(StatementParsingFlags flags)
242 {
243     return ParseExpressionStatement(flags);
244 }
245 
246 // NOLINTNEXTLINE(google-default-arguments)
ParseStructStatement(StatementParsingFlags flags,ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags modFlags)247 ir::ETSStructDeclaration *ParserImpl::ParseStructStatement([[maybe_unused]] StatementParsingFlags flags,
248                                                            [[maybe_unused]] ir::ClassDefinitionModifiers modifiers,
249                                                            [[maybe_unused]] ir::ModifierFlags modFlags)
250 {
251     ThrowSyntaxError("Illegal start of expression", Lexer()->GetToken().Start());
252 }
253 
254 // NOLINTNEXTLINE(google-default-arguments)
ParseClassStatement(StatementParsingFlags flags,ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags modFlags)255 ir::ClassDeclaration *ParserImpl::ParseClassStatement(StatementParsingFlags flags,
256                                                       ir::ClassDefinitionModifiers modifiers,
257                                                       ir::ModifierFlags modFlags)
258 {
259     if ((flags & StatementParsingFlags::ALLOW_LEXICAL) == 0) {
260         ThrowSyntaxError("Lexical declaration is not allowed in single statement context");
261     }
262 
263     return ParseClassDeclaration(modifiers, modFlags);
264 }
265 
ParseStructDeclaration(ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)266 ir::ETSStructDeclaration *ParserImpl::ParseStructDeclaration(ir::ClassDefinitionModifiers modifiers,
267                                                              ir::ModifierFlags flags)
268 {
269     const lexer::SourcePosition startLoc = lexer_->GetToken().Start();
270     modifiers |= ir::ClassDefinitionModifiers::DECLARATION;
271     if ((GetContext().Status() & ParserStatus::IN_EXTERNAL) != 0) {
272         modifiers |= ir::ClassDefinitionModifiers::FROM_EXTERNAL;
273     }
274 
275     if ((flags & ir::ModifierFlags::ABSTRACT) != 0U) {
276         ThrowSyntaxError("struct declaration is not allowed to use 'abstract' modifiers.");
277     }
278 
279     ir::ClassDefinition *classDefinition = ParseClassDefinition(modifiers, flags);
280 
281     if ((classDefinition->Modifiers() & ir::ClassDefinitionModifiers::HAS_SUPER) != 0U) {
282         ThrowSyntaxError("struct declaration cannot extends form other class");
283     }
284 
285     lexer::SourcePosition endLoc = classDefinition->End();
286     auto *structDecl = AllocNode<ir::ETSStructDeclaration>(classDefinition, Allocator());
287     structDecl->SetRange({startLoc, endLoc});
288     return structDecl;
289 }
290 
ParseClassDeclaration(ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)291 ir::ClassDeclaration *ParserImpl::ParseClassDeclaration(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags)
292 {
293     const lexer::SourcePosition startLoc = lexer_->GetToken().Start();
294     modifiers |= ir::ClassDefinitionModifiers::DECLARATION;
295     if ((GetContext().Status() & ParserStatus::IN_EXTERNAL) != 0) {
296         modifiers |= ir::ClassDefinitionModifiers::FROM_EXTERNAL;
297     }
298 
299     ir::ClassDefinition *classDefinition = ParseClassDefinition(modifiers, flags);
300 
301     lexer::SourcePosition endLoc = classDefinition->End();
302     auto *classDecl = AllocNode<ir::ClassDeclaration>(classDefinition, Allocator());
303     classDecl->SetRange({startLoc, endLoc});
304     return classDecl;
305 }
306 
CheckFunctionDeclaration(StatementParsingFlags flags)307 void ParserImpl::CheckFunctionDeclaration(StatementParsingFlags flags)
308 {
309     if ((flags & StatementParsingFlags::LABELLED) != 0) {
310         ThrowSyntaxError(
311             "In strict mode code, functions can only be "
312             "declared at top level, inside a block, "
313             "or "
314             "as the body of an if statement");
315     }
316 
317     if ((flags & StatementParsingFlags::ALLOW_LEXICAL) == 0) {
318         if ((flags & (StatementParsingFlags::IF_ELSE | StatementParsingFlags::LABELLED)) == 0) {
319             ThrowSyntaxError("Lexical declaration is not allowed in single statement context");
320         }
321 
322         if (lexer_->Lookahead() == lexer::LEX_CHAR_ASTERISK) {
323             ThrowSyntaxError("Generators can only be declared at the top level or inside a block");
324         }
325     }
326 }
327 
ConsumeSemicolon(ir::Statement * statement)328 void ParserImpl::ConsumeSemicolon(ir::Statement *statement)
329 {
330     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
331         statement->SetEnd(lexer_->GetToken().End());
332         lexer_->NextToken();
333         return;
334     }
335 
336     if (!lexer_->GetToken().NewLine()) {
337         if (lexer_->GetToken().Type() != lexer::TokenType::EOS &&
338             lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
339             ThrowSyntaxError("Unexpected token");
340         }
341     }
342 }
343 
ParseStatementList(StatementParsingFlags flags)344 ArenaVector<ir::Statement *> ParserImpl::ParseStatementList(StatementParsingFlags flags)
345 {
346     ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
347     ParseDirectivePrologue(&statements);
348 
349     auto endType =
350         (flags & StatementParsingFlags::GLOBAL) != 0 ? lexer::TokenType::EOS : lexer::TokenType::PUNCTUATOR_RIGHT_BRACE;
351 
352     while (lexer_->GetToken().Type() != endType) {
353         statements.push_back(ParseStatement(flags));
354     }
355 
356     return statements;
357 }
358 
ParseDirective(ArenaVector<ir::Statement * > * statements)359 bool ParserImpl::ParseDirective(ArenaVector<ir::Statement *> *statements)
360 {
361     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
362 
363     const util::StringView &str = lexer_->GetToken().String();
364 
365     const auto status = static_cast<ParserStatus>(
366         context_.Status() & (ParserStatus::CONSTRUCTOR_FUNCTION | ParserStatus::HAS_COMPLEX_PARAM));
367     if (status == ParserStatus::HAS_COMPLEX_PARAM && str.Is("use strict")) {
368         ThrowSyntaxError(
369             "Illegal 'use strict' directive in function with "
370             "non-simple parameter list");
371     }
372 
373     ir::Expression *exprNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
374     bool isDirective = exprNode->IsStringLiteral();
375 
376     auto *exprStatement = AllocNode<ir::ExpressionStatement>(exprNode);
377     exprStatement->SetRange(exprNode->Range());
378 
379     ConsumeSemicolon(exprStatement);
380     statements->push_back(exprStatement);
381 
382     return isDirective;
383 }
384 
ParseDirectivePrologue(ArenaVector<ir::Statement * > * statements)385 void ParserImpl::ParseDirectivePrologue(ArenaVector<ir::Statement *> *statements)
386 {
387     while (true) {
388         if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING || !ParseDirective(statements)) {
389             break;
390         }
391     }
392 }
393 
ParseAssertStatement()394 ir::Statement *ParserImpl::ParseAssertStatement()
395 {
396     return nullptr;
397 }
398 
ValidateLabeledStatement(lexer::TokenType type)399 void ParserImpl::ValidateLabeledStatement([[maybe_unused]] lexer::TokenType type) {}
400 
ParseBlockStatement()401 ir::BlockStatement *ParserImpl::ParseBlockStatement()
402 {
403     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
404 
405     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
406     lexer_->NextToken();
407     auto statements = ParseStatementList();
408 
409     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
410         ThrowSyntaxError("Expected a '}'");
411     }
412 
413     auto *blockNode = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
414     blockNode->SetRange({startLoc, lexer_->GetToken().End()});
415 
416     lexer_->NextToken();
417     return blockNode;
418 }
419 
ThrowPossibleOutOfBoundaryJumpError(bool allowBreak)420 void ParserImpl::ThrowPossibleOutOfBoundaryJumpError([[maybe_unused]] bool allowBreak) {}
421 
ThrowIllegalBreakError()422 void ParserImpl::ThrowIllegalBreakError()
423 {
424     ThrowSyntaxError("Illegal break statement");
425 }
426 
ParseBreakStatement()427 ir::BreakStatement *ParserImpl::ParseBreakStatement()
428 {
429     bool allowBreak = (context_.Status() & (ParserStatus::IN_ITERATION | ParserStatus::IN_SWITCH)) != 0;
430 
431     ThrowPossibleOutOfBoundaryJumpError(allowBreak);
432 
433     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
434     lexer_->NextToken();
435 
436     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON ||
437         lexer_->GetToken().Type() == lexer::TokenType::EOS || lexer_->GetToken().NewLine() ||
438         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
439         if (!allowBreak) {
440             ThrowIllegalBreakError();
441         }
442 
443         auto *breakStatement = AllocNode<ir::BreakStatement>();
444         breakStatement->SetRange({startLoc, lexer_->GetToken().End()});
445 
446         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
447             lexer_->NextToken();
448         }
449 
450         return breakStatement;
451     }
452 
453     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
454         ThrowSyntaxError("Unexpected token.");
455     }
456 
457     const auto &label = lexer_->GetToken().Ident();
458 
459     if (context_.FindLabel(label) == nullptr) {
460         ThrowSyntaxError("Undefined label");
461     }
462 
463     auto *identNode = AllocNode<ir::Identifier>(label, Allocator());
464     identNode->SetRange(lexer_->GetToken().Loc());
465 
466     auto *breakStatement = AllocNode<ir::BreakStatement>(identNode);
467     breakStatement->SetRange({startLoc, lexer_->GetToken().End()});
468 
469     lexer_->NextToken();
470     ConsumeSemicolon(breakStatement);
471 
472     return breakStatement;
473 }
474 
ThrowIllegalContinueError()475 void ParserImpl::ThrowIllegalContinueError()
476 {
477     ThrowSyntaxError("Illegal continue statement");
478 }
479 
ParseContinueStatement()480 ir::ContinueStatement *ParserImpl::ParseContinueStatement()
481 {
482     ThrowPossibleOutOfBoundaryJumpError((context_.Status() & (ParserStatus::IN_ITERATION | ParserStatus::IN_SWITCH)) !=
483                                         0U);
484 
485     if ((context_.Status() & ParserStatus::IN_ITERATION) == 0) {
486         ThrowIllegalContinueError();
487     }
488 
489     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
490     lexer::SourcePosition endLoc = lexer_->GetToken().End();
491     lexer_->NextToken();
492 
493     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
494         auto *continueStatement = AllocNode<ir::ContinueStatement>();
495         continueStatement->SetRange({startLoc, lexer_->GetToken().End()});
496         lexer_->NextToken();
497         return continueStatement;
498     }
499 
500     if (lexer_->GetToken().NewLine() || lexer_->GetToken().Type() == lexer::TokenType::EOS ||
501         lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
502         auto *continueStatement = AllocNode<ir::ContinueStatement>();
503         continueStatement->SetRange({startLoc, endLoc});
504         return continueStatement;
505     }
506 
507     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
508         ThrowSyntaxError("Unexpected token.");
509     }
510 
511     const auto &label = lexer_->GetToken().Ident();
512     const ParserContext *labelCtx = context_.FindLabel(label);
513 
514     if (labelCtx == nullptr || (labelCtx->Status() & ParserStatus::IN_ITERATION) == 0) {
515         ThrowSyntaxError("Undefined label");
516     }
517 
518     auto *identNode = AllocNode<ir::Identifier>(label, Allocator());
519     identNode->SetRange(lexer_->GetToken().Loc());
520 
521     auto *continueStatement = AllocNode<ir::ContinueStatement>(identNode);
522     continueStatement->SetRange({startLoc, lexer_->GetToken().End()});
523 
524     lexer_->NextToken();
525     ConsumeSemicolon(continueStatement);
526 
527     return continueStatement;
528 }
529 
ParseDoWhileStatement()530 ir::DoWhileStatement *ParserImpl::ParseDoWhileStatement()
531 {
532     IterationContext iterCtx(&context_);
533 
534     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
535     lexer_->NextToken();
536     ir::Statement *body = ParseStatement();
537 
538     if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_WHILE) {
539         ThrowSyntaxError("Missing 'while' keyword in a 'DoWhileStatement'");
540     }
541 
542     lexer_->NextToken();
543     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
544         ThrowSyntaxError("Missing left parenthesis in a 'DoWhileStatement'");
545     }
546 
547     lexer_->NextToken();
548 
549     ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
550 
551     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
552         ThrowSyntaxError("Missing right parenthesis in a 'DoWhileStatement'");
553     }
554 
555     auto *doWhileStatement = AllocNode<ir::DoWhileStatement>(body, test);
556     doWhileStatement->SetRange({startLoc, lexer_->GetToken().End()});
557 
558     lexer_->NextToken();
559 
560     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
561         doWhileStatement->SetEnd(lexer_->GetToken().End());
562         lexer_->NextToken();
563     }
564 
565     return doWhileStatement;
566 }
567 
ParseFunctionDeclaration(bool canBeAnonymous,ParserStatus newStatus)568 ir::FunctionDeclaration *ParserImpl::ParseFunctionDeclaration(bool canBeAnonymous, ParserStatus newStatus)
569 {
570     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
571 
572     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION);
573     ParserStatus savedStatus = context_.Status();
574 
575     lexer_->NextToken();
576 
577     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
578         newStatus |= ParserStatus::GENERATOR_FUNCTION;
579         lexer_->NextToken();
580     }
581 
582     context_.Status() = savedStatus;
583 
584     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
585         if (canBeAnonymous) {
586             ir::ScriptFunction *func = ParseFunction(newStatus | ParserStatus::NEED_RETURN_TYPE);
587             func->SetStart(startLoc);
588 
589             auto *funcDecl = AllocNode<ir::FunctionDeclaration>(Allocator(), func, true);
590             funcDecl->SetRange(func->Range());
591             return funcDecl;
592         }
593 
594         ThrowSyntaxError("Unexpected token, expected identifier after 'function' keyword");
595     }
596 
597     CheckRestrictedBinding();
598     auto *identNode = ExpectIdentifier();
599 
600     newStatus |= ParserStatus::FUNCTION_DECLARATION;
601     ir::ScriptFunction *func = ParseFunction(newStatus | ParserStatus::NEED_RETURN_TYPE);
602 
603     func->SetIdent(identNode);
604     func->SetStart(startLoc);
605     auto *funcDecl = AllocNode<ir::FunctionDeclaration>(Allocator(), func);
606     funcDecl->SetRange(func->Range());
607 
608     if (func->IsOverload() && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
609         lexer_->NextToken();
610     }
611 
612     return funcDecl;
613 }
614 
ParseExpressionStatement(StatementParsingFlags flags)615 ir::Statement *ParserImpl::ParseExpressionStatement(StatementParsingFlags flags)
616 {
617     const auto startPos = lexer_->Save();
618     ParserStatus savedStatus = context_.Status();
619 
620     if (lexer_->GetToken().IsAsyncModifier()) {
621         lexer_->NextToken();
622 
623         if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION && !lexer_->GetToken().NewLine()) {
624             if ((flags & StatementParsingFlags::ALLOW_LEXICAL) == 0) {
625                 ThrowSyntaxError("Lexical declaration is not allowed in single statement context");
626             }
627 
628             ir::FunctionDeclaration *functionDecl = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION);
629             functionDecl->SetStart(startPos.GetToken().Start());
630 
631             return functionDecl;
632         }
633 
634         lexer_->Rewind(startPos);
635     }
636 
637     ir::Expression *exprNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
638     context_.Status() = savedStatus;
639     lexer::SourcePosition endPos = exprNode->End();
640 
641     auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(exprNode);
642     exprStatementNode->SetRange({startPos.GetToken().Start(), endPos});
643     ConsumeSemicolon(exprStatementNode);
644 
645     return exprStatementNode;
646 }
647 
648 // NOLINTBEGIN(cert-err58-cpp)
649 static std::string const INVALID_LEFT_HAND_IN_FOR_OF =
650     "Invalid left-hand side in 'for' statement: must have a single binding."s;
651 static std::string const UNEXPECTED_TOKEN = "Unexpected token"s;
652 static std::string const MISSING_LEFT_IN_FOR = "Missing left parenthesis in 'for' statement."s;
653 static std::string const MISSING_RIGHT_IN_FOR = "Missing right parenthesis in 'for' statement."s;
654 static std::string const INVALID_TYPE_ANNOTATION_IN_FOR =
655     "Type annotation is not allowed when existing variable is used as loop iterator in 'for' statement."s;
656 // NOLINTEND(cert-err58-cpp)
657 
ParseForInOf(ir::AstNode * initNode,ExpressionParseFlags exprFlags,bool isAwait)658 std::tuple<ForStatementKind, ir::Expression *, ir::Expression *> ParserImpl::ParseForInOf(
659     ir::AstNode *initNode, ExpressionParseFlags exprFlags, bool isAwait)
660 {
661     ForStatementKind forKind = ForStatementKind::UPDATE;
662     ir::Expression *updateNode = nullptr;
663     ir::Expression *rightNode = nullptr;
664 
665     if (lexer_->GetToken().IsForInOf()) {
666         const ir::VariableDeclarator *varDecl = initNode->AsVariableDeclaration()->Declarators().front();
667 
668         if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN) {
669             if (varDecl->Init() != nullptr) {
670                 ThrowSyntaxError("for-in loop variable declaration may not have an initializer");
671             }
672             forKind = ForStatementKind::IN;
673             exprFlags = ExpressionParseFlags::ACCEPT_COMMA;
674             ValidateForInStatement();
675         } else {
676             if (varDecl->Init() != nullptr) {
677                 ThrowSyntaxError("for-of loop variable declaration may not have an initializer");
678             }
679 
680             forKind = ForStatementKind::OF;
681         }
682 
683         lexer_->NextToken();
684         rightNode = ParseExpression(exprFlags);
685     } else {
686         if (isAwait) {
687             ThrowSyntaxError("Unexpected token");
688         }
689 
690         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
691             ThrowSyntaxError("Invalid left-hand side in 'For[In/Of]Statement'");
692         } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
693             lexer_->NextToken();
694         } else {
695             rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::IN_FOR);
696             if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
697                 ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
698             }
699             lexer_->NextToken();
700         }
701 
702         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
703             updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::IN_FOR);
704         }
705     }
706 
707     return {forKind, rightNode, updateNode};
708 }
709 
ParseForInOf(ir::Expression * leftNode,ExpressionParseFlags exprFlags,bool isAwait)710 std::tuple<ForStatementKind, ir::AstNode *, ir::Expression *, ir::Expression *> ParserImpl::ParseForInOf(
711     ir::Expression *leftNode, ExpressionParseFlags exprFlags, bool isAwait)
712 {
713     ForStatementKind forKind = ForStatementKind::UPDATE;
714     ir::AstNode *initNode = nullptr;
715     ir::Expression *updateNode = nullptr;
716     ir::Expression *rightNode = nullptr;
717 
718     if (lexer_->GetToken().IsForInOf()) {
719         if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN) {
720             forKind = ForStatementKind::IN;
721             exprFlags = ExpressionParseFlags::ACCEPT_COMMA;
722             ValidateForInStatement();
723         } else {
724             forKind = ForStatementKind::OF;
725         }
726 
727         bool isValid = true;
728         switch (leftNode->Type()) {
729             case ir::AstNodeType::IDENTIFIER:
730             case ir::AstNodeType::MEMBER_EXPRESSION: {
731                 break;
732             }
733             case ir::AstNodeType::ARRAY_EXPRESSION: {
734                 isValid = leftNode->AsArrayExpression()->ConvertibleToArrayPattern();
735                 break;
736             }
737             case ir::AstNodeType::OBJECT_EXPRESSION: {
738                 isValid = leftNode->AsObjectExpression()->ConvertibleToObjectPattern();
739                 break;
740             }
741             default: {
742                 isValid = false;
743             }
744         }
745 
746         if (!isValid) {
747             ValidateLvalueAssignmentTarget(leftNode);
748         }
749 
750         initNode = leftNode;
751         lexer_->NextToken();
752         rightNode = ParseExpression(exprFlags);
753 
754         return {forKind, initNode, rightNode, updateNode};
755     }
756 
757     if (isAwait) {
758         ThrowSyntaxError("Unexpected token");
759     }
760 
761     ir::Expression *expr = ParseAssignmentExpression(leftNode);
762 
763     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
764         initNode = ParseSequenceExpression(expr);
765     } else {
766         initNode = expr;
767     }
768 
769     if (initNode->IsConditionalExpression()) {
770         ir::ConditionalExpression *condExpr = initNode->AsConditionalExpression();
771         if (condExpr->Alternate()->IsBinaryExpression()) {
772             const auto *binaryExpr = condExpr->Alternate()->AsBinaryExpression();
773             if (binaryExpr->OperatorType() == lexer::TokenType::KEYW_IN) {
774                 ThrowSyntaxError("Invalid left-hand side in for-in statement");
775             }
776         }
777     }
778 
779     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
780         ThrowSyntaxError("Invalid left-hand side in 'For[In/Of]Statement'");
781     }
782 
783     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
784         ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
785     }
786 
787     lexer_->NextToken();
788 
789     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
790         lexer_->NextToken();
791     } else {
792         rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::IN_FOR);
793 
794         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
795             ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
796         }
797         lexer_->NextToken();
798     }
799 
800     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
801         updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::IN_FOR);
802     }
803 
804     return {forKind, initNode, rightNode, updateNode};
805 }
806 
ParseForUpdate(bool isAwait)807 std::tuple<ir::Expression *, ir::Expression *> ParserImpl::ParseForUpdate(bool isAwait)
808 {
809     if (isAwait) {
810         ThrowSyntaxError("Unexpected token");
811     }
812 
813     ir::Expression *updateNode = nullptr;
814     ir::Expression *rightNode = nullptr;
815 
816     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
817         lexer_->NextToken();
818     } else {
819         rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::IN_FOR);
820         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
821             ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
822         }
823         lexer_->NextToken();
824     }
825 
826     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
827         updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::IN_FOR);
828     }
829 
830     return {rightNode, updateNode};
831 }
832 
ParseForStatement()833 ir::Statement *ParserImpl::ParseForStatement()
834 {
835     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
836     ForStatementKind forKind = ForStatementKind::UPDATE;
837     ir::AstNode *initNode = nullptr;
838     ir::Expression *updateNode = nullptr;
839     ir::Expression *leftNode = nullptr;
840     ir::Expression *rightNode = nullptr;
841     bool canBeForInOf = true;
842     bool isAwait = false;
843     lexer_->NextToken();
844     VariableParsingFlags varFlags = VariableParsingFlags::IN_FOR;
845     ExpressionParseFlags exprFlags = ExpressionParseFlags::NO_OPTS;
846 
847     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) {
848         isAwait = true;
849         varFlags |= VariableParsingFlags::DISALLOW_INIT;
850         lexer_->NextToken();
851     }
852 
853     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
854         ThrowSyntaxError(MISSING_LEFT_IN_FOR, lexer_->GetToken().Start());
855     }
856     lexer_->NextToken();
857 
858     lexer::TokenType tokenType;
859     auto const currentPosition = lexer_->Save();
860     do {
861         tokenType = lexer_->GetToken().Type();
862         if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OF) {
863             varFlags |= VariableParsingFlags::FOR_OF;
864             break;
865         }
866         if (tokenType == lexer::TokenType::KEYW_IN) {
867             varFlags |= VariableParsingFlags::STOP_AT_IN;
868             break;
869         }
870         lexer_->NextToken();
871     } while (tokenType != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS &&
872              tokenType != lexer::TokenType::PUNCTUATOR_LEFT_BRACE &&
873              tokenType != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS && tokenType != lexer::TokenType::EOS);
874     lexer_->Rewind(currentPosition);
875 
876     switch (lexer_->GetToken().Type()) {
877         case lexer::TokenType::KEYW_VAR: {
878             initNode = ParseVariableDeclaration(varFlags | VariableParsingFlags::VAR);
879             break;
880         }
881         case lexer::TokenType::KEYW_LET: {
882             initNode = ParseVariableDeclaration(varFlags | VariableParsingFlags::LET);
883             break;
884         }
885         case lexer::TokenType::KEYW_CONST: {
886             initNode = ParseVariableDeclaration(varFlags | VariableParsingFlags::CONST |
887                                                 VariableParsingFlags::ACCEPT_CONST_NO_INIT);
888             break;
889         }
890         case lexer::TokenType::PUNCTUATOR_SEMI_COLON: {
891             if (isAwait) {
892                 ThrowSyntaxError(UNEXPECTED_TOKEN, lexer_->GetToken().Start());
893             }
894 
895             canBeForInOf = false;
896             lexer_->NextToken();
897             break;
898         }
899         default: {
900             leftNode = ParseUnaryOrPrefixUpdateExpression(ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
901             break;
902         }
903     }
904 
905     IterationContext iterCtx(&context_);
906 
907     if (initNode != nullptr) {
908         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
909             lexer_->NextToken();
910             canBeForInOf = false;
911         } else if (initNode->AsVariableDeclaration()->Declarators().size() > 1 && lexer_->GetToken().IsForInOf()) {
912             ThrowSyntaxError(INVALID_LEFT_HAND_IN_FOR_OF, initNode->AsVariableDeclaration()->Declarators()[1]->Start());
913         }
914     }
915 
916     // VariableDeclaration->DeclarationSize > 1 or seen semi_colon
917     if (!canBeForInOf) {
918         std::tie(rightNode, updateNode) = ParseForUpdate(isAwait);
919     } else if (leftNode != nullptr) {
920         // initNode was parsed as LHS
921         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
922             ThrowSyntaxError(INVALID_TYPE_ANNOTATION_IN_FOR, lexer_->GetToken().Start());
923         }
924         std::tie(forKind, initNode, rightNode, updateNode) = ParseForInOf(leftNode, exprFlags, isAwait);
925     } else if (initNode != nullptr) {
926         // initNode was parsed as VariableDeclaration and declaration size = 1
927         std::tie(forKind, rightNode, updateNode) = ParseForInOf(initNode, exprFlags, isAwait);
928     }
929 
930     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) {
931         lexer_->NextToken();
932     }
933     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
934         ThrowSyntaxError(MISSING_RIGHT_IN_FOR, lexer_->GetToken().Start());
935     }
936     lexer_->NextToken();
937 
938     ir::Statement *bodyNode = ParseStatement();
939     lexer::SourcePosition endLoc = bodyNode->End();
940 
941     ir::Statement *forStatement = nullptr;
942 
943     if (forKind == ForStatementKind::UPDATE) {
944         forStatement = AllocNode<ir::ForUpdateStatement>(initNode, rightNode, updateNode, bodyNode);
945     } else if (forKind == ForStatementKind::IN) {
946         forStatement = AllocNode<ir::ForInStatement>(initNode, rightNode, bodyNode);
947     } else {
948         forStatement = AllocNode<ir::ForOfStatement>(initNode, rightNode, bodyNode, isAwait);
949     }
950 
951     forStatement->SetRange({startLoc, endLoc});
952 
953     return forStatement;
954 }
955 
ThrowIfBodyEmptyError(ir::Statement * consequent)956 void ParserImpl::ThrowIfBodyEmptyError([[maybe_unused]] ir::Statement *consequent) {}
957 
ParseIfStatement()958 ir::IfStatement *ParserImpl::ParseIfStatement()
959 {
960     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
961     lexer::SourcePosition endLoc = lexer_->GetToken().End();
962     lexer_->NextToken();
963 
964     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
965         ThrowSyntaxError("Missing left parenthesis in an 'IfStatement'");
966     }
967 
968     lexer_->NextToken();
969     ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
970 
971     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
972         ThrowSyntaxError("Missing right parenthesis in an 'IfStatement'");
973     }
974 
975     lexer_->NextToken();
976     ir::Statement *consequent = ParseStatement(StatementParsingFlags::IF_ELSE | StatementParsingFlags::ALLOW_LEXICAL);
977 
978     ThrowIfBodyEmptyError(consequent);
979 
980     endLoc = consequent->End();
981     ir::Statement *alternate = nullptr;
982 
983     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_ELSE) {
984         lexer_->NextToken();  // eat ELSE keyword
985         alternate = ParseStatement(StatementParsingFlags::IF_ELSE | StatementParsingFlags::ALLOW_LEXICAL);
986         endLoc = alternate->End();
987     }
988 
989     auto *ifStatement = AllocNode<ir::IfStatement>(test, consequent, alternate);
990     ifStatement->SetRange({startLoc, endLoc});
991     return ifStatement;
992 }
993 
ParseLabelledStatement(const lexer::LexerPosition & pos)994 ir::LabelledStatement *ParserImpl::ParseLabelledStatement(const lexer::LexerPosition &pos)
995 {
996     const util::StringView &actualLabel = pos.GetToken().Ident();
997 
998     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AWAIT && context_.IsModule()) {
999         ThrowSyntaxError("'await' is a reserved identifier in module code", pos.GetToken().Start());
1000     }
1001 
1002     if (context_.FindLabel(actualLabel) != nullptr) {
1003         ThrowSyntaxError("Label already declared", pos.GetToken().Start());
1004     }
1005 
1006     SavedParserContext newCtx(this, ParserStatus::IN_LABELED, actualLabel);
1007 
1008     auto *identNode = AllocNode<ir::Identifier>(actualLabel, Allocator());
1009     identNode->SetRange(pos.GetToken().Loc());
1010 
1011     lexer_->NextToken();
1012 
1013     ValidateLabeledStatement(Lexer()->GetToken().Type());
1014 
1015     ir::Statement *body = ParseStatement(StatementParsingFlags::LABELLED);
1016 
1017     auto *labeledStatement = AllocNode<ir::LabelledStatement>(identNode, body);
1018     labeledStatement->SetRange({pos.GetToken().Start(), body->End()});
1019 
1020     return labeledStatement;
1021 }
1022 
ParseReturnStatement()1023 ir::ReturnStatement *ParserImpl::ParseReturnStatement()
1024 {
1025     if ((context_.Status() & ParserStatus::FUNCTION) == 0) {
1026         ThrowSyntaxError("return keyword should be used in function body");
1027     }
1028 
1029     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1030     lexer::SourcePosition endLoc = lexer_->GetToken().End();
1031     lexer_->NextToken();
1032 
1033     bool hasArgument = (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
1034                         lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
1035                         lexer_->GetToken().Type() != lexer::TokenType::EOS && !lexer_->GetToken().NewLine());
1036 
1037     ir::ReturnStatement *returnStatement = nullptr;
1038 
1039     if (hasArgument) {
1040         ir::Expression *expression = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1041         endLoc = expression->End();
1042         returnStatement = AllocNode<ir::ReturnStatement>(expression);
1043     } else {
1044         returnStatement = AllocNode<ir::ReturnStatement>();
1045     }
1046 
1047     returnStatement->SetRange({startLoc, endLoc});
1048     ConsumeSemicolon(returnStatement);
1049 
1050     context_.Status() |= ParserStatus::FUNCTION_HAS_RETURN_STATEMENT;
1051     return returnStatement;
1052 }
1053 
ThrowMultipleDefaultError()1054 void ParserImpl::ThrowMultipleDefaultError()
1055 {
1056     ThrowSyntaxError("Multiple default clauses.");
1057 }
1058 
ParseSwitchCaseStatement(bool * seenDefault)1059 ir::SwitchCaseStatement *ParserImpl::ParseSwitchCaseStatement(bool *seenDefault)
1060 {
1061     lexer::SourcePosition caseStartLoc = lexer_->GetToken().Start();
1062     ir::Expression *testExpr = nullptr;
1063 
1064     switch (lexer_->GetToken().KeywordType()) {
1065         case lexer::TokenType::KEYW_CASE: {
1066             lexer_->NextToken();
1067             testExpr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1068             break;
1069         }
1070         case lexer::TokenType::KEYW_DEFAULT: {
1071             if (*seenDefault) {
1072                 ThrowMultipleDefaultError();
1073             }
1074             *seenDefault = true;
1075             lexer_->NextToken();
1076             break;
1077         }
1078         default: {
1079             ThrowSyntaxError("Unexpected token, expected 'case' or 'default'.");
1080         }
1081     }
1082 
1083     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
1084         ThrowSyntaxError("Unexpected token, expected ':'");
1085     }
1086 
1087     ArenaVector<ir::Statement *> consequents(Allocator()->Adapter());
1088     lexer::SourcePosition caseEndLoc = lexer_->GetToken().End();
1089 
1090     lexer_->NextToken();
1091 
1092     while (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CASE &&
1093            lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_DEFAULT &&
1094            lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1095         ir::Statement *consequent = ParseStatement(StatementParsingFlags::ALLOW_LEXICAL);
1096         caseEndLoc = consequent->End();
1097         consequents.push_back(consequent);
1098     }
1099 
1100     auto *caseNode = AllocNode<ir::SwitchCaseStatement>(testExpr, std::move(consequents));
1101     caseNode->SetRange({caseStartLoc, caseEndLoc});
1102     return caseNode;
1103 }
1104 
ParseSwitchStatement()1105 ir::SwitchStatement *ParserImpl::ParseSwitchStatement()
1106 {
1107     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1108     lexer_->NextToken();
1109     if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS)) {
1110         ThrowSyntaxError("Unexpected token, expected '('");
1111     }
1112 
1113     lexer_->NextToken();
1114     ir::Expression *discriminant = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1115 
1116     if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS)) {
1117         ThrowSyntaxError("Unexpected token, expected ')'");
1118     }
1119 
1120     lexer_->NextToken();
1121     SwitchContext switchContext(&context_);
1122 
1123     if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE)) {
1124         ThrowSyntaxError("Unexpected token, expected '{'");
1125     }
1126 
1127     lexer_->NextToken();
1128     bool seenDefault = false;
1129     ArenaVector<ir::SwitchCaseStatement *> cases(Allocator()->Adapter());
1130 
1131     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1132         cases.push_back(ParseSwitchCaseStatement(&seenDefault));
1133     }
1134 
1135     auto *switchStatement = AllocNode<ir::SwitchStatement>(discriminant, std::move(cases));
1136     switchStatement->SetRange({startLoc, lexer_->GetToken().End()});
1137 
1138     lexer_->NextToken();
1139 
1140     return switchStatement;
1141 }
1142 
ThrowIllegalNewLineErrorAfterThrow()1143 void ParserImpl::ThrowIllegalNewLineErrorAfterThrow()
1144 {
1145     ThrowSyntaxError("Illegal newline after throw");
1146 }
1147 
ParseThrowStatement()1148 ir::ThrowStatement *ParserImpl::ParseThrowStatement()
1149 {
1150     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1151     lexer_->NextToken();
1152 
1153     if (lexer_->GetToken().NewLine()) {
1154         ThrowIllegalNewLineErrorAfterThrow();
1155     }
1156 
1157     ir::Expression *expression = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1158     lexer::SourcePosition endLoc = expression->End();
1159 
1160     auto *throwStatement = AllocNode<ir::ThrowStatement>(expression);
1161     throwStatement->SetRange({startLoc, endLoc});
1162     ConsumeSemicolon(throwStatement);
1163 
1164     return throwStatement;
1165 }
1166 
ParseCatchParamTypeAnnotation(ir::AnnotatedExpression * param)1167 void ParserImpl::ParseCatchParamTypeAnnotation([[maybe_unused]] ir::AnnotatedExpression *param) {}
1168 
ParseCatchParam()1169 ir::Expression *ParserImpl::ParseCatchParam()
1170 {
1171     ir::AnnotatedExpression *param = nullptr;
1172 
1173     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1174         return param;
1175     }
1176 
1177     lexer_->NextToken();  // eat left paren
1178 
1179     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1180         CheckRestrictedBinding();
1181         param = ExpectIdentifier();
1182     } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1183         param = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1184     } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1185         param = ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1186     } else {
1187         ThrowSyntaxError("Unexpected token in catch parameter");
1188     }
1189 
1190     ParseCatchParamTypeAnnotation(param);
1191 
1192     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1193         ThrowSyntaxError("Unexpected token, expected ')'");
1194     }
1195 
1196     lexer_->NextToken();
1197 
1198     return param;
1199 }
1200 
ParseCatchClause()1201 ir::CatchClause *ParserImpl::ParseCatchClause()
1202 {
1203     lexer::SourcePosition catchStartLoc = lexer_->GetToken().Start();
1204     lexer_->NextToken();  // eat 'catch' keyword
1205 
1206     ir::Expression *param = ParseCatchParam();
1207 
1208     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1209         ThrowSyntaxError("Unexpected token, expected '{'");
1210     }
1211 
1212     ir::BlockStatement *catchBlock = ParseBlockStatement();
1213     lexer::SourcePosition endLoc = catchBlock->End();
1214 
1215     auto *catchClause = AllocNode<ir::CatchClause>(param, catchBlock);
1216     catchClause->SetRange({catchStartLoc, endLoc});
1217 
1218     return catchClause;
1219 }
1220 
ParseTryStatement()1221 ir::Statement *ParserImpl::ParseTryStatement()
1222 {
1223     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1224     lexer::SourcePosition endLoc = lexer_->GetToken().End();
1225 
1226     lexer_->NextToken();
1227 
1228     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1229         ThrowSyntaxError("Unexpected token, expected '{'");
1230     }
1231 
1232     ir::BlockStatement *body = ParseBlockStatement();
1233 
1234     if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CATCH &&
1235         lexer_->GetToken().Type() != lexer::TokenType::KEYW_FINALLY) {
1236         ThrowSyntaxError("Missing catch or finally clause");
1237     }
1238 
1239     ir::CatchClause *catchClause = nullptr;
1240     ir::BlockStatement *finallyClause = nullptr;
1241     ArenaVector<ir::CatchClause *> catchClauses(Allocator()->Adapter());
1242 
1243     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_CATCH) {
1244         catchClause = ParseCatchClause();
1245         endLoc = catchClause->End();
1246         catchClauses.push_back(catchClause);
1247     }
1248 
1249     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FINALLY) {
1250         lexer_->NextToken();  // eat 'finally' keyword
1251 
1252         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1253             ThrowSyntaxError("Unexpected token, expected '{'");
1254         }
1255 
1256         finallyClause = ParseBlockStatement();
1257         endLoc = finallyClause->End();
1258     }
1259 
1260     ArenaVector<std::pair<compiler::LabelPair, const ir::Statement *>> finalizerInsertions(Allocator()->Adapter());
1261 
1262     auto *tryStatement = AllocNode<ir::TryStatement>(body, std::move(catchClauses), finallyClause, finalizerInsertions);
1263     tryStatement->SetRange({startLoc, endLoc});
1264     return tryStatement;
1265 }
1266 
ValidateDeclaratorId()1267 void ParserImpl::ValidateDeclaratorId()
1268 {
1269     if (InAmbientContext()) {
1270         return;
1271     }
1272 
1273     CheckRestrictedBinding();
1274 }
1275 
ParseVariableDeclaratorInitializer(ir::Expression * init,VariableParsingFlags flags,const lexer::SourcePosition & startLoc)1276 ir::VariableDeclarator *ParserImpl::ParseVariableDeclaratorInitializer(ir::Expression *init, VariableParsingFlags flags,
1277                                                                        const lexer::SourcePosition &startLoc)
1278 {
1279     if ((flags & VariableParsingFlags::DISALLOW_INIT) != 0) {
1280         ThrowSyntaxError("for-await-of loop variable declaration may not have an initializer");
1281     }
1282 
1283     lexer_->NextToken();
1284 
1285     if (InAmbientContext() && (flags & VariableParsingFlags::CONST) == 0) {
1286         ThrowSyntaxError("Initializers are not allowed in ambient contexts.");
1287     }
1288 
1289     auto exprFlags = ((flags & VariableParsingFlags::STOP_AT_IN) != 0 ? ExpressionParseFlags::STOP_AT_IN
1290                                                                       : ExpressionParseFlags::NO_OPTS);
1291 
1292     ir::Expression *initializer = ParseExpression(exprFlags);
1293     lexer::SourcePosition endLoc = initializer->End();
1294 
1295     auto *declarator = AllocNode<ir::VariableDeclarator>(GetFlag(flags), init, initializer);
1296     declarator->SetRange({startLoc, endLoc});
1297 
1298     return declarator;
1299 }
1300 
ParseVariableDeclaratorKey(VariableParsingFlags flags)1301 ir::AnnotatedExpression *ParserImpl::ParseVariableDeclaratorKey([[maybe_unused]] VariableParsingFlags flags)
1302 {
1303     switch (lexer_->GetToken().Type()) {
1304         case lexer::TokenType::LITERAL_IDENT: {
1305             ValidateDeclaratorId();
1306             return ExpectIdentifier(true);
1307         }
1308         case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
1309             return ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1310         }
1311         case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
1312             return ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1313         }
1314         default: {
1315             break;
1316         }
1317     }
1318 
1319     ThrowSyntaxError("Unexpected token in variable declaration");
1320     return nullptr;
1321 }
1322 
GetFlag(VariableParsingFlags flags)1323 ir::VariableDeclaratorFlag ParserImpl::GetFlag(VariableParsingFlags flags)
1324 {
1325     constexpr auto VARIABLE_FLAGS =
1326         (VariableParsingFlags::VAR | VariableParsingFlags::LET | VariableParsingFlags::CONST);
1327     switch (static_cast<VariableParsingFlags>(flags & VARIABLE_FLAGS)) {
1328         case VariableParsingFlags::CONST:
1329             return ir::VariableDeclaratorFlag::CONST;
1330         case VariableParsingFlags::VAR:
1331             return ir::VariableDeclaratorFlag::VAR;
1332         case VariableParsingFlags::LET:
1333             return ir::VariableDeclaratorFlag::LET;
1334         default:
1335             UNREACHABLE();
1336     }
1337 }
1338 
ParseVariableDeclarator(ir::Expression * init,lexer::SourcePosition startLoc,VariableParsingFlags flags)1339 ir::VariableDeclarator *ParserImpl::ParseVariableDeclarator(ir::Expression *init, lexer::SourcePosition startLoc,
1340                                                             VariableParsingFlags flags)
1341 {
1342     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
1343         return ParseVariableDeclaratorInitializer(init, flags, startLoc);
1344     }
1345 
1346     if ((flags & VariableParsingFlags::CONST) != 0U && (flags & VariableParsingFlags::ACCEPT_CONST_NO_INIT) == 0U) {
1347         ThrowSyntaxError("Missing initializer in const declaration");
1348     }
1349 
1350     if ((flags & VariableParsingFlags::IN_FOR) == 0U && (init->IsArrayPattern() || init->IsObjectPattern())) {
1351         ThrowSyntaxError("Missing initializer in destructuring declaration");
1352     }
1353 
1354     lexer::SourcePosition endLoc = init->End();
1355     auto declarator = AllocNode<ir::VariableDeclarator>(GetFlag(flags), init);
1356     declarator->SetRange({startLoc, endLoc});
1357 
1358     return declarator;
1359 }
1360 
ParseVariableDeclarator(VariableParsingFlags flags)1361 ir::VariableDeclarator *ParserImpl::ParseVariableDeclarator(VariableParsingFlags flags)
1362 {
1363     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1364     ir::Expression *init = ParseVariableDeclaratorKey(flags);
1365     ir::VariableDeclarator *declarator = ParseVariableDeclarator(init, startLoc, flags);
1366 
1367     return declarator;
1368 }
1369 
ParsePotentialConstEnum(VariableParsingFlags flags)1370 ir::Statement *ParserImpl::ParsePotentialConstEnum([[maybe_unused]] VariableParsingFlags flags)
1371 {
1372     ThrowSyntaxError("Variable declaration expected.");
1373 }
1374 
ThrowIfVarDeclaration(VariableParsingFlags flags)1375 void ParserImpl::ThrowIfVarDeclaration([[maybe_unused]] VariableParsingFlags flags) {}
1376 
ParseVariableDeclaration(VariableParsingFlags flags)1377 ir::Statement *ParserImpl::ParseVariableDeclaration(VariableParsingFlags flags)
1378 {
1379     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1380 
1381     if ((flags & VariableParsingFlags::NO_SKIP_VAR_KIND) == 0) {
1382         lexer_->NextToken();
1383     }
1384 
1385     ThrowIfVarDeclaration(flags);
1386 
1387     if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_ENUM) {
1388         return ParsePotentialConstEnum(flags);
1389     }
1390 
1391     ArenaVector<ir::VariableDeclarator *> declarators(Allocator()->Adapter());
1392 
1393     while (true) {
1394         ir::VariableDeclarator *declarator = ParseVariableDeclarator(flags);
1395 
1396         declarators.push_back(declarator);
1397 
1398         if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) {
1399             break;
1400         }
1401         lexer_->NextToken();
1402     }
1403 
1404     auto varKind = ir::VariableDeclaration::VariableDeclarationKind::VAR;
1405 
1406     if ((flags & VariableParsingFlags::LET) != 0) {
1407         varKind = ir::VariableDeclaration::VariableDeclarationKind::LET;
1408     } else if ((flags & VariableParsingFlags::CONST) != 0) {
1409         varKind = ir::VariableDeclaration::VariableDeclarationKind::CONST;
1410     }
1411 
1412     lexer::SourcePosition endLoc = declarators.back()->End();
1413     auto *declaration =
1414         AllocNode<ir::VariableDeclaration>(varKind, Allocator(), std::move(declarators), InAmbientContext());
1415     declaration->SetRange({startLoc, endLoc});
1416 
1417     return declaration;
1418 }
1419 
ParseWhileStatement()1420 ir::WhileStatement *ParserImpl::ParseWhileStatement()
1421 {
1422     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1423     lexer_->NextToken();
1424     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1425         ThrowSyntaxError("Unexpected token, expected '('");
1426     }
1427 
1428     lexer_->NextToken();
1429     ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1430 
1431     if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1432         ThrowSyntaxError("Unexpected token, expected ')'");
1433     }
1434 
1435     lexer_->NextToken();
1436     IterationContext iterCtx(&context_);
1437     ir::Statement *body = ParseStatement();
1438 
1439     lexer::SourcePosition endLoc = body->End();
1440     auto *whileStatement = AllocNode<ir::WhileStatement>(test, body);
1441     whileStatement->SetRange({startLoc, endLoc});
1442 
1443     return whileStatement;
1444 }
1445 
1446 // NOLINTNEXTLINE(google-default-arguments)
ParseExportDefaultDeclaration(const lexer::SourcePosition & startLoc,bool isExportEquals)1447 ir::ExportDefaultDeclaration *ParserImpl::ParseExportDefaultDeclaration(const lexer::SourcePosition &startLoc,
1448                                                                         bool isExportEquals)
1449 {
1450     lexer_->NextToken();  // eat `default` keyword or `=`
1451 
1452     ir::AstNode *declNode = nullptr;
1453     bool eatSemicolon = false;
1454 
1455     switch (lexer_->GetToken().Type()) {
1456         case lexer::TokenType::KEYW_FUNCTION: {
1457             declNode = ParseFunctionDeclaration(true);
1458             break;
1459         }
1460         case lexer::TokenType::KEYW_CLASS: {
1461             declNode = ParseClassDeclaration(ir::ClassDefinitionModifiers::NONE);
1462             break;
1463         }
1464         case lexer::TokenType::LITERAL_IDENT: {
1465             switch (lexer_->GetToken().KeywordType()) {
1466                 case lexer::TokenType::KEYW_STRUCT: {
1467                     declNode = ParseStructDeclaration(ir::ClassDefinitionModifiers::NONE);
1468                     break;
1469                 }
1470                 case lexer::TokenType::KEYW_ASYNC: {
1471                     if ((lexer_->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) == 0) {
1472                         lexer_->NextToken();  // eat `async`
1473                         declNode = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION);
1474                         break;
1475                     }
1476 
1477                     [[fallthrough]];
1478                 }
1479                 default: {
1480                     declNode = ParseExpression();
1481                     eatSemicolon = true;
1482                     break;
1483                 }
1484             }
1485 
1486             break;
1487         }
1488         default: {
1489             declNode = ParseExpression();
1490             eatSemicolon = true;
1491             break;
1492         }
1493     }
1494 
1495     lexer::SourcePosition endLoc = declNode->End();
1496     auto *exportDeclaration = AllocNode<ir::ExportDefaultDeclaration>(declNode, isExportEquals);
1497     exportDeclaration->SetRange({startLoc, endLoc});
1498 
1499     if (eatSemicolon) {
1500         ConsumeSemicolon(exportDeclaration);
1501     }
1502 
1503     return exportDeclaration;
1504 }
1505 
ParseNamedExport(const lexer::Token & exportedToken)1506 ir::Identifier *ParserImpl::ParseNamedExport(const lexer::Token &exportedToken)
1507 {
1508     if (exportedToken.Type() != lexer::TokenType::LITERAL_IDENT) {
1509         ThrowSyntaxError("Unexpected token, expected an identifier.");
1510     }
1511 
1512     CheckRestrictedBinding(exportedToken.KeywordType());
1513 
1514     const util::StringView &exportedString = exportedToken.Ident();
1515 
1516     auto *exported = AllocNode<ir::Identifier>(exportedString, Allocator());
1517     exported->SetRange(exportedToken.Loc());
1518 
1519     return exported;
1520 }
1521 
ParseExportAllDeclaration(const lexer::SourcePosition & startLoc)1522 ir::ExportAllDeclaration *ParserImpl::ParseExportAllDeclaration(const lexer::SourcePosition &startLoc)
1523 {
1524     lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat `*` character
1525 
1526     ir::Identifier *exported = nullptr;
1527 
1528     if (CheckModuleAsModifier()) {
1529         lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
1530         exported = ParseNamedExport(lexer_->GetToken());
1531         lexer_->NextToken();  // eat exported name
1532     }
1533 
1534     ir::StringLiteral *source = ParseFromClause();
1535     lexer::SourcePosition endLoc = source->End();
1536 
1537     auto *exportDeclaration = AllocNode<ir::ExportAllDeclaration>(source, exported);
1538     exportDeclaration->SetRange({startLoc, endLoc});
1539 
1540     ConsumeSemicolon(exportDeclaration);
1541 
1542     return exportDeclaration;
1543 }
1544 
ParseExportNamedSpecifiers(const lexer::SourcePosition & startLoc)1545 ir::ExportNamedDeclaration *ParserImpl::ParseExportNamedSpecifiers(const lexer::SourcePosition &startLoc)
1546 {
1547     lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat `{` character
1548 
1549     ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter());
1550 
1551     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1552         if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1553             ThrowSyntaxError("Unexpected token");
1554         }
1555 
1556         lexer::Token localToken = lexer_->GetToken();
1557         auto *local = AllocNode<ir::Identifier>(lexer_->GetToken().Ident(), Allocator());
1558         local->SetRange(lexer_->GetToken().Loc());
1559 
1560         lexer_->NextToken();  // eat local name
1561 
1562         ir::Identifier *exported = nullptr;
1563 
1564         if (CheckModuleAsModifier()) {
1565             lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat `as` literal
1566             exported = ParseNamedExport(lexer_->GetToken());
1567             lexer_->NextToken();  // eat exported name
1568         } else {
1569             exported = ParseNamedExport(localToken);
1570         }
1571 
1572         auto *specifier = AllocNode<ir::ExportSpecifier>(local, exported);
1573         specifier->SetRange({local->Start(), exported->End()});
1574 
1575         specifiers.push_back(specifier);
1576 
1577         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
1578             lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat comma
1579         }
1580     }
1581 
1582     lexer::SourcePosition endPos = lexer_->GetToken().End();
1583     lexer_->NextToken();  // eat right brace
1584 
1585     ir::StringLiteral *source = nullptr;
1586 
1587     if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_FROM) {
1588         source = ParseFromClause();
1589     }
1590 
1591     auto *exportDeclaration = AllocNode<ir::ExportNamedDeclaration>(Allocator(), source, std::move(specifiers));
1592     exportDeclaration->SetRange({startLoc, endPos});
1593     ConsumeSemicolon(exportDeclaration);
1594 
1595     return exportDeclaration;
1596 }
1597 
ParseNamedExportDeclaration(const lexer::SourcePosition & startLoc)1598 ir::ExportNamedDeclaration *ParserImpl::ParseNamedExportDeclaration(const lexer::SourcePosition &startLoc)
1599 {
1600     ir::Statement *decl = nullptr;
1601 
1602     switch (lexer_->GetToken().Type()) {
1603         case lexer::TokenType::KEYW_VAR: {
1604             decl = ParseVariableDeclaration(VariableParsingFlags::VAR);
1605             break;
1606         }
1607         case lexer::TokenType::KEYW_CONST: {
1608             decl = ParseVariableDeclaration(VariableParsingFlags::CONST);
1609             break;
1610         }
1611         case lexer::TokenType::KEYW_LET: {
1612             decl = ParseVariableDeclaration(VariableParsingFlags::LET);
1613             break;
1614         }
1615         case lexer::TokenType::KEYW_FUNCTION: {
1616             decl = ParseFunctionDeclaration(false, ParserStatus::NO_OPTS);
1617             break;
1618         }
1619         case lexer::TokenType::KEYW_CLASS: {
1620             decl = ParseClassDeclaration(ir::ClassDefinitionModifiers::ID_REQUIRED);
1621             break;
1622         }
1623         case lexer::TokenType::LITERAL_IDENT: {
1624             if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_STRUCT) {
1625                 decl = ParseStructDeclaration(ir::ClassDefinitionModifiers::NONE);
1626                 break;
1627             }
1628             [[fallthrough]];
1629         }
1630         default: {
1631             if (!lexer_->GetToken().IsAsyncModifier()) {
1632                 ThrowSyntaxError("Unexpected token");
1633             }
1634 
1635             lexer_->NextToken();  // eat `async` keyword
1636             decl = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION);
1637         }
1638     }
1639 
1640     if (decl->IsVariableDeclaration()) {
1641         ConsumeSemicolon(decl);
1642     }
1643 
1644     lexer::SourcePosition endLoc = decl->End();
1645     ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter());
1646     auto *exportDeclaration = AllocNode<ir::ExportNamedDeclaration>(Allocator(), decl, std::move(specifiers));
1647     exportDeclaration->SetRange({startLoc, endLoc});
1648 
1649     return exportDeclaration;
1650 }
1651 
ParseExportDeclaration(StatementParsingFlags flags)1652 ir::Statement *ParserImpl::ParseExportDeclaration(StatementParsingFlags flags)
1653 {
1654     if ((flags & StatementParsingFlags::GLOBAL) == 0) {
1655         ThrowSyntaxError("'import' and 'export' may only appear at the top level");
1656     }
1657 
1658     if (!context_.IsModule()) {
1659         ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'");
1660     }
1661 
1662     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1663     lexer_->NextToken();  // eat `export` keyword
1664 
1665     switch (lexer_->GetToken().Type()) {
1666         case lexer::TokenType::PUNCTUATOR_MULTIPLY: {
1667             return ParseExportAllDeclaration(startLoc);
1668         }
1669         case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
1670             return ParseExportNamedSpecifiers(startLoc);
1671         }
1672         default: {
1673             if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DEFAULT) {
1674                 return ParseExportDefaultDeclaration(startLoc);
1675             }
1676             return ParseNamedExportDeclaration(startLoc);
1677         }
1678     }
1679 }
1680 
ParseNameSpaceImport(ArenaVector<ir::AstNode * > * specifiers)1681 void ParserImpl::ParseNameSpaceImport(ArenaVector<ir::AstNode *> *specifiers)
1682 {
1683     lexer::SourcePosition namespaceStart = lexer_->GetToken().Start();
1684     lexer_->NextToken();  // eat `*` character
1685 
1686     if (!CheckModuleAsModifier()) {
1687         ThrowSyntaxError("Unexpected token.");
1688     }
1689 
1690     lexer_->NextToken();  // eat `as` literal
1691 
1692     ir::Identifier *local = ParseNamedImport(lexer_->GetToken());
1693 
1694     auto *specifier = AllocNode<ir::ImportNamespaceSpecifier>(local);
1695     specifier->SetRange({namespaceStart, lexer_->GetToken().End()});
1696     specifiers->push_back(specifier);
1697 
1698     lexer_->NextToken();  // eat local name
1699 }
1700 
ParseNamedImport(const lexer::Token & importedToken)1701 ir::Identifier *ParserImpl::ParseNamedImport(const lexer::Token &importedToken)
1702 {
1703     if (importedToken.Type() != lexer::TokenType::LITERAL_IDENT) {
1704         ThrowSyntaxError("Unexpected token");
1705     }
1706 
1707     CheckRestrictedBinding(importedToken.KeywordType());
1708 
1709     auto *local = AllocNode<ir::Identifier>(importedToken.Ident(), Allocator());
1710     local->SetRange(importedToken.Loc());
1711 
1712     return local;
1713 }
1714 
ParseNamedImportSpecifiers(ArenaVector<ir::AstNode * > * specifiers)1715 void ParserImpl::ParseNamedImportSpecifiers(ArenaVector<ir::AstNode *> *specifiers)
1716 {
1717     lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat `{` character
1718 
1719     while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1720         if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1721             ThrowSyntaxError("Unexpected token");
1722         }
1723 
1724         lexer::Token importedToken = lexer_->GetToken();
1725         auto *imported = AllocNode<ir::Identifier>(importedToken.Ident(), Allocator());
1726         ir::Identifier *local = nullptr;
1727         imported->SetRange(lexer_->GetToken().Loc());
1728 
1729         lexer_->NextToken();  // eat import name
1730 
1731         if (CheckModuleAsModifier()) {
1732             lexer_->NextToken();  // eat `as` literal
1733             local = ParseNamedImport(lexer_->GetToken());
1734             lexer_->NextToken();  // eat local name
1735         } else {
1736             local = ParseNamedImport(importedToken);
1737         }
1738 
1739         auto *specifier = AllocNode<ir::ImportSpecifier>(imported, local);
1740         specifier->SetRange({imported->Start(), local->End()});
1741         specifiers->push_back(specifier);
1742 
1743         if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
1744             lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat comma
1745         }
1746     }
1747 
1748     lexer_->NextToken();  // eat right brace
1749 }
1750 
ParseImportDefaultSpecifier(ArenaVector<ir::AstNode * > * specifiers)1751 ir::AstNode *ParserImpl::ParseImportDefaultSpecifier(ArenaVector<ir::AstNode *> *specifiers)
1752 {
1753     ir::Identifier *local = ParseNamedImport(lexer_->GetToken());
1754     lexer_->NextToken();  // eat local name
1755 
1756     auto *specifier = AllocNode<ir::ImportDefaultSpecifier>(local);
1757     specifier->SetRange(specifier->Local()->Range());
1758     specifiers->push_back(specifier);
1759 
1760     lexer_->NextToken();  // eat specifier name
1761 
1762     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
1763         lexer_->NextToken();  // eat comma
1764     }
1765 
1766     return nullptr;
1767 }
1768 
ParseFromClause(bool requireFrom)1769 ir::StringLiteral *ParserImpl::ParseFromClause(bool requireFrom)
1770 {
1771     if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) {
1772         if (requireFrom) {
1773             ThrowSyntaxError("Unexpected token.");
1774         }
1775     } else {
1776         lexer_->NextToken();  // eat `from` literal
1777     }
1778 
1779     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
1780         ThrowSyntaxError("Unexpected token.");
1781     }
1782 
1783     ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
1784 
1785     auto *source = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
1786     source->SetRange(lexer_->GetToken().Loc());
1787 
1788     lexer_->NextToken();
1789 
1790     return source;
1791 }
1792 
ParseImportSpecifiers(ArenaVector<ir::AstNode * > * specifiers)1793 ir::AstNode *ParserImpl::ParseImportSpecifiers(ArenaVector<ir::AstNode *> *specifiers)
1794 {
1795     ASSERT(specifiers->empty());
1796 
1797     if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1798         ir::AstNode *astNode = ParseImportDefaultSpecifier(specifiers);
1799 
1800         if (astNode != nullptr) {
1801             return astNode;
1802         }
1803     }
1804 
1805     if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
1806         ParseNameSpaceImport(specifiers);
1807     } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1808         ParseNamedImportSpecifiers(specifiers);
1809     }
1810     return nullptr;
1811 }
1812 
ParseImportDeclaration(StatementParsingFlags flags)1813 ir::Statement *ParserImpl::ParseImportDeclaration(StatementParsingFlags flags)
1814 {
1815     if ((flags & StatementParsingFlags::GLOBAL) == 0) {
1816         ThrowSyntaxError("'import' and 'export' may only appear at the top level");
1817     }
1818 
1819     if (!context_.IsModule()) {
1820         ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'");
1821     }
1822 
1823     char32_t nextChar = lexer_->Lookahead();
1824     if (nextChar == lexer::LEX_CHAR_LEFT_PAREN || nextChar == lexer::LEX_CHAR_DOT) {
1825         return ParseExpressionStatement();
1826     }
1827 
1828     lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1829     lexer_->NextToken();  // eat import
1830 
1831     ArenaVector<ir::AstNode *> specifiers(Allocator()->Adapter());
1832 
1833     ir::StringLiteral *source = nullptr;
1834 
1835     if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
1836         ParseImportSpecifiers(&specifiers);
1837         source = ParseFromClause(true);
1838     } else {
1839         source = ParseFromClause(false);
1840     }
1841 
1842     lexer::SourcePosition endLoc = source->End();
1843     auto *importDeclaration = AllocNode<ir::ImportDeclaration>(source, std::move(specifiers));
1844     importDeclaration->SetRange({startLoc, endLoc});
1845 
1846     ConsumeSemicolon(importDeclaration);
1847 
1848     return importDeclaration;
1849 }
1850 }  // namespace panda::es2panda::parser
1851