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