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