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