1 /**
2  * Copyright (c) 2021-2024 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 "ETSparser.h"
17 #include "ETSNolintParser.h"
18 #include <utility>
19 
20 #include "macros.h"
21 #include "parser/parserFlags.h"
22 #include "parser/parserStatusContext.h"
23 #include "util/helpers.h"
24 #include "util/language.h"
25 #include "utils/arena_containers.h"
26 #include "varbinder/varbinder.h"
27 #include "varbinder/ETSBinder.h"
28 #include "lexer/lexer.h"
29 #include "lexer/ETSLexer.h"
30 #include "ir/astNode.h"
31 #include "ir/base/decorator.h"
32 #include "ir/base/catchClause.h"
33 #include "ir/base/scriptFunction.h"
34 #include "ir/base/methodDefinition.h"
35 #include "ir/base/spreadElement.h"
36 #include "ir/statements/namespaceDeclaration.h"
37 #include "ir/expressions/identifier.h"
38 #include "ir/expressions/functionExpression.h"
39 #include "ir/expressions/dummyNode.h"
40 #include "ir/module/importDeclaration.h"
41 #include "ir/module/importDefaultSpecifier.h"
42 #include "ir/module/importSpecifier.h"
43 #include "ir/module/exportSpecifier.h"
44 #include "ir/module/exportNamedDeclaration.h"
45 #include "ir/ets/etsPrimitiveType.h"
46 #include "ir/ets/etsPackageDeclaration.h"
47 #include "ir/ets/etsReExportDeclaration.h"
48 #include "ir/ets/etsWildcardType.h"
49 #include "ir/ets/etsTuple.h"
50 #include "ir/ets/etsFunctionType.h"
51 #include "ir/ets/etsScript.h"
52 #include "ir/ets/etsTypeReference.h"
53 #include "ir/ets/etsTypeReferencePart.h"
54 #include "ir/ets/etsNullishTypes.h"
55 #include "ir/ets/etsUnionType.h"
56 #include "ir/ets/etsImportSource.h"
57 #include "ir/ets/etsImportDeclaration.h"
58 #include "ir/ets/etsStructDeclaration.h"
59 #include "ir/module/importNamespaceSpecifier.h"
60 #include "ir/ts/tsInterfaceDeclaration.h"
61 #include "ir/ts/tsTypeParameterInstantiation.h"
62 #include "ir/ts/tsInterfaceBody.h"
63 #include "ir/ts/tsImportEqualsDeclaration.h"
64 #include "ir/ts/tsArrayType.h"
65 #include "ir/ts/tsQualifiedName.h"
66 #include "ir/ts/tsTypeReference.h"
67 #include "ir/ts/tsTypeParameter.h"
68 #include "ir/ts/tsInterfaceHeritage.h"
69 #include "ir/ts/tsFunctionType.h"
70 #include "ir/ts/tsTypeAliasDeclaration.h"
71 #include "ir/ts/tsTypeParameterDeclaration.h"
72 #include "ir/ts/tsThisType.h"
73 #include "generated/signatures.h"
74 
75 namespace ark::es2panda::parser {
76 class FunctionContext;
77 
78 using namespace std::literals::string_literals;
79 
ETSParser(Program *program, const CompilerOptions &options, ParserStatus status)80 ETSParser::ETSParser(Program *program, const CompilerOptions &options, ParserStatus status)
81     : TypedParser(program, options, status), globalProgram_(GetProgram())
82 {
83     importPathManager_ = std::make_unique<util::ImportPathManager>(Allocator(), ArkTSConfig(), GetOptions().stdLib);
84 }
85 
86 bool ETSParser::IsETSParser() const noexcept
87 {
88     return true;
89 }
90 
InitLexer(const SourceFile &sourceFile)91 std::unique_ptr<lexer::Lexer> ETSParser::InitLexer(const SourceFile &sourceFile)
92 {
93     GetProgram()->SetSource(sourceFile);
94     auto lexer = std::make_unique<lexer::ETSLexer>(&GetContext());
95     SetLexer(lexer.get());
96     return lexer;
97 }
98 
ParseProgram(ScriptKind kind)99 void ETSParser::ParseProgram(ScriptKind kind)
100 {
101     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
102     Lexer()->NextToken();
103     GetProgram()->SetKind(kind);
104 
105     if (GetProgram()->SourceFilePath().Utf8()[0] == '@') {
106         // NOTE(user): handle multiple sourceFiles
107     }
108 
109     ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
110     auto decl = ParsePackageDeclaration();
111     if (decl != nullptr) {
112         statements.emplace_back(decl);
113         // If we found a package declaration, then add all files with the same package to the package parse list
114         AddPackageSourcesToParseList();
115     }
116 
117     auto script = ParseETSGlobalScript(startLoc, statements);
118 
119     AddExternalSource(ParseSources(true));
120     GetProgram()->SetAst(script);
121     GetProgram()->SetDeclarationModuleInfo();
122 }
123 
ParseETSGlobalScript(lexer::SourcePosition startLoc, ArenaVector<ir::Statement *> &statements)124 ir::ETSScript *ETSParser::ParseETSGlobalScript(lexer::SourcePosition startLoc, ArenaVector<ir::Statement *> &statements)
125 {
126     ETSNolintParser etsnolintParser(this);
127     etsnolintParser.CollectETSNolints();
128 
129     auto imports = ParseImportDeclarations();
130     statements.insert(statements.end(), imports.begin(), imports.end());
131 
132     auto topLevelStatements = ParseTopLevelDeclaration();
133     statements.insert(statements.end(), topLevelStatements.begin(), topLevelStatements.end());
134 
135     etsnolintParser.ApplyETSNolintsToStatements(statements);
136 
137     auto *etsScript = AllocNode<ir::ETSScript>(Allocator(), std::move(statements), GetProgram());
138     etsScript->SetRange({startLoc, Lexer()->GetToken().End()});
139     return etsScript;
140 }
141 
AddExternalSource(const std::vector<Program *> &programs)142 void ETSParser::AddExternalSource(const std::vector<Program *> &programs)
143 {
144     auto &extSources = globalProgram_->ExternalSources();
145 
146     for (auto *newProg : programs) {
147         const util::StringView moduleName = newProg->ModuleName();
148         if (extSources.count(moduleName) == 0) {
149             extSources.try_emplace(moduleName, Allocator()->Adapter());
150         }
151 
152         extSources.at(moduleName).emplace_back(newProg);
153     }
154 }
155 
ParseDefaultSources(std::string_view srcFile, std::string_view importSrc)156 ArenaVector<ir::ETSImportDeclaration *> ETSParser::ParseDefaultSources(std::string_view srcFile,
157                                                                        std::string_view importSrc)
158 {
159     auto isp = InnerSourceParser(this);
160     SourceFile source(srcFile, importSrc);
161     auto lexer = InitLexer(source);
162 
163     Lexer()->NextToken();
164 
165     GetContext().Status() |= ParserStatus::IN_DEFAULT_IMPORTS;
166     auto statements = ParseImportDeclarations();
167     GetContext().Status() &= ~ParserStatus::IN_DEFAULT_IMPORTS;
168 
169     AddExternalSource(ParseSources());
170     return statements;
171 }
172 
AddDirectImportsToDirectExternalSources( const ArenaVector<util::StringView> &directImportsFromMainSource, parser::Program *const newProg) const173 void ETSParser::AddDirectImportsToDirectExternalSources(
174     const ArenaVector<util::StringView> &directImportsFromMainSource, parser::Program *const newProg) const
175 {
176     if (std::find_if(directImportsFromMainSource.begin(), directImportsFromMainSource.end(),
177                      [newProg](const util::StringView &sv) { return sv == newProg->AbsoluteName(); }) ==
178         directImportsFromMainSource.end()) {
179         return;
180     }
181 
182     const util::StringView name = newProg->Ast()->Statements().empty() ? newProg->FileName() : newProg->ModuleName();
183     if (GetProgram()->DirectExternalSources().count(name) == 0) {
184         GetProgram()->DirectExternalSources().try_emplace(name, Allocator()->Adapter());
185     }
186     GetProgram()->DirectExternalSources().at(name).emplace_back(newProg);
187 }
188 
TryParseSource(const util::ImportPathManager::ParseInfo &parseListIdx, util::UString *extSrc, const ArenaVector<util::StringView> &directImportsFromMainSource, std::vector<Program *> &programs)189 void ETSParser::TryParseSource(const util::ImportPathManager::ParseInfo &parseListIdx, util::UString *extSrc,
190                                const ArenaVector<util::StringView> &directImportsFromMainSource,
191                                std::vector<Program *> &programs)
192 {
193     try {
194         parser::Program *newProg =
195             ParseSource({parseListIdx.sourcePath.Utf8(), extSrc->View().Utf8(), parseListIdx.sourcePath.Utf8(), false});
196 
197         if (!parseListIdx.isImplicitPackageImported || newProg->IsPackageModule()) {
198             AddDirectImportsToDirectExternalSources(directImportsFromMainSource, newProg);
199             // don't insert the separate modules into the programs, when we collect implicit package imports
200             programs.emplace_back(newProg);
201         }
202     } catch (const Error &) {
203         // Here file is not a valid STS source. Ignore and continue if it's implicit package import, else throw
204         // the syntax error as usual
205 
206         if (!parseListIdx.isImplicitPackageImported) {
207             throw;
208         }
209 
210         util::Helpers::LogWarning("Error during parse of file '", parseListIdx.sourcePath,
211                                   "' in compiled package. File will be omitted.");
212     }
213 }
214 
ParseSources(bool firstSource)215 std::vector<Program *> ETSParser::ParseSources(bool firstSource)
216 {
217     std::vector<Program *> programs;
218 
219     auto &parseList = importPathManager_->ParseList();
220 
221     ArenaVector<util::StringView> directImportsFromMainSource(Allocator()->Adapter());
222 
223     if (firstSource) {
224         for (auto pl : parseList) {
225             if (pl.isParsed) {
226                 // Handle excluded files, which are already set to be parsed before parsing them
227                 continue;
228             }
229             directImportsFromMainSource.emplace_back(pl.sourcePath);
230         }
231     }
232 
233     auto notParsedElement =
234         std::find_if(parseList.begin(), parseList.end(), [](const auto &parseInfo) { return !parseInfo.isParsed; });
235 
236     // NOTE (mmartin): Need a more optimal solution here
237     // This is needed, as during a parsing of a file, programs can be re-added to the parseList, which needs to be
238     // re-parsed. This won't change the size of the list, so with only the 'for loop', there can be unparsed files
239     // remained.
240     // An example for this, is when a file is added as an implicit package import, but it's erroneous, so we just ignore
241     // the file. But when the same file is also added with an explicit import declaration, then we need to re-parse it,
242     // and throw the syntax error.
243     while (notParsedElement != parseList.end()) {
244         // This parse list `paths` can grow in the meantime, so keep this index-based iteration
245         // NOLINTNEXTLINE(modernize-loop-convert)
246         for (size_t idx = 0; idx < parseList.size(); idx++) {
247             // check if already parsed
248             if (parseList[idx].isParsed) {
249                 continue;
250             }
251             std::ifstream inputStream(parseList[idx].sourcePath.Mutf8());
252             const auto data = importPathManager_->GetImportData(parseList[idx].sourcePath, Extension());
253             if (!data.hasDecl) {
254                 importPathManager_->MarkAsParsed(parseList[idx].sourcePath);
255                 continue;
256             }
257 
258             if (GetProgram()->SourceFilePath().Is(parseList[idx].sourcePath.Mutf8())) {
259                 return programs;
260             }
261 
262             if (inputStream.fail()) {
263                 ThrowSyntaxError({"Failed to open file: ", parseList[idx].sourcePath.Mutf8()});
264             }
265 
266             std::stringstream ss;
267             ss << inputStream.rdbuf();
268             auto externalSource = ss.str();
269 
270             auto currentLang = GetContext().SetLanguage(data.lang);
271             auto extSrc = Allocator()->New<util::UString>(externalSource, Allocator());
272             importPathManager_->MarkAsParsed(parseList[idx].sourcePath);
273 
274             // In case of implicit package import, if we find a malformed STS file in the package's directory, instead
275             // of aborting compilation we just ignore the file
276 
277             // NOTE (mmartin): after the multiple syntax error handling in the parser is implemented, this try-catch
278             // must be changed, as exception throwing will be removed
279 
280             TryParseSource(parseList[idx], extSrc, directImportsFromMainSource, programs);
281 
282             GetContext().SetLanguage(currentLang);
283         }
284 
285         notParsedElement =
286             std::find_if(parseList.begin(), parseList.end(), [](const auto &parseInfo) { return !parseInfo.isParsed; });
287     }
288 
289     return programs;
290 }
291 
ParseSource(const SourceFile &sourceFile)292 parser::Program *ETSParser::ParseSource(const SourceFile &sourceFile)
293 {
294     importPathManager_->MarkAsParsed(sourceFile.filePath);
295     auto *program = Allocator()->New<parser::Program>(Allocator(), GetProgram()->VarBinder());
296     auto esp = ExternalSourceParser(this, program);
297     auto lexer = InitLexer(sourceFile);
298 
299     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
300     Lexer()->NextToken();
301 
302     ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
303     auto decl = ParsePackageDeclaration();
304     if (decl != nullptr) {
305         statements.emplace_back(decl);
306     }
307     auto script = ParseETSGlobalScript(startLoc, statements);
308     program->SetAst(script);
309     GetProgram()->SetDeclarationModuleInfo();
310     return program;
311 }
312 
ParseIdentKeyword()313 ir::Statement *ETSParser::ParseIdentKeyword()
314 {
315     const auto token = Lexer()->GetToken();
316     ASSERT(token.Type() == lexer::TokenType::LITERAL_IDENT);
317     switch (token.KeywordType()) {
318         case lexer::TokenType::KEYW_STRUCT: {
319             // Remove this ThrowSyntaxError when struct is implemented in #12726
320             ThrowSyntaxError("Struct types are not supported yet!");
321         }
322         case lexer::TokenType::KEYW_TYPE: {
323             return ParseTypeAliasDeclaration();
324         }
325         default: {
326             break;
327         }
328     }
329     return nullptr;
330 }
331 
ParseFunction(ParserStatus newStatus, ir::Identifier *className)332 ir::ScriptFunction *ETSParser::ParseFunction(ParserStatus newStatus, ir::Identifier *className)
333 {
334     FunctionContext functionContext(this, newStatus | ParserStatus::FUNCTION);
335     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
336     auto [signature, throwMarker] = ParseFunctionSignature(newStatus, className);
337 
338     ir::AstNode *body = nullptr;
339     lexer::SourcePosition endLoc = startLoc;
340     bool isOverload = false;
341     bool isArrow = (newStatus & ParserStatus::ARROW_FUNCTION) != 0;
342 
343     if ((newStatus & ParserStatus::ASYNC_FUNCTION) != 0) {
344         functionContext.AddFlag(ir::ScriptFunctionFlags::ASYNC);
345     }
346 
347     if (isArrow) {
348         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
349             ThrowSyntaxError("'=>' expected");
350         }
351 
352         functionContext.AddFlag(ir::ScriptFunctionFlags::ARROW);
353         Lexer()->NextToken();
354     }
355 
356     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
357         std::tie(std::ignore, body, endLoc, isOverload) =
358             ParseFunctionBody(signature.Params(), newStatus, GetContext().Status());
359     } else if (isArrow) {
360         body = ParseExpression();
361         endLoc = body->AsExpression()->End();
362         functionContext.AddFlag(ir::ScriptFunctionFlags::EXPRESSION);
363     }
364 
365     if ((GetContext().Status() & ParserStatus::FUNCTION_HAS_RETURN_STATEMENT) != 0) {
366         functionContext.AddFlag(ir::ScriptFunctionFlags::HAS_RETURN);
367         GetContext().Status() ^= ParserStatus::FUNCTION_HAS_RETURN_STATEMENT;
368     }
369     functionContext.AddFlag(throwMarker);
370 
371     bool isDeclare = InAmbientContext();
372     if (functionContext.IsAsync() && isDeclare) {
373         ThrowSyntaxError("The modifier async cannot be used in an ambient context.");
374     }
375 
376     // clang-format off
377     ir::ModifierFlags mFlags = isDeclare ? ir::ModifierFlags::DECLARE : ir::ModifierFlags::NONE;
378     ir::ScriptFunctionFlags funcFlags =
379         isDeclare ? (functionContext.Flags() | ir::ScriptFunctionFlags::EXTERNAL) : functionContext.Flags();
380     auto *funcNode = AllocNode<ir::ScriptFunction>(
381         Allocator(), ir::ScriptFunction::ScriptFunctionData {body, std::move(signature), funcFlags, mFlags, isDeclare,
382                                                              GetContext().GetLanguage()});
383     funcNode->SetRange({startLoc, endLoc});
384     // clang-format on
385 
386     return funcNode;
387 }
388 
ParseFunctionBody( [[maybe_unused]] const ArenaVector<ir::Expression *> &params, [[maybe_unused]] ParserStatus newStatus, [[maybe_unused]] ParserStatus contextStatus)389 std::tuple<bool, ir::BlockStatement *, lexer::SourcePosition, bool> ETSParser::ParseFunctionBody(
390     [[maybe_unused]] const ArenaVector<ir::Expression *> &params, [[maybe_unused]] ParserStatus newStatus,
391     [[maybe_unused]] ParserStatus contextStatus)
392 {
393     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
394         LogSyntaxError({"Expected token '{', got '", TokenToString(Lexer()->GetToken().Type()), "'"});
395         return {false, nullptr, Lexer()->GetToken().End(), false};
396     }
397 
398     ir::BlockStatement *body = ParseBlockStatement();
399 
400     return {true, body, body->End(), false};
401 }
402 
ParseFunctionThrowMarker(bool isRethrowsAllowed)403 ir::ScriptFunctionFlags ETSParser::ParseFunctionThrowMarker(bool isRethrowsAllowed)
404 {
405     ir::ScriptFunctionFlags throwMarker = ir::ScriptFunctionFlags::NONE;
406 
407     if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
408         if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_THROWS) {
409             Lexer()->NextToken();  // eat 'throws'
410             throwMarker = ir::ScriptFunctionFlags::THROWS;
411         } else if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_RETHROWS) {
412             if (isRethrowsAllowed) {
413                 Lexer()->NextToken();  // eat 'rethrows'
414                 throwMarker = ir::ScriptFunctionFlags::RETHROWS;
415             } else {
416                 ThrowSyntaxError("Only 'throws' can be used with function types");
417             }
418         }
419     }
420 
421     return throwMarker;
422 }
423 
ParseInnerTypeDeclaration(ir::ModifierFlags memberModifiers, lexer::LexerPosition savedPos, bool isStepToken, bool seenStatic)424 ir::AstNode *ETSParser::ParseInnerTypeDeclaration(ir::ModifierFlags memberModifiers, lexer::LexerPosition savedPos,
425                                                   bool isStepToken, bool seenStatic)
426 {
427     if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) == 0) {
428         ThrowSyntaxError("Local type declaration (class, struct, interface and enum) support is not yet implemented.");
429     }
430 
431     // remove saved_pos nolint
432     Lexer()->Rewind(savedPos);
433     if (isStepToken) {
434         Lexer()->NextToken();
435     }
436 
437     Lexer()->GetToken().SetTokenType(Lexer()->GetToken().KeywordType());
438     ir::AstNode *typeDecl = ParseTypeDeclaration(true);
439     memberModifiers &= (ir::ModifierFlags::PUBLIC | ir::ModifierFlags::PROTECTED | ir::ModifierFlags::PRIVATE |
440                         ir::ModifierFlags::INTERNAL);
441     typeDecl->AddModifier(memberModifiers);
442 
443     if (!seenStatic) {
444         if (typeDecl->IsClassDeclaration()) {
445             typeDecl->AsClassDeclaration()->Definition()->AsClassDefinition()->SetInnerModifier();
446         } else if (typeDecl->IsETSStructDeclaration()) {
447             typeDecl->AsETSStructDeclaration()->Definition()->AsClassDefinition()->SetInnerModifier();
448         }
449     }
450 
451     return typeDecl;
452 }
453 
ParseInnerConstructorDeclaration(ir::ModifierFlags memberModifiers, const lexer::SourcePosition &startLoc)454 ir::AstNode *ETSParser::ParseInnerConstructorDeclaration(ir::ModifierFlags memberModifiers,
455                                                          const lexer::SourcePosition &startLoc)
456 {
457     if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) != 0) {
458         ThrowSyntaxError({"Namespaces should not have a constructor"});
459     }
460     if ((memberModifiers & (~(ir::ModifierFlags::ACCESS | ir::ModifierFlags::DECLARE))) != 0) {
461         ThrowSyntaxError(
462             {"The modifier for a constructor should be limited to access modifiers(private, internal, protected, "
463              "public)."});
464     }
465     auto *memberName = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
466     memberModifiers |= ir::ModifierFlags::CONSTRUCTOR;
467     Lexer()->NextToken();
468     auto *classMethod = ParseClassMethodDefinition(memberName, memberModifiers);
469     classMethod->SetStart(startLoc);
470 
471     return classMethod;
472 }
473 
CreateInvokeIdentifier()474 ir::Identifier *ETSParser::CreateInvokeIdentifier()
475 {
476     util::StringView tokenName = util::StringView {compiler::Signatures::STATIC_INVOKE_METHOD};
477     auto ident = AllocNode<ir::Identifier>(tokenName, Allocator());
478     ident->SetReference(false);
479     ident->SetRange({Lexer()->GetToken().Start(), Lexer()->GetToken().End()});
480     return ident;
481 }
482 
CheckAccessorDeclaration(ir::ModifierFlags memberModifiers)483 void ETSParser::CheckAccessorDeclaration(ir::ModifierFlags memberModifiers)
484 {
485     ir::ModifierFlags methodModifiersNotAccessorModifiers = ir::ModifierFlags::NATIVE | ir::ModifierFlags::ASYNC;
486     if ((memberModifiers & methodModifiersNotAccessorModifiers) != 0) {
487         ThrowSyntaxError("Modifiers of getter and setter are limited to ('abstract', 'static', 'final', 'override').");
488     }
489 }
490 
ParseInnerRest(const ArenaVector<ir::AstNode *> &properties, ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags memberModifiers, const lexer::SourcePosition &startLoc)491 ir::AstNode *ETSParser::ParseInnerRest(const ArenaVector<ir::AstNode *> &properties,
492                                        ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags memberModifiers,
493                                        const lexer::SourcePosition &startLoc)
494 {
495     if (Lexer()->Lookahead() != lexer::LEX_CHAR_LEFT_PAREN && Lexer()->Lookahead() != lexer::LEX_CHAR_LESS_THAN &&
496         (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_GET ||
497          Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_SET)) {
498         CheckAccessorDeclaration(memberModifiers);
499         return ParseClassGetterSetterMethod(properties, modifiers, memberModifiers);
500     }
501 
502     if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) != 0) {
503         auto type = Lexer()->GetToken().Type();
504         if (type == lexer::TokenType::KEYW_FUNCTION || type == lexer::TokenType::KEYW_LET ||
505             type == lexer::TokenType::KEYW_CONST) {
506             Lexer()->NextToken();
507         }
508     }
509 
510     auto parseClassMethod = [&memberModifiers, &startLoc, this](ir::Identifier *methodName) {
511         auto *classMethod = ParseClassMethodDefinition(methodName, memberModifiers, nullptr);
512         classMethod->SetStart(startLoc);
513         return classMethod;
514     };
515 
516     if (InAmbientContext()) {
517         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS &&
518             (GetContext().Status() & ParserStatus::IN_CLASS_BODY) != 0U) {
519             // Special case for processing of special '(param: type): returnType` identifier using in ambient context
520             auto ident = CreateInvokeIdentifier();
521             memberModifiers |= ir::ModifierFlags::STATIC;
522             return parseClassMethod(ident);
523         }
524         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
525             auto const savePos = Lexer()->Save();
526             Lexer()->NextToken();
527             if (Lexer()->GetToken().Ident().Is("Symbol")) {
528                 Lexer()->Rewind(savePos);
529             } else {
530                 return ParseAmbientSignature();
531             }
532         }
533     }
534 
535     auto *memberName = ExpectIdentifier();
536     if (memberName == nullptr) {  // Error processing.
537         return nullptr;
538     }
539 
540     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS ||
541         Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
542         return parseClassMethod(memberName);
543     }
544 
545     ArenaVector<ir::AstNode *> fieldDeclarations(Allocator()->Adapter());
546     auto *placeholder = AllocNode<ir::TSInterfaceBody>(std::move(fieldDeclarations));
547     ParseClassFieldDefinition(memberName, memberModifiers, placeholder->BodyPtr());
548     return placeholder;
549 }
550 
ParseTypeDeclarationAbstractFinal(bool allowStatic, ir::ClassDefinitionModifiers modifiers)551 ir::Statement *ETSParser::ParseTypeDeclarationAbstractFinal(bool allowStatic, ir::ClassDefinitionModifiers modifiers)
552 {
553     auto flags = ParseClassModifiers();
554     if (allowStatic && (flags & ir::ModifierFlags::STATIC) == 0U) {
555         modifiers |= ir::ClassDefinitionModifiers::INNER;
556     }
557 
558     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS) {
559         return ParseClassDeclaration(modifiers, flags);
560     }
561 
562     if (IsStructKeyword()) {
563         return ParseStructDeclaration(modifiers, flags);
564     }
565 
566     ThrowUnexpectedToken(Lexer()->GetToken().Type());
567 }
568 
ParseTypeDeclaration(bool allowStatic)569 ir::Statement *ETSParser::ParseTypeDeclaration(bool allowStatic)
570 {
571     auto savedPos = Lexer()->Save();
572 
573     auto modifiers = ir::ClassDefinitionModifiers::ID_REQUIRED | ir::ClassDefinitionModifiers::CLASS_DECL;
574 
575     auto tokenType = Lexer()->GetToken().Type();
576     switch (tokenType) {
577         case lexer::TokenType::KEYW_STATIC: {
578             if (!allowStatic) {
579                 ThrowUnexpectedToken(Lexer()->GetToken().Type());
580             }
581 
582             Lexer()->NextToken();
583 
584             if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_INTERFACE) {
585                 return ParseInterfaceDeclaration(true);
586             }
587 
588             Lexer()->Rewind(savedPos);
589             [[fallthrough]];
590         }
591         case lexer::TokenType::KEYW_ABSTRACT:
592         case lexer::TokenType::KEYW_FINAL: {
593             return ParseTypeDeclarationAbstractFinal(allowStatic, modifiers);
594         }
595         case lexer::TokenType::KEYW_ENUM: {
596             return ParseEnumDeclaration(false);
597         }
598         case lexer::TokenType::KEYW_INTERFACE: {
599             return ParseInterfaceDeclaration(false);
600         }
601         case lexer::TokenType::KEYW_NAMESPACE: {
602             if (!InAmbientContext()) {
603                 ThrowSyntaxError("Namespaces are declare only");
604             }
605             GetContext().Status() |= ParserStatus::IN_NAMESPACE;
606             auto *ns = ParseNamespaceDeclaration(ir::ModifierFlags::DECLARE | ir::ModifierFlags::EXPORT);
607             GetContext().Status() &= ~ParserStatus::IN_NAMESPACE;
608             return ns;
609         }
610         case lexer::TokenType::KEYW_CLASS: {
611             return ParseClassDeclaration(modifiers);
612         }
613         case lexer::TokenType::LITERAL_IDENT: {
614             if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STRUCT) {
615                 return ParseStructDeclaration(modifiers);
616             }
617             [[fallthrough]];
618         }
619         default: {
620             ThrowUnexpectedToken(Lexer()->GetToken().Type());
621         }
622     }
623 }
624 
ParseTypeAliasDeclaration()625 ir::TSTypeAliasDeclaration *ETSParser::ParseTypeAliasDeclaration()
626 {
627     ASSERT(Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE);
628 
629     lexer::SourcePosition typeStart = Lexer()->GetToken().Start();
630     Lexer()->NextToken();  // eat type keyword
631 
632     if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
633         ThrowSyntaxError("Identifier expected");
634     }
635 
636     if (Lexer()->GetToken().IsReservedTypeName()) {
637         std::string errMsg("Type alias name cannot be '");
638         errMsg.append(TokenToString(Lexer()->GetToken().KeywordType()));
639         errMsg.append("'");
640         ThrowSyntaxError(errMsg.c_str());
641     }
642 
643     const util::StringView ident = Lexer()->GetToken().Ident();
644     auto *id = AllocNode<ir::Identifier>(ident, Allocator());
645     id->SetRange(Lexer()->GetToken().Loc());
646 
647     auto *typeAliasDecl = AllocNode<ir::TSTypeAliasDeclaration>(Allocator(), id);
648 
649     Lexer()->NextToken();  // eat alias name
650 
651     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
652         auto options =
653             TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::ALLOW_DECLARATION_SITE_VARIANCE;
654         ir::TSTypeParameterDeclaration *params = ParseTypeParameterDeclaration(&options);
655         typeAliasDecl->SetTypeParameters(params);
656         params->SetParent(typeAliasDecl);
657     }
658 
659     if (!Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_SUBSTITUTION)) {
660         ThrowSyntaxError("'=' expected");
661     }
662 
663     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
664     ir::TypeNode *typeAnnotation = ParseTypeAnnotation(&options);
665     if (typeAnnotation != nullptr) {  // Error processing.
666         typeAliasDecl->SetTsTypeAnnotation(typeAnnotation);
667         typeAnnotation->SetParent(typeAliasDecl);
668     }
669 
670     typeAliasDecl->SetRange({typeStart, Lexer()->GetToken().End()});
671     return typeAliasDecl;
672 }
673 
CheckDefaultParameters(const ir::ScriptFunction *const function) const674 std::pair<bool, std::size_t> ETSParser::CheckDefaultParameters(const ir::ScriptFunction *const function) const
675 {
676     bool hasDefaultParameter = false;
677     bool hasRestParameter = false;
678     std::size_t requiredParametersNumber = 0U;
679 
680     for (auto *const it : function->Params()) {
681         auto const *const param = it->AsETSParameterExpression();
682 
683         if (param->IsRestParameter()) {
684             hasRestParameter = true;
685             continue;
686         }
687 
688         if (hasRestParameter) {
689             ThrowSyntaxError("Rest parameter should be the last one.", param->Start());
690         }
691 
692         if (param->IsDefault()) {
693             hasDefaultParameter = true;
694             continue;
695         }
696 
697         if (hasDefaultParameter) {
698             ThrowSyntaxError("Required parameter follows default parameter(s).", param->Start());
699         }
700 
701         ++requiredParametersNumber;
702     }
703 
704     if (hasDefaultParameter && hasRestParameter) {
705         ThrowSyntaxError("Both optional and rest parameters are not allowed in function's parameter list.",
706                          function->Start());
707     }
708 
709     return std::make_pair(hasDefaultParameter, requiredParametersNumber);
710 }
711 
PrimitiveTypeToName(ir::PrimitiveType type)712 std::string ETSParser::PrimitiveTypeToName(ir::PrimitiveType type)
713 {
714     switch (type) {
715         case ir::PrimitiveType::BYTE:
716             return "byte";
717         case ir::PrimitiveType::INT:
718             return "int";
719         case ir::PrimitiveType::LONG:
720             return "long";
721         case ir::PrimitiveType::SHORT:
722             return "short";
723         case ir::PrimitiveType::FLOAT:
724             return "float";
725         case ir::PrimitiveType::DOUBLE:
726             return "double";
727         case ir::PrimitiveType::BOOLEAN:
728             return "boolean";
729         case ir::PrimitiveType::CHAR:
730             return "char";
731         case ir::PrimitiveType::VOID:
732             return "void";
733         default:
734             UNREACHABLE();
735     }
736 }
737 
GetNameForETSUnionType(const ir::TypeNode *typeAnnotation) const738 std::string ETSParser::GetNameForETSUnionType(const ir::TypeNode *typeAnnotation) const
739 {
740     ASSERT(typeAnnotation->IsETSUnionType());
741     std::string newstr;
742     for (size_t i = 0; i < typeAnnotation->AsETSUnionType()->Types().size(); i++) {
743         auto type = typeAnnotation->AsETSUnionType()->Types()[i];
744         std::string str = GetNameForTypeNode(type);
745         newstr += str;
746         if (i != typeAnnotation->AsETSUnionType()->Types().size() - 1) {
747             newstr += "|";
748         }
749     }
750     return newstr;
751 }
752 
GetNameForTypeNode(const ir::TypeNode *typeAnnotation) const753 std::string ETSParser::GetNameForTypeNode(const ir::TypeNode *typeAnnotation) const
754 {
755     if (typeAnnotation->IsETSUnionType()) {
756         return GetNameForETSUnionType(typeAnnotation);
757     }
758     if (typeAnnotation->IsETSPrimitiveType()) {
759         return PrimitiveTypeToName(typeAnnotation->AsETSPrimitiveType()->GetPrimitiveType());
760     }
761 
762     if (typeAnnotation->IsETSTypeReference()) {
763         std::string typeParamNames;
764         auto typeParam = typeAnnotation->AsETSTypeReference()->Part()->TypeParams();
765         if (typeParam != nullptr && typeParam->IsTSTypeParameterInstantiation()) {
766             typeParamNames = "<";
767             auto paramList = typeParam->Params();
768             for (auto param : paramList) {
769                 std::string typeParamName = GetNameForTypeNode(param);
770                 typeParamNames += typeParamName + ",";
771             }
772             typeParamNames.pop_back();
773             typeParamNames += ">";
774         }
775         return typeAnnotation->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Name().Mutf8() + typeParamNames;
776     }
777 
778     if (typeAnnotation->IsETSFunctionType()) {
779         std::string lambdaParams = " ";
780 
781         for (const auto *const param : typeAnnotation->AsETSFunctionType()->Params()) {
782             lambdaParams += param->AsETSParameterExpression()->Ident()->Name().Mutf8();
783             lambdaParams += ":";
784             lambdaParams += GetNameForTypeNode(param->AsETSParameterExpression()->Ident()->TypeAnnotation());
785             lambdaParams += ",";
786         }
787 
788         lambdaParams.pop_back();
789         const std::string returnTypeName = GetNameForTypeNode(typeAnnotation->AsETSFunctionType()->ReturnType());
790 
791         return "((" + lambdaParams + ") => " + returnTypeName + ")";
792     }
793 
794     if (typeAnnotation->IsTSArrayType()) {
795         // Note! array is required for the rest parameter.
796         return GetNameForTypeNode(typeAnnotation->AsTSArrayType()->ElementType()) + "[]";
797     }
798 
799     if (typeAnnotation->IsETSNullType()) {
800         return "null";
801     }
802 
803     if (typeAnnotation->IsETSUndefinedType()) {
804         return "undefined";
805     }
806 
807     UNREACHABLE();
808 }
809 
ValidateRestParameter(ir::Expression *param)810 void ETSParser::ValidateRestParameter(ir::Expression *param)
811 {
812     if (param->IsETSParameterExpression()) {
813         if (param->AsETSParameterExpression()->IsRestParameter()) {
814             GetContext().Status() |= ParserStatus::HAS_COMPLEX_PARAM;
815 
816             if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
817                 ThrowSyntaxError("Rest parameter must be the last formal parameter.");
818             }
819         }
820     }
821 }
822 
ValidateBreakLabel([[maybe_unused]] util::StringView label)823 bool ETSParser::ValidateBreakLabel([[maybe_unused]] util::StringView label)
824 {
825     // For ETS validate labels in checker via variables
826     return true;
827 }
828 
ValidateContinueLabel([[maybe_unused]] util::StringView label)829 bool ETSParser::ValidateContinueLabel([[maybe_unused]] util::StringView label)
830 {
831     // For ETS validate labels in checker via variables
832     return true;
833 }
834 
ParseTypeReferencePart( TypeAnnotationParsingOptions *options)835 std::tuple<ir::Expression *, ir::TSTypeParameterInstantiation *> ETSParser::ParseTypeReferencePart(
836     TypeAnnotationParsingOptions *options)
837 {
838     ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS;
839 
840     if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL) != 0) {
841         flags |= ExpressionParseFlags::POTENTIAL_CLASS_LITERAL;
842     }
843 
844     if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_NEW_ARRAY) != 0) {
845         flags |= ExpressionParseFlags::POTENTIAL_NEW_ARRAY;
846     }
847 
848     auto *typeName = ParseQualifiedName(flags);
849     if (typeName == nullptr) {
850         return {nullptr, nullptr};
851     }
852 
853     if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL) != 0 &&
854         (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS || IsStructKeyword())) {
855         return {typeName, nullptr};
856     }
857 
858     ir::TSTypeParameterInstantiation *typeParamInst = nullptr;
859     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT ||
860         Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
861         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
862             Lexer()->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
863         }
864         *options |= TypeAnnotationParsingOptions::ALLOW_WILDCARD;
865         typeParamInst = ParseTypeParameterInstantiation(options);
866         *options &= ~TypeAnnotationParsingOptions::ALLOW_WILDCARD;
867     }
868 
869     return {typeName, typeParamInst};
870 }
871 
ParseTypeReference(TypeAnnotationParsingOptions *options)872 ir::TypeNode *ETSParser::ParseTypeReference(TypeAnnotationParsingOptions *options)
873 {
874     auto startPos = Lexer()->GetToken().Start();
875     ir::ETSTypeReferencePart *typeRefPart = nullptr;
876 
877     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT) {
878         return ParseTypeFormatPlaceholder();
879     }
880 
881     while (true) {
882         auto partPos = Lexer()->GetToken().Start();
883         auto [typeName, typeParams] = ParseTypeReferencePart(options);
884         if (typeName == nullptr) {
885             return nullptr;
886         }
887 
888         typeRefPart = AllocNode<ir::ETSTypeReferencePart>(typeName, typeParams, typeRefPart);
889         typeRefPart->SetRange({partPos, Lexer()->GetToken().End()});
890 
891         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_PERIOD) {
892             break;
893         }
894 
895         Lexer()->NextToken();
896 
897         if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL) != 0 &&
898             (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS || IsStructKeyword())) {
899             break;
900         }
901     }
902 
903     auto *typeReference = AllocNode<ir::ETSTypeReference>(typeRefPart);
904     typeReference->SetRange({startPos, Lexer()->GetToken().End()});
905     return typeReference;
906 }
907 
ParseBaseTypeReference(TypeAnnotationParsingOptions *options)908 ir::TypeNode *ETSParser::ParseBaseTypeReference(TypeAnnotationParsingOptions *options)
909 {
910     ir::TypeNode *typeAnnotation = nullptr;
911 
912     switch (Lexer()->GetToken().KeywordType()) {
913         case lexer::TokenType::KEYW_BOOLEAN: {
914             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::BOOLEAN);
915             break;
916         }
917         case lexer::TokenType::KEYW_BYTE: {
918             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::BYTE);
919             break;
920         }
921         case lexer::TokenType::KEYW_CHAR: {
922             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::CHAR);
923             break;
924         }
925         case lexer::TokenType::KEYW_DOUBLE: {
926             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::DOUBLE);
927             break;
928         }
929         case lexer::TokenType::KEYW_FLOAT: {
930             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::FLOAT);
931             break;
932         }
933         case lexer::TokenType::KEYW_INT: {
934             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::INT);
935             break;
936         }
937         case lexer::TokenType::KEYW_LONG: {
938             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::LONG);
939             break;
940         }
941         case lexer::TokenType::KEYW_SHORT: {
942             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::SHORT);
943             break;
944         }
945 
946         default: {
947             break;
948         }
949     }
950 
951     return typeAnnotation;
952 }
953 
GetDefaultParamPosition(ArenaVector<ir::Expression *> params)954 std::optional<lexer::SourcePosition> ETSParser::GetDefaultParamPosition(ArenaVector<ir::Expression *> params)
955 {
956     for (auto &param : params) {
957         if (param->IsETSParameterExpression() && param->AsETSParameterExpression()->IsDefault()) {
958             return param->AsETSParameterExpression()->Initializer()->Start();
959         }
960     }
961     return {};
962 }
963 
ParseLiteralIdent(TypeAnnotationParsingOptions *options)964 ir::TypeNode *ETSParser::ParseLiteralIdent(TypeAnnotationParsingOptions *options)
965 {
966     if (const auto keyword = Lexer()->GetToken().KeywordType();
967         keyword == lexer::TokenType::KEYW_IN || keyword == lexer::TokenType::KEYW_OUT) {
968         return ParseWildcardType(options);
969     }
970 
971     if (Lexer()->GetToken().IsDefinableTypeName()) {
972         return GetTypeAnnotationOfPrimitiveType(Lexer()->GetToken().KeywordType(), options);
973     }
974 
975     return ParseTypeReference(options);
976 }
977 
ParseRightParenthesis(TypeAnnotationParsingOptions *options, ir::TypeNode *&typeAnnotation, lexer::LexerPosition savedPos)978 void ETSParser::ParseRightParenthesis(TypeAnnotationParsingOptions *options, ir::TypeNode *&typeAnnotation,
979                                       lexer::LexerPosition savedPos)
980 {
981     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
982         if (((*options) & TypeAnnotationParsingOptions::REPORT_ERROR) != 0) {
983             ThrowExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
984         }
985 
986         Lexer()->Rewind(savedPos);
987         typeAnnotation = nullptr;
988     } else {
989         Lexer()->NextToken();  // eat ')'
990     }
991 }
992 
ThrowIfVarDeclaration(VariableParsingFlags flags)993 void ETSParser::ThrowIfVarDeclaration(VariableParsingFlags flags)
994 {
995     if ((flags & VariableParsingFlags::VAR) != 0) {
996         ThrowUnexpectedToken(lexer::TokenType::KEYW_VAR);
997     }
998 }
999 
ParseExport(lexer::SourcePosition startLoc, ir::ModifierFlags modifiers)1000 ir::Statement *ETSParser::ParseExport(lexer::SourcePosition startLoc, ir::ModifierFlags modifiers)
1001 {
1002     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY ||
1003            Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE ||
1004            Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT);
1005     ArenaVector<ir::AstNode *> specifiers(Allocator()->Adapter());
1006 
1007     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
1008         ParseNameSpaceSpecifier(&specifiers, true);
1009     } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1010         auto specs = ParseNamedSpecifiers();
1011 
1012         if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_FROM) {
1013             specifiers = util::Helpers::ConvertVector<ir::AstNode>(specs.first);
1014         } else {
1015             ArenaVector<ir::ExportSpecifier *> exports(Allocator()->Adapter());
1016             for (auto spec : specs.first) {
1017                 exports.emplace_back(AllocNode<ir::ExportSpecifier>(spec->Local(), spec->Imported()));
1018             }
1019             auto result = AllocNode<ir::ExportNamedDeclaration>(Allocator(), static_cast<ir::StringLiteral *>(nullptr),
1020                                                                 std::move(exports));
1021             result->AddModifier(modifiers);
1022             return result;
1023         }
1024     } else {
1025         return ParseSingleExport(modifiers);
1026     }
1027 
1028     // re-export directive
1029     ir::ImportSource *reExportSource = ParseSourceFromClause(true);
1030 
1031     lexer::SourcePosition endLoc = reExportSource->Source()->End();
1032     auto *reExportDeclaration = AllocNode<ir::ETSImportDeclaration>(reExportSource, std::move(specifiers));
1033     reExportDeclaration->SetRange({startLoc, endLoc});
1034 
1035     ConsumeSemicolon(reExportDeclaration);
1036 
1037     auto reExport = AllocNode<ir::ETSReExportDeclaration>(reExportDeclaration, std::vector<std::string>(),
1038                                                           GetProgram()->SourceFilePath(), Allocator());
1039     reExport->AddModifier(modifiers);
1040     return reExport;
1041 }
1042 
ParsePackageDeclaration()1043 ir::ETSPackageDeclaration *ETSParser::ParsePackageDeclaration()
1044 {
1045     auto startLoc = Lexer()->GetToken().Start();
1046 
1047     if (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_PACKAGE) {
1048         // NOTE(rsipka): Unclear behavior/code. Currently, all entry programs omit the module name if it is not a
1049         // package module and the '--ets-module' option is not specified during compilation
1050         GetProgram()->SetModuleInfo(GetProgram()->FileName(), false, GetProgram()->IsEntryPoint() && !IsETSModule());
1051         return nullptr;
1052     }
1053 
1054     Lexer()->NextToken();
1055 
1056     ir::Expression *name = ParseQualifiedName();
1057 
1058     auto *packageDeclaration = AllocNode<ir::ETSPackageDeclaration>(name);
1059     packageDeclaration->SetRange({startLoc, Lexer()->GetToken().End()});
1060 
1061     ConsumeSemicolon(packageDeclaration);
1062 
1063     auto packageName =
1064         name->IsIdentifier() ? name->AsIdentifier()->Name() : name->AsTSQualifiedName()->ToString(Allocator());
1065 
1066     GetProgram()->SetModuleInfo(packageName, true);
1067 
1068     return packageDeclaration;
1069 }
1070 
ParseSourceFromClause(bool requireFrom)1071 ir::ImportSource *ETSParser::ParseSourceFromClause(bool requireFrom)
1072 {
1073     if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) {
1074         if (requireFrom) {
1075             ThrowSyntaxError("Unexpected token.");
1076         }
1077     } else {
1078         Lexer()->NextToken();  // eat `from`
1079     }
1080 
1081     if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
1082         ThrowSyntaxError("Unexpected token.");
1083     }
1084 
1085     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
1086     auto importPath = Lexer()->GetToken().Ident();
1087 
1088     auto resolvedImportPath = importPathManager_->ResolvePath(GetProgram()->AbsoluteName(), importPath);
1089     if (globalProgram_->AbsoluteName() != resolvedImportPath) {
1090         importPathManager_->AddToParseList(resolvedImportPath,
1091                                            (GetContext().Status() & ParserStatus::IN_DEFAULT_IMPORTS) != 0U
1092                                                ? util::ImportFlags::DEFAULT_IMPORT
1093                                                : util::ImportFlags::NONE);
1094     } else if (!IsETSModule()) {
1095         ThrowSyntaxError("Please compile `" + globalProgram_->FileName().Mutf8() + "." +
1096                          globalProgram_->SourceFile().GetExtension().Mutf8() +
1097                          "` with `--ets-module` option. It is being imported by another file.");
1098     }
1099 
1100     auto *resolvedSource = AllocNode<ir::StringLiteral>(resolvedImportPath);
1101     auto importData = importPathManager_->GetImportData(resolvedImportPath, Extension());
1102     auto *source = AllocNode<ir::StringLiteral>(importPath);
1103     source->SetRange(Lexer()->GetToken().Loc());
1104 
1105     Lexer()->NextToken();
1106 
1107     return Allocator()->New<ir::ImportSource>(source, resolvedSource, importData.lang, importData.hasDecl);
1108 }
1109 
ParseImportDeclarations()1110 ArenaVector<ir::ETSImportDeclaration *> ETSParser::ParseImportDeclarations()
1111 {
1112     std::vector<std::string> userPaths;
1113     ArenaVector<ir::ETSImportDeclaration *> statements(Allocator()->Adapter());
1114 
1115     while (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_IMPORT) {
1116         auto startLoc = Lexer()->GetToken().Start();
1117         Lexer()->NextToken();  // eat import
1118 
1119         ir::ImportKinds importKind =
1120             Lexer()->TryEatTokenKeyword(lexer::TokenType::KEYW_TYPE) ? ir::ImportKinds::TYPE : ir::ImportKinds::VALUE;
1121 
1122         ArenaVector<ir::AstNode *> specifiers(Allocator()->Adapter());
1123         ArenaVector<ir::AstNode *> defaultSpecifiers(Allocator()->Adapter());
1124 
1125         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
1126             if (importKind == ir::ImportKinds::TYPE) {
1127                 ThrowSyntaxError("Type import requires selective binding to define the required imported elements.");
1128             }
1129             ParseNameSpaceSpecifier(&specifiers);
1130         } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1131             auto specs = ParseNamedSpecifiers();
1132             specifiers = util::Helpers::ConvertVector<ir::AstNode>(specs.first);
1133             defaultSpecifiers = util::Helpers::ConvertVector<ir::AstNode>(specs.second);
1134         } else {
1135             ParseImportDefaultSpecifier(&specifiers);
1136         }
1137         auto pos = Lexer()->Save();
1138         if (!specifiers.empty()) {
1139             ir::ImportSource *importSource = ParseSourceFromClause(true);
1140 
1141             lexer::SourcePosition endLoc = importSource->Source()->End();
1142             auto *importDeclaration =
1143                 AllocNode<ir::ETSImportDeclaration>(importSource, std::move(specifiers), importKind);
1144             importDeclaration->SetRange({startLoc, endLoc});
1145 
1146             ConsumeSemicolon(importDeclaration);
1147             statements.push_back(importDeclaration);
1148         }
1149 
1150         if (!defaultSpecifiers.empty()) {
1151             Lexer()->Rewind(pos);
1152             ir::ImportSource *importSourceDefault = ParseSourceFromClause(true);
1153 
1154             lexer::SourcePosition endLocDef = importSourceDefault->Source()->End();
1155             auto *importDeclarationDefault =
1156                 AllocNode<ir::ETSImportDeclaration>(importSourceDefault, std::move(defaultSpecifiers), importKind);
1157             importDeclarationDefault->SetRange({startLoc, endLocDef});
1158 
1159             ConsumeSemicolon(importDeclarationDefault);
1160             util::Helpers::CheckDefaultImport(statements);
1161             statements.push_back(importDeclarationDefault);
1162         }
1163     }
1164 
1165     std::sort(statements.begin(), statements.end(), [](const auto *s1, const auto *s2) -> bool {
1166         return s1->Specifiers()[0]->IsImportNamespaceSpecifier() && !s2->Specifiers()[0]->IsImportNamespaceSpecifier();
1167     });
1168     return statements;
1169 }
1170 
ParseSingleExport(ir::ModifierFlags modifiers)1171 ir::ExportNamedDeclaration *ETSParser::ParseSingleExport(ir::ModifierFlags modifiers)
1172 {
1173     lexer::Token token = Lexer()->GetToken();
1174     auto *exported = AllocNode<ir::Identifier>(token.Ident(), Allocator());
1175     exported->SetReference();
1176     exported->SetRange(Lexer()->GetToken().Loc());
1177 
1178     Lexer()->NextToken();  // eat exported variable name
1179 
1180     ArenaVector<ir::ExportSpecifier *> exports(Allocator()->Adapter());
1181 
1182     exports.emplace_back(AllocNode<ir::ExportSpecifier>(exported, ParseNamedExport(token)));
1183     auto result = AllocNode<ir::ExportNamedDeclaration>(Allocator(), static_cast<ir::StringLiteral *>(nullptr),
1184                                                         std::move(exports));
1185     result->AddModifier(modifiers);
1186     ConsumeSemicolon(result);
1187 
1188     return result;
1189 }
1190 
IsDefaultImport()1191 bool ETSParser::IsDefaultImport()
1192 {
1193     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_DEFAULT) {
1194         Lexer()->NextToken();
1195         if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) {
1196             Lexer()->NextToken();
1197             return true;
1198         }
1199         ThrowSyntaxError("Unexpected token. 'as' keyword is expected.");
1200     }
1201     return false;
1202 }
1203 
1204 using ImportSpecifierVector = ArenaVector<ir::ImportSpecifier *>;
1205 using ImportDefaultSpecifierVector = ArenaVector<ir::ImportDefaultSpecifier *>;
ParseNamedSpecifiers()1206 std::pair<ImportSpecifierVector, ImportDefaultSpecifierVector> ETSParser::ParseNamedSpecifiers()
1207 {
1208     // NOTE(user): handle qualifiedName in file bindings: qualifiedName '.' '*'
1209     if (!Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_LEFT_BRACE)) {
1210         ThrowExpectedToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
1211     }
1212 
1213     auto fileName = GetProgram()->SourceFilePath().Mutf8();
1214 
1215     ArenaVector<ir::ImportSpecifier *> result(Allocator()->Adapter());
1216     ArenaVector<ir::ImportDefaultSpecifier *> resultDefault(Allocator()->Adapter());
1217 
1218     while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
1219         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
1220             ThrowSyntaxError("The '*' token is not allowed as a selective binding (between braces)");
1221         }
1222 
1223         if (!IsDefaultImport()) {
1224             if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1225                 ThrowSyntaxError("Unexpected token");
1226             }
1227 
1228             lexer::Token importedToken = Lexer()->GetToken();
1229             auto *imported = AllocNode<ir::Identifier>(importedToken.Ident(), Allocator());
1230             ir::Identifier *local = nullptr;
1231             imported->SetReference();
1232             imported->SetRange(Lexer()->GetToken().Loc());
1233 
1234             Lexer()->NextToken();
1235 
1236             if (CheckModuleAsModifier() && Lexer()->TryEatTokenType(lexer::TokenType::KEYW_AS)) {
1237                 local = ParseNamedImport(Lexer()->GetToken());
1238                 Lexer()->NextToken();
1239             } else {
1240                 local = ParseNamedImport(importedToken);
1241             }
1242 
1243             auto *specifier = AllocNode<ir::ImportSpecifier>(imported, local);
1244             specifier->SetRange({imported->Start(), local->End()});
1245 
1246             util::Helpers::CheckImportedName(result, specifier, fileName);
1247 
1248             result.emplace_back(specifier);
1249         } else {
1250             auto *imported = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
1251             imported->SetReference();
1252             imported->SetRange(Lexer()->GetToken().Loc());
1253             Lexer()->NextToken();
1254             auto *specifier = AllocNode<ir::ImportDefaultSpecifier>(imported);
1255             specifier->SetRange({imported->Start(), imported->End()});
1256 
1257             util::Helpers::CheckDefaultImportedName(resultDefault, specifier, fileName);
1258 
1259             resultDefault.emplace_back(specifier);
1260         }
1261         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
1262             Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat comma
1263         }
1264     }
1265     Lexer()->NextToken();  // eat '}'
1266     std::pair<ArenaVector<ir::ImportSpecifier *>, ArenaVector<ir::ImportDefaultSpecifier *>> resultSpecifiers(
1267         result, resultDefault);
1268 
1269     return resultSpecifiers;
1270 }
1271 
ParseNameSpaceSpecifier(ArenaVector<ir::AstNode *> *specifiers, bool isReExport)1272 void ETSParser::ParseNameSpaceSpecifier(ArenaVector<ir::AstNode *> *specifiers, bool isReExport)
1273 {
1274     lexer::SourcePosition namespaceStart = Lexer()->GetToken().Start();
1275     Lexer()->NextToken();  // eat `*` character
1276 
1277     if (!CheckModuleAsModifier()) {
1278         ThrowSyntaxError("Unexpected token.");
1279     }
1280 
1281     // Note (oeotvos) As a temporary solution we allow the stdlib to use namespace import without an alias, but this
1282     // should be handled at some point.
1283     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_FROM && !isReExport &&
1284         (GetContext().Status() & ParserStatus::IN_DEFAULT_IMPORTS) == 0) {
1285         ThrowSyntaxError("Unexpected token, expected 'as' but found 'from'");
1286     }
1287 
1288     auto *local = AllocNode<ir::Identifier>(util::StringView(""), Allocator());
1289     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA ||
1290         Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_FROM || isReExport) {
1291         local->SetReference();
1292         auto *specifier = AllocNode<ir::ImportNamespaceSpecifier>(local);
1293         specifier->SetRange({namespaceStart, Lexer()->GetToken().End()});
1294         specifiers->push_back(specifier);
1295         return;
1296     }
1297 
1298     ExpectToken(lexer::TokenType::KEYW_AS, true);  // eat `as` literal
1299     local = ParseNamedImport(Lexer()->GetToken());
1300 
1301     auto *specifier = AllocNode<ir::ImportNamespaceSpecifier>(local);
1302     specifier->SetRange({namespaceStart, Lexer()->GetToken().End()});
1303     specifiers->push_back(specifier);
1304 
1305     Lexer()->NextToken();  // eat local name
1306 }
1307 
ParseImportDefaultSpecifier(ArenaVector<ir::AstNode *> *specifiers)1308 ir::AstNode *ETSParser::ParseImportDefaultSpecifier(ArenaVector<ir::AstNode *> *specifiers)
1309 {
1310     if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1311         ThrowSyntaxError("Unexpected token, expected an identifier");
1312     }
1313 
1314     auto *imported = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
1315     imported->SetReference();
1316     imported->SetRange(Lexer()->GetToken().Loc());
1317     Lexer()->NextToken();  // Eat import specifier.
1318 
1319     if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) {
1320         ThrowSyntaxError("Unexpected token, expected 'from'");
1321     }
1322 
1323     auto *specifier = AllocNode<ir::ImportDefaultSpecifier>(imported);
1324     specifier->SetRange({imported->Start(), imported->End()});
1325     specifiers->push_back(specifier);
1326 
1327     return nullptr;
1328 }
1329 
CheckModuleAsModifier()1330 bool ETSParser::CheckModuleAsModifier()
1331 {
1332     if ((Lexer()->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0U) {
1333         ThrowSyntaxError("Escape sequences are not allowed in 'as' keyword");
1334     }
1335 
1336     return true;
1337 }
1338 
GetAnnotatedExpressionFromParam()1339 ir::AnnotatedExpression *ETSParser::GetAnnotatedExpressionFromParam()
1340 {
1341     ir::AnnotatedExpression *parameter;
1342 
1343     switch (Lexer()->GetToken().Type()) {
1344         case lexer::TokenType::LITERAL_IDENT: {
1345             parameter = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
1346             if (parameter->AsIdentifier()->Decorators().empty()) {
1347                 parameter->SetRange(Lexer()->GetToken().Loc());
1348             } else {
1349                 parameter->SetRange(
1350                     {parameter->AsIdentifier()->Decorators().front()->Start(), Lexer()->GetToken().End()});
1351             }
1352             break;
1353         }
1354 
1355         case lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD: {
1356             const auto startLoc = Lexer()->GetToken().Start();
1357             Lexer()->NextToken();
1358 
1359             if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1360                 ThrowSyntaxError("Unexpected token, expected an identifier.");
1361             }
1362 
1363             auto *const restIdent = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
1364             restIdent->SetRange(Lexer()->GetToken().Loc());
1365 
1366             parameter = AllocNode<ir::SpreadElement>(ir::AstNodeType::REST_ELEMENT, Allocator(), restIdent);
1367             parameter->SetRange({startLoc, Lexer()->GetToken().End()});
1368             break;
1369         }
1370 
1371         default: {
1372             ThrowSyntaxError("Unexpected token, expected an identifier.");
1373         }
1374     }
1375 
1376     Lexer()->NextToken();
1377     return parameter;
1378 }
1379 
1380 // NOLINTBEGIN(modernize-avoid-c-arrays)
1381 static constexpr char const NO_DEFAULT_FOR_REST[] = "Rest parameter cannot have the default value.";
1382 static constexpr char const ONLY_ARRAY_FOR_REST[] = "Rest parameter should be of an array type.";
1383 static constexpr char const EXPLICIT_PARAM_TYPE[] = "Parameter declaration should have an explicit type annotation.";
1384 // NOLINTEND(modernize-avoid-c-arrays)
1385 
CreateOptionalParameterTypeNode(ir::TypeNode *typeAnnotation, ir::ETSUndefinedType *defaultUndef)1386 ir::ETSUnionType *ETSParser::CreateOptionalParameterTypeNode(ir::TypeNode *typeAnnotation,
1387                                                              ir::ETSUndefinedType *defaultUndef)
1388 {
1389     ArenaVector<ir::TypeNode *> types(Allocator()->Adapter());
1390     if (typeAnnotation->IsETSUnionType()) {
1391         for (auto const &type : typeAnnotation->AsETSUnionType()->Types()) {
1392             types.push_back(type);
1393         }
1394     } else {
1395         types.push_back(typeAnnotation);
1396     }
1397     types.push_back(defaultUndef);
1398 
1399     auto *const unionType = AllocNode<ir::ETSUnionType>(std::move(types));
1400     unionType->SetRange({typeAnnotation->Start(), typeAnnotation->End()});
1401     return unionType;
1402 }
1403 
ParseFunctionParameter()1404 ir::Expression *ETSParser::ParseFunctionParameter()
1405 {
1406     auto *const paramIdent = GetAnnotatedExpressionFromParam();
1407 
1408     ir::ETSUndefinedType *defaultUndef = nullptr;
1409 
1410     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
1411         if (paramIdent->IsRestElement()) {
1412             ThrowSyntaxError(NO_DEFAULT_FOR_REST);
1413         }
1414         defaultUndef = AllocNode<ir::ETSUndefinedType>();
1415         defaultUndef->SetRange({Lexer()->GetToken().Start(), Lexer()->GetToken().End()});
1416         Lexer()->NextToken();  // eat '?'
1417     }
1418 
1419     const bool isArrow = (GetContext().Status() & ParserStatus::ARROW_FUNCTION) != 0;
1420 
1421     if (Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_COLON)) {
1422         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
1423         ir::TypeNode *typeAnnotation = ParseTypeAnnotation(&options);
1424         if (typeAnnotation == nullptr) {  // Error processing.
1425             return nullptr;
1426         }
1427 
1428         if (defaultUndef != nullptr) {
1429             typeAnnotation = CreateOptionalParameterTypeNode(typeAnnotation, defaultUndef);
1430         }
1431 
1432         if (paramIdent->IsRestElement() && !typeAnnotation->IsTSArrayType()) {
1433             ThrowSyntaxError(ONLY_ARRAY_FOR_REST);
1434         }
1435 
1436         typeAnnotation->SetParent(paramIdent);
1437         paramIdent->SetTsTypeAnnotation(typeAnnotation);
1438         paramIdent->SetEnd(typeAnnotation->End());
1439     } else if (!isArrow && defaultUndef == nullptr) {
1440         ThrowSyntaxError(EXPLICIT_PARAM_TYPE);
1441     }
1442 
1443     return ParseFunctionParameterExpression(paramIdent, defaultUndef);
1444 }
1445 
CreateParameterThis(const util::StringView className)1446 ir::Expression *ETSParser::CreateParameterThis(const util::StringView className)
1447 {
1448     auto *paramIdent = AllocNode<ir::Identifier>(varbinder::TypedBinder::MANDATORY_PARAM_THIS, Allocator());
1449     paramIdent->SetRange(Lexer()->GetToken().Loc());
1450 
1451     ir::Expression *classTypeName = AllocNode<ir::Identifier>(className, Allocator());
1452     classTypeName->AsIdentifier()->SetReference();
1453     classTypeName->SetRange(Lexer()->GetToken().Loc());
1454 
1455     auto typeRefPart = AllocNode<ir::ETSTypeReferencePart>(classTypeName, nullptr, nullptr);
1456     ir::TypeNode *typeAnnotation = AllocNode<ir::ETSTypeReference>(typeRefPart);
1457 
1458     typeAnnotation->SetParent(paramIdent);
1459     paramIdent->SetTsTypeAnnotation(typeAnnotation);
1460 
1461     auto *paramExpression = AllocNode<ir::ETSParameterExpression>(paramIdent, nullptr);
1462     paramExpression->SetRange({paramIdent->Start(), paramIdent->End()});
1463 
1464     return paramExpression;
1465 }
1466 
ParseVariableDeclaratorKey([[maybe_unused]] VariableParsingFlags flags)1467 ir::AnnotatedExpression *ETSParser::ParseVariableDeclaratorKey([[maybe_unused]] VariableParsingFlags flags)
1468 {
1469     ir::Identifier *init = ExpectIdentifier();
1470     ir::TypeNode *typeAnnotation = nullptr;
1471     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
1472         if ((flags & VariableParsingFlags::FOR_OF) != 0U) {
1473             ThrowSyntaxError("Optional variable is not allowed in for of statements");
1474         }
1475         Lexer()->NextToken();  // eat '?'
1476         init->AddModifier(ir::ModifierFlags::OPTIONAL);
1477     }
1478 
1479     if (auto const tokenType = Lexer()->GetToken().Type(); tokenType == lexer::TokenType::PUNCTUATOR_COLON) {
1480         Lexer()->NextToken();  // eat ':'
1481         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
1482         typeAnnotation = ParseTypeAnnotation(&options);
1483     } else if (tokenType != lexer::TokenType::PUNCTUATOR_SUBSTITUTION && (flags & VariableParsingFlags::FOR_OF) == 0U) {
1484         ThrowSyntaxError("Variable must be initialized or it's type must be declared");
1485     }
1486 
1487     if (typeAnnotation != nullptr) {
1488         init->SetTsTypeAnnotation(typeAnnotation);
1489         typeAnnotation->SetParent(init);
1490     }
1491 
1492     return init;
1493 }
1494 
ParseVariableDeclaratorInitializer(ir::Expression *init, VariableParsingFlags flags, const lexer::SourcePosition &startLoc)1495 ir::VariableDeclarator *ETSParser::ParseVariableDeclaratorInitializer(ir::Expression *init, VariableParsingFlags flags,
1496                                                                       const lexer::SourcePosition &startLoc)
1497 {
1498     if ((flags & VariableParsingFlags::DISALLOW_INIT) != 0) {
1499         ThrowSyntaxError("for-await-of loop variable declaration may not have an initializer");
1500     }
1501 
1502     Lexer()->NextToken();
1503 
1504     ir::Expression *initializer = ParseExpression();
1505 
1506     lexer::SourcePosition endLoc = initializer->End();
1507 
1508     auto *declarator = AllocNode<ir::VariableDeclarator>(GetFlag(flags), init, initializer);
1509     declarator->SetRange({startLoc, endLoc});
1510 
1511     return declarator;
1512 }
1513 
ParseVariableDeclarator(ir::Expression *init, lexer::SourcePosition startLoc, VariableParsingFlags flags)1514 ir::VariableDeclarator *ETSParser::ParseVariableDeclarator(ir::Expression *init, lexer::SourcePosition startLoc,
1515                                                            VariableParsingFlags flags)
1516 {
1517     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
1518         return ParseVariableDeclaratorInitializer(init, flags, startLoc);
1519     }
1520 
1521     if ((flags & VariableParsingFlags::CONST) != 0 &&
1522         static_cast<uint32_t>(flags & VariableParsingFlags::ACCEPT_CONST_NO_INIT) == 0U && !InAmbientContext()) {
1523         ThrowSyntaxError("Missing initializer in const declaration");
1524     }
1525 
1526     if (init->AsIdentifier()->TypeAnnotation() == nullptr && (flags & VariableParsingFlags::FOR_OF) == 0U) {
1527         ThrowSyntaxError("Variable must be initialized or it's type must be declared");
1528     }
1529 
1530     lexer::SourcePosition endLoc = init->End();
1531     auto declarator = AllocNode<ir::VariableDeclarator>(GetFlag(flags), init);
1532     declarator->SetRange({startLoc, endLoc});
1533 
1534     // NOTE (psiket)  Transfer the OPTIONAL flag from the init to the declarator?
1535     return declarator;
1536 }
1537 
ParseCatchParam()1538 ir::Expression *ETSParser::ParseCatchParam()
1539 {
1540     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1541         ThrowSyntaxError("Unexpected token, expected '('");
1542     }
1543 
1544     ir::AnnotatedExpression *param = nullptr;
1545 
1546     Lexer()->NextToken();  // eat left paren
1547 
1548     if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1549         CheckRestrictedBinding();
1550         param = ExpectIdentifier();
1551     } else {
1552         ThrowSyntaxError("Unexpected token in catch parameter, expected an identifier");
1553     }
1554 
1555     ParseCatchParamTypeAnnotation(param);
1556 
1557     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
1558         ThrowSyntaxError("Unexpected token, expected ')'");
1559     }
1560 
1561     Lexer()->NextToken();  // eat right paren
1562 
1563     return param;
1564 }
1565 
ParseCatchParamTypeAnnotation([[maybe_unused]] ir::AnnotatedExpression *param)1566 void ETSParser::ParseCatchParamTypeAnnotation([[maybe_unused]] ir::AnnotatedExpression *param)
1567 {
1568     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1569         Lexer()->NextToken();  // eat ':'
1570 
1571         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
1572         if (auto *typeAnnotation = ParseTypeAnnotation(&options); typeAnnotation != nullptr) {
1573             typeAnnotation->SetParent(param);
1574             param->SetTsTypeAnnotation(typeAnnotation);
1575         }
1576     }
1577 
1578     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
1579         ThrowSyntaxError("Catch clause variable cannot have an initializer");
1580     }
1581 }
1582 
ParseImportDeclaration([[maybe_unused]] StatementParsingFlags flags)1583 ir::Statement *ETSParser::ParseImportDeclaration([[maybe_unused]] StatementParsingFlags flags)
1584 {
1585     char32_t nextChar = Lexer()->Lookahead();
1586     if (nextChar == lexer::LEX_CHAR_LEFT_PAREN || nextChar == lexer::LEX_CHAR_DOT) {
1587         return ParseExpressionStatement();
1588     }
1589 
1590     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
1591     Lexer()->NextToken();  // eat import
1592 
1593     ArenaVector<ir::AstNode *> specifiers(Allocator()->Adapter());
1594 
1595     ir::ImportSource *importSource = nullptr;
1596 
1597     if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
1598         ir::AstNode *astNode = ParseImportSpecifiers(&specifiers);
1599         if (astNode != nullptr) {
1600             ASSERT(astNode->IsTSImportEqualsDeclaration());
1601             astNode->SetRange({startLoc, Lexer()->GetToken().End()});
1602             ConsumeSemicolon(astNode->AsTSImportEqualsDeclaration());
1603             return astNode->AsTSImportEqualsDeclaration();
1604         }
1605         importSource = ParseSourceFromClause(true);
1606     } else {
1607         importSource = ParseSourceFromClause(false);
1608     }
1609 
1610     lexer::SourcePosition endLoc = importSource->Source()->End();
1611     auto *importDeclaration = AllocNode<ir::ETSImportDeclaration>(importSource, std::move(specifiers));
1612     importDeclaration->SetRange({startLoc, endLoc});
1613 
1614     ConsumeSemicolon(importDeclaration);
1615 
1616     return importDeclaration;
1617 }
1618 
ParseExportDeclaration([[maybe_unused]] StatementParsingFlags flags)1619 ir::Statement *ETSParser::ParseExportDeclaration([[maybe_unused]] StatementParsingFlags flags)
1620 {
1621     ThrowUnexpectedToken(lexer::TokenType::KEYW_EXPORT);
1622 }
1623 
ParseExpressionOrTypeAnnotation(lexer::TokenType type, [[maybe_unused]] ExpressionParseFlags flags)1624 ir::Expression *ETSParser::ParseExpressionOrTypeAnnotation(lexer::TokenType type,
1625                                                            [[maybe_unused]] ExpressionParseFlags flags)
1626 {
1627     if (type == lexer::TokenType::KEYW_INSTANCEOF) {
1628         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR;
1629 
1630         if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_NULL) {
1631             auto *typeAnnotation = AllocNode<ir::NullLiteral>();
1632             typeAnnotation->SetRange(Lexer()->GetToken().Loc());
1633             Lexer()->NextToken();
1634 
1635             return typeAnnotation;
1636         }
1637 
1638         return ParseTypeAnnotation(&options);
1639     }
1640 
1641     return ParseExpression(ExpressionParseFlags::DISALLOW_YIELD);
1642 }
1643 
ParsePotentialGenericFunctionCall(ir::Expression *primaryExpr, ir::Expression **returnExpression, [[maybe_unused]] const lexer::SourcePosition &startLoc, bool ignoreCallExpression)1644 bool ETSParser::ParsePotentialGenericFunctionCall(ir::Expression *primaryExpr, ir::Expression **returnExpression,
1645                                                   [[maybe_unused]] const lexer::SourcePosition &startLoc,
1646                                                   bool ignoreCallExpression)
1647 {
1648     if (Lexer()->Lookahead() == lexer::LEX_CHAR_LESS_THAN ||
1649         (!primaryExpr->IsIdentifier() && !primaryExpr->IsMemberExpression())) {
1650         return true;
1651     }
1652 
1653     const auto savedPos = Lexer()->Save();
1654 
1655     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
1656         Lexer()->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
1657     }
1658 
1659     TypeAnnotationParsingOptions options =
1660         TypeAnnotationParsingOptions::ALLOW_WILDCARD | TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE;
1661     ir::TSTypeParameterInstantiation *typeParams = ParseTypeParameterInstantiation(&options);
1662 
1663     if (typeParams == nullptr) {
1664         Lexer()->Rewind(savedPos);
1665         return true;
1666     }
1667 
1668     if (Lexer()->GetToken().Type() == lexer::TokenType::EOS) {
1669         ThrowSyntaxError("'(' expected");
1670     }
1671 
1672     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
1673         if (!ignoreCallExpression) {
1674             *returnExpression = ParseCallExpression(*returnExpression, false, false);
1675             (*returnExpression)->AsCallExpression()->SetTypeParams(typeParams);
1676             return false;
1677         }
1678 
1679         return true;
1680     }
1681 
1682     Lexer()->Rewind(savedPos);
1683     return true;
1684 }
1685 
ParseTypeVarianceModifier(TypeAnnotationParsingOptions *const options)1686 ir::ModifierFlags ETSParser::ParseTypeVarianceModifier(TypeAnnotationParsingOptions *const options)
1687 {
1688     if ((*options & TypeAnnotationParsingOptions::ALLOW_WILDCARD) == 0 &&
1689         (*options & TypeAnnotationParsingOptions::ALLOW_DECLARATION_SITE_VARIANCE) == 0) {
1690         ThrowSyntaxError("Variance modifier is not allowed here.");
1691     }
1692 
1693     switch (Lexer()->GetToken().KeywordType()) {
1694         case lexer::TokenType::KEYW_IN: {
1695             Lexer()->NextToken();
1696             return ir::ModifierFlags::IN;
1697         }
1698         case lexer::TokenType::KEYW_OUT: {
1699             Lexer()->NextToken();
1700             return ir::ModifierFlags::OUT;
1701         }
1702         default: {
1703             return ir::ModifierFlags::NONE;
1704         }
1705     }
1706 }
1707 
ParseAmbientSignature()1708 ir::AstNode *ETSParser::ParseAmbientSignature()
1709 {
1710     auto const startPos = Lexer()->GetToken().Start();
1711 
1712     if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1713         ThrowSyntaxError("Unexpected token at", Lexer()->GetToken().Start());
1714     }
1715     auto const indexName = Lexer()->GetToken().Ident();
1716 
1717     Lexer()->NextToken();
1718     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
1719         ThrowSyntaxError("Index type expected in index signature", Lexer()->GetToken().Start());
1720     }
1721 
1722     Lexer()->NextToken();  // eat ":"
1723     if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_NUMBER) {
1724         ThrowSyntaxError("Index type must be number in index signature", Lexer()->GetToken().Start());
1725     }
1726 
1727     Lexer()->NextToken();  // eat indexType
1728     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
1729         ThrowSyntaxError("] expected in index signature", Lexer()->GetToken().Start());
1730     }
1731 
1732     Lexer()->NextToken();  // eat "]"
1733     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
1734         ThrowSyntaxError("An index signature must have a type annotation.", Lexer()->GetToken().Start());
1735     }
1736 
1737     Lexer()->NextToken();  // eat ":"
1738     if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1739         ThrowSyntaxError("Return type of index signature from exported class or interface need to be identifier",
1740                          Lexer()->GetToken().Start());
1741     }
1742     auto const returnType =
1743         AllocNode<ir::ETSTypeReferencePart>(AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator()));
1744 
1745     auto dummyNode = AllocNode<ir::DummyNode>(compiler::Signatures::AMBIENT_INDEXER, indexName, returnType,
1746                                               ir::DummyNodeFlag::INDEXER);
1747     dummyNode->SetRange({startPos, Lexer()->GetToken().End()});
1748     Lexer()->NextToken();  // eat return type
1749     return dummyNode;
1750 }
1751 
ParseTypeParameter([[maybe_unused]] TypeAnnotationParsingOptions *options)1752 ir::TSTypeParameter *ETSParser::ParseTypeParameter([[maybe_unused]] TypeAnnotationParsingOptions *options)
1753 {
1754     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
1755 
1756     const auto varianceModifier = [this, options] {
1757         switch (Lexer()->GetToken().KeywordType()) {
1758             case lexer::TokenType::KEYW_IN:
1759             case lexer::TokenType::KEYW_OUT:
1760                 return ParseTypeVarianceModifier(options);
1761             default:
1762                 return ir::ModifierFlags::NONE;
1763         }
1764     }();
1765 
1766     auto *paramIdent = ExpectIdentifier();
1767 
1768     ir::TypeNode *constraint = nullptr;
1769     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
1770         Lexer()->NextToken();
1771         TypeAnnotationParsingOptions newOptions =
1772             TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE;
1773         constraint = ParseTypeAnnotation(&newOptions);
1774     }
1775 
1776     ir::TypeNode *defaultType = nullptr;
1777 
1778     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
1779         Lexer()->NextToken();  // eat '='
1780         defaultType = ParseTypeAnnotation(options);
1781     }
1782 
1783     auto *typeParam = AllocNode<ir::TSTypeParameter>(paramIdent, constraint, defaultType, varianceModifier);
1784 
1785     typeParam->SetRange({startLoc, Lexer()->GetToken().End()});
1786     return typeParam;
1787 }
1788 
ParseClassIdent([[maybe_unused]] ir::ClassDefinitionModifiers modifiers)1789 ir::Identifier *ETSParser::ParseClassIdent([[maybe_unused]] ir::ClassDefinitionModifiers modifiers)
1790 {
1791     return ExpectIdentifier(false, true);
1792 }
1793 
IsStructKeyword() const1794 bool ETSParser::IsStructKeyword() const
1795 {
1796     return (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
1797             Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STRUCT);
1798 }
1799 
ParseTrailingBlock(ir::CallExpression *callExpr)1800 void ETSParser::ParseTrailingBlock(ir::CallExpression *callExpr)
1801 {
1802     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1803         callExpr->SetIsTrailingBlockInNewLine(Lexer()->GetToken().NewLine());
1804         callExpr->SetTrailingBlock(ParseBlockStatement());
1805     }
1806 }
1807 
ParseCoercedNumberLiteral()1808 ir::Expression *ETSParser::ParseCoercedNumberLiteral()
1809 {
1810     if ((Lexer()->GetToken().Flags() & lexer::TokenFlags::NUMBER_FLOAT) != 0U) {
1811         auto *number = AllocNode<ir::NumberLiteral>(Lexer()->GetToken().GetNumber());
1812         number->SetRange(Lexer()->GetToken().Loc());
1813         auto *floatType = AllocNode<ir::ETSPrimitiveType>(ir::PrimitiveType::FLOAT);
1814         floatType->SetRange(Lexer()->GetToken().Loc());
1815         auto *asExpression = AllocNode<ir::TSAsExpression>(number, floatType, true);
1816         asExpression->SetRange(Lexer()->GetToken().Loc());
1817 
1818         Lexer()->NextToken();
1819         return asExpression;
1820     }
1821     return ParseNumberLiteral();
1822 }
1823 
CheckDeclare()1824 void ETSParser::CheckDeclare()
1825 {
1826     ASSERT(Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE);
1827 
1828     if (InAmbientContext()) {
1829         ThrowSyntaxError("A 'declare' modifier cannot be used in an already ambient context.");
1830     }
1831 
1832     GetContext().Status() |= ParserStatus::IN_AMBIENT_CONTEXT;
1833 
1834     Lexer()->NextToken();  // eat 'declare'
1835 
1836     switch (Lexer()->GetToken().KeywordType()) {
1837         case lexer::TokenType::KEYW_LET:
1838         case lexer::TokenType::KEYW_CONST:
1839         case lexer::TokenType::KEYW_FUNCTION:
1840         case lexer::TokenType::KEYW_CLASS:
1841         case lexer::TokenType::KEYW_NAMESPACE:
1842         case lexer::TokenType::KEYW_ENUM:
1843         case lexer::TokenType::KEYW_TYPE:
1844         case lexer::TokenType::KEYW_ABSTRACT:
1845         case lexer::TokenType::KEYW_FINAL:
1846         case lexer::TokenType::KEYW_INTERFACE:
1847         case lexer::TokenType::KEYW_ASYNC: {
1848             return;
1849         }
1850         default: {
1851             ThrowSyntaxError("Unexpected token.");
1852         }
1853     }
1854 }
1855 
ParseFunctionDeclaration(bool canBeAnonymous, ir::ModifierFlags modifiers)1856 ir::FunctionDeclaration *ETSParser::ParseFunctionDeclaration(bool canBeAnonymous, ir::ModifierFlags modifiers)
1857 {
1858     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
1859 
1860     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION);
1861     Lexer()->NextToken();
1862     auto newStatus = ParserStatus::NEED_RETURN_TYPE | ParserStatus::ALLOW_SUPER;
1863 
1864     if ((modifiers & ir::ModifierFlags::ASYNC) != 0) {
1865         newStatus |= ParserStatus::ASYNC_FUNCTION;
1866     }
1867     if (Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_MULTIPLY)) {
1868         newStatus |= ParserStatus::GENERATOR_FUNCTION;
1869     }
1870 
1871     ir::Identifier *className = nullptr;
1872     ir::Identifier *identNode = nullptr;
1873     if (Lexer()->Lookahead() == lexer::LEX_CHAR_DOT) {
1874         className = ExpectIdentifier();
1875         if (className != nullptr) {
1876             newStatus |= ParserStatus::IN_EXTENSION_FUNCTION;
1877         }
1878         Lexer()->NextToken();
1879         identNode = ExpectIdentifier();
1880     } else if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1881         identNode = ExpectIdentifier();
1882     } else if (!canBeAnonymous) {
1883         LogSyntaxError("Unexpected token, expected identifier after 'function' keyword");
1884     }
1885     newStatus |= ParserStatus::FUNCTION_DECLARATION;
1886     if (identNode != nullptr) {
1887         CheckRestrictedBinding(identNode->Name(), identNode->Start());
1888     }
1889 
1890     ir::ScriptFunction *func = ParseFunction(newStatus, className);
1891     if (identNode != nullptr) {  // Error processing.
1892         func->SetIdent(identNode);
1893     }
1894 
1895     auto *funcDecl = AllocNode<ir::FunctionDeclaration>(Allocator(), func);
1896     if (func->IsOverload() && Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1897         Lexer()->NextToken();
1898     }
1899     funcDecl->SetRange(func->Range());
1900     func->AddModifier(modifiers);
1901     func->SetStart(startLoc);
1902 
1903     if (className != nullptr) {
1904         func->AddFlag(ir::ScriptFunctionFlags::INSTANCE_EXTENSION_METHOD);
1905     }
1906 
1907     return funcDecl;
1908 }
1909 
AddPackageSourcesToParseList()1910 void ETSParser::AddPackageSourcesToParseList()
1911 {
1912     importPathManager_->AddToParseList(GetProgram()->SourceFileFolder(), util::ImportFlags::IMPLICIT_PACKAGE_IMPORT);
1913 
1914     // Global program file is always in the same folder that we scanned, but we don't need to parse it twice
1915     importPathManager_->MarkAsParsed(globalProgram_->SourceFilePath());
1916 }
1917 
1918 //================================================================================================//
1919 //  ExternalSourceParser class
1920 //================================================================================================//
1921 
ExternalSourceParser(ETSParser *parser, Program *newProgram)1922 ExternalSourceParser::ExternalSourceParser(ETSParser *parser, Program *newProgram)
1923     : parser_(parser),
1924       savedProgram_(parser_->GetProgram()),
1925       savedLexer_(parser_->Lexer()),
1926       savedTopScope_(parser_->GetProgram()->VarBinder()->TopScope())
1927 {
1928     parser_->SetProgram(newProgram);
1929     parser_->GetContext().SetProgram(newProgram);
1930 }
1931 
~ExternalSourceParser()1932 ExternalSourceParser::~ExternalSourceParser()
1933 {
1934     parser_->SetLexer(savedLexer_);
1935     parser_->SetProgram(savedProgram_);
1936     parser_->GetContext().SetProgram(savedProgram_);
1937     parser_->GetProgram()->VarBinder()->ResetTopScope(savedTopScope_);
1938 }
1939 
1940 //================================================================================================//
1941 //  InnerSourceParser class
1942 //================================================================================================//
1943 
InnerSourceParser(ETSParser *parser)1944 InnerSourceParser::InnerSourceParser(ETSParser *parser)
1945     : parser_(parser),
1946       savedLexer_(parser_->Lexer()),
1947       savedSourceCode_(parser_->GetProgram()->SourceCode()),
1948       savedSourceFile_(parser_->GetProgram()->SourceFilePath()),
1949       savedSourceFilePath_(parser_->GetProgram()->SourceFileFolder())
1950 {
1951 }
1952 
~InnerSourceParser()1953 InnerSourceParser::~InnerSourceParser()
1954 {
1955     parser_->SetLexer(savedLexer_);
1956     parser_->GetProgram()->SetSource(savedSourceCode_, savedSourceFile_, savedSourceFilePath_);
1957 }
1958 }  // namespace ark::es2panda::parser
1959