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 <util/helpers.h>
17 #include <binder/tsBinding.h>
18 #include <ir/astNode.h>
19 #include <ir/base/catchClause.h>
20 #include <ir/base/classDefinition.h>
21 #include <ir/base/decorator.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/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/ts/tsEnumDeclaration.h>
62 #include <ir/ts/tsExternalModuleReference.h>
63 #include <ir/ts/tsImportEqualsDeclaration.h>
64 #include <ir/ts/tsInterfaceBody.h>
65 #include <ir/ts/tsInterfaceDeclaration.h>
66 #include <ir/ts/tsInterfaceHeritage.h>
67 #include <ir/ts/tsModuleBlock.h>
68 #include <ir/ts/tsModuleDeclaration.h>
69 #include <ir/ts/tsNamespaceExportDeclaration.h>
70 #include <ir/ts/tsTypeAliasDeclaration.h>
71 #include <ir/ts/tsTypeParameter.h>
72 #include <ir/ts/tsTypeParameterDeclaration.h>
73 #include <ir/ts/tsTypeParameterInstantiation.h>
74 #include <ir/ts/tsTypeReference.h>
75 #include <lexer/lexer.h>
76 #include <lexer/token/letters.h>
77 #include <lexer/token/sourceLocation.h>
78 #include <util/ustring.h>
79
80 #include <tuple>
81
82 #include "parserImpl.h"
83
84 namespace panda::es2panda::parser {
85
CheckDeclare()86 bool ParserImpl::CheckDeclare()
87 {
88 ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE);
89
90 const auto startPos = lexer_->Save();
91 lexer_->NextToken(); // eat 'declare'
92 if (lexer_->GetToken().NewLine()) {
93 lexer_->Rewind(startPos);
94 return false;
95 }
96 switch (lexer_->GetToken().Type()) {
97 case lexer::TokenType::KEYW_VAR:
98 case lexer::TokenType::KEYW_LET:
99 case lexer::TokenType::KEYW_CONST:
100 case lexer::TokenType::KEYW_FUNCTION:
101 case lexer::TokenType::KEYW_CLASS: {
102 break;
103 }
104 case lexer::TokenType::LITERAL_IDENT: {
105 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE ||
106 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_MODULE ||
107 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_GLOBAL ||
108 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NAMESPACE ||
109 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ENUM ||
110 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT ||
111 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_INTERFACE) {
112 break;
113 }
114
115 [[fallthrough]];
116 }
117 default: {
118 lexer_->Rewind(startPos);
119 return false;
120 }
121 }
122
123 if (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT) {
124 lexer_->Rewind(startPos);
125 ThrowSyntaxError("A 'declare' modifier cannot be used in an already ambient context.");
126 }
127
128 return true;
129 }
130
IsLabelFollowedByIterationStatement()131 bool ParserImpl::IsLabelFollowedByIterationStatement()
132 {
133 lexer_->NextToken();
134
135 switch (lexer_->GetToken().Type()) {
136 case lexer::TokenType::KEYW_DO:
137 case lexer::TokenType::KEYW_FOR:
138 case lexer::TokenType::KEYW_WHILE: {
139 return true;
140 }
141 case lexer::TokenType::LITERAL_IDENT: {
142 if (lexer_->Lookahead() == LEX_CHAR_COLON) {
143 lexer_->NextToken();
144 return IsLabelFollowedByIterationStatement();
145 }
146
147 [[fallthrough]];
148 }
149 default:
150 return false;
151 }
152 return false;
153 }
154
IsTsDeclarationStatement() const155 bool ParserImpl::IsTsDeclarationStatement() const
156 {
157 const auto startPos = lexer_->Save();
158 bool isTsDeclarationStatement = false;
159
160 auto keywordType = lexer_->GetToken().KeywordType();
161 lexer_->NextToken();
162 switch (keywordType) {
163 case lexer::TokenType::KEYW_MODULE:
164 case lexer::TokenType::KEYW_NAMESPACE: {
165 isTsDeclarationStatement = !lexer_->GetToken().NewLine() &&
166 (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
167 lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
168 break;
169 }
170 case lexer::TokenType::KEYW_GLOBAL: {
171 isTsDeclarationStatement = lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT ||
172 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE ||
173 lexer_->GetToken().Type() == lexer::TokenType::KEYW_EXPORT;
174 break;
175 }
176 case lexer::TokenType::KEYW_INTERFACE:
177 case lexer::TokenType::KEYW_TYPE: {
178 isTsDeclarationStatement = !lexer_->GetToken().NewLine() &&
179 lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT;
180 break;
181 }
182 case lexer::TokenType::KEYW_ENUM: {
183 isTsDeclarationStatement = true;
184 break;
185 }
186 default: {
187 break;
188 }
189 }
190
191 lexer_->Rewind(startPos);
192 return isTsDeclarationStatement;
193 }
194
ParseStatement(StatementParsingFlags flags)195 ir::Statement *ParserImpl::ParseStatement(StatementParsingFlags flags)
196 {
197 bool isDeclare = false;
198 auto decorators = ParseDecorators();
199
200 if (Extension() == ScriptExtension::TS) {
201 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) {
202 isDeclare = CheckDeclare();
203 }
204
205 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT) {
206 const auto startPos = lexer_->Save();
207 lexer_->NextToken(); // eat abstract keyword
208
209 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) {
210 if (isDeclare) {
211 ThrowSyntaxError("'declare' modifier already seen.");
212 }
213 lexer_->NextToken();
214 isDeclare = true;
215 }
216
217 if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS) {
218 lexer_->Rewind(startPos);
219 } else {
220 return ParseClassStatement(flags, isDeclare, std::move(decorators), true);
221 }
222 }
223
224 if ((lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_GLOBAL ||
225 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_MODULE ||
226 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NAMESPACE) &&
227 IsTsDeclarationStatement()) {
228 auto savedStatus = context_.Status();
229 if (isDeclare) {
230 context_.Status() |= ParserStatus::IN_AMBIENT_CONTEXT;
231 }
232 ir::TSModuleDeclaration *decl = ParseTsModuleDeclaration(isDeclare);
233 context_.Status() = savedStatus;
234 return decl;
235 }
236 }
237
238 switch (lexer_->GetToken().Type()) {
239 case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
240 return ParseBlockStatement();
241 }
242 case lexer::TokenType::PUNCTUATOR_SEMI_COLON: {
243 return ParseEmptyStatement();
244 }
245 case lexer::TokenType::KEYW_EXPORT: {
246 return ParseExportDeclaration(flags, std::move(decorators));
247 }
248 case lexer::TokenType::KEYW_IMPORT: {
249 return ParseImportDeclaration(flags);
250 }
251 case lexer::TokenType::KEYW_FUNCTION: {
252 return ParseFunctionStatement(flags, isDeclare);
253 }
254 case lexer::TokenType::KEYW_CLASS: {
255 return ParseClassStatement(flags, isDeclare, std::move(decorators));
256 }
257 case lexer::TokenType::KEYW_VAR: {
258 return ParseVarStatement(isDeclare);
259 }
260 case lexer::TokenType::KEYW_LET: {
261 return ParseLetStatement(flags, isDeclare);
262 }
263 case lexer::TokenType::KEYW_CONST: {
264 return ParseConstStatement(flags, isDeclare);
265 }
266 case lexer::TokenType::KEYW_IF: {
267 return ParseIfStatement();
268 }
269 case lexer::TokenType::KEYW_DO: {
270 return ParseDoWhileStatement();
271 }
272 case lexer::TokenType::KEYW_FOR: {
273 return ParseForStatement();
274 }
275 case lexer::TokenType::KEYW_TRY: {
276 return ParseTryStatement();
277 }
278 case lexer::TokenType::KEYW_WHILE: {
279 return ParseWhileStatement();
280 }
281 case lexer::TokenType::KEYW_BREAK: {
282 return ParseBreakStatement();
283 }
284 case lexer::TokenType::KEYW_CONTINUE: {
285 return ParseContinueStatement();
286 }
287 case lexer::TokenType::KEYW_THROW: {
288 return ParseThrowStatement();
289 }
290 case lexer::TokenType::KEYW_RETURN: {
291 return ParseReturnStatement();
292 }
293 case lexer::TokenType::KEYW_SWITCH: {
294 return ParseSwitchStatement();
295 }
296 case lexer::TokenType::KEYW_DEBUGGER: {
297 return ParseDebuggerStatement();
298 }
299 case lexer::TokenType::LITERAL_IDENT: {
300 return ParsePotentialExpressionStatement(flags, isDeclare);
301 }
302 default: {
303 break;
304 }
305 }
306
307 return ParseExpressionStatement(flags);
308 }
309
ParseTsModuleDeclaration(bool isDeclare,bool isExport)310 ir::TSModuleDeclaration *ParserImpl::ParseTsModuleDeclaration(bool isDeclare, bool isExport)
311 {
312 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
313 context_.Status() |= ParserStatus::TS_MODULE;
314
315 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_GLOBAL) {
316 return ParseTsAmbientExternalModuleDeclaration(startLoc, isDeclare);
317 }
318
319 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_NAMESPACE) {
320 lexer_->NextToken();
321 } else {
322 ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_MODULE);
323 lexer_->NextToken();
324 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
325 return ParseTsAmbientExternalModuleDeclaration(startLoc, isDeclare);
326 }
327 }
328
329 return ParseTsModuleOrNamespaceDelaration(startLoc, isDeclare, isExport);
330 }
331
ParseTsAmbientExternalModuleDeclaration(const lexer::SourcePosition & startLoc,bool isDeclare)332 ir::TSModuleDeclaration *ParserImpl::ParseTsAmbientExternalModuleDeclaration(const lexer::SourcePosition &startLoc,
333 bool isDeclare)
334 {
335 bool isGlobal = false;
336 ir::Expression *name = nullptr;
337
338 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_GLOBAL) {
339 isGlobal = true;
340 name = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
341 } else {
342 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
343
344 if (!isDeclare && !(context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT)) {
345 ThrowSyntaxError("Only ambient modules can use quoted names");
346 }
347
348 name = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
349 }
350
351 name->SetRange(lexer_->GetToken().Loc());
352
353 lexer_->NextToken();
354
355 binder::ExportBindings *exportBindings = Allocator()->New<binder::ExportBindings>(Allocator());
356 auto localCtx = binder::LexicalScope<binder::TSModuleScope>(Binder(), exportBindings);
357
358 ir::Statement *body = nullptr;
359 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
360 body = ParseTsModuleBlock();
361 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
362 lexer_->NextToken();
363 } else if (!lexer_->GetToken().NewLine()) {
364 ThrowSyntaxError("';' expected");
365 }
366
367 auto *moduleDecl = AllocNode<ir::TSModuleDeclaration>(localCtx.GetScope(), name, body, isDeclare, isGlobal);
368 moduleDecl->SetRange({startLoc, lexer_->GetToken().End()});
369 localCtx.GetScope()->BindNode(moduleDecl);
370
371 return moduleDecl;
372 }
373
ParseTsModuleOrNamespaceDelaration(const lexer::SourcePosition & startLoc,bool isDeclare,bool isExport)374 ir::TSModuleDeclaration *ParserImpl::ParseTsModuleOrNamespaceDelaration(const lexer::SourcePosition &startLoc,
375 bool isDeclare, bool isExport)
376 {
377 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
378 ThrowSyntaxError("Identifier expected");
379 }
380
381 auto name = lexer_->GetToken().Ident();
382 auto *parentScope = Binder()->GetScope();
383 binder::Variable *res = parentScope->FindLocalTSVariable<binder::TSBindingType::NAMESPACE>(name);
384 if (!res && isExport && parentScope->IsTSModuleScope()) {
385 res = parentScope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::NAMESPACE>(name);
386 if (res != nullptr) {
387 parentScope->AddLocalTSVariable<binder::TSBindingType::NAMESPACE>(name, res);
388 }
389 }
390 if (res == nullptr) {
391 Binder()->AddTsDecl<binder::NamespaceDecl>(lexer_->GetToken().Start(), isDeclare, Allocator(), name);
392 res = parentScope->FindLocalTSVariable<binder::TSBindingType::NAMESPACE>(name);
393 if (isExport && parentScope->IsTSModuleScope()) {
394 parentScope->AsTSModuleScope()->AddExportTSVariable<binder::TSBindingType::NAMESPACE>(name, res);
395 }
396 res->AsNamespaceVariable()->SetExportBindings(Allocator()->New<binder::ExportBindings>(Allocator()));
397 }
398 binder::ExportBindings *exportBindings = res->AsNamespaceVariable()->GetExportBindings();
399
400 auto *identNode = AllocNode<ir::Identifier>(name);
401 identNode->SetRange(lexer_->GetToken().Loc());
402
403 lexer_->NextToken();
404
405 ir::Statement *body = nullptr;
406
407 auto savedStatus = context_.Status();
408 if (isDeclare) {
409 context_.Status() |= ParserStatus::IN_AMBIENT_CONTEXT;
410 }
411
412 auto localCtx = binder::LexicalScope<binder::TSModuleScope>(Binder(), exportBindings);
413
414 bool isInstantiated = false;
415 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
416 lexer_->NextToken();
417 lexer::SourcePosition moduleStart = lexer_->GetToken().Start();
418 body = ParseTsModuleOrNamespaceDelaration(moduleStart, false, true);
419 isInstantiated = body->AsTSModuleDeclaration()->IsInstantiated();
420 } else {
421 body = ParseTsModuleBlock();
422 auto statements = body->AsTSModuleBlock()->Statements();
423 for (auto *it : statements) {
424 auto statement = it;
425 if (statement->IsExportNamedDeclaration()) {
426 statement = statement->AsExportNamedDeclaration()->Decl();
427 }
428 if (statement != nullptr &&
429 !statement->IsTSInterfaceDeclaration() && !statement->IsTSTypeAliasDeclaration() &&
430 (!statement->IsTSModuleDeclaration() || statement->AsTSModuleDeclaration()->IsInstantiated())) {
431 isInstantiated = true;
432 break;
433 }
434 }
435 }
436 if (isDeclare) {
437 isInstantiated = false;
438 }
439
440 context_.Status() = savedStatus;
441
442 auto *moduleDecl = AllocNode<ir::TSModuleDeclaration>(localCtx.GetScope(), identNode, body,
443 isDeclare, false, isInstantiated);
444 moduleDecl->SetRange({startLoc, lexer_->GetToken().End()});
445 localCtx.GetScope()->BindNode(moduleDecl);
446 res->Declaration()->AsNamespaceDecl()->Add(moduleDecl);
447
448 return moduleDecl;
449 }
450
ParseTsImportEqualsDeclaration(const lexer::SourcePosition & startLoc,bool isExport)451 ir::TSImportEqualsDeclaration *ParserImpl::ParseTsImportEqualsDeclaration(const lexer::SourcePosition &startLoc,
452 bool isExport)
453 {
454 ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_IMPORT);
455 lexer_->NextToken();
456 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
457 ThrowSyntaxError("Unexpected token");
458 }
459
460 auto *id = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
461 id->SetRange(lexer_->GetToken().Loc());
462 lexer_->NextToken(); // eat id name
463
464 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
465 ThrowSyntaxError("'=' expected");
466 }
467 lexer_->NextToken(); // eat substitution
468
469 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
470 ThrowSyntaxError("identifier expected");
471 }
472
473 if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_REQUIRE ||
474 lexer_->Lookahead() != LEX_CHAR_LEFT_PAREN) {
475 binder::DeclarationFlags declflag = binder::DeclarationFlags::NONE;
476 auto *decl = Binder()->AddDecl<binder::ImportEqualsDecl>(id->Start(), declflag, false, id->Name());
477 decl->BindNode(id);
478 auto *scope = Binder()->GetScope();
479 auto name = id->Name();
480 auto *var = scope->FindLocalTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name);
481 ASSERT(var != nullptr);
482 var->AsImportEqualsVariable()->SetScope(scope);
483 if (isExport && scope->IsTSModuleScope()) {
484 scope->AsTSModuleScope()->AddExportTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name, var);
485 }
486 }
487
488 auto *importEqualsDecl = AllocNode<ir::TSImportEqualsDeclaration>(id, ParseModuleReference(), isExport);
489 importEqualsDecl->SetRange({startLoc, lexer_->GetToken().End()});
490
491 ConsumeSemicolon(importEqualsDecl);
492
493 return importEqualsDecl;
494 }
495
ParseTsNamespaceExportDeclaration(const lexer::SourcePosition & startLoc)496 ir::TSNamespaceExportDeclaration *ParserImpl::ParseTsNamespaceExportDeclaration(const lexer::SourcePosition &startLoc)
497 {
498 if (!IsDtsFile()) {
499 ThrowSyntaxError("namespace export declaration is only supported in TypeScript '.d.ts'");
500 }
501 ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS);
502 lexer_->NextToken(); // eat as keyword
503 if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_NAMESPACE) {
504 ThrowSyntaxError("'namespace' expected");
505 }
506 lexer_->NextToken(); // eat namespace keyword
507 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
508 ThrowSyntaxError("identifier expected");
509 }
510
511 auto *id = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
512 id->SetRange(lexer_->GetToken().Loc());
513 lexer_->NextToken(); // eat identifier
514
515 auto *namespaceExportDecl = AllocNode<ir::TSNamespaceExportDeclaration>(id);
516 namespaceExportDecl->SetRange({startLoc, lexer_->GetToken().End()});
517
518 ConsumeSemicolon(namespaceExportDecl);
519
520 return namespaceExportDecl;
521 }
522
ParseTsModuleBlock()523 ir::TSModuleBlock *ParserImpl::ParseTsModuleBlock()
524 {
525 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
526 ThrowSyntaxError("'{' expected.");
527 }
528
529 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
530 lexer_->NextToken();
531 auto statements = ParseStatementList();
532
533 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
534 ThrowSyntaxError("Expected a '}'");
535 }
536
537 auto *blockNode = AllocNode<ir::TSModuleBlock>(std::move(statements));
538 blockNode->SetRange({startLoc, lexer_->GetToken().End()});
539
540 lexer_->NextToken();
541 return blockNode;
542 }
543
ParseVarStatement(bool isDeclare)544 ir::Statement *ParserImpl::ParseVarStatement(bool isDeclare)
545 {
546 auto *variableDecl = ParseVariableDeclaration(VariableParsingFlags::VAR, isDeclare);
547 ConsumeSemicolon(variableDecl);
548 return variableDecl;
549 }
550
ParseLetStatement(StatementParsingFlags flags,bool isDeclare)551 ir::Statement *ParserImpl::ParseLetStatement(StatementParsingFlags flags, bool isDeclare)
552 {
553 if (!(flags & StatementParsingFlags::ALLOW_LEXICAL)) {
554 ThrowSyntaxError("The 'let' declarations can only be declared at the top level or inside a block.");
555 }
556
557 auto *variableDecl = ParseVariableDeclaration(VariableParsingFlags::LET, isDeclare);
558 ConsumeSemicolon(variableDecl);
559 return variableDecl;
560 }
561
ParseConstStatement(StatementParsingFlags flags,bool isDeclare)562 ir::Statement *ParserImpl::ParseConstStatement(StatementParsingFlags flags, bool isDeclare)
563 {
564 lexer::SourcePosition constVarStar = lexer_->GetToken().Start();
565 lexer_->NextToken();
566
567 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ENUM) {
568 if (Extension() == ScriptExtension::TS) {
569 return ParseEnumDeclaration(false, isDeclare, true);
570 }
571 ThrowSyntaxError("Unexpected token");
572 }
573
574 if (!(flags & StatementParsingFlags::ALLOW_LEXICAL)) {
575 ThrowSyntaxError("The 'const' declarations can only be declared at the top level or inside a block.");
576 }
577
578 auto *variableDecl =
579 ParseVariableDeclaration(VariableParsingFlags::CONST | VariableParsingFlags::NO_SKIP_VAR_KIND, isDeclare);
580 variableDecl->SetStart(constVarStar);
581 ConsumeSemicolon(variableDecl);
582
583 return variableDecl;
584 }
585
ParseEmptyStatement()586 ir::EmptyStatement *ParserImpl::ParseEmptyStatement()
587 {
588 auto *empty = AllocNode<ir::EmptyStatement>();
589 empty->SetRange(lexer_->GetToken().Loc());
590 lexer_->NextToken();
591 return empty;
592 }
593
ParseDebuggerStatement()594 ir::DebuggerStatement *ParserImpl::ParseDebuggerStatement()
595 {
596 auto *debuggerNode = AllocNode<ir::DebuggerStatement>();
597 debuggerNode->SetRange(lexer_->GetToken().Loc());
598 lexer_->NextToken();
599 ConsumeSemicolon(debuggerNode);
600 return debuggerNode;
601 }
602
ParseFunctionStatement(StatementParsingFlags flags,bool isDeclare)603 ir::Statement *ParserImpl::ParseFunctionStatement(StatementParsingFlags flags, bool isDeclare)
604 {
605 CheckFunctionDeclaration(flags);
606
607 if (!(flags & StatementParsingFlags::STMT_LEXICAL_SCOPE_NEEDED)) {
608 return ParseFunctionDeclaration(false, ParserStatus::NO_OPTS, isDeclare);
609 }
610
611 auto localCtx = binder::LexicalScope<binder::LocalScope>(Binder());
612 ArenaVector<ir::Statement *> stmts(Allocator()->Adapter());
613 auto *funcDecl = ParseFunctionDeclaration(false, ParserStatus::NO_OPTS, isDeclare);
614 stmts.push_back(funcDecl);
615
616 auto *localBlockStmt = AllocNode<ir::BlockStatement>(localCtx.GetScope(), std::move(stmts));
617 localBlockStmt->SetRange(funcDecl->Range());
618 localCtx.GetScope()->BindNode(localBlockStmt);
619
620 return funcDecl;
621 }
622
ParsePotentialExpressionStatement(StatementParsingFlags flags,bool isDeclare)623 ir::Statement *ParserImpl::ParsePotentialExpressionStatement(StatementParsingFlags flags, bool isDeclare)
624 {
625 if (lexer_->Lookahead() == LEX_CHAR_COLON) {
626 const auto pos = lexer_->Save();
627 lexer_->NextToken();
628 return ParseLabelledStatement(pos);
629 }
630
631 if (Extension() == ScriptExtension::TS && IsTsDeclarationStatement()) {
632 switch (lexer_->GetToken().KeywordType()) {
633 case lexer::TokenType::KEYW_ENUM: {
634 return ParseEnumDeclaration(false, isDeclare, false);
635 }
636 case lexer::TokenType::KEYW_TYPE: {
637 return ParseTsTypeAliasDeclaration(isDeclare);
638 }
639 case lexer::TokenType::KEYW_INTERFACE: {
640 return ParseTsInterfaceDeclaration(isDeclare);
641 }
642 default:
643 break;
644 }
645 }
646
647 return ParseExpressionStatement(flags);
648 }
649
ParseClassStatement(StatementParsingFlags flags,bool isDeclare,ArenaVector<ir::Decorator * > && decorators,bool isAbstract)650 ir::ClassDeclaration *ParserImpl::ParseClassStatement(StatementParsingFlags flags, bool isDeclare,
651 ArenaVector<ir::Decorator *> &&decorators, bool isAbstract)
652 {
653 if (!(flags & StatementParsingFlags::ALLOW_LEXICAL)) {
654 ThrowSyntaxError("Lexical 'class' declaration is not allowed in single statement context");
655 }
656
657 return ParseClassDeclaration(true, std::move(decorators), isDeclare, isAbstract);
658 }
659
ParseClassDeclaration(bool idRequired,ArenaVector<ir::Decorator * > && decorators,bool isDeclare,bool isAbstract,bool isExported)660 ir::ClassDeclaration *ParserImpl::ParseClassDeclaration(bool idRequired, ArenaVector<ir::Decorator *> &&decorators,
661 bool isDeclare, bool isAbstract, bool isExported)
662 {
663 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
664 ir::ClassDefinition *classDefinition = ParseClassDefinition(true, idRequired, isDeclare, isAbstract);
665 if (isExported && !idRequired) {
666 classDefinition->SetAsExportDefault();
667 }
668
669 auto location = classDefinition->Ident() ? classDefinition->Ident()->Start() : startLoc;
670 auto className = classDefinition->GetName();
671 ASSERT(!className.Empty());
672
673 binder::DeclarationFlags flag = isExported ? binder::DeclarationFlags::EXPORT : binder::DeclarationFlags::NONE;
674 auto *decl = Binder()->AddDecl<binder::ClassDecl>(location, flag, classDefinition->Declare(), className);
675
676 decl->BindNode(classDefinition);
677
678 lexer::SourcePosition endLoc = classDefinition->End();
679 auto *classDecl = AllocNode<ir::ClassDeclaration>(classDefinition, std::move(decorators));
680 classDecl->SetRange({startLoc, endLoc});
681 return classDecl;
682 }
683
ParseTsTypeAliasDeclaration(bool isDeclare)684 ir::TSTypeAliasDeclaration *ParserImpl::ParseTsTypeAliasDeclaration(bool isDeclare)
685 {
686 ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE);
687 lexer::SourcePosition typeStart = lexer_->GetToken().Start();
688 lexer_->NextToken(); // eat type keyword
689
690 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
691 ThrowSyntaxError("Identifier expected");
692 }
693
694 if (lexer_->GetToken().IsReservedTypeName()) {
695 std::string errMsg("Type alias name cannot be '");
696 errMsg.append(TokenToString(lexer_->GetToken().KeywordType()));
697 errMsg.append("'");
698 ThrowSyntaxError(errMsg.c_str());
699 }
700
701 const util::StringView &ident = lexer_->GetToken().Ident();
702 binder::TSBinding tsBinding(Allocator(), ident);
703 auto *decl = Binder()->AddTsDecl<binder::TypeAliasDecl>(lexer_->GetToken().Start(), isDeclare, tsBinding.View());
704
705 auto *id = AllocNode<ir::Identifier>(ident);
706 id->SetRange(lexer_->GetToken().Loc());
707 lexer_->NextToken();
708
709 ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
710 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
711 typeParamDecl = ParseTsTypeParameterDeclaration();
712 }
713
714 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
715 ThrowSyntaxError("'=' expected");
716 }
717
718 lexer_->NextToken(); // eat '='
719
720 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
721 ir::Expression *typeAnnotation = ParseTsTypeAnnotation(&options);
722
723 auto *typeAliasDecl = AllocNode<ir::TSTypeAliasDeclaration>(id, typeParamDecl, typeAnnotation, isDeclare);
724 typeAliasDecl->SetRange({typeStart, lexer_->GetToken().End()});
725 decl->BindNode(typeAliasDecl);
726 ConsumeSemicolon(typeAliasDecl);
727
728 return typeAliasDecl;
729 }
730
ParseTsInterfaceDeclaration(bool isDeclare)731 ir::TSInterfaceDeclaration *ParserImpl::ParseTsInterfaceDeclaration(bool isDeclare)
732 {
733 ASSERT(lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_INTERFACE);
734 context_.Status() |= ParserStatus::ALLOW_THIS_TYPE;
735 lexer::SourcePosition interfaceStart = lexer_->GetToken().Start();
736 lexer_->NextToken(); // eat interface keyword
737
738 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
739 ThrowSyntaxError("Identifier expected");
740 }
741
742 if (lexer_->GetToken().IsReservedTypeName()) {
743 std::string errMsg("Interface name cannot be '");
744 errMsg.append(TokenToString(lexer_->GetToken().KeywordType()));
745 errMsg.append("'");
746 ThrowSyntaxError(errMsg.c_str());
747 }
748
749 const util::StringView &ident = lexer_->GetToken().Ident();
750 binder::TSBinding tsBinding(Allocator(), ident);
751
752 const auto &bindings = Binder()->GetScope()->Bindings();
753 auto res = bindings.find(tsBinding.View());
754 binder::InterfaceDecl *decl {};
755
756 if (res == bindings.end()) {
757 decl = Binder()->AddTsDecl<binder::InterfaceDecl>(lexer_->GetToken().Start(), isDeclare,
758 Allocator(), tsBinding.View());
759 } else if (!res->second->Declaration()->IsInterfaceDecl()) {
760 Binder()->ThrowRedeclaration(lexer_->GetToken().Start(), ident);
761 } else {
762 decl = res->second->Declaration()->AsInterfaceDecl();
763 }
764
765 auto *id = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
766 id->SetRange(lexer_->GetToken().Loc());
767 id->SetReference();
768 lexer_->NextToken();
769
770 binder::LexicalScope<binder::LocalScope> localScope(Binder());
771
772 ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
773 if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
774 typeParamDecl = ParseTsTypeParameterDeclaration();
775 }
776
777 ArenaVector<ir::TSInterfaceHeritage *> extends(Allocator()->Adapter());
778 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_EXTENDS) {
779 lexer_->NextToken(); // eat extends keyword
780 while (true) {
781 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
782 ThrowSyntaxError("Identifier expected");
783 }
784
785 const lexer::SourcePosition &heritageStart = lexer_->GetToken().Start();
786 lexer::SourcePosition heritageEnd = lexer_->GetToken().End();
787 ir::Expression *expr = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
788 expr->AsIdentifier()->SetReference();
789 expr->SetRange(lexer_->GetToken().Loc());
790
791 if (lexer_->Lookahead() == LEX_CHAR_LESS_THAN) {
792 lexer_->ForwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
793 } else {
794 lexer_->NextToken();
795 }
796
797 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
798 expr = ParseTsQualifiedReference(expr);
799 }
800
801 ir::TSTypeParameterInstantiation *typeParamInst = nullptr;
802 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
803 typeParamInst = ParseTsTypeParameterInstantiation();
804 heritageEnd = typeParamInst->End();
805 }
806
807 auto *typeReference = AllocNode<ir::TSTypeReference>(expr, typeParamInst);
808 typeReference->SetRange({heritageStart, heritageEnd});
809 auto *heritage = AllocNode<ir::TSInterfaceHeritage>(typeReference);
810 heritage->SetRange(typeReference->Range());
811 extends.push_back(heritage);
812
813 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
814 break;
815 }
816
817 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) {
818 ThrowSyntaxError("',' expected");
819 }
820
821 lexer_->NextToken();
822 }
823 }
824
825 lexer::SourcePosition bodyStart = lexer_->GetToken().Start();
826 auto members = ParseTsTypeLiteralOrInterface();
827
828 auto *body = AllocNode<ir::TSInterfaceBody>(std::move(members));
829 body->SetRange({bodyStart, lexer_->GetToken().End()});
830
831 auto *interfaceDecl =
832 AllocNode<ir::TSInterfaceDeclaration>(localScope.GetScope(), id, typeParamDecl, body, std::move(extends));
833 interfaceDecl->SetRange({interfaceStart, lexer_->GetToken().End()});
834
835 ASSERT(decl);
836
837 if (res == bindings.end()) {
838 decl->BindNode(interfaceDecl);
839 }
840 decl->AsInterfaceDecl()->Add(interfaceDecl);
841
842 lexer_->NextToken();
843 context_.Status() &= ~ParserStatus::ALLOW_THIS_TYPE;
844
845 return interfaceDecl;
846 }
847
CheckFunctionDeclaration(StatementParsingFlags flags)848 void ParserImpl::CheckFunctionDeclaration(StatementParsingFlags flags)
849 {
850 if (flags & StatementParsingFlags::ALLOW_LEXICAL) {
851 return;
852 }
853
854 if (lexer_->Lookahead() == LEX_CHAR_ASTERISK) {
855 ThrowSyntaxError("Generators can only be declared at the top level or inside a block.");
856 }
857
858 ThrowSyntaxError(
859 "In strict mode code, functions can only be "
860 "declared at top level, inside a block, "
861 "or "
862 "as the body of an if statement");
863 }
864
ConsumeSemicolon(ir::Statement * statement)865 void ParserImpl::ConsumeSemicolon(ir::Statement *statement)
866 {
867 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
868 statement->SetEnd(lexer_->GetToken().End());
869 lexer_->NextToken();
870 return;
871 }
872
873 if (!lexer_->GetToken().NewLine()) {
874 if (lexer_->GetToken().Type() != lexer::TokenType::EOS &&
875 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
876 ThrowSyntaxError("Unexpected token");
877 }
878 }
879 }
880
ParseStatementList(StatementParsingFlags flags)881 ArenaVector<ir::Statement *> ParserImpl::ParseStatementList(StatementParsingFlags flags)
882 {
883 ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
884 ParseDirectivePrologue(&statements);
885
886 auto endType =
887 (flags & StatementParsingFlags::GLOBAL) ? lexer::TokenType::EOS : lexer::TokenType::PUNCTUATOR_RIGHT_BRACE;
888
889 while (lexer_->GetToken().Type() != endType) {
890 statements.push_back(ParseStatement(flags));
891 }
892
893 return statements;
894 }
895
ParseDirective(ArenaVector<ir::Statement * > * statements)896 bool ParserImpl::ParseDirective(ArenaVector<ir::Statement *> *statements)
897 {
898 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
899
900 const util::StringView &str = lexer_->GetToken().String();
901
902 const auto status = static_cast<ParserStatus>(
903 context_.Status() & (ParserStatus::CONSTRUCTOR_FUNCTION | ParserStatus::HAS_COMPLEX_PARAM));
904 if (status == ParserStatus::HAS_COMPLEX_PARAM && str.Is("use strict")) {
905 ThrowSyntaxError(
906 "Illegal 'use strict' directive in function with "
907 "non-simple parameter list");
908 }
909
910 ir::Expression *exprNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
911 bool isDirective = exprNode->IsStringLiteral();
912
913 auto *exprStatement = AllocNode<ir::ExpressionStatement>(exprNode);
914 exprStatement->SetRange(exprNode->Range());
915
916 ConsumeSemicolon(exprStatement);
917 statements->push_back(exprStatement);
918
919 return isDirective;
920 }
921
ParseDirectivePrologue(ArenaVector<ir::Statement * > * statements)922 void ParserImpl::ParseDirectivePrologue(ArenaVector<ir::Statement *> *statements)
923 {
924 while (true) {
925 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING || !ParseDirective(statements)) {
926 break;
927 }
928 }
929 }
930
ParseBlockStatement(binder::Scope * scope)931 ir::BlockStatement *ParserImpl::ParseBlockStatement(binder::Scope *scope)
932 {
933 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
934
935 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
936 lexer_->NextToken();
937 auto statements = ParseStatementList();
938
939 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
940 ThrowSyntaxError("Expected a '}'");
941 }
942
943 auto *blockNode = AllocNode<ir::BlockStatement>(scope, std::move(statements));
944 blockNode->SetRange({startLoc, lexer_->GetToken().End()});
945 scope->BindNode(blockNode);
946
947 return blockNode;
948 }
949
ParseBlockStatement()950 ir::BlockStatement *ParserImpl::ParseBlockStatement()
951 {
952 auto localCtx = binder::LexicalScope<binder::LocalScope>(Binder());
953 auto *blockNode = ParseBlockStatement(localCtx.GetScope());
954 lexer_->NextToken();
955 return blockNode;
956 }
957
ParseBreakStatement()958 ir::BreakStatement *ParserImpl::ParseBreakStatement()
959 {
960 bool allowBreak = (context_.Status() & (ParserStatus::IN_ITERATION | ParserStatus::IN_SWITCH));
961
962 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
963 lexer_->NextToken();
964
965 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON ||
966 lexer_->GetToken().Type() == lexer::TokenType::EOS || lexer_->GetToken().NewLine() ||
967 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
968
969 if (!allowBreak && Extension() == ScriptExtension::JS) {
970 ThrowSyntaxError("Illegal break statement");
971 }
972
973 if (!allowBreak && Extension() == ScriptExtension::TS) {
974 if (context_.Status() & ParserStatus::FUNCTION) {
975 ThrowSyntaxError("Jump target cannot cross function boundary");
976 } else {
977 ThrowSyntaxError(
978 "A 'break' statement can only be used within an "
979 "enclosing iteration or switch statement");
980 }
981 }
982
983 auto *breakStatement = AllocNode<ir::BreakStatement>();
984 breakStatement->SetRange({startLoc, lexer_->GetToken().End()});
985 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
986 lexer_->NextToken();
987 }
988
989 return breakStatement;
990 }
991
992 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
993 ThrowSyntaxError("Unexpected token.");
994 }
995
996 const auto &label = lexer_->GetToken().Ident();
997
998 if (!context_.FindLabel(label)) {
999 ThrowSyntaxError("Undefined label");
1000 }
1001
1002 auto *identNode = AllocNode<ir::Identifier>(label);
1003 identNode->SetRange(lexer_->GetToken().Loc());
1004
1005 auto *breakStatement = AllocNode<ir::BreakStatement>(identNode);
1006 breakStatement->SetRange({startLoc, lexer_->GetToken().End()});
1007
1008 lexer_->NextToken();
1009 ConsumeSemicolon(breakStatement);
1010
1011 return breakStatement;
1012 }
1013
ParseContinueStatement()1014 ir::ContinueStatement *ParserImpl::ParseContinueStatement()
1015 {
1016 if (Extension() == ScriptExtension::TS &&
1017 (static_cast<ParserStatus>(context_.Status() & (ParserStatus::FUNCTION | ParserStatus::IN_ITERATION |
1018 ParserStatus::IN_SWITCH)) == ParserStatus::FUNCTION)) {
1019 ThrowSyntaxError("Jump target cannot cross function boundary");
1020 }
1021
1022 if (!(context_.Status() & ParserStatus::IN_ITERATION)) {
1023 if (Extension() == ScriptExtension::JS) {
1024 ThrowSyntaxError("Illegal continue statement");
1025 }
1026 if (Extension() == ScriptExtension::TS) {
1027 ThrowSyntaxError(
1028 "A 'continue' statement can only be used within an "
1029 "enclosing iteration statement");
1030 }
1031 }
1032
1033 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1034 lexer::SourcePosition endLoc = lexer_->GetToken().End();
1035 lexer_->NextToken();
1036
1037 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1038 auto *continueStatement = AllocNode<ir::ContinueStatement>();
1039 continueStatement->SetRange({startLoc, lexer_->GetToken().End()});
1040 lexer_->NextToken();
1041 return continueStatement;
1042 }
1043
1044 if (lexer_->GetToken().NewLine() || lexer_->GetToken().Type() == lexer::TokenType::EOS ||
1045 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1046 auto *continueStatement = AllocNode<ir::ContinueStatement>();
1047 continueStatement->SetRange({startLoc, endLoc});
1048 return continueStatement;
1049 }
1050
1051 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1052 ThrowSyntaxError("Unexpected token.");
1053 }
1054
1055 const auto &label = lexer_->GetToken().Ident();
1056 const ParserContext *labelCtx = context_.FindLabel(label);
1057
1058 if (!labelCtx || !(labelCtx->Status() & (ParserStatus::IN_ITERATION | ParserStatus::IN_LABELED)) ||
1059 (labelCtx->Status() & ParserStatus::DISALLOW_CONTINUE)) {
1060 ThrowSyntaxError("Undefined label");
1061 }
1062
1063 auto *identNode = AllocNode<ir::Identifier>(label);
1064 identNode->SetRange(lexer_->GetToken().Loc());
1065
1066 auto *continueStatement = AllocNode<ir::ContinueStatement>(identNode);
1067 continueStatement->SetRange({startLoc, lexer_->GetToken().End()});
1068
1069 lexer_->NextToken();
1070 ConsumeSemicolon(continueStatement);
1071
1072 return continueStatement;
1073 }
1074
ParseDoWhileStatement()1075 ir::DoWhileStatement *ParserImpl::ParseDoWhileStatement()
1076 {
1077 IterationContext<binder::LoopScope> iterCtx(&context_, Binder());
1078
1079 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1080 lexer_->NextToken();
1081 ir::Statement *body = ParseStatement();
1082
1083 if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_WHILE) {
1084 ThrowSyntaxError("Missing 'while' keyword in a 'DoWhileStatement'");
1085 }
1086
1087 lexer_->NextToken();
1088 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1089 ThrowSyntaxError("Missing left parenthesis in a 'DoWhileStatement'");
1090 }
1091
1092 lexer_->NextToken();
1093
1094 ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1095
1096 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1097 ThrowSyntaxError("Missing right parenthesis in a 'DoWhileStatement'");
1098 }
1099
1100 auto *doWhileStatement = AllocNode<ir::DoWhileStatement>(iterCtx.LexicalScope().GetScope(), body, test);
1101 doWhileStatement->SetRange({startLoc, lexer_->GetToken().End()});
1102 iterCtx.LexicalScope().GetScope()->BindNode(doWhileStatement);
1103
1104 lexer_->NextToken();
1105
1106 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1107 doWhileStatement->SetEnd(lexer_->GetToken().End());
1108 lexer_->NextToken();
1109 }
1110
1111 return doWhileStatement;
1112 }
1113
ParseFunctionDeclaration(bool canBeAnonymous,ParserStatus newStatus,bool isDeclare)1114 ir::FunctionDeclaration *ParserImpl::ParseFunctionDeclaration(bool canBeAnonymous, ParserStatus newStatus,
1115 bool isDeclare)
1116 {
1117 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1118
1119 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION);
1120 ParserStatus savedStatus = context_.Status();
1121
1122 lexer_->NextToken();
1123
1124 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
1125 newStatus |= ParserStatus::GENERATOR_FUNCTION;
1126 lexer_->NextToken();
1127 }
1128
1129 context_.Status() = savedStatus;
1130
1131 // e.g. export default function () {}
1132 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT &&
1133 lexer_->GetToken().Type() != lexer::TokenType::KEYW_AWAIT) {
1134 if (canBeAnonymous) {
1135 ir::ScriptFunction *func = ParseFunction(newStatus, isDeclare);
1136 if (func->Body() != nullptr) {
1137 lexer_->NextToken();
1138 }
1139 func->SetStart(startLoc);
1140 func->SetAsExportDefault();
1141
1142 auto *funcDecl = AllocNode<ir::FunctionDeclaration>(func);
1143 funcDecl->SetRange(func->Range());
1144
1145 binder::DeclarationFlags declflag = (newStatus & ParserStatus::EXPORT_REACHED) ?
1146 binder::DeclarationFlags::EXPORT : binder::DeclarationFlags::NONE;
1147 Binder()->AddDecl<binder::FunctionDecl>(startLoc, declflag, isDeclare, Allocator(),
1148 parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME, func);
1149
1150 return funcDecl;
1151 }
1152
1153 ThrowSyntaxError("Unexpected token, expected identifier after 'function' keyword");
1154 }
1155
1156 if (!isDeclare) {
1157 CheckStrictReservedWord();
1158 }
1159
1160 util::StringView ident = lexer_->GetToken().Ident();
1161
1162 auto *identNode = AllocNode<ir::Identifier>(ident);
1163 identNode->SetRange(lexer_->GetToken().Loc());
1164 lexer_->NextToken();
1165
1166 newStatus |= ParserStatus::FUNCTION_DECLARATION;
1167 ir::ScriptFunction *func = ParseFunction(newStatus, isDeclare);
1168 if (func->Body() != nullptr) {
1169 lexer_->NextToken();
1170 }
1171
1172 func->SetIdent(identNode);
1173 func->SetStart(startLoc);
1174 auto *funcDecl = AllocNode<ir::FunctionDeclaration>(func);
1175 funcDecl->SetRange(func->Range());
1176
1177 AddFunctionToBinder(func, newStatus);
1178
1179 if (func->IsOverload() && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1180 lexer_->NextToken();
1181 }
1182
1183 CheckOptionalBindingPatternParameter(func);
1184
1185 return funcDecl;
1186 }
1187
AddFunctionToBinder(ir::ScriptFunction * func,ParserStatus newStatus)1188 void ParserImpl::AddFunctionToBinder(ir::ScriptFunction *func, ParserStatus newStatus)
1189 {
1190 binder::DeclarationFlags declflag = (newStatus & ParserStatus::EXPORT_REACHED) ?
1191 binder::DeclarationFlags::EXPORT : binder::DeclarationFlags::NONE;
1192 const ir::Identifier *identNode = func->Id();
1193 const lexer::SourcePosition &startLoc = func->Start();
1194 const util::StringView ident = identNode->Name();
1195 if (Extension() == ScriptExtension::TS) {
1196 const auto &bindings = Binder()->GetScope()->Bindings();
1197 auto res = bindings.find(ident);
1198 binder::Decl *currentDecl = res == bindings.end() ? nullptr : res->second->Declaration();
1199 binder::FunctionDecl *decl {};
1200
1201 if (res == bindings.end() ||
1202 (currentDecl->IsClassDecl() && currentDecl->AsClassDecl()->IsDeclare())) {
1203 decl = Binder()->AddDecl<binder::FunctionDecl>(identNode->Start(), declflag, func->Declare(),
1204 Allocator(), ident, func);
1205 } else {
1206 if (!currentDecl->IsFunctionDecl()) {
1207 Binder()->ThrowRedeclaration(startLoc, currentDecl->Name());
1208 }
1209
1210 decl = currentDecl->AsFunctionDecl();
1211
1212 if (!decl->Node()->AsScriptFunction()->IsOverload()) {
1213 Binder()->ThrowRedeclaration(startLoc, currentDecl->Name());
1214 }
1215 if (!func->IsOverload()) {
1216 decl->BindNode(func);
1217 }
1218 }
1219
1220 decl->Add(func);
1221 } else {
1222 Binder()->AddDecl<binder::FunctionDecl>(identNode->Start(), declflag, func->Declare(),
1223 Allocator(), ident, func);
1224 }
1225 }
1226
CheckOptionalBindingPatternParameter(ir::ScriptFunction * func) const1227 void ParserImpl::CheckOptionalBindingPatternParameter(ir::ScriptFunction *func) const
1228 {
1229 if (func->Declare() || func->IsOverload()) {
1230 return;
1231 }
1232 for (auto *it : func->Params()) {
1233 if ((it->IsObjectPattern() && it->AsObjectPattern()->Optional()) ||
1234 (it->IsArrayPattern() && it->AsArrayPattern()->Optional())) {
1235 ThrowSyntaxError(
1236 "A binding pattern parameter cannot be optional in an "
1237 "implementation signature", it->Start());
1238 }
1239 }
1240 }
1241
ParseExpressionStatement(StatementParsingFlags flags)1242 ir::Statement *ParserImpl::ParseExpressionStatement(StatementParsingFlags flags)
1243 {
1244 const auto startPos = lexer_->Save();
1245 ParserStatus savedStatus = context_.Status();
1246
1247 if (lexer_->GetToken().IsAsyncModifier()) {
1248 context_.Status() |= ParserStatus::ASYNC_FUNCTION;
1249 lexer_->NextToken();
1250
1251 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION && !lexer_->GetToken().NewLine()) {
1252 if (!(flags & StatementParsingFlags::ALLOW_LEXICAL)) {
1253 ThrowSyntaxError("Async functions can only be declared at the top level or inside a block.");
1254 }
1255
1256 ir::FunctionDeclaration *functionDecl = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION);
1257 functionDecl->SetStart(startPos.token.Start());
1258
1259 return functionDecl;
1260 }
1261
1262 lexer_->Rewind(startPos);
1263 }
1264
1265 ir::Expression *exprNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1266 context_.Status() = savedStatus;
1267 lexer::SourcePosition endPos = exprNode->End();
1268
1269 auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(exprNode);
1270 exprStatementNode->SetRange({startPos.token.Start(), endPos});
1271 ConsumeSemicolon(exprStatementNode);
1272
1273 return exprStatementNode;
1274 }
1275
ParseForInOf(ir::AstNode * initNode,ExpressionParseFlags exprFlags,bool isAwait)1276 std::tuple<ForStatementKind, ir::Expression *, ir::Expression *> ParserImpl::ParseForInOf(
1277 ir::AstNode *initNode, ExpressionParseFlags exprFlags, bool isAwait)
1278 {
1279 ForStatementKind forKind = ForStatementKind::UPDATE;
1280 ir::Expression *updateNode = nullptr;
1281 ir::Expression *rightNode = nullptr;
1282
1283 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN ||
1284 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OF) {
1285 const ir::VariableDeclarator *varDecl = initNode->AsVariableDeclaration()->Declarators().front();
1286
1287 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN) {
1288 if (varDecl->Init()) {
1289 ThrowSyntaxError("for-in loop variable declaration may not have an initializer");
1290 }
1291 forKind = ForStatementKind::IN;
1292 exprFlags = ExpressionParseFlags::ACCEPT_COMMA;
1293 } else {
1294 if (varDecl->Init()) {
1295 ThrowSyntaxError("for-of loop variable declaration may not have an initializer");
1296 }
1297
1298 forKind = ForStatementKind::OF;
1299 }
1300
1301 lexer_->NextToken();
1302 rightNode = ParseExpression(exprFlags);
1303 } else {
1304 if (isAwait) {
1305 ThrowSyntaxError("Unexpected token");
1306 }
1307
1308 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1309 ThrowSyntaxError("Invalid left-hand side in 'For[In/Of]Statement'");
1310 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1311 lexer_->NextToken();
1312 } else {
1313 rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1314 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1315 ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
1316 }
1317 lexer_->NextToken();
1318 }
1319
1320 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1321 updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1322 }
1323 }
1324
1325 return {forKind, rightNode, updateNode};
1326 }
1327
ParseForInOf(ir::Expression * leftNode,ExpressionParseFlags exprFlags,bool isAwait)1328 std::tuple<ForStatementKind, ir::AstNode *, ir::Expression *, ir::Expression *> ParserImpl::ParseForInOf(
1329 ir::Expression *leftNode, ExpressionParseFlags exprFlags, bool isAwait)
1330 {
1331 ForStatementKind forKind = ForStatementKind::UPDATE;
1332 ir::AstNode *initNode = nullptr;
1333 ir::Expression *updateNode = nullptr;
1334 ir::Expression *rightNode = nullptr;
1335
1336 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN ||
1337 (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OF)) {
1338 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN) {
1339 forKind = ForStatementKind::IN;
1340 exprFlags = ExpressionParseFlags::ACCEPT_COMMA;
1341 } else {
1342 forKind = ForStatementKind::OF;
1343 }
1344
1345 bool isValid = true;
1346 switch (leftNode->Type()) {
1347 case ir::AstNodeType::IDENTIFIER:
1348 case ir::AstNodeType::MEMBER_EXPRESSION: {
1349 break;
1350 }
1351 case ir::AstNodeType::ARRAY_EXPRESSION: {
1352 isValid = leftNode->AsArrayExpression()->ConvertibleToArrayPattern();
1353 break;
1354 }
1355 case ir::AstNodeType::OBJECT_EXPRESSION: {
1356 isValid = leftNode->AsObjectExpression()->ConvertibleToObjectPattern();
1357 break;
1358 }
1359 default: {
1360 isValid = false;
1361 }
1362 }
1363
1364 if (!isValid) {
1365 ValidateLvalueAssignmentTarget(leftNode);
1366 }
1367
1368 initNode = leftNode;
1369 lexer_->NextToken();
1370 rightNode = ParseExpression(exprFlags);
1371
1372 return {forKind, initNode, rightNode, updateNode};
1373 }
1374
1375 if (isAwait) {
1376 ThrowSyntaxError("Unexpected token");
1377 }
1378
1379 exprFlags &= ExpressionParseFlags::POTENTIALLY_IN_PATTERN;
1380 ir::Expression *expr = ParseAssignmentExpression(leftNode, exprFlags);
1381
1382 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
1383 initNode = ParseSequenceExpression(expr);
1384 } else {
1385 initNode = expr;
1386 }
1387
1388 if (initNode->IsConditionalExpression()) {
1389 ir::ConditionalExpression *condExpr = initNode->AsConditionalExpression();
1390 if (condExpr->Alternate()->IsBinaryExpression()) {
1391 const auto *binaryExpr = condExpr->Alternate()->AsBinaryExpression();
1392 if (binaryExpr->OperatorType() == lexer::TokenType::KEYW_IN) {
1393 ThrowSyntaxError("Invalid left-hand side in for-in statement");
1394 }
1395 }
1396 }
1397
1398 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1399 ThrowSyntaxError("Invalid left-hand side in 'For[In/Of]Statement'");
1400 }
1401
1402 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1403 ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
1404 }
1405
1406 lexer_->NextToken();
1407
1408 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1409 lexer_->NextToken();
1410 } else {
1411 rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1412
1413 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1414 ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
1415 }
1416 lexer_->NextToken();
1417 }
1418
1419 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1420 updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1421 }
1422
1423 return {forKind, initNode, rightNode, updateNode};
1424 }
1425
ParseForUpdate(bool isAwait)1426 std::tuple<ir::Expression *, ir::Expression *> ParserImpl::ParseForUpdate(bool isAwait)
1427 {
1428 if (isAwait) {
1429 ThrowSyntaxError("Unexpected token");
1430 }
1431
1432 ir::Expression *updateNode = nullptr;
1433 ir::Expression *rightNode = nullptr;
1434
1435 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1436 lexer_->NextToken();
1437 } else {
1438 rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1439 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1440 ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
1441 }
1442 lexer_->NextToken();
1443 }
1444
1445 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1446 updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1447 }
1448
1449 return {rightNode, updateNode};
1450 }
1451
ParseForStatement()1452 ir::Statement *ParserImpl::ParseForStatement()
1453 {
1454 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1455 ForStatementKind forKind = ForStatementKind::UPDATE;
1456 ir::AstNode *initNode = nullptr;
1457 ir::Expression *updateNode = nullptr;
1458 ir::Expression *leftNode = nullptr;
1459 ir::Expression *rightNode = nullptr;
1460 bool canBeForInOf = true;
1461 bool isAwait = false;
1462 lexer_->NextToken();
1463 VariableParsingFlags varFlags = VariableParsingFlags::STOP_AT_IN | VariableParsingFlags::IN_FOR;
1464 ExpressionParseFlags exprFlags = ExpressionParseFlags::NO_OPTS;
1465
1466 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) {
1467 isAwait = true;
1468 varFlags |= VariableParsingFlags::DISALLOW_INIT;
1469 lexer_->NextToken();
1470 }
1471
1472 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1473 ThrowSyntaxError("Missing left parenthesis in a 'ForStatement'");
1474 }
1475 lexer_->NextToken();
1476
1477 IterationContext<binder::LoopScope> iterCtx(&context_, Binder());
1478
1479 switch (lexer_->GetToken().Type()) {
1480 case lexer::TokenType::KEYW_VAR: {
1481 initNode = ParseVariableDeclaration(varFlags | VariableParsingFlags::VAR);
1482 break;
1483 }
1484 case lexer::TokenType::KEYW_LET: {
1485 initNode = ParseVariableDeclaration(varFlags | VariableParsingFlags::LET);
1486 break;
1487 }
1488 case lexer::TokenType::KEYW_CONST: {
1489 initNode = ParseVariableDeclaration(varFlags | VariableParsingFlags::CONST |
1490 VariableParsingFlags::ACCEPT_CONST_NO_INIT);
1491 break;
1492 }
1493 case lexer::TokenType::PUNCTUATOR_SEMI_COLON: {
1494 if (isAwait) {
1495 ThrowSyntaxError("Unexpected token");
1496 }
1497
1498 canBeForInOf = false;
1499 lexer_->NextToken();
1500 break;
1501 }
1502 default: {
1503 leftNode = ParseUnaryOrPrefixUpdateExpression(ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
1504
1505 break;
1506 }
1507 }
1508
1509 if (initNode != nullptr) {
1510 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1511 lexer_->NextToken();
1512 canBeForInOf = false;
1513 } else {
1514 canBeForInOf = initNode->AsVariableDeclaration()->Declarators().size() == 1;
1515 }
1516 }
1517
1518 // VariableDeclaration->DeclarationSize > 1 or seen semi_colon
1519 if (!canBeForInOf) {
1520 std::tie(rightNode, updateNode) = ParseForUpdate(isAwait);
1521 } else if (leftNode) {
1522 // initNode was parsed as LHS
1523 if (leftNode->IsArrayExpression() || leftNode->IsObjectExpression()) {
1524 exprFlags |= ExpressionParseFlags::POTENTIALLY_IN_PATTERN;
1525 }
1526 std::tie(forKind, initNode, rightNode, updateNode) = ParseForInOf(leftNode, exprFlags, isAwait);
1527 } else if (initNode) {
1528 // initNode was parsed as VariableDeclaration and declaration size = 1
1529 std::tie(forKind, rightNode, updateNode) = ParseForInOf(initNode, exprFlags, isAwait);
1530 }
1531
1532 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1533 ThrowSyntaxError("Unexpected token, expected ')' in 'ForStatement'.");
1534 }
1535 lexer_->NextToken();
1536
1537 ir::Statement *bodyNode = ParseStatement();
1538 lexer::SourcePosition endLoc = bodyNode->End();
1539
1540 ir::Statement *forStatement = nullptr;
1541 auto *loopScope = iterCtx.LexicalScope().GetScope();
1542
1543 if (forKind == ForStatementKind::UPDATE) {
1544 forStatement = AllocNode<ir::ForUpdateStatement>(loopScope, initNode, rightNode, updateNode, bodyNode);
1545 } else if (forKind == ForStatementKind::IN) {
1546 forStatement = AllocNode<ir::ForInStatement>(loopScope, initNode, rightNode, bodyNode);
1547 } else {
1548 forStatement = AllocNode<ir::ForOfStatement>(loopScope, initNode, rightNode, bodyNode, isAwait);
1549 }
1550
1551 forStatement->SetRange({startLoc, endLoc});
1552 loopScope->BindNode(forStatement);
1553
1554 return forStatement;
1555 }
1556
ParseIfStatement()1557 ir::IfStatement *ParserImpl::ParseIfStatement()
1558 {
1559 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1560 lexer::SourcePosition endLoc = lexer_->GetToken().End();
1561 lexer_->NextToken();
1562
1563 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1564 ThrowSyntaxError("Missing left parenthesis in an 'IfStatement'");
1565 }
1566
1567 lexer_->NextToken();
1568 ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1569
1570 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1571 ThrowSyntaxError("Missing right parenthesis in an 'IfStatement'");
1572 }
1573
1574 lexer_->NextToken();
1575 ir::Statement *consequent = ParseStatement(StatementParsingFlags::IF_ELSE);
1576
1577 if (Extension() == ScriptExtension::TS && consequent->IsEmptyStatement()) {
1578 ThrowSyntaxError("The body of an if statement cannot be the empty statement");
1579 }
1580
1581 endLoc = consequent->End();
1582 ir::Statement *alternate = nullptr;
1583
1584 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_ELSE) {
1585 lexer_->NextToken(); // eat ELSE keyword
1586 alternate = ParseStatement(StatementParsingFlags::IF_ELSE);
1587 endLoc = alternate->End();
1588 }
1589
1590 auto *ifStatement = AllocNode<ir::IfStatement>(test, consequent, alternate);
1591 ifStatement->SetRange({startLoc, endLoc});
1592 return ifStatement;
1593 }
1594
ParseLabelledStatement(const lexer::LexerPosition & pos)1595 ir::LabelledStatement *ParserImpl::ParseLabelledStatement(const lexer::LexerPosition &pos)
1596 {
1597 const auto savedPos = lexer_->Save();
1598 bool isLabelFollowedByIterationStatement = IsLabelFollowedByIterationStatement();
1599 lexer_->Rewind(savedPos);
1600
1601 const util::StringView &actualLabel = pos.token.Ident();
1602
1603 // TODO(frobert) : check correctness
1604 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AWAIT && context_.IsModule()) {
1605 ThrowSyntaxError("'await' is a reserved identifier in module code", pos.token.Start());
1606 }
1607
1608 if (context_.FindLabel(actualLabel)) {
1609 ThrowSyntaxError("Label already declared", pos.token.Start());
1610 }
1611
1612 SavedParserContext newCtx(this, ParserStatus::IN_LABELED | context_.Status(), actualLabel);
1613 if (isLabelFollowedByIterationStatement) {
1614 context_.Status() &= ~ParserStatus::DISALLOW_CONTINUE;
1615 } else {
1616 context_.Status() |= ParserStatus::DISALLOW_CONTINUE;
1617 }
1618
1619 auto *identNode = AllocNode<ir::Identifier>(actualLabel);
1620 identNode->SetRange(pos.token.Loc());
1621
1622 lexer_->NextToken();
1623
1624 ir::Statement *body = ParseStatement(StatementParsingFlags::LABELLED);
1625
1626 auto *labeledStatement = AllocNode<ir::LabelledStatement>(identNode, body);
1627 labeledStatement->SetRange({pos.token.Start(), body->End()});
1628
1629 return labeledStatement;
1630 }
1631
ParseReturnStatement()1632 ir::ReturnStatement *ParserImpl::ParseReturnStatement()
1633 {
1634 if (!(context_.Status() & ParserStatus::FUNCTION)) {
1635 ThrowSyntaxError("return keyword should be used in function body");
1636 }
1637
1638 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1639 lexer::SourcePosition endLoc = lexer_->GetToken().End();
1640 lexer_->NextToken();
1641
1642 bool hasArgument = (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
1643 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
1644 lexer_->GetToken().Type() != lexer::TokenType::EOS && !lexer_->GetToken().NewLine());
1645
1646 ir::ReturnStatement *returnStatement = nullptr;
1647
1648 if (hasArgument) {
1649 ir::Expression *expression = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1650 endLoc = expression->End();
1651 returnStatement = AllocNode<ir::ReturnStatement>(expression);
1652 } else {
1653 returnStatement = AllocNode<ir::ReturnStatement>();
1654 }
1655
1656 returnStatement->SetRange({startLoc, endLoc});
1657 ConsumeSemicolon(returnStatement);
1658
1659 return returnStatement;
1660 }
1661
ParseSwitchCaseStatement(bool * seenDefault)1662 ir::SwitchCaseStatement *ParserImpl::ParseSwitchCaseStatement(bool *seenDefault)
1663 {
1664 lexer::SourcePosition caseStartLoc = lexer_->GetToken().Start();
1665 ir::Expression *testExpr = nullptr;
1666
1667 switch (lexer_->GetToken().Type()) {
1668 case lexer::TokenType::KEYW_CASE: {
1669 lexer_->NextToken();
1670 testExpr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1671 break;
1672 }
1673 case lexer::TokenType::KEYW_DEFAULT: {
1674 if (*seenDefault) {
1675 if (Extension() == ScriptExtension::TS) {
1676 ThrowSyntaxError(
1677 "A 'default' clause cannot appear more than once in a "
1678 "'switch' statement");
1679 } else {
1680 ThrowSyntaxError("Multiple default clauses.");
1681 }
1682 }
1683 *seenDefault = true;
1684 lexer_->NextToken();
1685 break;
1686 }
1687 default: {
1688 ThrowSyntaxError("Unexpected token, expected 'case' or 'default'.");
1689 }
1690 }
1691
1692 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
1693 ThrowSyntaxError("Unexpected token, expected ':'");
1694 }
1695
1696 ArenaVector<ir::Statement *> consequents(Allocator()->Adapter());
1697 lexer::SourcePosition caseEndLoc = lexer_->GetToken().End();
1698
1699 lexer_->NextToken();
1700
1701 while (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CASE &&
1702 lexer_->GetToken().Type() != lexer::TokenType::KEYW_DEFAULT &&
1703 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1704 ir::Statement *consequent = ParseStatement(StatementParsingFlags::ALLOW_LEXICAL);
1705 caseEndLoc = consequent->End();
1706 consequents.push_back(consequent);
1707 }
1708
1709 auto *caseNode = AllocNode<ir::SwitchCaseStatement>(testExpr, std::move(consequents));
1710 caseNode->SetRange({caseStartLoc, caseEndLoc});
1711 return caseNode;
1712 }
1713
ParseSwitchStatement()1714 ir::SwitchStatement *ParserImpl::ParseSwitchStatement()
1715 {
1716 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1717 lexer_->NextToken();
1718 if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS)) {
1719 ThrowSyntaxError("Unexpected token, expected '('");
1720 }
1721
1722 lexer_->NextToken();
1723 ir::Expression *discriminant = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1724
1725 if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS)) {
1726 ThrowSyntaxError("Unexpected token, expected ')'");
1727 }
1728
1729 lexer_->NextToken();
1730 SwitchContext switchContext(&context_);
1731
1732 if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE)) {
1733 ThrowSyntaxError("Unexpected token, expected '{'");
1734 }
1735
1736 lexer_->NextToken();
1737 bool seenDefault = false;
1738 auto localCtx = binder::LexicalScope<binder::LocalScope>(Binder());
1739 ArenaVector<ir::SwitchCaseStatement *> cases(Allocator()->Adapter());
1740
1741 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1742 cases.push_back(ParseSwitchCaseStatement(&seenDefault));
1743 }
1744
1745 auto *switchStatement = AllocNode<ir::SwitchStatement>(localCtx.GetScope(), discriminant, std::move(cases));
1746 switchStatement->SetRange({startLoc, lexer_->GetToken().End()});
1747 localCtx.GetScope()->BindNode(switchStatement);
1748
1749 lexer_->NextToken();
1750
1751 return switchStatement;
1752 }
1753
ParseThrowStatement()1754 ir::ThrowStatement *ParserImpl::ParseThrowStatement()
1755 {
1756 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1757 lexer_->NextToken();
1758
1759 if (lexer_->GetToken().NewLine()) {
1760 if (Extension() == ScriptExtension::JS) {
1761 ThrowSyntaxError("Illegal newline after throw");
1762 }
1763
1764 if (Extension() == ScriptExtension::TS) {
1765 ThrowSyntaxError("Line break not permitted here");
1766 }
1767 }
1768
1769 ir::Expression *expression = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1770 lexer::SourcePosition endLoc = expression->End();
1771
1772 auto *throwStatement = AllocNode<ir::ThrowStatement>(expression);
1773 throwStatement->SetRange({startLoc, endLoc});
1774 ConsumeSemicolon(throwStatement);
1775
1776 return throwStatement;
1777 }
1778
ParseCatchParam()1779 ir::Expression *ParserImpl::ParseCatchParam()
1780 {
1781 ir::Expression *param = nullptr;
1782
1783 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1784 return param;
1785 }
1786
1787 lexer_->NextToken(); // eat left paren
1788
1789 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1790 switch (lexer_->GetToken().KeywordType()) {
1791 case lexer::TokenType::KEYW_EVAL: {
1792 ThrowSyntaxError("Binding 'eval' in strict mode is invalid");
1793 }
1794 case lexer::TokenType::KEYW_ARGUMENTS: {
1795 ThrowSyntaxError("Binding 'arguments' in strict mode is invalid");
1796 }
1797 default: {
1798 break;
1799 }
1800 }
1801
1802 param = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1803 param->SetRange(lexer_->GetToken().Loc());
1804
1805 lexer_->NextToken();
1806 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1807 param = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1808 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1809 param = ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1810 } else {
1811 ThrowSyntaxError("Unexpected token in catch parameter");
1812 }
1813
1814 Binder()->AddParamDecl(param);
1815
1816 if (Extension() == ScriptExtension::TS) {
1817 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1818 lexer_->NextToken(); // eat ':'
1819
1820 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1821 param->SetTsTypeAnnotation(ParseTsTypeAnnotation(&options));
1822 }
1823
1824 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
1825 ThrowSyntaxError("Catch clause variable cannot have an initializer");
1826 }
1827 }
1828
1829 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1830 ThrowSyntaxError("Unexpected token, expected ')'");
1831 }
1832
1833 lexer_->NextToken();
1834
1835 return param;
1836 }
1837
ParseCatchClause()1838 ir::CatchClause *ParserImpl::ParseCatchClause()
1839 {
1840 lexer::SourcePosition catchStartLoc = lexer_->GetToken().Start();
1841 lexer_->NextToken(); // eat 'catch' keyword
1842
1843 auto catchParamCtx = binder::LexicalScope<binder::CatchParamScope>(Binder());
1844 auto *catchParamScope = catchParamCtx.GetScope();
1845
1846 ir::Expression *param = ParseCatchParam();
1847 catchParamScope->BindNode(param);
1848
1849 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1850 ThrowSyntaxError("Unexpected token, expected '{'");
1851 }
1852
1853 auto catchCtx = binder::LexicalScope<binder::CatchScope>(Binder());
1854 auto *catchScope = catchCtx.GetScope();
1855 catchScope->AssignParamScope(catchParamScope);
1856
1857 ir::BlockStatement *catchBlock = ParseBlockStatement(catchScope);
1858 lexer_->NextToken();
1859 lexer::SourcePosition endLoc = catchBlock->End();
1860
1861 auto *catchClause = AllocNode<ir::CatchClause>(catchScope, param, catchBlock);
1862 catchClause->SetRange({catchStartLoc, endLoc});
1863 catchScope->BindNode(catchClause);
1864
1865 return catchClause;
1866 }
1867
ParseTryStatement()1868 ir::TryStatement *ParserImpl::ParseTryStatement()
1869 {
1870 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1871 lexer::SourcePosition endLoc = lexer_->GetToken().End();
1872
1873 lexer_->NextToken();
1874
1875 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1876 ThrowSyntaxError("Unexpected token, expected '{'");
1877 }
1878
1879 ir::BlockStatement *body = ParseBlockStatement();
1880
1881 if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CATCH &&
1882 lexer_->GetToken().Type() != lexer::TokenType::KEYW_FINALLY) {
1883 ThrowSyntaxError("Missing catch or finally clause");
1884 }
1885
1886 ir::CatchClause *catchClause = nullptr;
1887 ir::BlockStatement *finnalyClause = nullptr;
1888
1889 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_CATCH) {
1890 catchClause = ParseCatchClause();
1891 endLoc = catchClause->End();
1892 }
1893
1894 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FINALLY) {
1895 lexer_->NextToken(); // eat 'finally' keyword
1896
1897 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1898 ThrowSyntaxError("Unexpected token, expected '{'");
1899 }
1900
1901 finnalyClause = ParseBlockStatement();
1902 endLoc = finnalyClause->End();
1903 }
1904
1905 auto *tryStatement = AllocNode<ir::TryStatement>(body, catchClause, finnalyClause);
1906 tryStatement->SetRange({startLoc, endLoc});
1907 return tryStatement;
1908 }
1909
1910 // TODO(frobert) : merge into lexer::LexerNextTokenFlags
ValidateDeclaratorId()1911 void ParserImpl::ValidateDeclaratorId()
1912 {
1913 if (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT) {
1914 return;
1915 }
1916
1917 switch (lexer_->GetToken().KeywordType()) {
1918 case lexer::TokenType::KEYW_AWAIT: {
1919 if (context_.IsModule()) {
1920 ThrowSyntaxError("'await' is not permitted as an identifier in module code");
1921 }
1922 break;
1923 }
1924 case lexer::TokenType::KEYW_EVAL: {
1925 ThrowSyntaxError("Binding 'eval' in strict mode is invalid");
1926 }
1927 case lexer::TokenType::KEYW_ARGUMENTS: {
1928 ThrowSyntaxError("Binding 'arguments' in strict mode is invalid");
1929 }
1930 case lexer::TokenType::KEYW_LET: {
1931 ThrowSyntaxError("let is disallowed as a lexically bound name");
1932 break;
1933 }
1934 case lexer::TokenType::KEYW_STATIC:
1935 case lexer::TokenType::KEYW_IMPLEMENTS:
1936 case lexer::TokenType::KEYW_INTERFACE:
1937 case lexer::TokenType::KEYW_PACKAGE:
1938 case lexer::TokenType::KEYW_PRIVATE:
1939 case lexer::TokenType::KEYW_PROTECTED:
1940 case lexer::TokenType::KEYW_PUBLIC:
1941 case lexer::TokenType::KEYW_YIELD: {
1942 ThrowSyntaxError("Unexpected reserved word");
1943 }
1944 default: {
1945 break;
1946 }
1947 }
1948 }
1949
ParseVariableDeclaratorInitializer(ir::Expression * init,VariableParsingFlags flags,const lexer::SourcePosition & startLoc,bool isDeclare)1950 ir::VariableDeclarator *ParserImpl::ParseVariableDeclaratorInitializer(ir::Expression *init, VariableParsingFlags flags,
1951 const lexer::SourcePosition &startLoc,
1952 bool isDeclare)
1953 {
1954 if (flags & VariableParsingFlags::DISALLOW_INIT) {
1955 ThrowSyntaxError("for-await-of loop variable declaration may not have an initializer");
1956 }
1957
1958 lexer_->NextToken();
1959
1960 if (isDeclare && !(flags & VariableParsingFlags::CONST)) {
1961 ThrowSyntaxError("Initializers are not allowed in ambient contexts.");
1962 }
1963
1964 auto exprFlags =
1965 ((flags & VariableParsingFlags::STOP_AT_IN) ? ExpressionParseFlags::STOP_AT_IN : ExpressionParseFlags::NO_OPTS);
1966
1967 ir::Expression *initializer = ParseExpression(exprFlags);
1968 lexer::SourcePosition endLoc = initializer->End();
1969
1970 auto *declarator = AllocNode<ir::VariableDeclarator>(init, initializer);
1971 declarator->SetRange({startLoc, endLoc});
1972
1973 return declarator;
1974 }
1975
ParseVariableDeclarator(VariableParsingFlags flags,bool isDeclare)1976 ir::VariableDeclarator *ParserImpl::ParseVariableDeclarator(VariableParsingFlags flags, bool isDeclare)
1977 {
1978 ir::Expression *init = nullptr;
1979 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1980 switch (lexer_->GetToken().Type()) {
1981 case lexer::TokenType::LITERAL_IDENT: {
1982 ValidateDeclaratorId();
1983
1984 if (!(flags & VariableParsingFlags::VAR) &&
1985 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_LET) {
1986 ThrowSyntaxError("let is disallowed as a lexically bound name");
1987 }
1988
1989 const util::StringView &identStr = lexer_->GetToken().Ident();
1990 init = AllocNode<ir::Identifier>(identStr);
1991 init->SetRange(lexer_->GetToken().Loc());
1992
1993 if (Extension() == ScriptExtension::TS) {
1994 init->AsIdentifier()->SetReference();
1995 }
1996
1997 lexer_->NextToken();
1998 break;
1999 }
2000 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
2001 init = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
2002 break;
2003 }
2004 case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
2005 init = ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN);
2006 break;
2007 }
2008 default: {
2009 ThrowSyntaxError("Unexpected token in variable declaration");
2010 }
2011 }
2012
2013 bool isDefinite = false;
2014 if (Extension() == ScriptExtension::TS) {
2015 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) {
2016 lexer_->NextToken(); // eat '!'
2017 isDefinite = true;
2018 }
2019 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
2020 lexer_->NextToken(); // eat ':'
2021 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
2022 init->SetTsTypeAnnotation(ParseTsTypeAnnotation(&options));
2023 }
2024 }
2025
2026 ir::VariableDeclarator *declarator {};
2027
2028 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
2029 declarator = ParseVariableDeclaratorInitializer(init, flags, startLoc, isDeclare);
2030 } else {
2031 if (!isDeclare && (flags & VariableParsingFlags::CONST) &&
2032 !(flags & VariableParsingFlags::ACCEPT_CONST_NO_INIT) &&
2033 !(context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT)) {
2034 ThrowSyntaxError("Missing initializer in const declaration");
2035 }
2036
2037 if (!isDeclare && !(flags & VariableParsingFlags::IN_FOR) &&
2038 (init->IsArrayPattern() || init->IsObjectPattern())) {
2039 ThrowSyntaxError("Missing initializer in destructuring declaration");
2040 }
2041
2042 lexer::SourcePosition endLoc = init->End();
2043 declarator = AllocNode<ir::VariableDeclarator>(init);
2044 declarator->SetRange({startLoc, endLoc});
2045 }
2046
2047 declarator->SetDefinite(isDefinite);
2048
2049 std::vector<const ir::Identifier *> bindings = util::Helpers::CollectBindingNames(init);
2050
2051 for (const auto *binding : bindings) {
2052 binder::Decl *decl = nullptr;
2053 binder::DeclarationFlags declflag = (flags & VariableParsingFlags::EXPORTED) ?
2054 binder::DeclarationFlags::EXPORT : binder::DeclarationFlags::NONE;
2055 if (flags & VariableParsingFlags::EXPORTED_IN_TSMODULE) {
2056 declflag |= binder::DeclarationFlags::EXPORT_IN_TSMODULE;
2057 }
2058
2059 if (flags & VariableParsingFlags::VAR) {
2060 decl = Binder()->AddDecl<binder::VarDecl>(startLoc, declflag, isDeclare, binding->Name());
2061 } else if (flags & VariableParsingFlags::LET) {
2062 decl = Binder()->AddDecl<binder::LetDecl>(startLoc, declflag, isDeclare, binding->Name());
2063 } else {
2064 decl = Binder()->AddDecl<binder::ConstDecl>(startLoc, declflag, isDeclare, binding->Name());
2065 }
2066
2067 decl->BindNode(init);
2068 }
2069
2070 return declarator;
2071 }
2072
ParseVariableDeclaration(VariableParsingFlags flags,bool isDeclare,bool isExport)2073 ir::Statement *ParserImpl::ParseVariableDeclaration(VariableParsingFlags flags, bool isDeclare, bool isExport)
2074 {
2075 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2076
2077 if (!(flags & VariableParsingFlags::NO_SKIP_VAR_KIND)) {
2078 lexer_->NextToken();
2079 }
2080
2081 if ((flags & VariableParsingFlags::LET) && util::Helpers::IsGlobalIdentifier(lexer_->GetToken().Ident())) {
2082 ThrowSyntaxError("Declaration name conflicts with built-in global identifier '"
2083 + lexer_->GetToken().Ident().Mutf8() + "'.");
2084 }
2085
2086 if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ENUM) {
2087 if (!(flags & VariableParsingFlags::CONST)) {
2088 ThrowSyntaxError("Variable declaration expected.");
2089 }
2090 return ParseEnumDeclaration(isExport, isDeclare, true);
2091 }
2092
2093 ArenaVector<ir::VariableDeclarator *> declarators(Allocator()->Adapter());
2094
2095 while (true) {
2096 ir::VariableDeclarator *declarator = ParseVariableDeclarator(flags, isDeclare);
2097
2098 declarators.push_back(declarator);
2099
2100 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) {
2101 break;
2102 }
2103 lexer_->NextToken();
2104 }
2105
2106 auto varKind = ir::VariableDeclaration::VariableDeclarationKind::VAR;
2107
2108 if (flags & VariableParsingFlags::LET) {
2109 varKind = ir::VariableDeclaration::VariableDeclarationKind::LET;
2110 } else if (flags & VariableParsingFlags::CONST) {
2111 varKind = ir::VariableDeclaration::VariableDeclarationKind::CONST;
2112 }
2113
2114 lexer::SourcePosition endLoc = declarators.back()->End();
2115 auto *declaration = AllocNode<ir::VariableDeclaration>(varKind, std::move(declarators), isDeclare);
2116 declaration->SetRange({startLoc, endLoc});
2117
2118 return declaration;
2119 }
2120
ParseWhileStatement()2121 ir::WhileStatement *ParserImpl::ParseWhileStatement()
2122 {
2123 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2124 lexer_->NextToken();
2125 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
2126 ThrowSyntaxError("Unexpected token, expected '('");
2127 }
2128
2129 lexer_->NextToken();
2130 ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
2131
2132 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
2133 ThrowSyntaxError("Unexpected token, expected ')'");
2134 }
2135
2136 lexer_->NextToken();
2137 IterationContext<binder::LoopScope> iterCtx(&context_, Binder());
2138 ir::Statement *body = ParseStatement();
2139
2140 lexer::SourcePosition endLoc = body->End();
2141 auto *whileStatement = AllocNode<ir::WhileStatement>(iterCtx.LexicalScope().GetScope(), test, body);
2142 whileStatement->SetRange({startLoc, endLoc});
2143 iterCtx.LexicalScope().GetScope()->BindNode(whileStatement);
2144
2145 return whileStatement;
2146 }
2147
AddImportEntryItem(const ir::StringLiteral * source,const ArenaVector<ir::AstNode * > * specifiers,bool isType)2148 void ParserImpl::AddImportEntryItem(const ir::StringLiteral *source,
2149 const ArenaVector<ir::AstNode *> *specifiers, bool isType)
2150 {
2151 if (context_.IsTsModule()) {
2152 return;
2153 }
2154
2155 ASSERT(source != nullptr);
2156 auto *moduleRecord = isType ? GetSourceTextTypeModuleRecord() : GetSourceTextModuleRecord();
2157 ASSERT(moduleRecord != nullptr);
2158 auto moduleRequestIdx = moduleRecord->AddModuleRequest(source->Str());
2159
2160 if (specifiers == nullptr) {
2161 if (isType) {
2162 ThrowSyntaxError("Unexpected import type syntax", source->Start());
2163 }
2164 return;
2165 }
2166
2167 for (auto *it : *specifiers) {
2168 switch (it->Type()) {
2169 case ir::AstNodeType::IMPORT_DEFAULT_SPECIFIER: {
2170 auto localName = it->AsImportDefaultSpecifier()->Local()->Name();
2171 auto importName = parser::SourceTextModuleRecord::DEFAULT_EXTERNAL_NAME;
2172 auto localId = it->AsImportDefaultSpecifier()->Local();
2173 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ImportEntry>(
2174 localName, importName, moduleRequestIdx, localId, nullptr);
2175 moduleRecord->AddImportEntry(entry);
2176 break;
2177 }
2178 case ir::AstNodeType::IMPORT_NAMESPACE_SPECIFIER: {
2179 auto localName = it->AsImportNamespaceSpecifier()->Local()->Name();
2180 auto localId = it->AsImportNamespaceSpecifier()->Local();
2181 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ImportEntry>(
2182 localName, moduleRequestIdx, localId);
2183 moduleRecord->AddStarImportEntry(entry);
2184 break;
2185 }
2186 case ir::AstNodeType::IMPORT_SPECIFIER: {
2187 auto localName = it->AsImportSpecifier()->Local()->Name();
2188 auto importName = it->AsImportSpecifier()->Imported()->Name();
2189 auto localId = it->AsImportSpecifier()->Local();
2190 auto importId = it->AsImportSpecifier()->Imported();
2191 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ImportEntry>(
2192 localName, importName, moduleRequestIdx, localId, importId);
2193 moduleRecord->AddImportEntry(entry);
2194 break;
2195 }
2196 default: {
2197 ThrowSyntaxError("Unexpected astNode type", it->Start());
2198 }
2199 }
2200 }
2201 }
2202
AddExportNamedEntryItem(const ArenaVector<ir::ExportSpecifier * > & specifiers,const ir::StringLiteral * source,bool isType)2203 void ParserImpl::AddExportNamedEntryItem(const ArenaVector<ir::ExportSpecifier *> &specifiers,
2204 const ir::StringLiteral *source, bool isType)
2205 {
2206 // The exported objects in the TSModuleScope do not need to be allocated index.
2207 if (context_.IsTsModule()) {
2208 ASSERT(Binder()->GetScope()->IsTSModuleScope());
2209 return;
2210 }
2211 auto moduleRecord = isType ? GetSourceTextTypeModuleRecord() : GetSourceTextModuleRecord();
2212 ASSERT(moduleRecord != nullptr);
2213 if (source) {
2214 auto moduleRequestIdx = moduleRecord->AddModuleRequest(source->Str());
2215
2216 for (auto *it : specifiers) {
2217 auto exportSpecifier = it->AsExportSpecifier();
2218 auto importName = exportSpecifier->Local()->Name();
2219 auto exportName = exportSpecifier->Exported()->Name();
2220 auto importId = exportSpecifier->Local();
2221 auto exportId = exportSpecifier->Exported();
2222 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2223 exportName, importName, moduleRequestIdx, exportId, importId);
2224 if (!moduleRecord->AddIndirectExportEntry(entry)) {
2225 ThrowSyntaxError("Duplicate export name of '" + exportName.Mutf8() + "'",
2226 exportSpecifier->Start());
2227 }
2228 }
2229 } else {
2230 for (auto *it : specifiers) {
2231 auto exportSpecifier = it->AsExportSpecifier();
2232 auto exportName = exportSpecifier->Exported()->Name();
2233 auto localName = exportSpecifier->Local()->Name();
2234 auto exportId = exportSpecifier->Exported();
2235 auto localId = exportSpecifier->Local();
2236 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2237 exportName, localName, exportId, localId);
2238 if (!moduleRecord->AddLocalExportEntry(entry)) {
2239 ThrowSyntaxError("Duplicate export name of '" + exportName.Mutf8() + "'",
2240 exportSpecifier->Start());
2241 }
2242 }
2243 }
2244 }
2245
AddExportStarEntryItem(const lexer::SourcePosition & startLoc,const ir::StringLiteral * source,const ir::Identifier * exported)2246 void ParserImpl::AddExportStarEntryItem(const lexer::SourcePosition &startLoc, const ir::StringLiteral *source,
2247 const ir::Identifier *exported)
2248 {
2249 auto moduleRecord = GetSourceTextModuleRecord();
2250 ASSERT(moduleRecord != nullptr);
2251 ASSERT(source != nullptr);
2252 auto moduleRequestIdx = moduleRecord->AddModuleRequest(source->Str());
2253
2254 if (exported != nullptr) {
2255 /* Transform [NamespaceExport] into [NamespaceImport] & [LocalExport]
2256 * e.g. export * as ns from 'test.js'
2257 * --->
2258 * import * as [internalName] from 'test.js'
2259 * export { [internalName] as ns }
2260 */
2261 auto namespaceExportInternalName = GetNamespaceExportInternalName();
2262 auto *decl = Binder()->AddDecl<binder::ConstDecl>(startLoc, binder::DeclarationFlags::EXPORT,
2263 false, namespaceExportInternalName);
2264 decl->BindNode(exported);
2265
2266 auto *importEntry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ImportEntry>(
2267 namespaceExportInternalName, moduleRequestIdx, nullptr);
2268 auto *exportEntry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2269 exported->Name(), namespaceExportInternalName, exported, nullptr);
2270 moduleRecord->AddStarImportEntry(importEntry);
2271 if (!moduleRecord->AddLocalExportEntry(exportEntry)) {
2272 ThrowSyntaxError("Duplicate export name of '" + exported->Name().Mutf8() + "'", exported->Start());
2273 }
2274 return;
2275 }
2276
2277 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(moduleRequestIdx);
2278 moduleRecord->AddStarExportEntry(entry);
2279 }
2280
AddExportDefaultEntryItem(const ir::AstNode * declNode)2281 void ParserImpl::AddExportDefaultEntryItem(const ir::AstNode *declNode)
2282 {
2283 if (context_.IsTsModule()) {
2284 return;
2285 }
2286
2287 ASSERT(declNode != nullptr);
2288 if (declNode->IsTSInterfaceDeclaration() ||
2289 (declNode->IsFunctionDeclaration() && declNode->AsFunctionDeclaration()->Function()->IsOverload())) {
2290 return;
2291 }
2292
2293 auto moduleRecord = GetSourceTextModuleRecord();
2294 ASSERT(moduleRecord != nullptr);
2295 util::StringView exportName = parser::SourceTextModuleRecord::DEFAULT_EXTERNAL_NAME;
2296 util::StringView localName = parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME;
2297 if (declNode->IsFunctionDeclaration() || declNode->IsClassDeclaration()) {
2298 localName = declNode->IsFunctionDeclaration() ? declNode->AsFunctionDeclaration()->Function()->GetName() :
2299 declNode->AsClassDeclaration()->Definition()->GetName();
2300 }
2301
2302 ASSERT(!localName.Empty());
2303 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2304 exportName, localName, nullptr, nullptr);
2305 if (!moduleRecord->AddLocalExportEntry(entry)) {
2306 ThrowSyntaxError("Duplicate export name of '" + exportName.Mutf8() + "'", declNode->Start());
2307 }
2308 }
2309
AddExportLocalEntryItem(const ir::Statement * declNode,bool isTsModule)2310 void ParserImpl::AddExportLocalEntryItem(const ir::Statement *declNode, bool isTsModule)
2311 {
2312 ASSERT(declNode != nullptr);
2313 auto moduleRecord = GetSourceTextModuleRecord();
2314 ASSERT(isTsModule || moduleRecord != nullptr);
2315 binder::TSModuleScope *tsModuleScope = nullptr;
2316 if (isTsModule) {
2317 ASSERT(Binder()->GetScope()->IsTSModuleScope());
2318 tsModuleScope = Binder()->GetScope()->AsTSModuleScope();
2319 }
2320 if (declNode->IsVariableDeclaration()) {
2321 auto declarators = declNode->AsVariableDeclaration()->Declarators();
2322 for (auto *decl : declarators) {
2323 std::vector<const ir::Identifier *> bindings = util::Helpers::CollectBindingNames(decl->Id());
2324 for (const auto *binding : bindings) {
2325 if (isTsModule) {
2326 tsModuleScope->AddExportVariable(binding->Name());
2327 } else {
2328 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2329 binding->Name(), binding->Name(), binding, binding);
2330 if (!moduleRecord->AddLocalExportEntry(entry)) {
2331 ThrowSyntaxError("Duplicate export name of '" + binding->Name().Mutf8()
2332 + "'", binding->Start());
2333 }
2334 }
2335 }
2336 }
2337 }
2338 if (declNode->IsFunctionDeclaration() || declNode->IsClassDeclaration()) {
2339 auto name = declNode->IsFunctionDeclaration() ?
2340 declNode->AsFunctionDeclaration()->Function()->Id() :
2341 declNode->AsClassDeclaration()->Definition()->Ident();
2342 if (name == nullptr) {
2343 ThrowSyntaxError("A class or function declaration without the default modifier must have a name.",
2344 declNode->Start());
2345 }
2346 if (declNode->IsFunctionDeclaration() && declNode->AsFunctionDeclaration()->Function()->IsOverload()) {
2347 return;
2348 }
2349 if (isTsModule) {
2350 tsModuleScope->AddExportVariable(name->Name());
2351 } else {
2352 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2353 name->Name(), name->Name(), name, name);
2354 if (!moduleRecord->AddLocalExportEntry(entry)) {
2355 ThrowSyntaxError("Duplicate export name of '" + name->Name().Mutf8() + "'", name->Start());
2356 }
2357 }
2358 }
2359 AddTsTypeExportLocalEntryItem(declNode, isTsModule, tsModuleScope);
2360 }
2361
AddTsTypeExportLocalEntryItem(const ir::Statement * declNode,bool isTsModule,binder::TSModuleScope * tsModuleScope)2362 void ParserImpl::AddTsTypeExportLocalEntryItem(const ir::Statement *declNode, bool isTsModule,
2363 binder::TSModuleScope *tsModuleScope)
2364 {
2365 if (!declNode->IsTSInterfaceDeclaration() && !declNode->IsTSTypeAliasDeclaration()) {
2366 return;
2367 }
2368 auto name = declNode->IsTSInterfaceDeclaration() ?
2369 declNode->AsTSInterfaceDeclaration()->Id() : declNode->AsTSTypeAliasDeclaration()->Id();
2370 if (name == nullptr) {
2371 ThrowSyntaxError("An interface or type alias declaration must have a name.");
2372 }
2373 if (isTsModule) {
2374 binder::TSBinding tsBinding(Allocator(), name->Name());
2375 tsModuleScope->AddExportVariable(tsBinding.View());
2376 }
2377 }
2378
ParseExportDefaultDeclaration(const lexer::SourcePosition & startLoc,ArenaVector<ir::Decorator * > decorators,bool isExportEquals)2379 ir::ExportDefaultDeclaration *ParserImpl::ParseExportDefaultDeclaration(const lexer::SourcePosition &startLoc,
2380 ArenaVector<ir::Decorator *> decorators,
2381 bool isExportEquals)
2382 {
2383 lexer_->NextToken(); // eat `default` keyword or `=`
2384
2385 ir::AstNode *declNode = nullptr;
2386 bool eatSemicolon = false;
2387
2388 if (!decorators.empty() && lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS &&
2389 (context_.Status() & ParserStatus::IN_CLASS_BODY) == 0) {
2390 ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2391 }
2392
2393 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION) {
2394 declNode = ParseFunctionDeclaration(true, ParserStatus::EXPORT_REACHED);
2395 } else if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_CLASS) {
2396 declNode = ParseClassDeclaration(false, std::move(decorators), false, false, true);
2397 } else if (lexer_->GetToken().IsAsyncModifier()) {
2398 lexer_->NextToken(); // eat `async` keyword
2399 declNode = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION | ParserStatus::EXPORT_REACHED);
2400 } else if (Extension() == ScriptExtension::TS &&
2401 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_INTERFACE) {
2402 declNode = ParseTsInterfaceDeclaration(false);
2403 } else if (Extension() == ScriptExtension::TS &&
2404 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT) {
2405 lexer_->NextToken();
2406 if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS) {
2407 ThrowSyntaxError("Unexpected token, expected 'class'.");
2408 }
2409 declNode = ParseClassDeclaration(false, std::move(decorators), false, true, true);
2410 } else {
2411 declNode = ParseExpression();
2412 Binder()->AddDecl<binder::LetDecl>(declNode->Start(), binder::DeclarationFlags::EXPORT,
2413 false, parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME);
2414 eatSemicolon = true;
2415 }
2416
2417 // record default export entry
2418 if (!isExportEquals) {
2419 AddExportDefaultEntryItem(declNode);
2420 }
2421
2422 lexer::SourcePosition endLoc = declNode->End();
2423 auto *exportDeclaration = AllocNode<ir::ExportDefaultDeclaration>(declNode, isExportEquals);
2424 exportDeclaration->SetRange({startLoc, endLoc});
2425
2426 if (eatSemicolon) {
2427 ConsumeSemicolon(exportDeclaration);
2428 }
2429
2430 return exportDeclaration;
2431 }
2432
ParseNamedExport(const lexer::Token & exportedToken)2433 ir::Identifier *ParserImpl::ParseNamedExport(const lexer::Token &exportedToken)
2434 {
2435 if (exportedToken.Type() != lexer::TokenType::LITERAL_IDENT) {
2436 ThrowSyntaxError("Unexpected token, expected an identifier.");
2437 }
2438
2439 const util::StringView &exportedString = exportedToken.Ident();
2440
2441 auto *exported = AllocNode<ir::Identifier>(exportedString);
2442 exported->SetRange(exportedToken.Loc());
2443
2444 return exported;
2445 }
2446
ParseExportAllDeclaration(const lexer::SourcePosition & startLoc)2447 ir::ExportAllDeclaration *ParserImpl::ParseExportAllDeclaration(const lexer::SourcePosition &startLoc)
2448 {
2449 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat `*` character
2450
2451 ir::Identifier *exported = nullptr;
2452
2453 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
2454 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2455 exported = ParseNamedExport(lexer_->GetToken());
2456 lexer_->NextToken(); // eat exported name
2457 }
2458
2459 ir::StringLiteral *source = ParseFromClause();
2460 lexer::SourcePosition endLoc = source->End();
2461
2462 // record export star entry
2463 AddExportStarEntryItem(startLoc, source, exported);
2464
2465 auto *exportDeclaration = AllocNode<ir::ExportAllDeclaration>(source, exported);
2466 exportDeclaration->SetRange({startLoc, endLoc});
2467
2468 ConsumeSemicolon(exportDeclaration);
2469
2470 return exportDeclaration;
2471 }
2472
ParseExportNamedSpecifiers(const lexer::SourcePosition & startLoc,bool isType)2473 ir::ExportNamedDeclaration *ParserImpl::ParseExportNamedSpecifiers(const lexer::SourcePosition &startLoc,
2474 bool isType)
2475 {
2476 if (Extension() == ScriptExtension::TS && context_.IsTsModule() &&
2477 !(context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT)) {
2478 ThrowSyntaxError("Export declarations are not permitted in a namespace.");
2479 }
2480
2481 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat `{` character
2482
2483 ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter());
2484
2485 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
2486 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2487 ThrowSyntaxError("Unexpected token");
2488 }
2489
2490 lexer::Token localToken = lexer_->GetToken();
2491 auto *local = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
2492 local->SetRange(lexer_->GetToken().Loc());
2493
2494 if (Extension() == ScriptExtension::TS) {
2495 local->SetReference();
2496 }
2497
2498 lexer_->NextToken(); // eat local name
2499
2500 ir::Identifier *exported = nullptr;
2501
2502 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
2503 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat `as` literal
2504 exported = ParseNamedExport(lexer_->GetToken());
2505 lexer_->NextToken(); // eat exported name
2506 } else {
2507 exported = ParseNamedExport(localToken);
2508 }
2509
2510 auto *specifier = AllocNode<ir::ExportSpecifier>(local, exported);
2511 specifier->SetRange({local->Start(), exported->End()});
2512
2513 specifiers.push_back(specifier);
2514
2515 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2516 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat comma
2517 }
2518 }
2519
2520 lexer::SourcePosition endPos = lexer_->GetToken().End();
2521 lexer_->NextToken(); // eat right brace
2522
2523 ir::StringLiteral *source = nullptr;
2524
2525 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_FROM) {
2526 source = ParseFromClause();
2527 }
2528
2529 // record ExportEntry
2530 AddExportNamedEntryItem(specifiers, source, isType);
2531
2532 auto *exportDeclaration = AllocNode<ir::ExportNamedDeclaration>(source, std::move(specifiers), isType);
2533 exportDeclaration->SetRange({startLoc, endPos});
2534 ConsumeSemicolon(exportDeclaration);
2535
2536 return exportDeclaration;
2537 }
2538
ParseNamedExportDeclaration(const lexer::SourcePosition & startLoc,ArenaVector<ir::Decorator * > && decorators)2539 ir::ExportNamedDeclaration *ParserImpl::ParseNamedExportDeclaration(const lexer::SourcePosition &startLoc,
2540 ArenaVector<ir::Decorator *> &&decorators)
2541 {
2542 ir::Statement *decl = nullptr;
2543
2544 bool isDeclare = false;
2545 bool isTsModule = context_.IsTsModule();
2546
2547 if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) {
2548 isDeclare = CheckDeclare();
2549 }
2550
2551 if (!decorators.empty() && lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS &&
2552 (context_.Status() & ParserStatus::IN_CLASS_BODY) == 0 &&
2553 !(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2554 (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT))) {
2555 ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2556 }
2557
2558 VariableParsingFlags flag = isTsModule ?
2559 VariableParsingFlags::EXPORTED_IN_TSMODULE : VariableParsingFlags::EXPORTED;
2560 ParserStatus status = isTsModule ? ParserStatus::NO_OPTS : ParserStatus::EXPORT_REACHED;
2561
2562 switch (lexer_->GetToken().Type()) {
2563 case lexer::TokenType::KEYW_VAR: {
2564 decl = ParseVariableDeclaration(flag | VariableParsingFlags::VAR, isDeclare, true);
2565 break;
2566 }
2567 case lexer::TokenType::KEYW_CONST: {
2568 decl = ParseVariableDeclaration(flag | VariableParsingFlags::CONST, isDeclare, true);
2569 break;
2570 }
2571 case lexer::TokenType::KEYW_LET: {
2572 decl = ParseVariableDeclaration(flag | VariableParsingFlags::LET, isDeclare, true);
2573 break;
2574 }
2575 case lexer::TokenType::KEYW_FUNCTION: {
2576 decl = ParseFunctionDeclaration(false, status, isDeclare);
2577 break;
2578 }
2579 case lexer::TokenType::KEYW_CLASS: {
2580 decl = ParseClassDeclaration(true, std::move(decorators), isDeclare || IsDtsFile(), false, !isTsModule);
2581 break;
2582 }
2583 case lexer::TokenType::LITERAL_IDENT: {
2584 if (Extension() == ScriptExtension::TS) {
2585 switch (lexer_->GetToken().KeywordType()) {
2586 case lexer::TokenType::KEYW_LET: {
2587 decl = ParseVariableDeclaration(VariableParsingFlags::LET, isDeclare);
2588 break;
2589 }
2590 case lexer::TokenType::KEYW_ENUM: {
2591 decl = ParseEnumDeclaration(true, isDeclare, false);
2592 break;
2593 }
2594 case lexer::TokenType::KEYW_INTERFACE: {
2595 decl = ParseTsInterfaceDeclaration(isDeclare);
2596 break;
2597 }
2598 case lexer::TokenType::KEYW_TYPE: {
2599 decl = ParseTsTypeAliasDeclaration(isDeclare);
2600 break;
2601 }
2602 case lexer::TokenType::KEYW_GLOBAL:
2603 case lexer::TokenType::KEYW_MODULE:
2604 case lexer::TokenType::KEYW_NAMESPACE: {
2605 auto savedStatus = context_.Status();
2606 if (isDeclare) {
2607 context_.Status() |= ParserStatus::IN_AMBIENT_CONTEXT;
2608 }
2609 decl = ParseTsModuleDeclaration(isDeclare, true);
2610 context_.Status() = savedStatus;
2611 break;
2612 }
2613 case lexer::TokenType::KEYW_ABSTRACT: {
2614 lexer_->NextToken(); // eat abstract keyword
2615
2616 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) {
2617 if (isDeclare) {
2618 ThrowSyntaxError("'declare' modifier already seen.");
2619 }
2620 lexer_->NextToken();
2621 isDeclare = true;
2622 }
2623
2624 if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS) {
2625 ThrowSyntaxError("Unexpected token, expected 'class'.");
2626 }
2627 decl = ParseClassDeclaration(true, std::move(decorators),
2628 isDeclare || IsDtsFile(), true, !isTsModule);
2629 break;
2630 }
2631 default: {
2632 break;
2633 }
2634 }
2635
2636 if (decl) {
2637 break;
2638 }
2639 }
2640
2641 [[fallthrough]];
2642 }
2643 default: {
2644 if (!lexer_->GetToken().IsAsyncModifier()) {
2645 ThrowSyntaxError("Unexpected token");
2646 }
2647
2648 lexer_->NextToken(); // eat `async` keyword
2649 decl = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION | status);
2650 }
2651 }
2652
2653 if (decl->IsVariableDeclaration()) {
2654 ConsumeSemicolon(decl);
2655 }
2656
2657 AddExportLocalEntryItem(decl, isTsModule);
2658
2659 lexer::SourcePosition endLoc = decl->End();
2660 ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter());
2661 auto *exportDeclaration = AllocNode<ir::ExportNamedDeclaration>(decl, std::move(specifiers));
2662 exportDeclaration->SetRange({startLoc, endLoc});
2663
2664 return exportDeclaration;
2665 }
2666
ParseExportDeclaration(StatementParsingFlags flags,ArenaVector<ir::Decorator * > && decorators)2667 ir::Statement *ParserImpl::ParseExportDeclaration(StatementParsingFlags flags,
2668 ArenaVector<ir::Decorator *> &&decorators)
2669 {
2670 if (Extension() == ScriptExtension::JS || !context_.IsTsModule()) {
2671 if (!(flags & StatementParsingFlags::GLOBAL)) {
2672 ThrowSyntaxError("'import' and 'export' may only appear at the top level");
2673 }
2674
2675 if (!context_.IsModule()) {
2676 ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'");
2677 }
2678 }
2679
2680 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2681 lexer_->NextToken(); // eat `export` keyword
2682
2683 // won't set `isType` for type alias
2684 bool isType = false;
2685 if (Extension() == ScriptExtension::TS &&
2686 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE) {
2687 const auto savedPos = lexer_->Save();
2688 lexer_->NextToken(); // eat type
2689 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2690 isType = true;
2691 } else {
2692 lexer_->Rewind(savedPos);
2693 }
2694 }
2695
2696 switch (lexer_->GetToken().Type()) {
2697 case lexer::TokenType::KEYW_DEFAULT: { // export default Id
2698 return ParseExportDefaultDeclaration(startLoc, std::move(decorators));
2699 }
2700 case lexer::TokenType::PUNCTUATOR_MULTIPLY: { // export * ...
2701 return ParseExportAllDeclaration(startLoc);
2702 }
2703 case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { // export { ... } ...
2704 return ParseExportNamedSpecifiers(startLoc, isType);
2705 }
2706 case lexer::TokenType::KEYW_IMPORT: {
2707 return ParseTsImportEqualsDeclaration(startLoc, true);
2708 }
2709 case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: {
2710 if (Extension() == ScriptExtension::TS) {
2711 return ParseExportDefaultDeclaration(startLoc, std::move(decorators), true);
2712 }
2713
2714 [[fallthrough]];
2715 }
2716 case lexer::TokenType::LITERAL_IDENT: {
2717 if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
2718 return ParseTsNamespaceExportDeclaration(startLoc);
2719 }
2720
2721 [[fallthrough]];
2722 }
2723 default: { // export [var] id
2724 ir::ExportNamedDeclaration *exportDecl = ParseNamedExportDeclaration(startLoc, std::move(decorators));
2725
2726 if (Extension() == ScriptExtension::TS && exportDecl->Decl()->IsVariableDeclaration() &&
2727 !(flags & StatementParsingFlags::GLOBAL) && exportDecl->Parent() &&
2728 !exportDecl->Parent()->IsTSModuleBlock() && !context_.IsModule()) {
2729 ThrowSyntaxError("Modifiers cannot appear here'");
2730 }
2731
2732 return exportDecl;
2733 }
2734 }
2735 }
2736
ParseNameSpaceImport(ArenaVector<ir::AstNode * > * specifiers,bool isType)2737 void ParserImpl::ParseNameSpaceImport(ArenaVector<ir::AstNode *> *specifiers, bool isType)
2738 {
2739 lexer::SourcePosition namespaceStart = lexer_->GetToken().Start();
2740 lexer_->NextToken(); // eat `*` character
2741
2742 if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_AS) {
2743 ThrowSyntaxError("Unexpected token.");
2744 }
2745
2746 lexer_->NextToken(); // eat `as` literal
2747
2748 ir::Identifier *local = ParseNamedImport(lexer_->GetToken());
2749
2750 auto *specifier = AllocNode<ir::ImportNamespaceSpecifier>(local);
2751 specifier->SetRange({namespaceStart, lexer_->GetToken().End()});
2752 specifiers->push_back(specifier);
2753
2754 binder::Decl *decl = AddImportDecl(isType, local->Name(), namespaceStart,
2755 binder::DeclarationFlags::NAMESPACE_IMPORT);
2756 decl->BindNode(specifier);
2757
2758 lexer_->NextToken(); // eat local name
2759 }
2760
AddImportDecl(bool isType,util::StringView name,lexer::SourcePosition startPos,binder::DeclarationFlags flag)2761 binder::Decl *ParserImpl::AddImportDecl(bool isType,
2762 util::StringView name,
2763 lexer::SourcePosition startPos,
2764 binder::DeclarationFlags flag)
2765 {
2766 if (isType) {
2767 binder::TSBinding tsBinding(Allocator(), name);
2768 return Binder()->AddTsDecl<binder::TypeAliasDecl>(startPos, flag, false, tsBinding.View());
2769 }
2770 return Binder()->AddDecl<binder::ConstDecl>(startPos, flag, false, name);
2771 }
2772
ParseNamedImport(const lexer::Token & importedToken)2773 ir::Identifier *ParserImpl::ParseNamedImport(const lexer::Token &importedToken)
2774 {
2775 if (importedToken.Type() != lexer::TokenType::LITERAL_IDENT) {
2776 ThrowSyntaxError("Unexpected token");
2777 }
2778
2779 switch (importedToken.KeywordType()) {
2780 case lexer::TokenType::KEYW_EVAL: {
2781 ThrowSyntaxError("Binding 'eval' in strict mode is invalid");
2782 }
2783 case lexer::TokenType::KEYW_ARGUMENTS: {
2784 ThrowSyntaxError("Binding 'arguments' in strict mode is invalid");
2785 }
2786 default: {
2787 break;
2788 }
2789 }
2790
2791 auto *local = AllocNode<ir::Identifier>(importedToken.Ident());
2792 local->SetRange(importedToken.Loc());
2793
2794 return local;
2795 }
2796
ParseNamedImportSpecifiers(ArenaVector<ir::AstNode * > * specifiers,bool isType)2797 void ParserImpl::ParseNamedImportSpecifiers(ArenaVector<ir::AstNode *> *specifiers, bool isType)
2798 {
2799 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat `{` character
2800
2801 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
2802 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2803 ThrowSyntaxError("Unexpected token");
2804 }
2805
2806 lexer::Token importedToken = lexer_->GetToken();
2807 auto *imported = AllocNode<ir::Identifier>(importedToken.Ident());
2808 ir::Identifier *local = nullptr;
2809 imported->SetRange(lexer_->GetToken().Loc());
2810
2811 lexer_->NextToken(); // eat import name
2812
2813 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
2814 lexer_->NextToken(); // eat `as` literal
2815 local = ParseNamedImport(lexer_->GetToken());
2816 lexer_->NextToken(); // eat local name
2817 } else {
2818 local = ParseNamedImport(importedToken);
2819 }
2820
2821 auto *specifier = AllocNode<ir::ImportSpecifier>(imported, local);
2822 specifier->SetRange({imported->Start(), local->End()});
2823 specifiers->push_back(specifier);
2824
2825 binder::Decl *decl = AddImportDecl(isType, local->Name(), local->Start(), binder::DeclarationFlags::IMPORT);
2826 decl->BindNode(specifier);
2827
2828 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2829 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat comma
2830 }
2831 }
2832
2833 lexer_->NextToken(); // eat right brace
2834 }
2835
ParseModuleReference()2836 ir::Expression *ParserImpl::ParseModuleReference()
2837 {
2838 ir::Expression *result = nullptr;
2839
2840 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2841 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_REQUIRE &&
2842 lexer_->Lookahead() == LEX_CHAR_LEFT_PAREN) {
2843 lexer::SourcePosition start = lexer_->GetToken().Start();
2844 lexer_->NextToken(); // eat 'require'
2845 lexer_->NextToken(); // eat '('
2846
2847 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
2848 ThrowSyntaxError("String literal expected.");
2849 }
2850
2851 result = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
2852 result->SetRange(lexer_->GetToken().Loc());
2853 lexer_->NextToken();
2854
2855 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
2856 ThrowSyntaxError("')' expected.");
2857 }
2858
2859 result = AllocNode<ir::TSExternalModuleReference>(result);
2860 result->SetRange({start, lexer_->GetToken().End()});
2861 lexer_->NextToken(); // eat ')'
2862 } else {
2863 result = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
2864 result->SetRange(lexer_->GetToken().Loc());
2865 lexer_->NextToken();
2866
2867 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
2868 result = ParseTsQualifiedReference(result);
2869 }
2870 }
2871
2872 return result;
2873 }
2874
ParseImportDefaultSpecifier(ArenaVector<ir::AstNode * > * specifiers,bool isType)2875 ir::AstNode *ParserImpl::ParseImportDefaultSpecifier(ArenaVector<ir::AstNode *> *specifiers, bool isType)
2876 {
2877 ir::Identifier *local = ParseNamedImport(lexer_->GetToken());
2878 lexer_->NextToken(); // eat local name
2879
2880 if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
2881 lexer_->NextToken(); // eat substitution
2882 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2883 ThrowSyntaxError("identifier expected");
2884 }
2885 if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_REQUIRE ||
2886 lexer_->Lookahead() != LEX_CHAR_LEFT_PAREN) {
2887 auto *decl = Binder()->AddDecl<binder::ImportEqualsDecl>(local->Start(), binder::DeclarationFlags::NONE,
2888 false, local->Name());
2889 decl->BindNode(local);
2890 auto *scope = Binder()->GetScope();
2891 auto *var = scope->FindLocalTSVariable<binder::TSBindingType::IMPORT_EQUALS>(local->Name());
2892 ASSERT(var != nullptr);
2893 var->AsImportEqualsVariable()->SetScope(scope);
2894 }
2895
2896 auto *importEqualsDecl = AllocNode<ir::TSImportEqualsDeclaration>(local, ParseModuleReference(), false);
2897
2898 return importEqualsDecl;
2899 }
2900
2901 auto *specifier = AllocNode<ir::ImportDefaultSpecifier>(local);
2902 specifier->SetRange(specifier->Local()->Range());
2903 specifiers->push_back(specifier);
2904
2905 binder::Decl *decl = AddImportDecl(isType, local->Name(), local->Start(), binder::DeclarationFlags::IMPORT);
2906 decl->BindNode(specifier);
2907
2908 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2909 lexer_->NextToken(); // eat comma
2910 }
2911
2912 return nullptr;
2913 }
2914
ParseFromClause(bool requireFrom)2915 ir::StringLiteral *ParserImpl::ParseFromClause(bool requireFrom)
2916 {
2917 if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) {
2918 if (requireFrom) {
2919 ThrowSyntaxError("Unexpected token.");
2920 }
2921 } else {
2922 lexer_->NextToken(); // eat `from` literal
2923 }
2924
2925 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
2926 ThrowSyntaxError("Unexpected token.");
2927 }
2928
2929 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
2930
2931 auto *source = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
2932 source->SetRange(lexer_->GetToken().Loc());
2933
2934 lexer_->NextToken();
2935
2936 return source;
2937 }
2938
ParseImportSpecifiers(ArenaVector<ir::AstNode * > * specifiers,bool isType)2939 ir::AstNode *ParserImpl::ParseImportSpecifiers(ArenaVector<ir::AstNode *> *specifiers, bool isType)
2940 {
2941 ASSERT(specifiers->empty());
2942
2943 // import [default] from 'source'
2944 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
2945 ir::AstNode *astNode = ParseImportDefaultSpecifier(specifiers, isType);
2946 if (astNode != nullptr) {
2947 return astNode;
2948 }
2949 }
2950
2951 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
2952 ParseNameSpaceImport(specifiers, isType);
2953 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2954 ParseNamedImportSpecifiers(specifiers, isType);
2955 }
2956 return nullptr;
2957 }
2958
ParseImportDeclaration(StatementParsingFlags flags)2959 ir::Statement *ParserImpl::ParseImportDeclaration(StatementParsingFlags flags)
2960 {
2961 char32_t nextChar = lexer_->Lookahead();
2962 // dynamic import || import.meta
2963 if (nextChar == LEX_CHAR_LEFT_PAREN || nextChar == LEX_CHAR_DOT) {
2964 return ParseExpressionStatement();
2965 }
2966
2967 if (Extension() == ScriptExtension::JS) {
2968 if (!(flags & StatementParsingFlags::GLOBAL)) {
2969 ThrowSyntaxError("'import' and 'export' may only appear at the top level");
2970 }
2971
2972 if (!context_.IsModule()) {
2973 ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'");
2974 }
2975 }
2976
2977 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2978 lexer_->NextToken(); // eat import
2979
2980 bool isType = false;
2981 if (Extension() == ScriptExtension::TS &&
2982 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE) {
2983 const auto savedPos = lexer_->Save();
2984 lexer_->NextToken(); // eat type
2985 if ((lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2986 lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) ||
2987 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE ||
2988 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
2989 isType = true;
2990 } else {
2991 lexer_->Rewind(savedPos);
2992 }
2993 }
2994
2995 ArenaVector<ir::AstNode *> specifiers(Allocator()->Adapter());
2996
2997 ir::StringLiteral *source = nullptr;
2998
2999 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
3000 ir::AstNode *astNode = ParseImportSpecifiers(&specifiers, isType);
3001 if (astNode != nullptr) {
3002 ASSERT(astNode->IsTSImportEqualsDeclaration());
3003 astNode->SetRange({startLoc, lexer_->GetToken().End()});
3004 ConsumeSemicolon(astNode->AsTSImportEqualsDeclaration());
3005 return astNode->AsTSImportEqualsDeclaration();
3006 }
3007 if (Extension() == ScriptExtension::TS && !context_.IsModule()) {
3008 ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'");
3009 }
3010 source = ParseFromClause(true);
3011 AddImportEntryItem(source, &specifiers, isType);
3012 } else {
3013 if (Extension() == ScriptExtension::TS && !context_.IsModule()) {
3014 ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'");
3015 }
3016 // import 'source'
3017 source = ParseFromClause(false);
3018 AddImportEntryItem(source, nullptr, isType);
3019 }
3020
3021 lexer::SourcePosition endLoc = source->End();
3022 auto *importDeclaration = AllocNode<ir::ImportDeclaration>(source, std::move(specifiers), isType);
3023 importDeclaration->SetRange({startLoc, endLoc});
3024
3025 ConsumeSemicolon(importDeclaration);
3026
3027 return importDeclaration;
3028 }
3029
3030 } // namespace panda::es2panda::parser
3031