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