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