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 if (!allowBreak && Extension() == ScriptExtension::JS) {
969 ThrowSyntaxError("Illegal break statement");
970 }
971
972 if (!allowBreak && Extension() == ScriptExtension::TS) {
973 if (context_.Status() & ParserStatus::FUNCTION) {
974 ThrowSyntaxError("Jump target cannot cross function boundary");
975 } else {
976 ThrowSyntaxError(
977 "A 'break' statement can only be used within an "
978 "enclosing iteration or switch statement");
979 }
980 }
981
982 auto *breakStatement = AllocNode<ir::BreakStatement>();
983 breakStatement->SetRange({startLoc, lexer_->GetToken().End()});
984 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
985 lexer_->NextToken();
986 }
987
988 return breakStatement;
989 }
990
991 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
992 ThrowSyntaxError("Unexpected token.");
993 }
994
995 const auto &label = lexer_->GetToken().Ident();
996
997 if (!context_.FindLabel(label)) {
998 ThrowSyntaxError("Undefined label");
999 }
1000
1001 auto *identNode = AllocNode<ir::Identifier>(label);
1002 identNode->SetRange(lexer_->GetToken().Loc());
1003
1004 auto *breakStatement = AllocNode<ir::BreakStatement>(identNode);
1005 breakStatement->SetRange({startLoc, lexer_->GetToken().End()});
1006
1007 lexer_->NextToken();
1008 ConsumeSemicolon(breakStatement);
1009
1010 return breakStatement;
1011 }
1012
ParseContinueStatement()1013 ir::ContinueStatement *ParserImpl::ParseContinueStatement()
1014 {
1015 if (Extension() == ScriptExtension::TS &&
1016 (static_cast<ParserStatus>(context_.Status() & (ParserStatus::FUNCTION | ParserStatus::IN_ITERATION |
1017 ParserStatus::IN_SWITCH)) == ParserStatus::FUNCTION)) {
1018 ThrowSyntaxError("Jump target cannot cross function boundary");
1019 }
1020
1021 if (!(context_.Status() & ParserStatus::IN_ITERATION)) {
1022 if (Extension() == ScriptExtension::JS) {
1023 ThrowSyntaxError("Illegal continue statement");
1024 }
1025 if (Extension() == ScriptExtension::TS) {
1026 ThrowSyntaxError(
1027 "A 'continue' statement can only be used within an "
1028 "enclosing iteration statement");
1029 }
1030 }
1031
1032 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1033 lexer::SourcePosition endLoc = lexer_->GetToken().End();
1034 lexer_->NextToken();
1035
1036 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1037 auto *continueStatement = AllocNode<ir::ContinueStatement>();
1038 continueStatement->SetRange({startLoc, lexer_->GetToken().End()});
1039 lexer_->NextToken();
1040 return continueStatement;
1041 }
1042
1043 if (lexer_->GetToken().NewLine() || lexer_->GetToken().Type() == lexer::TokenType::EOS ||
1044 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1045 auto *continueStatement = AllocNode<ir::ContinueStatement>();
1046 continueStatement->SetRange({startLoc, endLoc});
1047 return continueStatement;
1048 }
1049
1050 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1051 ThrowSyntaxError("Unexpected token.");
1052 }
1053
1054 const auto &label = lexer_->GetToken().Ident();
1055 const ParserContext *labelCtx = context_.FindLabel(label);
1056
1057 if (!labelCtx || !(labelCtx->Status() & (ParserStatus::IN_ITERATION | ParserStatus::IN_LABELED)) ||
1058 (labelCtx->Status() & ParserStatus::DISALLOW_CONTINUE)) {
1059 ThrowSyntaxError("Undefined label");
1060 }
1061
1062 auto *identNode = AllocNode<ir::Identifier>(label);
1063 identNode->SetRange(lexer_->GetToken().Loc());
1064
1065 auto *continueStatement = AllocNode<ir::ContinueStatement>(identNode);
1066 continueStatement->SetRange({startLoc, lexer_->GetToken().End()});
1067
1068 lexer_->NextToken();
1069 ConsumeSemicolon(continueStatement);
1070
1071 return continueStatement;
1072 }
1073
ParseDoWhileStatement()1074 ir::DoWhileStatement *ParserImpl::ParseDoWhileStatement()
1075 {
1076 IterationContext<binder::LoopScope> iterCtx(&context_, Binder());
1077
1078 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1079 lexer_->NextToken();
1080 ir::Statement *body = ParseStatement();
1081
1082 if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_WHILE) {
1083 ThrowSyntaxError("Missing 'while' keyword in a 'DoWhileStatement'");
1084 }
1085
1086 lexer_->NextToken();
1087 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1088 ThrowSyntaxError("Missing left parenthesis in a 'DoWhileStatement'");
1089 }
1090
1091 lexer_->NextToken();
1092
1093 ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1094
1095 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1096 ThrowSyntaxError("Missing right parenthesis in a 'DoWhileStatement'");
1097 }
1098
1099 auto *doWhileStatement = AllocNode<ir::DoWhileStatement>(iterCtx.LexicalScope().GetScope(), body, test);
1100 doWhileStatement->SetRange({startLoc, lexer_->GetToken().End()});
1101 iterCtx.LexicalScope().GetScope()->BindNode(doWhileStatement);
1102
1103 lexer_->NextToken();
1104
1105 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1106 doWhileStatement->SetEnd(lexer_->GetToken().End());
1107 lexer_->NextToken();
1108 }
1109
1110 return doWhileStatement;
1111 }
1112
ParseFunctionDeclaration(bool canBeAnonymous,ParserStatus newStatus,bool isDeclare)1113 ir::FunctionDeclaration *ParserImpl::ParseFunctionDeclaration(bool canBeAnonymous, ParserStatus newStatus,
1114 bool isDeclare)
1115 {
1116 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1117
1118 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION);
1119 ParserStatus savedStatus = context_.Status();
1120
1121 lexer_->NextToken();
1122
1123 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
1124 newStatus |= ParserStatus::GENERATOR_FUNCTION;
1125 lexer_->NextToken();
1126 }
1127
1128 context_.Status() = savedStatus;
1129
1130 // e.g. export default function () {}
1131 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT &&
1132 lexer_->GetToken().Type() != lexer::TokenType::KEYW_AWAIT) {
1133 if (canBeAnonymous) {
1134 ir::ScriptFunction *func = ParseFunction(newStatus, isDeclare);
1135 if (func->Body() != nullptr) {
1136 lexer_->NextToken();
1137 }
1138 func->SetStart(startLoc);
1139 func->SetAsExportDefault();
1140
1141 auto *funcDecl = AllocNode<ir::FunctionDeclaration>(func);
1142 funcDecl->SetRange(func->Range());
1143
1144 binder::DeclarationFlags declflag = (newStatus & ParserStatus::EXPORT_REACHED) ?
1145 binder::DeclarationFlags::EXPORT : binder::DeclarationFlags::NONE;
1146 Binder()->AddDecl<binder::FunctionDecl>(startLoc, declflag, isDeclare, Allocator(),
1147 parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME, func);
1148
1149 return funcDecl;
1150 }
1151
1152 ThrowSyntaxError("Unexpected token, expected identifier after 'function' keyword");
1153 }
1154
1155 if (!isDeclare) {
1156 CheckStrictReservedWord();
1157 }
1158
1159 util::StringView ident = lexer_->GetToken().Ident();
1160
1161 auto *identNode = AllocNode<ir::Identifier>(ident);
1162 identNode->SetRange(lexer_->GetToken().Loc());
1163 lexer_->NextToken();
1164
1165 newStatus |= ParserStatus::FUNCTION_DECLARATION;
1166 ir::ScriptFunction *func = ParseFunction(newStatus, isDeclare);
1167 if (func->Body() != nullptr) {
1168 lexer_->NextToken();
1169 }
1170
1171 func->SetIdent(identNode);
1172 func->SetStart(startLoc);
1173 auto *funcDecl = AllocNode<ir::FunctionDeclaration>(func);
1174 funcDecl->SetRange(func->Range());
1175
1176 AddFunctionToBinder(func, newStatus);
1177
1178 if (func->IsOverload() && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1179 lexer_->NextToken();
1180 }
1181
1182 CheckOptionalBindingPatternParameter(func);
1183
1184 return funcDecl;
1185 }
1186
AddFunctionToBinder(ir::ScriptFunction * func,ParserStatus newStatus)1187 void ParserImpl::AddFunctionToBinder(ir::ScriptFunction *func, ParserStatus newStatus)
1188 {
1189 binder::DeclarationFlags declflag = (newStatus & ParserStatus::EXPORT_REACHED) ?
1190 binder::DeclarationFlags::EXPORT : binder::DeclarationFlags::NONE;
1191 const ir::Identifier *identNode = func->Id();
1192 const lexer::SourcePosition &startLoc = func->Start();
1193 const util::StringView ident = identNode->Name();
1194 if (Extension() == ScriptExtension::TS) {
1195 const auto &bindings = Binder()->GetScope()->Bindings();
1196 auto res = bindings.find(ident);
1197 binder::Decl *currentDecl = res == bindings.end() ? nullptr : res->second->Declaration();
1198 binder::FunctionDecl *decl {};
1199
1200 if (res == bindings.end() ||
1201 (currentDecl->IsClassDecl() && currentDecl->AsClassDecl()->IsDeclare())) {
1202 decl = Binder()->AddDecl<binder::FunctionDecl>(identNode->Start(), declflag, func->Declare(),
1203 Allocator(), ident, func);
1204 } else {
1205 if (!currentDecl->IsFunctionDecl()) {
1206 Binder()->ThrowRedeclaration(startLoc, currentDecl->Name());
1207 }
1208
1209 decl = currentDecl->AsFunctionDecl();
1210 if (!decl->Node()->AsScriptFunction()->IsOverload()) {
1211 Binder()->ThrowRedeclaration(startLoc, currentDecl->Name());
1212 }
1213 if (!func->IsOverload()) {
1214 decl->BindNode(func);
1215 }
1216 }
1217
1218 decl->Add(func);
1219 } else {
1220 Binder()->AddDecl<binder::FunctionDecl>(identNode->Start(), declflag, func->Declare(),
1221 Allocator(), ident, func);
1222 }
1223 }
1224
CheckOptionalBindingPatternParameter(ir::ScriptFunction * func) const1225 void ParserImpl::CheckOptionalBindingPatternParameter(ir::ScriptFunction *func) const
1226 {
1227 if (func->Declare() || func->IsOverload()) {
1228 return;
1229 }
1230 for (auto *it : func->Params()) {
1231 if ((it->IsObjectPattern() && it->AsObjectPattern()->Optional()) ||
1232 (it->IsArrayPattern() && it->AsArrayPattern()->Optional())) {
1233 ThrowSyntaxError(
1234 "A binding pattern parameter cannot be optional in an "
1235 "implementation signature", it->Start());
1236 }
1237 }
1238 }
1239
ParseExpressionStatement(StatementParsingFlags flags)1240 ir::Statement *ParserImpl::ParseExpressionStatement(StatementParsingFlags flags)
1241 {
1242 const auto startPos = lexer_->Save();
1243 ParserStatus savedStatus = context_.Status();
1244
1245 if (lexer_->GetToken().IsAsyncModifier()) {
1246 context_.Status() |= ParserStatus::ASYNC_FUNCTION;
1247 lexer_->NextToken();
1248
1249 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION && !lexer_->GetToken().NewLine()) {
1250 if (!(flags & StatementParsingFlags::ALLOW_LEXICAL)) {
1251 ThrowSyntaxError("Async functions can only be declared at the top level or inside a block.");
1252 }
1253
1254 ir::FunctionDeclaration *functionDecl = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION);
1255 functionDecl->SetStart(startPos.token.Start());
1256
1257 return functionDecl;
1258 }
1259
1260 lexer_->Rewind(startPos);
1261 }
1262
1263 ir::Expression *exprNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1264 context_.Status() = savedStatus;
1265 lexer::SourcePosition endPos = exprNode->End();
1266
1267 auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(exprNode);
1268 exprStatementNode->SetRange({startPos.token.Start(), endPos});
1269 ConsumeSemicolon(exprStatementNode);
1270
1271 return exprStatementNode;
1272 }
1273
ParseForInOf(ir::AstNode * initNode,ExpressionParseFlags exprFlags,bool isAwait)1274 std::tuple<ForStatementKind, ir::Expression *, ir::Expression *> ParserImpl::ParseForInOf(
1275 ir::AstNode *initNode, ExpressionParseFlags exprFlags, bool isAwait)
1276 {
1277 ForStatementKind forKind = ForStatementKind::UPDATE;
1278 ir::Expression *updateNode = nullptr;
1279 ir::Expression *rightNode = nullptr;
1280
1281 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN ||
1282 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OF) {
1283 const ir::VariableDeclarator *varDecl = initNode->AsVariableDeclaration()->Declarators().front();
1284
1285 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN) {
1286 if (varDecl->Init()) {
1287 ThrowSyntaxError("for-in loop variable declaration may not have an initializer");
1288 }
1289 forKind = ForStatementKind::IN;
1290 exprFlags = ExpressionParseFlags::ACCEPT_COMMA;
1291 } else {
1292 if (varDecl->Init()) {
1293 ThrowSyntaxError("for-of loop variable declaration may not have an initializer");
1294 }
1295
1296 forKind = ForStatementKind::OF;
1297 }
1298
1299 lexer_->NextToken();
1300 rightNode = ParseExpression(exprFlags);
1301 } else {
1302 if (isAwait) {
1303 ThrowSyntaxError("Unexpected token");
1304 }
1305
1306 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1307 ThrowSyntaxError("Invalid left-hand side in 'For[In/Of]Statement'");
1308 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1309 lexer_->NextToken();
1310 } else {
1311 rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1312 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1313 ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
1314 }
1315 lexer_->NextToken();
1316 }
1317
1318 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1319 updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1320 }
1321 }
1322
1323 return {forKind, rightNode, updateNode};
1324 }
1325
ParseForInOf(ir::Expression * leftNode,ExpressionParseFlags exprFlags,bool isAwait)1326 std::tuple<ForStatementKind, ir::AstNode *, ir::Expression *, ir::Expression *> ParserImpl::ParseForInOf(
1327 ir::Expression *leftNode, ExpressionParseFlags exprFlags, bool isAwait)
1328 {
1329 ForStatementKind forKind = ForStatementKind::UPDATE;
1330 ir::AstNode *initNode = nullptr;
1331 ir::Expression *updateNode = nullptr;
1332 ir::Expression *rightNode = nullptr;
1333
1334 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN ||
1335 (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_OF)) {
1336 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_IN) {
1337 forKind = ForStatementKind::IN;
1338 exprFlags = ExpressionParseFlags::ACCEPT_COMMA;
1339 } else {
1340 forKind = ForStatementKind::OF;
1341 }
1342
1343 bool isValid = true;
1344 switch (leftNode->Type()) {
1345 case ir::AstNodeType::IDENTIFIER:
1346 case ir::AstNodeType::MEMBER_EXPRESSION: {
1347 break;
1348 }
1349 case ir::AstNodeType::ARRAY_EXPRESSION: {
1350 isValid = leftNode->AsArrayExpression()->ConvertibleToArrayPattern();
1351 break;
1352 }
1353 case ir::AstNodeType::OBJECT_EXPRESSION: {
1354 isValid = leftNode->AsObjectExpression()->ConvertibleToObjectPattern();
1355 break;
1356 }
1357 default: {
1358 isValid = false;
1359 }
1360 }
1361
1362 if (!isValid) {
1363 ValidateLvalueAssignmentTarget(leftNode);
1364 }
1365
1366 initNode = leftNode;
1367 lexer_->NextToken();
1368 rightNode = ParseExpression(exprFlags);
1369
1370 return {forKind, initNode, rightNode, updateNode};
1371 }
1372
1373 if (isAwait) {
1374 ThrowSyntaxError("Unexpected token");
1375 }
1376
1377 exprFlags &= ExpressionParseFlags::POTENTIALLY_IN_PATTERN;
1378 ir::Expression *expr = ParseAssignmentExpression(leftNode, exprFlags);
1379
1380 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
1381 initNode = ParseSequenceExpression(expr);
1382 } else {
1383 initNode = expr;
1384 }
1385
1386 if (initNode->IsConditionalExpression()) {
1387 ir::ConditionalExpression *condExpr = initNode->AsConditionalExpression();
1388 if (condExpr->Alternate()->IsBinaryExpression()) {
1389 const auto *binaryExpr = condExpr->Alternate()->AsBinaryExpression();
1390 if (binaryExpr->OperatorType() == lexer::TokenType::KEYW_IN) {
1391 ThrowSyntaxError("Invalid left-hand side in for-in statement");
1392 }
1393 }
1394 }
1395
1396 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1397 ThrowSyntaxError("Invalid left-hand side in 'For[In/Of]Statement'");
1398 }
1399
1400 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1401 ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
1402 }
1403
1404 lexer_->NextToken();
1405
1406 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1407 lexer_->NextToken();
1408 } else {
1409 rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1410
1411 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1412 ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
1413 }
1414 lexer_->NextToken();
1415 }
1416
1417 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1418 updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1419 }
1420
1421 return {forKind, initNode, rightNode, updateNode};
1422 }
1423
ParseForUpdate(bool isAwait)1424 std::tuple<ir::Expression *, ir::Expression *> ParserImpl::ParseForUpdate(bool isAwait)
1425 {
1426 if (isAwait) {
1427 ThrowSyntaxError("Unexpected token");
1428 }
1429
1430 ir::Expression *updateNode = nullptr;
1431 ir::Expression *rightNode = nullptr;
1432
1433 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1434 lexer_->NextToken();
1435 } else {
1436 rightNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1437 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1438 ThrowSyntaxError("Unexpected token, expected ';' in 'ForStatement'.");
1439 }
1440 lexer_->NextToken();
1441 }
1442
1443 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1444 updateNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1445 }
1446
1447 return {rightNode, updateNode};
1448 }
1449
ParseForStatement()1450 ir::Statement *ParserImpl::ParseForStatement()
1451 {
1452 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1453 ForStatementKind forKind = ForStatementKind::UPDATE;
1454 ir::AstNode *initNode = nullptr;
1455 ir::Expression *updateNode = nullptr;
1456 ir::Expression *leftNode = nullptr;
1457 ir::Expression *rightNode = nullptr;
1458 bool canBeForInOf = true;
1459 bool isAwait = false;
1460 lexer_->NextToken();
1461 VariableParsingFlags varFlags = VariableParsingFlags::STOP_AT_IN | VariableParsingFlags::IN_FOR;
1462 ExpressionParseFlags exprFlags = ExpressionParseFlags::NO_OPTS;
1463
1464 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) {
1465 isAwait = true;
1466 varFlags |= VariableParsingFlags::DISALLOW_INIT;
1467 lexer_->NextToken();
1468 }
1469
1470 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1471 ThrowSyntaxError("Missing left parenthesis in a 'ForStatement'");
1472 }
1473 lexer_->NextToken();
1474
1475 IterationContext<binder::LoopScope> iterCtx(&context_, Binder());
1476
1477 switch (lexer_->GetToken().Type()) {
1478 case lexer::TokenType::KEYW_VAR: {
1479 initNode = ParseVariableDeclaration(varFlags | VariableParsingFlags::VAR);
1480 break;
1481 }
1482 case lexer::TokenType::KEYW_LET: {
1483 initNode = ParseVariableDeclaration(varFlags | VariableParsingFlags::LET);
1484 break;
1485 }
1486 case lexer::TokenType::KEYW_CONST: {
1487 initNode = ParseVariableDeclaration(varFlags | VariableParsingFlags::CONST |
1488 VariableParsingFlags::ACCEPT_CONST_NO_INIT);
1489 break;
1490 }
1491 case lexer::TokenType::PUNCTUATOR_SEMI_COLON: {
1492 if (isAwait) {
1493 ThrowSyntaxError("Unexpected token");
1494 }
1495
1496 canBeForInOf = false;
1497 lexer_->NextToken();
1498 break;
1499 }
1500 default: {
1501 leftNode = ParseUnaryOrPrefixUpdateExpression(ExpressionParseFlags::POTENTIALLY_IN_PATTERN);
1502
1503 break;
1504 }
1505 }
1506
1507 if (initNode != nullptr) {
1508 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1509 lexer_->NextToken();
1510 canBeForInOf = false;
1511 } else {
1512 canBeForInOf = initNode->AsVariableDeclaration()->Declarators().size() == 1;
1513 }
1514 }
1515
1516 // VariableDeclaration->DeclarationSize > 1 or seen semi_colon
1517 if (!canBeForInOf) {
1518 std::tie(rightNode, updateNode) = ParseForUpdate(isAwait);
1519 } else if (leftNode) {
1520 // initNode was parsed as LHS
1521 if (leftNode->IsArrayExpression() || leftNode->IsObjectExpression()) {
1522 exprFlags |= ExpressionParseFlags::POTENTIALLY_IN_PATTERN;
1523 }
1524 std::tie(forKind, initNode, rightNode, updateNode) = ParseForInOf(leftNode, exprFlags, isAwait);
1525 } else if (initNode) {
1526 // initNode was parsed as VariableDeclaration and declaration size = 1
1527 std::tie(forKind, rightNode, updateNode) = ParseForInOf(initNode, exprFlags, isAwait);
1528 }
1529
1530 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1531 ThrowSyntaxError("Unexpected token, expected ')' in 'ForStatement'.");
1532 }
1533 lexer_->NextToken();
1534
1535 ir::Statement *bodyNode = ParseStatement();
1536 lexer::SourcePosition endLoc = bodyNode->End();
1537
1538 ir::Statement *forStatement = nullptr;
1539 auto *loopScope = iterCtx.LexicalScope().GetScope();
1540
1541 if (forKind == ForStatementKind::UPDATE) {
1542 forStatement = AllocNode<ir::ForUpdateStatement>(loopScope, initNode, rightNode, updateNode, bodyNode);
1543 } else if (forKind == ForStatementKind::IN) {
1544 forStatement = AllocNode<ir::ForInStatement>(loopScope, initNode, rightNode, bodyNode);
1545 } else {
1546 forStatement = AllocNode<ir::ForOfStatement>(loopScope, initNode, rightNode, bodyNode, isAwait);
1547 }
1548
1549 forStatement->SetRange({startLoc, endLoc});
1550 loopScope->BindNode(forStatement);
1551
1552 return forStatement;
1553 }
1554
ParseIfStatement()1555 ir::IfStatement *ParserImpl::ParseIfStatement()
1556 {
1557 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1558 lexer::SourcePosition endLoc = lexer_->GetToken().End();
1559 lexer_->NextToken();
1560
1561 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1562 ThrowSyntaxError("Missing left parenthesis in an 'IfStatement'");
1563 }
1564
1565 lexer_->NextToken();
1566 ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1567
1568 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1569 ThrowSyntaxError("Missing right parenthesis in an 'IfStatement'");
1570 }
1571
1572 lexer_->NextToken();
1573 ir::Statement *consequent = ParseStatement(StatementParsingFlags::IF_ELSE);
1574
1575 if (Extension() == ScriptExtension::TS && consequent->IsEmptyStatement()) {
1576 ThrowSyntaxError("The body of an if statement cannot be the empty statement");
1577 }
1578
1579 endLoc = consequent->End();
1580 ir::Statement *alternate = nullptr;
1581
1582 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_ELSE) {
1583 lexer_->NextToken(); // eat ELSE keyword
1584 alternate = ParseStatement(StatementParsingFlags::IF_ELSE);
1585 endLoc = alternate->End();
1586 }
1587
1588 auto *ifStatement = AllocNode<ir::IfStatement>(test, consequent, alternate);
1589 ifStatement->SetRange({startLoc, endLoc});
1590 return ifStatement;
1591 }
1592
ParseLabelledStatement(const lexer::LexerPosition & pos)1593 ir::LabelledStatement *ParserImpl::ParseLabelledStatement(const lexer::LexerPosition &pos)
1594 {
1595 const auto savedPos = lexer_->Save();
1596 bool isLabelFollowedByIterationStatement = IsLabelFollowedByIterationStatement();
1597 lexer_->Rewind(savedPos);
1598
1599 const util::StringView &actualLabel = pos.token.Ident();
1600
1601 // TODO(frobert) : check correctness
1602 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AWAIT && context_.IsModule()) {
1603 ThrowSyntaxError("'await' is a reserved identifier in module code", pos.token.Start());
1604 }
1605
1606 if (context_.FindLabel(actualLabel)) {
1607 ThrowSyntaxError("Label already declared", pos.token.Start());
1608 }
1609
1610 SavedParserContext newCtx(this, ParserStatus::IN_LABELED | context_.Status(), actualLabel);
1611 if (isLabelFollowedByIterationStatement) {
1612 context_.Status() &= ~ParserStatus::DISALLOW_CONTINUE;
1613 } else {
1614 context_.Status() |= ParserStatus::DISALLOW_CONTINUE;
1615 }
1616
1617 auto *identNode = AllocNode<ir::Identifier>(actualLabel);
1618 identNode->SetRange(pos.token.Loc());
1619
1620 lexer_->NextToken();
1621
1622 ir::Statement *body = ParseStatement(StatementParsingFlags::LABELLED);
1623
1624 auto *labeledStatement = AllocNode<ir::LabelledStatement>(identNode, body);
1625 labeledStatement->SetRange({pos.token.Start(), body->End()});
1626
1627 return labeledStatement;
1628 }
1629
ParseReturnStatement()1630 ir::ReturnStatement *ParserImpl::ParseReturnStatement()
1631 {
1632 if (!(context_.Status() & ParserStatus::FUNCTION)) {
1633 ThrowSyntaxError("return keyword should be used in function body");
1634 }
1635
1636 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1637 lexer::SourcePosition endLoc = lexer_->GetToken().End();
1638 lexer_->NextToken();
1639
1640 bool hasArgument = (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON &&
1641 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
1642 lexer_->GetToken().Type() != lexer::TokenType::EOS && !lexer_->GetToken().NewLine());
1643
1644 ir::ReturnStatement *returnStatement = nullptr;
1645
1646 if (hasArgument) {
1647 ir::Expression *expression = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1648 endLoc = expression->End();
1649 returnStatement = AllocNode<ir::ReturnStatement>(expression);
1650 } else {
1651 returnStatement = AllocNode<ir::ReturnStatement>();
1652 }
1653
1654 returnStatement->SetRange({startLoc, endLoc});
1655 ConsumeSemicolon(returnStatement);
1656
1657 return returnStatement;
1658 }
1659
ParseSwitchCaseStatement(bool * seenDefault)1660 ir::SwitchCaseStatement *ParserImpl::ParseSwitchCaseStatement(bool *seenDefault)
1661 {
1662 lexer::SourcePosition caseStartLoc = lexer_->GetToken().Start();
1663 ir::Expression *testExpr = nullptr;
1664
1665 switch (lexer_->GetToken().Type()) {
1666 case lexer::TokenType::KEYW_CASE: {
1667 lexer_->NextToken();
1668 testExpr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1669 break;
1670 }
1671 case lexer::TokenType::KEYW_DEFAULT: {
1672 if (*seenDefault) {
1673 if (Extension() == ScriptExtension::TS) {
1674 ThrowSyntaxError(
1675 "A 'default' clause cannot appear more than once in a "
1676 "'switch' statement");
1677 } else {
1678 ThrowSyntaxError("Multiple default clauses.");
1679 }
1680 }
1681 *seenDefault = true;
1682 lexer_->NextToken();
1683 break;
1684 }
1685 default: {
1686 ThrowSyntaxError("Unexpected token, expected 'case' or 'default'.");
1687 }
1688 }
1689
1690 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
1691 ThrowSyntaxError("Unexpected token, expected ':'");
1692 }
1693
1694 ArenaVector<ir::Statement *> consequents(Allocator()->Adapter());
1695 lexer::SourcePosition caseEndLoc = lexer_->GetToken().End();
1696
1697 lexer_->NextToken();
1698
1699 while (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CASE &&
1700 lexer_->GetToken().Type() != lexer::TokenType::KEYW_DEFAULT &&
1701 lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1702 ir::Statement *consequent = ParseStatement(StatementParsingFlags::ALLOW_LEXICAL);
1703 caseEndLoc = consequent->End();
1704 consequents.push_back(consequent);
1705 }
1706
1707 auto *caseNode = AllocNode<ir::SwitchCaseStatement>(testExpr, std::move(consequents));
1708 caseNode->SetRange({caseStartLoc, caseEndLoc});
1709 return caseNode;
1710 }
1711
ParseSwitchStatement()1712 ir::SwitchStatement *ParserImpl::ParseSwitchStatement()
1713 {
1714 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1715 lexer_->NextToken();
1716 if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS)) {
1717 ThrowSyntaxError("Unexpected token, expected '('");
1718 }
1719
1720 lexer_->NextToken();
1721 ir::Expression *discriminant = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1722
1723 if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS)) {
1724 ThrowSyntaxError("Unexpected token, expected ')'");
1725 }
1726
1727 lexer_->NextToken();
1728 SwitchContext switchContext(&context_);
1729
1730 if (!(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE)) {
1731 ThrowSyntaxError("Unexpected token, expected '{'");
1732 }
1733
1734 lexer_->NextToken();
1735 bool seenDefault = false;
1736 auto localCtx = binder::LexicalScope<binder::LocalScope>(Binder());
1737 ArenaVector<ir::SwitchCaseStatement *> cases(Allocator()->Adapter());
1738
1739 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1740 cases.push_back(ParseSwitchCaseStatement(&seenDefault));
1741 }
1742
1743 auto *switchStatement = AllocNode<ir::SwitchStatement>(localCtx.GetScope(), discriminant, std::move(cases));
1744 switchStatement->SetRange({startLoc, lexer_->GetToken().End()});
1745 localCtx.GetScope()->BindNode(switchStatement);
1746
1747 lexer_->NextToken();
1748
1749 return switchStatement;
1750 }
1751
ParseThrowStatement()1752 ir::ThrowStatement *ParserImpl::ParseThrowStatement()
1753 {
1754 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1755 lexer_->NextToken();
1756
1757 if (lexer_->GetToken().NewLine()) {
1758 if (Extension() == ScriptExtension::JS) {
1759 ThrowSyntaxError("Illegal newline after throw");
1760 }
1761
1762 if (Extension() == ScriptExtension::TS) {
1763 ThrowSyntaxError("Line break not permitted here");
1764 }
1765 }
1766
1767 ir::Expression *expression = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
1768 lexer::SourcePosition endLoc = expression->End();
1769
1770 auto *throwStatement = AllocNode<ir::ThrowStatement>(expression);
1771 throwStatement->SetRange({startLoc, endLoc});
1772 ConsumeSemicolon(throwStatement);
1773
1774 return throwStatement;
1775 }
1776
ParseCatchParam()1777 ir::Expression *ParserImpl::ParseCatchParam()
1778 {
1779 ir::Expression *param = nullptr;
1780
1781 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1782 return param;
1783 }
1784
1785 lexer_->NextToken(); // eat left paren
1786
1787 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1788 switch (lexer_->GetToken().KeywordType()) {
1789 case lexer::TokenType::KEYW_EVAL: {
1790 ThrowSyntaxError("Binding 'eval' in strict mode is invalid");
1791 }
1792 case lexer::TokenType::KEYW_ARGUMENTS: {
1793 ThrowSyntaxError("Binding 'arguments' in strict mode is invalid");
1794 }
1795 default: {
1796 break;
1797 }
1798 }
1799
1800 param = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
1801 param->SetRange(lexer_->GetToken().Loc());
1802
1803 lexer_->NextToken();
1804 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
1805 param = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1806 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1807 param = ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN);
1808 } else {
1809 ThrowSyntaxError("Unexpected token in catch parameter");
1810 }
1811
1812 Binder()->AddParamDecl(param);
1813
1814 if (Extension() == ScriptExtension::TS) {
1815 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1816 lexer_->NextToken(); // eat ':'
1817
1818 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1819 param->SetTsTypeAnnotation(ParseTsTypeAnnotation(&options));
1820 }
1821
1822 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
1823 ThrowSyntaxError("Catch clause variable cannot have an initializer");
1824 }
1825 }
1826
1827 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1828 ThrowSyntaxError("Unexpected token, expected ')'");
1829 }
1830
1831 lexer_->NextToken();
1832
1833 return param;
1834 }
1835
ParseCatchClause()1836 ir::CatchClause *ParserImpl::ParseCatchClause()
1837 {
1838 lexer::SourcePosition catchStartLoc = lexer_->GetToken().Start();
1839 lexer_->NextToken(); // eat 'catch' keyword
1840
1841 auto catchParamCtx = binder::LexicalScope<binder::CatchParamScope>(Binder());
1842 auto *catchParamScope = catchParamCtx.GetScope();
1843
1844 ir::Expression *param = ParseCatchParam();
1845 catchParamScope->BindNode(param);
1846
1847 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1848 ThrowSyntaxError("Unexpected token, expected '{'");
1849 }
1850
1851 auto catchCtx = binder::LexicalScope<binder::CatchScope>(Binder());
1852 auto *catchScope = catchCtx.GetScope();
1853 catchScope->AssignParamScope(catchParamScope);
1854
1855 ir::BlockStatement *catchBlock = ParseBlockStatement(catchScope);
1856 lexer_->NextToken();
1857 lexer::SourcePosition endLoc = catchBlock->End();
1858
1859 auto *catchClause = AllocNode<ir::CatchClause>(catchScope, param, catchBlock);
1860 catchClause->SetRange({catchStartLoc, endLoc});
1861 catchScope->BindNode(catchClause);
1862
1863 return catchClause;
1864 }
1865
ParseTryStatement()1866 ir::TryStatement *ParserImpl::ParseTryStatement()
1867 {
1868 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1869 lexer::SourcePosition endLoc = lexer_->GetToken().End();
1870
1871 lexer_->NextToken();
1872
1873 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1874 ThrowSyntaxError("Unexpected token, expected '{'");
1875 }
1876
1877 ir::BlockStatement *body = ParseBlockStatement();
1878
1879 if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CATCH &&
1880 lexer_->GetToken().Type() != lexer::TokenType::KEYW_FINALLY) {
1881 ThrowSyntaxError("Missing catch or finally clause");
1882 }
1883
1884 ir::CatchClause *catchClause = nullptr;
1885 ir::BlockStatement *finnalyClause = nullptr;
1886
1887 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_CATCH) {
1888 catchClause = ParseCatchClause();
1889 endLoc = catchClause->End();
1890 }
1891
1892 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FINALLY) {
1893 lexer_->NextToken(); // eat 'finally' keyword
1894
1895 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1896 ThrowSyntaxError("Unexpected token, expected '{'");
1897 }
1898
1899 finnalyClause = ParseBlockStatement();
1900 endLoc = finnalyClause->End();
1901 }
1902
1903 auto *tryStatement = AllocNode<ir::TryStatement>(body, catchClause, finnalyClause);
1904 tryStatement->SetRange({startLoc, endLoc});
1905 return tryStatement;
1906 }
1907
1908 // TODO(frobert) : merge into lexer::LexerNextTokenFlags
ValidateDeclaratorId()1909 void ParserImpl::ValidateDeclaratorId()
1910 {
1911 if (context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT) {
1912 return;
1913 }
1914
1915 switch (lexer_->GetToken().KeywordType()) {
1916 case lexer::TokenType::KEYW_AWAIT: {
1917 if (context_.IsModule()) {
1918 ThrowSyntaxError("'await' is not permitted as an identifier in module code");
1919 }
1920 break;
1921 }
1922 case lexer::TokenType::KEYW_EVAL: {
1923 ThrowSyntaxError("Binding 'eval' in strict mode is invalid");
1924 }
1925 case lexer::TokenType::KEYW_ARGUMENTS: {
1926 ThrowSyntaxError("Binding 'arguments' in strict mode is invalid");
1927 }
1928 case lexer::TokenType::KEYW_LET: {
1929 ThrowSyntaxError("let is disallowed as a lexically bound name");
1930 break;
1931 }
1932 case lexer::TokenType::KEYW_STATIC:
1933 case lexer::TokenType::KEYW_IMPLEMENTS:
1934 case lexer::TokenType::KEYW_INTERFACE:
1935 case lexer::TokenType::KEYW_PACKAGE:
1936 case lexer::TokenType::KEYW_PRIVATE:
1937 case lexer::TokenType::KEYW_PROTECTED:
1938 case lexer::TokenType::KEYW_PUBLIC:
1939 case lexer::TokenType::KEYW_YIELD: {
1940 ThrowSyntaxError("Unexpected reserved word");
1941 }
1942 default: {
1943 break;
1944 }
1945 }
1946 }
1947
ParseVariableDeclaratorInitializer(ir::Expression * init,VariableParsingFlags flags,const lexer::SourcePosition & startLoc,bool isDeclare)1948 ir::VariableDeclarator *ParserImpl::ParseVariableDeclaratorInitializer(ir::Expression *init, VariableParsingFlags flags,
1949 const lexer::SourcePosition &startLoc,
1950 bool isDeclare)
1951 {
1952 if (flags & VariableParsingFlags::DISALLOW_INIT) {
1953 ThrowSyntaxError("for-await-of loop variable declaration may not have an initializer");
1954 }
1955
1956 lexer_->NextToken();
1957
1958 if (isDeclare && !(flags & VariableParsingFlags::CONST)) {
1959 ThrowSyntaxError("Initializers are not allowed in ambient contexts.");
1960 }
1961
1962 auto exprFlags =
1963 ((flags & VariableParsingFlags::STOP_AT_IN) ? ExpressionParseFlags::STOP_AT_IN : ExpressionParseFlags::NO_OPTS);
1964
1965 ir::Expression *initializer = ParseExpression(exprFlags);
1966 lexer::SourcePosition endLoc = initializer->End();
1967
1968 auto *declarator = AllocNode<ir::VariableDeclarator>(init, initializer);
1969 declarator->SetRange({startLoc, endLoc});
1970
1971 return declarator;
1972 }
1973
ParseVariableDeclarator(VariableParsingFlags flags,bool isDeclare)1974 ir::VariableDeclarator *ParserImpl::ParseVariableDeclarator(VariableParsingFlags flags, bool isDeclare)
1975 {
1976 ir::Expression *init = nullptr;
1977 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
1978 switch (lexer_->GetToken().Type()) {
1979 case lexer::TokenType::LITERAL_IDENT: {
1980 ValidateDeclaratorId();
1981
1982 if (!(flags & VariableParsingFlags::VAR) &&
1983 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_LET) {
1984 ThrowSyntaxError("let is disallowed as a lexically bound name");
1985 }
1986
1987 const util::StringView &identStr = lexer_->GetToken().Ident();
1988 init = AllocNode<ir::Identifier>(identStr);
1989 init->SetRange(lexer_->GetToken().Loc());
1990
1991 if (Extension() == ScriptExtension::TS) {
1992 init->AsIdentifier()->SetReference();
1993 }
1994
1995 lexer_->NextToken();
1996 break;
1997 }
1998 case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
1999 init = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN);
2000 break;
2001 }
2002 case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
2003 init = ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN);
2004 break;
2005 }
2006 default: {
2007 ThrowSyntaxError("Unexpected token in variable declaration");
2008 }
2009 }
2010
2011 bool isDefinite = false;
2012 if (Extension() == ScriptExtension::TS) {
2013 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) {
2014 lexer_->NextToken(); // eat '!'
2015 isDefinite = true;
2016 }
2017 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
2018 lexer_->NextToken(); // eat ':'
2019 TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
2020 init->SetTsTypeAnnotation(ParseTsTypeAnnotation(&options));
2021 }
2022 }
2023
2024 ir::VariableDeclarator *declarator {};
2025
2026 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
2027 declarator = ParseVariableDeclaratorInitializer(init, flags, startLoc, isDeclare);
2028 } else {
2029 if (!isDeclare && (flags & VariableParsingFlags::CONST) &&
2030 !(flags & VariableParsingFlags::ACCEPT_CONST_NO_INIT) &&
2031 !(context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT)) {
2032 ThrowSyntaxError("Missing initializer in const declaration");
2033 }
2034
2035 if (!isDeclare && !(flags & VariableParsingFlags::IN_FOR) &&
2036 (init->IsArrayPattern() || init->IsObjectPattern())) {
2037 ThrowSyntaxError("Missing initializer in destructuring declaration");
2038 }
2039
2040 lexer::SourcePosition endLoc = init->End();
2041 declarator = AllocNode<ir::VariableDeclarator>(init);
2042 declarator->SetRange({startLoc, endLoc});
2043 }
2044
2045 declarator->SetDefinite(isDefinite);
2046
2047 std::vector<const ir::Identifier *> bindings = util::Helpers::CollectBindingNames(init);
2048
2049 for (const auto *binding : bindings) {
2050 binder::Decl *decl = nullptr;
2051 binder::DeclarationFlags declflag = (flags & VariableParsingFlags::EXPORTED) ?
2052 binder::DeclarationFlags::EXPORT : binder::DeclarationFlags::NONE;
2053 if (flags & VariableParsingFlags::EXPORTED_IN_TSMODULE) {
2054 declflag |= binder::DeclarationFlags::EXPORT_IN_TSMODULE;
2055 }
2056
2057 if (flags & VariableParsingFlags::VAR) {
2058 decl = Binder()->AddDecl<binder::VarDecl>(startLoc, declflag, isDeclare, binding->Name());
2059 } else if (flags & VariableParsingFlags::LET) {
2060 decl = Binder()->AddDecl<binder::LetDecl>(startLoc, declflag, isDeclare, binding->Name());
2061 } else {
2062 decl = Binder()->AddDecl<binder::ConstDecl>(startLoc, declflag, isDeclare, binding->Name());
2063 }
2064
2065 decl->BindNode(init);
2066 }
2067
2068 return declarator;
2069 }
2070
ParseVariableDeclaration(VariableParsingFlags flags,bool isDeclare,bool isExport)2071 ir::Statement *ParserImpl::ParseVariableDeclaration(VariableParsingFlags flags, bool isDeclare, bool isExport)
2072 {
2073 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2074
2075 if (!(flags & VariableParsingFlags::NO_SKIP_VAR_KIND)) {
2076 lexer_->NextToken();
2077 }
2078
2079 if ((flags & VariableParsingFlags::LET) && util::Helpers::IsGlobalIdentifier(lexer_->GetToken().Ident())) {
2080 ThrowSyntaxError("Declaration name conflicts with built-in global identifier '"
2081 + lexer_->GetToken().Ident().Mutf8() + "'.");
2082 }
2083
2084 if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ENUM) {
2085 if (!(flags & VariableParsingFlags::CONST)) {
2086 ThrowSyntaxError("Variable declaration expected.");
2087 }
2088 return ParseEnumDeclaration(isExport, isDeclare, true);
2089 }
2090
2091 ArenaVector<ir::VariableDeclarator *> declarators(Allocator()->Adapter());
2092
2093 while (true) {
2094 ir::VariableDeclarator *declarator = ParseVariableDeclarator(flags, isDeclare);
2095
2096 declarators.push_back(declarator);
2097
2098 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) {
2099 break;
2100 }
2101 lexer_->NextToken();
2102 }
2103
2104 auto varKind = ir::VariableDeclaration::VariableDeclarationKind::VAR;
2105
2106 if (flags & VariableParsingFlags::LET) {
2107 varKind = ir::VariableDeclaration::VariableDeclarationKind::LET;
2108 } else if (flags & VariableParsingFlags::CONST) {
2109 varKind = ir::VariableDeclaration::VariableDeclarationKind::CONST;
2110 }
2111
2112 lexer::SourcePosition endLoc = declarators.back()->End();
2113 auto *declaration = AllocNode<ir::VariableDeclaration>(varKind, std::move(declarators), isDeclare);
2114 declaration->SetRange({startLoc, endLoc});
2115
2116 return declaration;
2117 }
2118
ParseWhileStatement()2119 ir::WhileStatement *ParserImpl::ParseWhileStatement()
2120 {
2121 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2122 lexer_->NextToken();
2123 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
2124 ThrowSyntaxError("Unexpected token, expected '('");
2125 }
2126
2127 lexer_->NextToken();
2128 ir::Expression *test = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA);
2129
2130 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
2131 ThrowSyntaxError("Unexpected token, expected ')'");
2132 }
2133
2134 lexer_->NextToken();
2135 IterationContext<binder::LoopScope> iterCtx(&context_, Binder());
2136 ir::Statement *body = ParseStatement();
2137
2138 lexer::SourcePosition endLoc = body->End();
2139 auto *whileStatement = AllocNode<ir::WhileStatement>(iterCtx.LexicalScope().GetScope(), test, body);
2140 whileStatement->SetRange({startLoc, endLoc});
2141 iterCtx.LexicalScope().GetScope()->BindNode(whileStatement);
2142
2143 return whileStatement;
2144 }
2145
AddImportEntryItem(const ir::StringLiteral * source,const ArenaVector<ir::AstNode * > * specifiers,bool isType)2146 void ParserImpl::AddImportEntryItem(const ir::StringLiteral *source,
2147 const ArenaVector<ir::AstNode *> *specifiers, bool isType)
2148 {
2149 if (context_.IsTsModule()) {
2150 return;
2151 }
2152
2153 ASSERT(source != nullptr);
2154 auto *moduleRecord = isType ? GetSourceTextTypeModuleRecord() : GetSourceTextModuleRecord();
2155 ASSERT(moduleRecord != nullptr);
2156 auto moduleRequestIdx = moduleRecord->AddModuleRequest(source->Str());
2157
2158 if (specifiers == nullptr) {
2159 if (isType) {
2160 ThrowSyntaxError("Unexpected import type syntax", source->Start());
2161 }
2162 return;
2163 }
2164
2165 for (auto *it : *specifiers) {
2166 switch (it->Type()) {
2167 case ir::AstNodeType::IMPORT_DEFAULT_SPECIFIER: {
2168 auto localName = it->AsImportDefaultSpecifier()->Local()->Name();
2169 auto importName = parser::SourceTextModuleRecord::DEFAULT_EXTERNAL_NAME;
2170 auto localId = it->AsImportDefaultSpecifier()->Local();
2171 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ImportEntry>(
2172 localName, importName, moduleRequestIdx, localId, nullptr);
2173 moduleRecord->AddImportEntry(entry);
2174 break;
2175 }
2176 case ir::AstNodeType::IMPORT_NAMESPACE_SPECIFIER: {
2177 auto localName = it->AsImportNamespaceSpecifier()->Local()->Name();
2178 auto localId = it->AsImportNamespaceSpecifier()->Local();
2179 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ImportEntry>(
2180 localName, moduleRequestIdx, localId);
2181 moduleRecord->AddStarImportEntry(entry);
2182 break;
2183 }
2184 case ir::AstNodeType::IMPORT_SPECIFIER: {
2185 auto localName = it->AsImportSpecifier()->Local()->Name();
2186 auto importName = it->AsImportSpecifier()->Imported()->Name();
2187 auto localId = it->AsImportSpecifier()->Local();
2188 auto importId = it->AsImportSpecifier()->Imported();
2189 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ImportEntry>(
2190 localName, importName, moduleRequestIdx, localId, importId);
2191 moduleRecord->AddImportEntry(entry);
2192 break;
2193 }
2194 default: {
2195 ThrowSyntaxError("Unexpected astNode type", it->Start());
2196 }
2197 }
2198 }
2199 }
2200
AddExportNamedEntryItem(const ArenaVector<ir::ExportSpecifier * > & specifiers,const ir::StringLiteral * source,bool isType)2201 void ParserImpl::AddExportNamedEntryItem(const ArenaVector<ir::ExportSpecifier *> &specifiers,
2202 const ir::StringLiteral *source, bool isType)
2203 {
2204 // The exported objects in the TSModuleScope do not need to be allocated index.
2205 if (context_.IsTsModule()) {
2206 ASSERT(Binder()->GetScope()->IsTSModuleScope());
2207 return;
2208 }
2209 auto moduleRecord = isType ? GetSourceTextTypeModuleRecord() : GetSourceTextModuleRecord();
2210 ASSERT(moduleRecord != nullptr);
2211 if (source) {
2212 auto moduleRequestIdx = moduleRecord->AddModuleRequest(source->Str());
2213
2214 for (auto *it : specifiers) {
2215 auto exportSpecifier = it->AsExportSpecifier();
2216 auto importName = exportSpecifier->Local()->Name();
2217 auto exportName = exportSpecifier->Exported()->Name();
2218 auto importId = exportSpecifier->Local();
2219 auto exportId = exportSpecifier->Exported();
2220 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2221 exportName, importName, moduleRequestIdx, exportId, importId);
2222 if (!moduleRecord->AddIndirectExportEntry(entry)) {
2223 ThrowSyntaxError("Duplicate export name of '" + exportName.Mutf8() + "'",
2224 exportSpecifier->Start());
2225 }
2226 }
2227 } else {
2228 for (auto *it : specifiers) {
2229 auto exportSpecifier = it->AsExportSpecifier();
2230 auto exportName = exportSpecifier->Exported()->Name();
2231 auto localName = exportSpecifier->Local()->Name();
2232 auto exportId = exportSpecifier->Exported();
2233 auto localId = exportSpecifier->Local();
2234 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2235 exportName, localName, exportId, localId);
2236 if (!moduleRecord->AddLocalExportEntry(entry)) {
2237 ThrowSyntaxError("Duplicate export name of '" + exportName.Mutf8() + "'",
2238 exportSpecifier->Start());
2239 }
2240 }
2241 }
2242 }
2243
AddExportStarEntryItem(const lexer::SourcePosition & startLoc,const ir::StringLiteral * source,const ir::Identifier * exported)2244 void ParserImpl::AddExportStarEntryItem(const lexer::SourcePosition &startLoc, const ir::StringLiteral *source,
2245 const ir::Identifier *exported)
2246 {
2247 auto moduleRecord = GetSourceTextModuleRecord();
2248 ASSERT(moduleRecord != nullptr);
2249 ASSERT(source != nullptr);
2250 auto moduleRequestIdx = moduleRecord->AddModuleRequest(source->Str());
2251
2252 if (exported != nullptr) {
2253 /* Transform [NamespaceExport] into [NamespaceImport] & [LocalExport]
2254 * e.g. export * as ns from 'test.js'
2255 * --->
2256 * import * as [internalName] from 'test.js'
2257 * export { [internalName] as ns }
2258 */
2259 auto namespaceExportInternalName = GetNamespaceExportInternalName();
2260 auto *decl = Binder()->AddDecl<binder::ConstDecl>(startLoc, binder::DeclarationFlags::EXPORT,
2261 false, namespaceExportInternalName);
2262 decl->BindNode(exported);
2263
2264 auto *importEntry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ImportEntry>(
2265 namespaceExportInternalName, moduleRequestIdx, nullptr);
2266 auto *exportEntry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2267 exported->Name(), namespaceExportInternalName, exported, nullptr);
2268 moduleRecord->AddStarImportEntry(importEntry);
2269 if (!moduleRecord->AddLocalExportEntry(exportEntry)) {
2270 ThrowSyntaxError("Duplicate export name of '" + exported->Name().Mutf8() + "'", exported->Start());
2271 }
2272 return;
2273 }
2274
2275 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(moduleRequestIdx);
2276 moduleRecord->AddStarExportEntry(entry);
2277 }
2278
AddExportDefaultEntryItem(const ir::AstNode * declNode)2279 void ParserImpl::AddExportDefaultEntryItem(const ir::AstNode *declNode)
2280 {
2281 if (context_.IsTsModule()) {
2282 return;
2283 }
2284
2285 ASSERT(declNode != nullptr);
2286 if (declNode->IsTSInterfaceDeclaration() ||
2287 (declNode->IsFunctionDeclaration() && declNode->AsFunctionDeclaration()->Function()->IsOverload())) {
2288 return;
2289 }
2290
2291 auto moduleRecord = GetSourceTextModuleRecord();
2292 ASSERT(moduleRecord != nullptr);
2293 util::StringView exportName = parser::SourceTextModuleRecord::DEFAULT_EXTERNAL_NAME;
2294 util::StringView localName = parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME;
2295 if (declNode->IsFunctionDeclaration() || declNode->IsClassDeclaration()) {
2296 localName = declNode->IsFunctionDeclaration() ? declNode->AsFunctionDeclaration()->Function()->GetName() :
2297 declNode->AsClassDeclaration()->Definition()->GetName();
2298 }
2299
2300 ASSERT(!localName.Empty());
2301 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2302 exportName, localName, nullptr, nullptr);
2303 if (!moduleRecord->AddLocalExportEntry(entry)) {
2304 ThrowSyntaxError("Duplicate export name of '" + exportName.Mutf8() + "'", declNode->Start());
2305 }
2306 }
2307
AddExportLocalEntryItem(const ir::Statement * declNode,bool isTsModule)2308 void ParserImpl::AddExportLocalEntryItem(const ir::Statement *declNode, bool isTsModule)
2309 {
2310 ASSERT(declNode != nullptr);
2311 auto moduleRecord = GetSourceTextModuleRecord();
2312 ASSERT(isTsModule || moduleRecord != nullptr);
2313 binder::TSModuleScope *tsModuleScope = nullptr;
2314 if (isTsModule) {
2315 ASSERT(Binder()->GetScope()->IsTSModuleScope());
2316 tsModuleScope = Binder()->GetScope()->AsTSModuleScope();
2317 }
2318 if (declNode->IsVariableDeclaration()) {
2319 auto declarators = declNode->AsVariableDeclaration()->Declarators();
2320 for (auto *decl : declarators) {
2321 std::vector<const ir::Identifier *> bindings = util::Helpers::CollectBindingNames(decl->Id());
2322 for (const auto *binding : bindings) {
2323 if (isTsModule) {
2324 tsModuleScope->AddExportVariable(binding->Name());
2325 } else {
2326 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2327 binding->Name(), binding->Name(), binding, binding);
2328 if (!moduleRecord->AddLocalExportEntry(entry)) {
2329 ThrowSyntaxError("Duplicate export name of '" + binding->Name().Mutf8()
2330 + "'", binding->Start());
2331 }
2332 }
2333 }
2334 }
2335 }
2336 if (declNode->IsFunctionDeclaration() || declNode->IsClassDeclaration()) {
2337 auto name = declNode->IsFunctionDeclaration() ?
2338 declNode->AsFunctionDeclaration()->Function()->Id() :
2339 declNode->AsClassDeclaration()->Definition()->Ident();
2340 if (name == nullptr) {
2341 ThrowSyntaxError("A class or function declaration without the default modifier must have a name.",
2342 declNode->Start());
2343 }
2344 if (declNode->IsFunctionDeclaration() && declNode->AsFunctionDeclaration()->Function()->IsOverload()) {
2345 return;
2346 }
2347 if (isTsModule) {
2348 tsModuleScope->AddExportVariable(name->Name());
2349 } else {
2350 auto *entry = moduleRecord->NewEntry<parser::SourceTextModuleRecord::ExportEntry>(
2351 name->Name(), name->Name(), name, name);
2352 if (!moduleRecord->AddLocalExportEntry(entry)) {
2353 ThrowSyntaxError("Duplicate export name of '" + name->Name().Mutf8() + "'", name->Start());
2354 }
2355 }
2356 }
2357 AddTsTypeExportLocalEntryItem(declNode, isTsModule, tsModuleScope);
2358 }
2359
AddTsTypeExportLocalEntryItem(const ir::Statement * declNode,bool isTsModule,binder::TSModuleScope * tsModuleScope)2360 void ParserImpl::AddTsTypeExportLocalEntryItem(const ir::Statement *declNode, bool isTsModule,
2361 binder::TSModuleScope *tsModuleScope)
2362 {
2363 if (!declNode->IsTSInterfaceDeclaration() && !declNode->IsTSTypeAliasDeclaration()) {
2364 return;
2365 }
2366 auto name = declNode->IsTSInterfaceDeclaration() ?
2367 declNode->AsTSInterfaceDeclaration()->Id() : declNode->AsTSTypeAliasDeclaration()->Id();
2368 if (name == nullptr) {
2369 ThrowSyntaxError("An interface or type alias declaration must have a name.");
2370 }
2371 if (isTsModule) {
2372 binder::TSBinding tsBinding(Allocator(), name->Name());
2373 tsModuleScope->AddExportVariable(tsBinding.View());
2374 }
2375 }
2376
ParseExportDefaultDeclaration(const lexer::SourcePosition & startLoc,ArenaVector<ir::Decorator * > decorators,bool isExportEquals)2377 ir::ExportDefaultDeclaration *ParserImpl::ParseExportDefaultDeclaration(const lexer::SourcePosition &startLoc,
2378 ArenaVector<ir::Decorator *> decorators,
2379 bool isExportEquals)
2380 {
2381 lexer_->NextToken(); // eat `default` keyword or `=`
2382
2383 ir::AstNode *declNode = nullptr;
2384 bool eatSemicolon = false;
2385
2386 if (!decorators.empty() && lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS &&
2387 (context_.Status() & ParserStatus::IN_CLASS_BODY) == 0) {
2388 ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2389 }
2390
2391 if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION) {
2392 declNode = ParseFunctionDeclaration(true, ParserStatus::EXPORT_REACHED);
2393 } else if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_CLASS) {
2394 declNode = ParseClassDeclaration(false, std::move(decorators), false, false, true);
2395 } else if (lexer_->GetToken().IsAsyncModifier()) {
2396 lexer_->NextToken(); // eat `async` keyword
2397 declNode = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION | ParserStatus::EXPORT_REACHED);
2398 } else if (Extension() == ScriptExtension::TS &&
2399 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_INTERFACE) {
2400 declNode = ParseTsInterfaceDeclaration(false);
2401 } else if (Extension() == ScriptExtension::TS &&
2402 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT) {
2403 lexer_->NextToken();
2404 if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS) {
2405 ThrowSyntaxError("Unexpected token, expected 'class'.");
2406 }
2407 declNode = ParseClassDeclaration(false, std::move(decorators), false, true, true);
2408 } else {
2409 declNode = ParseExpression();
2410 Binder()->AddDecl<binder::LetDecl>(declNode->Start(), binder::DeclarationFlags::EXPORT,
2411 false, parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME);
2412 eatSemicolon = true;
2413 }
2414
2415 // record default export entry
2416 if (!isExportEquals) {
2417 AddExportDefaultEntryItem(declNode);
2418 }
2419
2420 lexer::SourcePosition endLoc = declNode->End();
2421 auto *exportDeclaration = AllocNode<ir::ExportDefaultDeclaration>(declNode, isExportEquals);
2422 exportDeclaration->SetRange({startLoc, endLoc});
2423
2424 if (eatSemicolon) {
2425 ConsumeSemicolon(exportDeclaration);
2426 }
2427
2428 return exportDeclaration;
2429 }
2430
ParseNamedExport(const lexer::Token & exportedToken)2431 ir::Identifier *ParserImpl::ParseNamedExport(const lexer::Token &exportedToken)
2432 {
2433 if (exportedToken.Type() != lexer::TokenType::LITERAL_IDENT) {
2434 ThrowSyntaxError("Unexpected token, expected an identifier.");
2435 }
2436
2437 const util::StringView &exportedString = exportedToken.Ident();
2438
2439 auto *exported = AllocNode<ir::Identifier>(exportedString);
2440 exported->SetRange(exportedToken.Loc());
2441
2442 return exported;
2443 }
2444
ParseExportAllDeclaration(const lexer::SourcePosition & startLoc)2445 ir::ExportAllDeclaration *ParserImpl::ParseExportAllDeclaration(const lexer::SourcePosition &startLoc)
2446 {
2447 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat `*` character
2448
2449 ir::Identifier *exported = nullptr;
2450
2451 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
2452 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT);
2453 exported = ParseNamedExport(lexer_->GetToken());
2454 lexer_->NextToken(); // eat exported name
2455 }
2456
2457 ir::StringLiteral *source = ParseFromClause();
2458 lexer::SourcePosition endLoc = source->End();
2459
2460 // record export star entry
2461 AddExportStarEntryItem(startLoc, source, exported);
2462
2463 auto *exportDeclaration = AllocNode<ir::ExportAllDeclaration>(source, exported);
2464 exportDeclaration->SetRange({startLoc, endLoc});
2465
2466 ConsumeSemicolon(exportDeclaration);
2467
2468 return exportDeclaration;
2469 }
2470
ParseExportNamedSpecifiers(const lexer::SourcePosition & startLoc,bool isType)2471 ir::ExportNamedDeclaration *ParserImpl::ParseExportNamedSpecifiers(const lexer::SourcePosition &startLoc,
2472 bool isType)
2473 {
2474 if (Extension() == ScriptExtension::TS && context_.IsTsModule() &&
2475 !(context_.Status() & ParserStatus::IN_AMBIENT_CONTEXT)) {
2476 ThrowSyntaxError("Export declarations are not permitted in a namespace.");
2477 }
2478
2479 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat `{` character
2480
2481 ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter());
2482
2483 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
2484 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2485 ThrowSyntaxError("Unexpected token");
2486 }
2487
2488 lexer::Token localToken = lexer_->GetToken();
2489 auto *local = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
2490 local->SetRange(lexer_->GetToken().Loc());
2491
2492 if (Extension() == ScriptExtension::TS) {
2493 local->SetReference();
2494 }
2495
2496 lexer_->NextToken(); // eat local name
2497
2498 ir::Identifier *exported = nullptr;
2499
2500 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
2501 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat `as` literal
2502 exported = ParseNamedExport(lexer_->GetToken());
2503 lexer_->NextToken(); // eat exported name
2504 } else {
2505 exported = ParseNamedExport(localToken);
2506 }
2507
2508 auto *specifier = AllocNode<ir::ExportSpecifier>(local, exported);
2509 specifier->SetRange({local->Start(), exported->End()});
2510
2511 specifiers.push_back(specifier);
2512
2513 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2514 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat comma
2515 }
2516 }
2517
2518 lexer::SourcePosition endPos = lexer_->GetToken().End();
2519 lexer_->NextToken(); // eat right brace
2520
2521 ir::StringLiteral *source = nullptr;
2522
2523 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_FROM) {
2524 source = ParseFromClause();
2525 }
2526
2527 // record ExportEntry
2528 AddExportNamedEntryItem(specifiers, source, isType);
2529
2530 auto *exportDeclaration = AllocNode<ir::ExportNamedDeclaration>(source, std::move(specifiers), isType);
2531 exportDeclaration->SetRange({startLoc, endPos});
2532 ConsumeSemicolon(exportDeclaration);
2533
2534 return exportDeclaration;
2535 }
2536
ParseNamedExportDeclaration(const lexer::SourcePosition & startLoc,ArenaVector<ir::Decorator * > && decorators)2537 ir::ExportNamedDeclaration *ParserImpl::ParseNamedExportDeclaration(const lexer::SourcePosition &startLoc,
2538 ArenaVector<ir::Decorator *> &&decorators)
2539 {
2540 ir::Statement *decl = nullptr;
2541
2542 bool isDeclare = false;
2543 bool isTsModule = context_.IsTsModule();
2544
2545 if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) {
2546 isDeclare = CheckDeclare();
2547 }
2548
2549 if (!decorators.empty() && lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS &&
2550 (context_.Status() & ParserStatus::IN_CLASS_BODY) == 0 &&
2551 !(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2552 (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT))) {
2553 ThrowSyntaxError("Decorators are not valid here.", decorators.front()->Start());
2554 }
2555
2556 VariableParsingFlags flag = isTsModule ?
2557 VariableParsingFlags::EXPORTED_IN_TSMODULE : VariableParsingFlags::EXPORTED;
2558 ParserStatus status = isTsModule ? ParserStatus::NO_OPTS : ParserStatus::EXPORT_REACHED;
2559
2560 switch (lexer_->GetToken().Type()) {
2561 case lexer::TokenType::KEYW_VAR: {
2562 decl = ParseVariableDeclaration(flag | VariableParsingFlags::VAR, isDeclare, true);
2563 break;
2564 }
2565 case lexer::TokenType::KEYW_CONST: {
2566 decl = ParseVariableDeclaration(flag | VariableParsingFlags::CONST, isDeclare, true);
2567 break;
2568 }
2569 case lexer::TokenType::KEYW_LET: {
2570 decl = ParseVariableDeclaration(flag | VariableParsingFlags::LET, isDeclare, true);
2571 break;
2572 }
2573 case lexer::TokenType::KEYW_FUNCTION: {
2574 decl = ParseFunctionDeclaration(false, status, isDeclare);
2575 break;
2576 }
2577 case lexer::TokenType::KEYW_CLASS: {
2578 decl = ParseClassDeclaration(true, std::move(decorators), isDeclare || IsDtsFile(), false, !isTsModule);
2579 break;
2580 }
2581 case lexer::TokenType::LITERAL_IDENT: {
2582 if (Extension() == ScriptExtension::TS) {
2583 switch (lexer_->GetToken().KeywordType()) {
2584 case lexer::TokenType::KEYW_LET: {
2585 decl = ParseVariableDeclaration(VariableParsingFlags::LET, isDeclare);
2586 break;
2587 }
2588 case lexer::TokenType::KEYW_ENUM: {
2589 decl = ParseEnumDeclaration(true, isDeclare, false);
2590 break;
2591 }
2592 case lexer::TokenType::KEYW_INTERFACE: {
2593 decl = ParseTsInterfaceDeclaration(isDeclare);
2594 break;
2595 }
2596 case lexer::TokenType::KEYW_TYPE: {
2597 decl = ParseTsTypeAliasDeclaration(isDeclare);
2598 break;
2599 }
2600 case lexer::TokenType::KEYW_GLOBAL:
2601 case lexer::TokenType::KEYW_MODULE:
2602 case lexer::TokenType::KEYW_NAMESPACE: {
2603 auto savedStatus = context_.Status();
2604 if (isDeclare) {
2605 context_.Status() |= ParserStatus::IN_AMBIENT_CONTEXT;
2606 }
2607 decl = ParseTsModuleDeclaration(isDeclare, true);
2608 context_.Status() = savedStatus;
2609 break;
2610 }
2611 case lexer::TokenType::KEYW_ABSTRACT: {
2612 lexer_->NextToken(); // eat abstract keyword
2613
2614 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) {
2615 if (isDeclare) {
2616 ThrowSyntaxError("'declare' modifier already seen.");
2617 }
2618 lexer_->NextToken();
2619 isDeclare = true;
2620 }
2621
2622 if (lexer_->GetToken().Type() != lexer::TokenType::KEYW_CLASS) {
2623 ThrowSyntaxError("Unexpected token, expected 'class'.");
2624 }
2625 decl = ParseClassDeclaration(true, std::move(decorators),
2626 isDeclare || IsDtsFile(), true, !isTsModule);
2627 break;
2628 }
2629 default: {
2630 break;
2631 }
2632 }
2633
2634 if (decl) {
2635 break;
2636 }
2637 }
2638
2639 [[fallthrough]];
2640 }
2641 default: {
2642 if (!lexer_->GetToken().IsAsyncModifier()) {
2643 ThrowSyntaxError("Unexpected token");
2644 }
2645
2646 lexer_->NextToken(); // eat `async` keyword
2647 decl = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION | status);
2648 }
2649 }
2650
2651 if (decl->IsVariableDeclaration()) {
2652 ConsumeSemicolon(decl);
2653 }
2654
2655 AddExportLocalEntryItem(decl, isTsModule);
2656
2657 lexer::SourcePosition endLoc = decl->End();
2658 ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter());
2659 auto *exportDeclaration = AllocNode<ir::ExportNamedDeclaration>(decl, std::move(specifiers));
2660 exportDeclaration->SetRange({startLoc, endLoc});
2661
2662 return exportDeclaration;
2663 }
2664
ParseExportDeclaration(StatementParsingFlags flags,ArenaVector<ir::Decorator * > && decorators)2665 ir::Statement *ParserImpl::ParseExportDeclaration(StatementParsingFlags flags,
2666 ArenaVector<ir::Decorator *> &&decorators)
2667 {
2668 if (Extension() == ScriptExtension::JS || !context_.IsTsModule()) {
2669 if (!(flags & StatementParsingFlags::GLOBAL)) {
2670 ThrowSyntaxError("'import' and 'export' may only appear at the top level");
2671 }
2672
2673 if (!context_.IsModule()) {
2674 ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'");
2675 }
2676 }
2677
2678 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2679 lexer_->NextToken(); // eat `export` keyword
2680
2681 // won't set `isType` for type alias
2682 bool isType = false;
2683 if (Extension() == ScriptExtension::TS &&
2684 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE) {
2685 const auto savedPos = lexer_->Save();
2686 lexer_->NextToken(); // eat type
2687 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2688 isType = true;
2689 } else {
2690 lexer_->Rewind(savedPos);
2691 }
2692 }
2693
2694 switch (lexer_->GetToken().Type()) {
2695 case lexer::TokenType::KEYW_DEFAULT: { // export default Id
2696 return ParseExportDefaultDeclaration(startLoc, std::move(decorators));
2697 }
2698 case lexer::TokenType::PUNCTUATOR_MULTIPLY: { // export * ...
2699 return ParseExportAllDeclaration(startLoc);
2700 }
2701 case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { // export { ... } ...
2702 return ParseExportNamedSpecifiers(startLoc, isType);
2703 }
2704 case lexer::TokenType::KEYW_IMPORT: {
2705 return ParseTsImportEqualsDeclaration(startLoc, true);
2706 }
2707 case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: {
2708 if (Extension() == ScriptExtension::TS) {
2709 return ParseExportDefaultDeclaration(startLoc, std::move(decorators), true);
2710 }
2711
2712 [[fallthrough]];
2713 }
2714 case lexer::TokenType::LITERAL_IDENT: {
2715 if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
2716 return ParseTsNamespaceExportDeclaration(startLoc);
2717 }
2718
2719 [[fallthrough]];
2720 }
2721 default: { // export [var] id
2722 ir::ExportNamedDeclaration *exportDecl = ParseNamedExportDeclaration(startLoc, std::move(decorators));
2723
2724 if (Extension() == ScriptExtension::TS && exportDecl->Decl()->IsVariableDeclaration() &&
2725 !(flags & StatementParsingFlags::GLOBAL) && exportDecl->Parent() &&
2726 !exportDecl->Parent()->IsTSModuleBlock() && !context_.IsModule()) {
2727 ThrowSyntaxError("Modifiers cannot appear here'");
2728 }
2729
2730 return exportDecl;
2731 }
2732 }
2733 }
2734
ParseNameSpaceImport(ArenaVector<ir::AstNode * > * specifiers,bool isType)2735 void ParserImpl::ParseNameSpaceImport(ArenaVector<ir::AstNode *> *specifiers, bool isType)
2736 {
2737 lexer::SourcePosition namespaceStart = lexer_->GetToken().Start();
2738 lexer_->NextToken(); // eat `*` character
2739
2740 if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_AS) {
2741 ThrowSyntaxError("Unexpected token.");
2742 }
2743
2744 lexer_->NextToken(); // eat `as` literal
2745
2746 ir::Identifier *local = ParseNamedImport(lexer_->GetToken());
2747
2748 auto *specifier = AllocNode<ir::ImportNamespaceSpecifier>(local);
2749 specifier->SetRange({namespaceStart, lexer_->GetToken().End()});
2750 specifiers->push_back(specifier);
2751
2752 binder::Decl *decl = AddImportDecl(isType, local->Name(), namespaceStart,
2753 binder::DeclarationFlags::NAMESPACE_IMPORT);
2754 decl->BindNode(specifier);
2755
2756 lexer_->NextToken(); // eat local name
2757 }
2758
AddImportDecl(bool isType,util::StringView name,lexer::SourcePosition startPos,binder::DeclarationFlags flag)2759 binder::Decl *ParserImpl::AddImportDecl(bool isType,
2760 util::StringView name,
2761 lexer::SourcePosition startPos,
2762 binder::DeclarationFlags flag)
2763 {
2764 if (isType) {
2765 binder::TSBinding tsBinding(Allocator(), name);
2766 return Binder()->AddTsDecl<binder::TypeAliasDecl>(startPos, flag, false, tsBinding.View());
2767 }
2768 return Binder()->AddDecl<binder::ConstDecl>(startPos, flag, false, name);
2769 }
2770
ParseNamedImport(const lexer::Token & importedToken)2771 ir::Identifier *ParserImpl::ParseNamedImport(const lexer::Token &importedToken)
2772 {
2773 if (importedToken.Type() != lexer::TokenType::LITERAL_IDENT) {
2774 ThrowSyntaxError("Unexpected token");
2775 }
2776
2777 switch (importedToken.KeywordType()) {
2778 case lexer::TokenType::KEYW_EVAL: {
2779 ThrowSyntaxError("Binding 'eval' in strict mode is invalid");
2780 }
2781 case lexer::TokenType::KEYW_ARGUMENTS: {
2782 ThrowSyntaxError("Binding 'arguments' in strict mode is invalid");
2783 }
2784 default: {
2785 break;
2786 }
2787 }
2788
2789 auto *local = AllocNode<ir::Identifier>(importedToken.Ident());
2790 local->SetRange(importedToken.Loc());
2791
2792 return local;
2793 }
2794
ParseNamedImportSpecifiers(ArenaVector<ir::AstNode * > * specifiers,bool isType)2795 void ParserImpl::ParseNamedImportSpecifiers(ArenaVector<ir::AstNode *> *specifiers, bool isType)
2796 {
2797 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat `{` character
2798
2799 while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
2800 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2801 ThrowSyntaxError("Unexpected token");
2802 }
2803
2804 lexer::Token importedToken = lexer_->GetToken();
2805 auto *imported = AllocNode<ir::Identifier>(importedToken.Ident());
2806 ir::Identifier *local = nullptr;
2807 imported->SetRange(lexer_->GetToken().Loc());
2808
2809 lexer_->NextToken(); // eat import name
2810
2811 if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
2812 lexer_->NextToken(); // eat `as` literal
2813 local = ParseNamedImport(lexer_->GetToken());
2814 lexer_->NextToken(); // eat local name
2815 } else {
2816 local = ParseNamedImport(importedToken);
2817 }
2818
2819 auto *specifier = AllocNode<ir::ImportSpecifier>(imported, local);
2820 specifier->SetRange({imported->Start(), local->End()});
2821 specifiers->push_back(specifier);
2822
2823 binder::Decl *decl = AddImportDecl(isType, local->Name(), local->Start(), binder::DeclarationFlags::IMPORT);
2824 decl->BindNode(specifier);
2825
2826 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2827 lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); // eat comma
2828 }
2829 }
2830
2831 lexer_->NextToken(); // eat right brace
2832 }
2833
ParseModuleReference()2834 ir::Expression *ParserImpl::ParseModuleReference()
2835 {
2836 ir::Expression *result = nullptr;
2837
2838 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2839 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_REQUIRE &&
2840 lexer_->Lookahead() == LEX_CHAR_LEFT_PAREN) {
2841 lexer::SourcePosition start = lexer_->GetToken().Start();
2842 lexer_->NextToken(); // eat 'require'
2843 lexer_->NextToken(); // eat '('
2844
2845 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
2846 ThrowSyntaxError("String literal expected.");
2847 }
2848
2849 result = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
2850 result->SetRange(lexer_->GetToken().Loc());
2851 lexer_->NextToken();
2852
2853 if (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
2854 ThrowSyntaxError("')' expected.");
2855 }
2856
2857 result = AllocNode<ir::TSExternalModuleReference>(result);
2858 result->SetRange({start, lexer_->GetToken().End()});
2859 lexer_->NextToken(); // eat ')'
2860 } else {
2861 result = AllocNode<ir::Identifier>(lexer_->GetToken().Ident());
2862 result->SetRange(lexer_->GetToken().Loc());
2863 lexer_->NextToken();
2864
2865 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
2866 result = ParseTsQualifiedReference(result);
2867 }
2868 }
2869
2870 return result;
2871 }
2872
ParseImportDefaultSpecifier(ArenaVector<ir::AstNode * > * specifiers,bool isType)2873 ir::AstNode *ParserImpl::ParseImportDefaultSpecifier(ArenaVector<ir::AstNode *> *specifiers, bool isType)
2874 {
2875 ir::Identifier *local = ParseNamedImport(lexer_->GetToken());
2876 lexer_->NextToken(); // eat local name
2877
2878 if (Extension() == ScriptExtension::TS && lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
2879 lexer_->NextToken(); // eat substitution
2880 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
2881 ThrowSyntaxError("identifier expected");
2882 }
2883 if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_REQUIRE ||
2884 lexer_->Lookahead() != LEX_CHAR_LEFT_PAREN) {
2885 auto *decl = Binder()->AddDecl<binder::ImportEqualsDecl>(local->Start(), binder::DeclarationFlags::NONE,
2886 false, local->Name());
2887 decl->BindNode(local);
2888 auto *scope = Binder()->GetScope();
2889 auto *var = scope->FindLocalTSVariable<binder::TSBindingType::IMPORT_EQUALS>(local->Name());
2890 ASSERT(var != nullptr);
2891 var->AsImportEqualsVariable()->SetScope(scope);
2892 }
2893
2894 auto *importEqualsDecl = AllocNode<ir::TSImportEqualsDeclaration>(local, ParseModuleReference(), false);
2895
2896 return importEqualsDecl;
2897 }
2898
2899 auto *specifier = AllocNode<ir::ImportDefaultSpecifier>(local);
2900 specifier->SetRange(specifier->Local()->Range());
2901 specifiers->push_back(specifier);
2902
2903 binder::Decl *decl = AddImportDecl(isType, local->Name(), local->Start(), binder::DeclarationFlags::IMPORT);
2904 decl->BindNode(specifier);
2905
2906 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2907 lexer_->NextToken(); // eat comma
2908 }
2909
2910 return nullptr;
2911 }
2912
ParseFromClause(bool requireFrom)2913 ir::StringLiteral *ParserImpl::ParseFromClause(bool requireFrom)
2914 {
2915 if (lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) {
2916 if (requireFrom) {
2917 ThrowSyntaxError("Unexpected token.");
2918 }
2919 } else {
2920 lexer_->NextToken(); // eat `from` literal
2921 }
2922
2923 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
2924 ThrowSyntaxError("Unexpected token.");
2925 }
2926
2927 ASSERT(lexer_->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
2928
2929 auto *source = AllocNode<ir::StringLiteral>(lexer_->GetToken().String());
2930 source->SetRange(lexer_->GetToken().Loc());
2931
2932 lexer_->NextToken();
2933
2934 return source;
2935 }
2936
ParseImportSpecifiers(ArenaVector<ir::AstNode * > * specifiers,bool isType)2937 ir::AstNode *ParserImpl::ParseImportSpecifiers(ArenaVector<ir::AstNode *> *specifiers, bool isType)
2938 {
2939 ASSERT(specifiers->empty());
2940
2941 // import [default] from 'source'
2942 if (lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
2943 ir::AstNode *astNode = ParseImportDefaultSpecifier(specifiers, isType);
2944 if (astNode != nullptr) {
2945 return astNode;
2946 }
2947 }
2948
2949 if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
2950 ParseNameSpaceImport(specifiers, isType);
2951 } else if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2952 ParseNamedImportSpecifiers(specifiers, isType);
2953 }
2954 return nullptr;
2955 }
2956
ParseImportDeclaration(StatementParsingFlags flags)2957 ir::Statement *ParserImpl::ParseImportDeclaration(StatementParsingFlags flags)
2958 {
2959 char32_t nextChar = lexer_->Lookahead();
2960 // dynamic import || import.meta
2961 if (nextChar == LEX_CHAR_LEFT_PAREN || nextChar == LEX_CHAR_DOT) {
2962 return ParseExpressionStatement();
2963 }
2964
2965 if (Extension() == ScriptExtension::JS) {
2966 if (!(flags & StatementParsingFlags::GLOBAL)) {
2967 ThrowSyntaxError("'import' and 'export' may only appear at the top level");
2968 }
2969
2970 if (!context_.IsModule()) {
2971 ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'");
2972 }
2973 }
2974
2975 lexer::SourcePosition startLoc = lexer_->GetToken().Start();
2976 lexer_->NextToken(); // eat import
2977
2978 bool isType = false;
2979 if (Extension() == ScriptExtension::TS &&
2980 lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE) {
2981 const auto savedPos = lexer_->Save();
2982 lexer_->NextToken(); // eat type
2983 if ((lexer_->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
2984 lexer_->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) ||
2985 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE ||
2986 lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
2987 isType = true;
2988 } else {
2989 lexer_->Rewind(savedPos);
2990 }
2991 }
2992
2993 ArenaVector<ir::AstNode *> specifiers(Allocator()->Adapter());
2994
2995 ir::StringLiteral *source = nullptr;
2996
2997 if (lexer_->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
2998 ir::AstNode *astNode = ParseImportSpecifiers(&specifiers, isType);
2999 if (astNode != nullptr) {
3000 ASSERT(astNode->IsTSImportEqualsDeclaration());
3001 astNode->SetRange({startLoc, lexer_->GetToken().End()});
3002 ConsumeSemicolon(astNode->AsTSImportEqualsDeclaration());
3003 return astNode->AsTSImportEqualsDeclaration();
3004 }
3005 if (Extension() == ScriptExtension::TS && !context_.IsModule()) {
3006 ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'");
3007 }
3008 source = ParseFromClause(true);
3009 AddImportEntryItem(source, &specifiers, isType);
3010 } else {
3011 if (Extension() == ScriptExtension::TS && !context_.IsModule()) {
3012 ThrowSyntaxError("'import' and 'export' may appear only with 'sourceType: module'");
3013 }
3014 // import 'source'
3015 source = ParseFromClause(false);
3016 AddImportEntryItem(source, nullptr, isType);
3017 }
3018
3019 lexer::SourcePosition endLoc = source->End();
3020 auto *importDeclaration = AllocNode<ir::ImportDeclaration>(source, std::move(specifiers), isType);
3021 importDeclaration->SetRange({startLoc, endLoc});
3022
3023 ConsumeSemicolon(importDeclaration);
3024
3025 return importDeclaration;
3026 }
3027
3028 } // namespace panda::es2panda::parser
3029