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