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