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