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