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