• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <utility>
18 
19 #include "macros.h"
20 #include "parser/parserFlags.h"
21 #include "util/arktsconfig.h"
22 #include "util/helpers.h"
23 #include "util/language.h"
24 #include "varbinder/varbinder.h"
25 #include "varbinder/scope.h"
26 #include "varbinder/ETSBinder.h"
27 #include "lexer/lexer.h"
28 #include "lexer/ETSLexer.h"
29 #include "checker/types/ets/etsEnumType.h"
30 #include "ir/astNode.h"
31 #include "ir/base/classDefinition.h"
32 #include "ir/base/decorator.h"
33 #include "ir/base/catchClause.h"
34 #include "ir/base/classProperty.h"
35 #include "ir/base/scriptFunction.h"
36 #include "ir/base/methodDefinition.h"
37 #include "ir/base/classStaticBlock.h"
38 #include "ir/base/spreadElement.h"
39 #include "ir/expressions/identifier.h"
40 #include "ir/expressions/functionExpression.h"
41 #include "ir/statements/functionDeclaration.h"
42 #include "ir/statements/expressionStatement.h"
43 #include "ir/statements/classDeclaration.h"
44 #include "ir/statements/variableDeclarator.h"
45 #include "ir/statements/variableDeclaration.h"
46 #include "ir/expressions/arrayExpression.h"
47 #include "ir/expressions/assignmentExpression.h"
48 #include "ir/expressions/sequenceExpression.h"
49 #include "ir/expressions/callExpression.h"
50 #include "ir/expressions/blockExpression.h"
51 #include "ir/expressions/thisExpression.h"
52 #include "ir/expressions/superExpression.h"
53 #include "ir/expressions/memberExpression.h"
54 #include "ir/expressions/updateExpression.h"
55 #include "ir/expressions/arrowFunctionExpression.h"
56 #include "ir/expressions/unaryExpression.h"
57 #include "ir/expressions/yieldExpression.h"
58 #include "ir/expressions/awaitExpression.h"
59 #include "ir/expressions/literals/booleanLiteral.h"
60 #include "ir/expressions/literals/charLiteral.h"
61 #include "ir/expressions/literals/nullLiteral.h"
62 #include "ir/expressions/literals/numberLiteral.h"
63 #include "ir/expressions/literals/stringLiteral.h"
64 #include "ir/expressions/literals/undefinedLiteral.h"
65 #include "ir/expressions/templateLiteral.h"
66 #include "ir/expressions/objectExpression.h"
67 #include "ir/module/importDeclaration.h"
68 #include "ir/module/importDefaultSpecifier.h"
69 #include "ir/module/importSpecifier.h"
70 #include "ir/statements/assertStatement.h"
71 #include "ir/statements/blockStatement.h"
72 #include "ir/statements/emptyStatement.h"
73 #include "ir/statements/ifStatement.h"
74 #include "ir/statements/labelledStatement.h"
75 #include "ir/statements/switchStatement.h"
76 #include "ir/statements/throwStatement.h"
77 #include "ir/statements/tryStatement.h"
78 #include "ir/statements/whileStatement.h"
79 #include "ir/statements/doWhileStatement.h"
80 #include "ir/statements/breakStatement.h"
81 #include "ir/statements/continueStatement.h"
82 #include "ir/statements/debuggerStatement.h"
83 #include "ir/ets/etsLaunchExpression.h"
84 #include "ir/ets/etsClassLiteral.h"
85 #include "ir/ets/etsPrimitiveType.h"
86 #include "ir/ets/etsPackageDeclaration.h"
87 #include "ir/ets/etsReExportDeclaration.h"
88 #include "ir/ets/etsWildcardType.h"
89 #include "ir/ets/etsNewArrayInstanceExpression.h"
90 #include "ir/ets/etsTuple.h"
91 #include "ir/ets/etsFunctionType.h"
92 #include "ir/ets/etsNewClassInstanceExpression.h"
93 #include "ir/ets/etsNewMultiDimArrayInstanceExpression.h"
94 #include "ir/ets/etsScript.h"
95 #include "ir/ets/etsTypeReference.h"
96 #include "ir/ets/etsTypeReferencePart.h"
97 #include "ir/ets/etsUnionType.h"
98 #include "ir/ets/etsImportSource.h"
99 #include "ir/ets/etsImportDeclaration.h"
100 #include "ir/ets/etsStructDeclaration.h"
101 #include "ir/ets/etsParameterExpression.h"
102 #include "ir/module/importNamespaceSpecifier.h"
103 #include "ir/ts/tsAsExpression.h"
104 #include "ir/ts/tsInterfaceDeclaration.h"
105 #include "ir/ts/tsEnumDeclaration.h"
106 #include "ir/ts/tsTypeParameterInstantiation.h"
107 #include "ir/ts/tsInterfaceBody.h"
108 #include "ir/ts/tsImportEqualsDeclaration.h"
109 #include "ir/ts/tsArrayType.h"
110 #include "ir/ts/tsQualifiedName.h"
111 #include "ir/ts/tsTypeReference.h"
112 #include "ir/ts/tsTypeParameter.h"
113 #include "ir/ts/tsIntersectionType.h"
114 #include "ir/ts/tsInterfaceHeritage.h"
115 #include "ir/ts/tsFunctionType.h"
116 #include "ir/ts/tsClassImplements.h"
117 #include "ir/ts/tsEnumMember.h"
118 #include "ir/ts/tsTypeAliasDeclaration.h"
119 #include "ir/ts/tsTypeParameterDeclaration.h"
120 #include "ir/ts/tsNonNullExpression.h"
121 #include "ir/ts/tsThisType.h"
122 #include "libpandabase/os/file.h"
123 #include "generated/signatures.h"
124 
125 #if defined PANDA_TARGET_MOBILE
126 #define USE_UNIX_SYSCALL
127 #endif
128 
129 #ifdef USE_UNIX_SYSCALL
130 #include <dirent.h>
131 #include <sys/types.h>
132 #include <unistd.h>
133 #else
134 #if __has_include(<filesystem>)
135 #include <filesystem>
136 namespace fs = std::filesystem;
137 #elif __has_include(<experimental/filesystem>)
138 #include <experimental/filesystem>
139 namespace fs = std::experimental::filesystem;
140 #endif
141 #endif
142 
143 namespace panda::es2panda::parser {
144 using namespace std::literals::string_literals;
145 
InitLexer(const SourceFile & sourceFile)146 std::unique_ptr<lexer::Lexer> ETSParser::InitLexer(const SourceFile &sourceFile)
147 {
148     GetProgram()->SetSource(sourceFile);
149     auto lexer = std::make_unique<lexer::ETSLexer>(&GetContext());
150     SetLexer(lexer.get());
151     return lexer;
152 }
153 
ParseProgram(ScriptKind kind)154 void ETSParser::ParseProgram(ScriptKind kind)
155 {
156     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
157     Lexer()->NextToken();
158     GetProgram()->SetKind(kind);
159 
160     if (GetProgram()->SourceFilePath().Utf8()[0] == '@') {
161         // NOTE(user): handle multiple sourceFiles
162     }
163 
164     auto statements = PrepareGlobalClass();
165     ParseDefaultSources();
166 
167     ParseETSGlobalScript(startLoc, statements);
168 }
169 
ParseETSGlobalScript(lexer::SourcePosition startLoc,ArenaVector<ir::Statement * > & statements)170 void ETSParser::ParseETSGlobalScript(lexer::SourcePosition startLoc, ArenaVector<ir::Statement *> &statements)
171 {
172     auto paths = ParseImportDeclarations(statements);
173 
174     // clang-format off
175     auto removeParsedSources = [this](std::vector<std::string> &items) {
176         items.erase(remove_if(begin(items), end(items),
177                             [this](auto x) {
178                                 auto resolved = ResolveImportPath(x);
179                                 auto pathIter =
180                                     std::find_if(resolvedParsedSources_.begin(), resolvedParsedSources_.end(),
181                                                  [resolved](const auto &p) { return p.second == resolved; });
182                                 auto found = pathIter != resolvedParsedSources_.end();
183                                 if (found) {
184                                     resolvedParsedSources_.emplace(x, resolved);
185                                 }
186                                 return found;
187                             }),
188                     end(items));
189 
190         for (const auto &item : items) {
191             auto resolved = ResolveImportPath(item);
192             resolvedParsedSources_.emplace(item, resolved);
193             parsedSources_.push_back(resolved);
194         }
195     };
196     // clang-format on
197 
198     removeParsedSources(paths);
199 
200     ParseSources(paths, false);
201 
202     if (!GetProgram()->VarBinder()->AsETSBinder()->ReExportImports().empty()) {
203         std::vector<std::string> reExportPaths;
204 
205         for (auto reExport : GetProgram()->VarBinder()->AsETSBinder()->ReExportImports()) {
206             if (std::find(paths.begin(), paths.end(), reExport->GetProgramPath().Mutf8()) != paths.end()) {
207                 auto path =
208                     reExport->GetProgramPath().Mutf8().substr(0, reExport->GetProgramPath().Mutf8().find_last_of('/'));
209                 for (auto item : reExport->GetUserPaths()) {
210                     reExportPaths.push_back(
211                         path + "/" + item.Mutf8().substr(item.Mutf8().find_first_of('/') + 1, item.Mutf8().length()));
212                 }
213             }
214         }
215 
216         removeParsedSources(reExportPaths);
217 
218         ParseSources(reExportPaths, false);
219     }
220 
221     ParseTopLevelDeclaration(statements);
222 
223     auto *etsScript = AllocNode<ir::ETSScript>(Allocator(), std::move(statements), GetProgram());
224     etsScript->SetRange({startLoc, Lexer()->GetToken().End()});
225     GetProgram()->SetAst(etsScript);
226 }
227 
CreateGlobalClass()228 void ETSParser::CreateGlobalClass()
229 {
230     auto *ident = AllocNode<ir::Identifier>(compiler::Signatures::ETS_GLOBAL, Allocator());
231 
232     auto *classDef = AllocNode<ir::ClassDefinition>(Allocator(), ident, ir::ClassDefinitionModifiers::GLOBAL,
233                                                     ir::ModifierFlags::ABSTRACT, Language(Language::Id::ETS));
234     GetProgram()->SetGlobalClass(classDef);
235 
236     [[maybe_unused]] auto *classDecl = AllocNode<ir::ClassDeclaration>(classDef, Allocator());
237 }
238 
PrepareGlobalClass()239 ArenaVector<ir::Statement *> ETSParser::PrepareGlobalClass()
240 {
241     ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
242     ParsePackageDeclaration(statements);
243     CreateGlobalClass();
244 
245     return statements;
246 }
247 
PrepareExternalGlobalClass(const SourceFile & sourceFile)248 ArenaVector<ir::Statement *> ETSParser::PrepareExternalGlobalClass([[maybe_unused]] const SourceFile &sourceFile)
249 {
250     ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
251     ParsePackageDeclaration(statements);
252 
253     if (statements.empty()) {
254         GetProgram()->SetGlobalClass(globalProgram_->GlobalClass());
255     }
256 
257     auto &extSources = globalProgram_->ExternalSources();
258     const util::StringView name = GetProgram()->SourceFileFolder();
259 
260     auto res = extSources.end();
261     if (!statements.empty()) {
262         res = extSources.find(name);
263     } else {
264         auto path = GetProgram()->SourceFileFolder().Mutf8() + panda::os::file::File::GetPathDelim().at(0) +
265                     GetProgram()->GetPackageName().Mutf8();
266         auto resolved = ResolveImportPath(path);
267         resolvedParsedSources_.emplace(path, resolved);
268         GetProgram()->SetSource(GetProgram()->SourceCode(), GetProgram()->SourceFilePath(),
269                                 util::UString(resolved, Allocator()).View());
270     }
271 
272     if (res == extSources.end()) {
273         CreateGlobalClass();
274         auto insRes = extSources.emplace(GetProgram()->SourceFileFolder(), Allocator()->Adapter());
275         insRes.first->second.push_back(GetProgram());
276     } else {
277         res->second.push_back(GetProgram());
278         auto *extProg = res->second.front();
279         GetProgram()->SetGlobalClass(extProg->GlobalClass());
280         // NOTE(user): check nullptr cases and handle recursive imports
281     }
282 
283     return statements;
284 }
285 
IsCompitableExtension(const std::string & extension)286 static bool IsCompitableExtension(const std::string &extension)
287 {
288     return extension == ".ets" || extension == ".ts";
289 }
290 
CollectDefaultSources()291 void ETSParser::CollectDefaultSources()
292 {
293     std::vector<std::string> paths;
294     std::vector<std::string> stdlib = {"std/core", "std/math",       "std/containers",
295                                        "std/time", "std/interop/js", "escompat"};
296 
297 #ifdef USE_UNIX_SYSCALL
298     for (auto const &path : stdlib) {
299         auto resolvedPath = ResolveImportPath(path);
300         DIR *dir = opendir(resolvedPath.c_str());
301 
302         if (dir == nullptr) {
303             ThrowSyntaxError({"Cannot open folder: ", resolvedPath});
304         }
305 
306         struct dirent *entry;
307         while ((entry = readdir(dir)) != nullptr) {
308             if (entry->d_type != DT_REG) {
309                 continue;
310             }
311 
312             std::string fileName = entry->d_name;
313             std::string::size_type pos = fileName.find_last_of('.');
314             if (pos == std::string::npos || !IsCompitableExtension(fileName.substr(pos))) {
315                 continue;
316             }
317 
318             std::string filePath = path + "/" + entry->d_name;
319 
320             if (fileName == "Object.ets") {
321                 parsedSources_.emplace(parsedSources_.begin(), filePath);
322             } else {
323                 parsedSources_.emplace_back(filePath);
324             }
325         }
326 
327         closedir(dir);
328     }
329 #else
330     for (auto const &path : stdlib) {
331         for (auto const &entry : fs::directory_iterator(ResolveImportPath(path))) {
332             if (!fs::is_regular_file(entry) || !IsCompitableExtension(entry.path().extension().string())) {
333                 continue;
334             }
335 
336             std::string baseName = path;
337             std::size_t pos = entry.path().string().find_last_of(panda::os::file::File::GetPathDelim());
338 
339             baseName.append(entry.path().string().substr(pos, entry.path().string().size()));
340 
341             if (entry.path().filename().string() == "Object.ets") {
342                 parsedSources_.emplace(parsedSources_.begin(), baseName);
343             } else {
344                 parsedSources_.emplace_back(baseName);
345             }
346         }
347     }
348 #endif
349 }
350 
GetImportData(const std::string & path)351 ETSParser::ImportData ETSParser::GetImportData(const std::string &path)
352 {
353     auto &dynamicPaths = ArkTSConfig()->DynamicPaths();
354     auto key = panda::os::NormalizePath(path);
355 
356     auto it = dynamicPaths.find(key);
357     if (it == dynamicPaths.cend()) {
358         key = panda::os::RemoveExtension(key);
359     }
360 
361     while (it == dynamicPaths.cend() && !key.empty()) {
362         it = dynamicPaths.find(key);
363         if (it != dynamicPaths.cend()) {
364             break;
365         }
366         key = panda::os::GetParentDir(key);
367     }
368 
369     if (it != dynamicPaths.cend()) {
370         return {it->second.GetLanguage(), key, it->second.HasDecl()};
371     }
372     return {ToLanguage(Extension()), path, true};
373 }
374 
ResolveFullPathFromRelative(const std::string & path)375 std::string ETSParser::ResolveFullPathFromRelative(const std::string &path)
376 {
377     char pathDelimiter = panda::os::file::File::GetPathDelim().at(0);
378     auto resolvedFp = GetProgram()->ResolvedFilePath().Mutf8();
379     auto sourceFp = GetProgram()->SourceFileFolder().Mutf8();
380     if (resolvedFp.empty()) {
381         auto fp = sourceFp + pathDelimiter + path;
382         return util::Helpers::IsRealPath(fp) ? fp : path;
383     }
384     auto fp = resolvedFp + pathDelimiter + path;
385     if (util::Helpers::IsRealPath(fp)) {
386         return fp;
387     }
388     if (path.find(sourceFp) == 0) {
389         return resolvedFp + pathDelimiter + path.substr(sourceFp.size());
390     }
391     return path;
392 }
393 
ResolveImportPath(const std::string & path)394 std::string ETSParser::ResolveImportPath(const std::string &path)
395 {
396     char pathDelimiter = panda::os::file::File::GetPathDelim().at(0);
397     if (util::Helpers::IsRelativePath(path)) {
398         return util::Helpers::GetAbsPath(ResolveFullPathFromRelative(path));
399     }
400 
401     std::string baseUrl;
402     // Resolve delimeter character to basePath.
403     if (path.find('/') == 0) {
404         baseUrl = ArkTSConfig()->BaseUrl();
405 
406         baseUrl.append(path, 0, path.length());
407         return baseUrl;
408     }
409 
410     auto &dynamicPaths = ArkTSConfig()->DynamicPaths();
411     auto it = dynamicPaths.find(path);
412     if (it != dynamicPaths.cend() && !it->second.HasDecl()) {
413         return path;
414     }
415 
416     // Resolve the root part of the path.
417     // E.g. root part of std/math is std.
418     std::string::size_type pos = path.find('/');
419     bool containsDelim = (pos != std::string::npos);
420     std::string rootPart = containsDelim ? path.substr(0, pos) : path;
421     if (rootPart == "std" && !GetOptions().stdLib.empty()) {  // Get std path from CLI if provided
422         baseUrl = GetOptions().stdLib + "/std";
423     } else if (rootPart == "escompat" && !GetOptions().stdLib.empty()) {  // Get escompat path from CLI if provided
424         baseUrl = GetOptions().stdLib + "/escompat";
425     } else {
426         auto resolvedPath = ArkTSConfig()->ResolvePath(path);
427         if (resolvedPath.empty()) {
428             ThrowSyntaxError({"Can't find prefix for '", path, "' in ", ArkTSConfig()->ConfigPath()});
429         }
430         return resolvedPath;
431     }
432 
433     if (containsDelim) {
434         baseUrl.append(1, pathDelimiter);
435         baseUrl.append(path, rootPart.length() + 1, path.length());
436     }
437 
438     return baseUrl;
439 }
440 
GetSourceRegularPath(const std::string & path,const std::string & resolvedPath)441 std::tuple<std::string, bool> ETSParser::GetSourceRegularPath(const std::string &path, const std::string &resolvedPath)
442 {
443     if (!panda::os::file::File::IsRegularFile(resolvedPath)) {
444         std::string importExtension = ".ets";
445 
446         if (!panda::os::file::File::IsRegularFile(resolvedPath + importExtension)) {
447             importExtension = ".ts";
448 
449             if (!panda::os::file::File::IsRegularFile(resolvedPath + importExtension)) {
450                 ThrowSyntaxError("Incorrect path: " + resolvedPath);
451             }
452         }
453         return {path + importExtension, true};
454     }
455     return {path, false};
456 }
457 
CollectUserSourcesFromIndex(const std::string & path,const std::string & resolvedPath,std::vector<std::string> & userPaths)458 void ETSParser::CollectUserSourcesFromIndex([[maybe_unused]] const std::string &path,
459                                             [[maybe_unused]] const std::string &resolvedPath,
460                                             [[maybe_unused]] std::vector<std::string> &userPaths)
461 {
462 #ifdef USE_UNIX_SYSCALL
463     DIR *dir = opendir(resolvedPath.c_str());
464     bool isIndex = false;
465     std::vector<std::string> tmpPaths;
466 
467     if (dir == nullptr) {
468         ThrowSyntaxError({"Cannot open folder: ", resolvedPath});
469     }
470 
471     struct dirent *entry;
472     while ((entry = readdir(dir)) != nullptr) {
473         if (entry->d_type != DT_REG) {
474             continue;
475         }
476 
477         std::string fileName = entry->d_name;
478         std::string::size_type pos = fileName.find_last_of('.');
479         if (pos == std::string::npos || !IsCompitableExtension(fileName.substr(pos))) {
480             continue;
481         }
482 
483         std::string filePath = path + "/" + entry->d_name;
484 
485         if (fileName == "index.ets" || fileName == "index.ts") {
486             userPaths.emplace_back(filePath);
487             isIndex = true;
488             break;
489         } else if (fileName == "Object.ets") {
490             tmpPaths.emplace(userPaths.begin(), filePath);
491         } else {
492             tmpPaths.emplace_back(filePath);
493         }
494     }
495 
496     closedir(dir);
497 
498     if (!isIndex) {
499         userPaths.insert(userPaths.end(), tmpPaths.begin(), tmpPaths.end());
500     }
501 #endif
502 }
503 
CollectUserSources(const std::string & path)504 std::tuple<std::vector<std::string>, bool> ETSParser::CollectUserSources(const std::string &path)
505 {
506     std::vector<std::string> userPaths;
507 
508     const std::string resolvedPath = ResolveImportPath(path);
509     resolvedParsedSources_.emplace(path, resolvedPath);
510     const auto data = GetImportData(resolvedPath);
511     if (!data.hasDecl) {
512         return {userPaths, false};
513     }
514 
515     if (!panda::os::file::File::IsDirectory(resolvedPath)) {
516         std::string regularPath;
517         bool isModule = false;
518         std::tie(regularPath, isModule) = GetSourceRegularPath(path, resolvedPath);
519         userPaths.emplace_back(regularPath);
520         return {userPaths, isModule};
521     }
522 
523 #ifdef USE_UNIX_SYSCALL
524     CollectUserSourcesFromIndex(path, resolvedPath, userPaths);
525 #else
526     if (fs::exists(resolvedPath + "/index.ets")) {
527         userPaths.emplace_back(path + "/index.ets");
528     } else if (fs::exists(resolvedPath + "/index.ts")) {
529         userPaths.emplace_back(path + "/index.ts");
530     } else {
531         for (auto const &entry : fs::directory_iterator(resolvedPath)) {
532             if (!fs::is_regular_file(entry) || !IsCompitableExtension(entry.path().extension().string())) {
533                 continue;
534             }
535 
536             std::string baseName = path;
537             std::size_t pos = entry.path().string().find_last_of(panda::os::file::File::GetPathDelim());
538 
539             baseName.append(entry.path().string().substr(pos, entry.path().string().size()));
540             userPaths.emplace_back(baseName);
541         }
542     }
543 #endif
544     return {userPaths, false};
545 }
546 
ParseSources(const std::vector<std::string> & paths,bool isExternal)547 void ETSParser::ParseSources(const std::vector<std::string> &paths, bool isExternal)
548 {
549     GetContext().Status() |= isExternal ? ParserStatus::IN_EXTERNAL : ParserStatus::IN_IMPORT;
550 
551     const std::size_t pathCount = paths.size();
552     for (std::size_t idx = 0; idx < pathCount; idx++) {
553         std::string resolvedPath = ResolveImportPath(paths[idx]);
554         resolvedParsedSources_.emplace(paths[idx], resolvedPath);
555 
556         const auto data = GetImportData(resolvedPath);
557         if (!data.hasDecl) {
558             continue;
559         }
560 
561         std::ifstream inputStream(resolvedPath.c_str());
562 
563         if (GetProgram()->SourceFilePath().Is(resolvedPath)) {
564             break;
565         }
566 
567         if (inputStream.fail()) {
568             ThrowSyntaxError({"Failed to open file: ", resolvedPath.c_str()});
569         }
570 
571         std::stringstream ss;
572         ss << inputStream.rdbuf();
573         auto externalSource = ss.str();
574 
575         auto currentLang = GetContext().SetLanguage(data.lang);
576         ParseSource({paths[idx].c_str(), externalSource.c_str(), resolvedPath.c_str(), false});
577         GetContext().SetLanguage(currentLang);
578     }
579 
580     GetContext().Status() &= isExternal ? ~ParserStatus::IN_EXTERNAL : ~ParserStatus::IN_IMPORT;
581 }
582 
ParseDefaultSources()583 void ETSParser::ParseDefaultSources()
584 {
585     auto isp = InnerSourceParser(this);
586     SourceFile source(varbinder::ETSBinder::DEFAULT_IMPORT_SOURCE_FILE, varbinder::ETSBinder::DEFAULT_IMPORT_SOURCE);
587     auto lexer = InitLexer(source);
588     ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
589 
590     Lexer()->NextToken();
591 
592     GetContext().Status() |= ParserStatus::IN_DEFAULT_IMPORTS;
593 
594     ParseImportDeclarations(statements);
595     GetContext().Status() &= ~ParserStatus::IN_DEFAULT_IMPORTS;
596 
597     CollectDefaultSources();
598 
599     ParseSources(parsedSources_, true);
600 }
601 
ParseSource(const SourceFile & sourceFile)602 void ETSParser::ParseSource(const SourceFile &sourceFile)
603 {
604     auto *program = Allocator()->New<parser::Program>(Allocator(), GetProgram()->VarBinder());
605     auto esp = ExternalSourceParser(this, program);
606     auto lexer = InitLexer(sourceFile);
607 
608     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
609     Lexer()->NextToken();
610 
611     auto statements = PrepareExternalGlobalClass(sourceFile);
612     ParseETSGlobalScript(startLoc, statements);
613 }
614 
AddInitMethod(ArenaVector<ir::AstNode * > & globalProperties)615 ir::ScriptFunction *ETSParser::AddInitMethod(ArenaVector<ir::AstNode *> &globalProperties)
616 {
617     if (GetProgram()->Kind() == ScriptKind::STDLIB) {
618         return nullptr;
619     }
620 
621     // Lambda to create empty function node with signature: func(): void
622     // NOTE: replace with normal createFunction call
623     auto const createFunction =
624         [this](std::string_view const functionName, ir::ScriptFunctionFlags functionFlags,
625                ir::ModifierFlags const functionModifiers) -> std::pair<ir::ScriptFunction *, ir::MethodDefinition *> {
626         auto *initIdent = AllocNode<ir::Identifier>(functionName, Allocator());
627         ir::ScriptFunction *initFunc;
628 
629         {
630             ArenaVector<ir::Expression *> params(Allocator()->Adapter());
631 
632             ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
633             auto *initBody = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
634 
635             initFunc = AllocNode<ir::ScriptFunction>(ir::FunctionSignature(nullptr, std::move(params), nullptr),
636                                                      initBody, functionFlags, false, GetContext().GetLanguge());
637         }
638 
639         initFunc->SetIdent(initIdent);
640         initFunc->AddModifier(functionModifiers);
641 
642         auto *funcExpr = AllocNode<ir::FunctionExpression>(initFunc);
643 
644         auto *initMethod = AllocNode<ir::MethodDefinition>(ir::MethodDefinitionKind::METHOD, initIdent, funcExpr,
645                                                            functionModifiers, Allocator(), false);
646 
647         return std::make_pair(initFunc, initMethod);
648     };
649 
650     // Create public method for module re-initialization. The assignments and statements are sequentially called inside.
651     auto [init_func, init_method] = createFunction(compiler::Signatures::INIT_METHOD, ir::ScriptFunctionFlags::NONE,
652                                                    ir::ModifierFlags::STATIC | ir::ModifierFlags::PUBLIC);
653     globalProperties.emplace_back(init_method);
654 
655     return init_func;
656 }
657 
MarkNodeAsExported(ir::AstNode * node,lexer::SourcePosition startPos,bool defaultExport,std::size_t numOfElements)658 void ETSParser::MarkNodeAsExported(ir::AstNode *node, lexer::SourcePosition startPos, bool defaultExport,
659                                    std::size_t numOfElements)
660 {
661     ir::ModifierFlags flag = defaultExport ? ir::ModifierFlags::DEFAULT_EXPORT : ir::ModifierFlags::EXPORT;
662 
663     if (UNLIKELY(flag == ir::ModifierFlags::DEFAULT_EXPORT)) {
664         if (numOfElements > 1) {
665             ThrowSyntaxError("Only one default export is allowed in a module", startPos);
666         }
667     }
668 
669     node->AddModifier(flag);
670 }
671 
ParseTopLevelStatements(ArenaVector<ir::Statement * > & statements)672 ArenaVector<ir::AstNode *> ETSParser::ParseTopLevelStatements(ArenaVector<ir::Statement *> &statements)
673 {
674     ArenaVector<ir::AstNode *> globalProperties(Allocator()->Adapter());
675     fieldMap_.clear();
676     exportNameMap_.clear();
677 
678     // Add special '_$init$_' method that will hold all the top-level variable initializations (as assignments) and
679     // statements. By default it will be called in the global class static constructor but also it can be called
680     // directly from outside using public '_$init$_' method call in global scope.
681     // NOTE: now only a single-file modules are supported. Such a technique can be implemented in packages directly.
682     ir::ScriptFunction *initFunction = nullptr;
683     if (GetProgram()->GetPackageName().Empty()) {
684         initFunction = AddInitMethod(globalProperties);
685     }
686 
687     ParseTopLevelNextToken(statements, globalProperties, initFunction);
688 
689     // Add export modifier flag to nodes exported in previous statements.
690     for (auto &iter : exportNameMap_) {
691         util::StringView exportName = iter.first;
692         lexer::SourcePosition startLoc = exportNameMap_[exportName];
693         if (fieldMap_.count(exportName) == 0) {
694             ThrowSyntaxError("Cannot find name '" + std::string {exportName.Utf8()} + "' to export.", startLoc);
695         }
696         auto field = fieldMap_[exportName];
697         // selective export does not support default
698         MarkNodeAsExported(field, startLoc, false);
699     }
700     return globalProperties;
701 }
702 
ParseTopLevelType(ArenaVector<ir::Statement * > & statements,bool & defaultExport,std::size_t const currentPos,std::function<ir::Statement * (ETSParser *)> const & parserFunction)703 void ETSParser::ParseTopLevelType(ArenaVector<ir::Statement *> &statements, bool &defaultExport,
704                                   std::size_t const currentPos,
705                                   std::function<ir::Statement *(ETSParser *)> const &parserFunction)
706 {
707     ir::Statement *node = nullptr;
708 
709     node = parserFunction(this);
710     if (node != nullptr) {
711         if (currentPos != std::numeric_limits<std::size_t>::max()) {
712             MarkNodeAsExported(node, node->Start(), defaultExport);
713             defaultExport = false;
714         }
715         statements.push_back(node);
716     }
717 }
718 
ParseTopLevelNextTokenDefault(ArenaVector<ir::Statement * > & statements,ir::ScriptFunction * initFunction,size_t currentPos,lexer::TokenType tokenType,bool defaultExport)719 void ETSParser::ParseTopLevelNextTokenDefault(ArenaVector<ir::Statement *> &statements,
720                                               ir::ScriptFunction *initFunction, size_t currentPos,
721                                               lexer::TokenType tokenType, bool defaultExport)
722 {
723     if (IsStructKeyword()) {
724         ParseTopLevelType(statements, defaultExport, currentPos,
725                           [](ETSParser *obj) { return obj->ParseTypeDeclaration(false); });
726         return;
727     }
728 
729     if (initFunction != nullptr) {
730         if (auto *const statement = ParseTopLevelStatement(); statement != nullptr) {
731             statement->SetParent(initFunction->Body());
732             initFunction->Body()->AsBlockStatement()->Statements().emplace_back(statement);
733         }
734         return;
735     }
736 
737     ThrowUnexpectedToken(tokenType);
738 }
739 
ResolveMemberModifiers()740 ir::ModifierFlags ETSParser::ResolveMemberModifiers()
741 {
742     auto memberModifiers = ir::ModifierFlags::STATIC | ir::ModifierFlags::PUBLIC;
743 
744     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) {
745         CheckDeclare();
746         memberModifiers |= ir::ModifierFlags::DECLARE;
747     }
748     return memberModifiers;
749 }
750 
ParseTopLevelNextTokenResolution(ArenaVector<ir::Statement * > & statements,ArenaVector<ir::AstNode * > & globalProperties,ir::ScriptFunction * initFunction,size_t currentPos,bool defaultExport)751 lexer::SourcePosition ETSParser::ParseTopLevelNextTokenResolution(ArenaVector<ir::Statement *> &statements,
752                                                                   ArenaVector<ir::AstNode *> &globalProperties,
753                                                                   ir::ScriptFunction *initFunction, size_t currentPos,
754                                                                   bool defaultExport)
755 {
756     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
757     auto memberModifiers = ResolveMemberModifiers();
758 
759     switch (auto const tokenType = Lexer()->GetToken().Type(); tokenType) {
760         case lexer::TokenType::KEYW_CONST: {
761             memberModifiers |= ir::ModifierFlags::CONST;
762             [[fallthrough]];
763         }
764         case lexer::TokenType::KEYW_LET: {
765             Lexer()->NextToken();
766             ParseClassFieldDefinition(ExpectIdentifier(), memberModifiers, &globalProperties, initFunction, &startLoc);
767             break;
768         }
769         case lexer::TokenType::KEYW_ASYNC:
770         case lexer::TokenType::KEYW_NATIVE: {
771             ParseTokenOfNative(tokenType, memberModifiers);
772             [[fallthrough]];
773         }
774         case lexer::TokenType::KEYW_FUNCTION: {
775             ParseTokenOfFunction(memberModifiers, startLoc, globalProperties);
776             break;
777         }
778         case lexer::TokenType::KEYW_NAMESPACE:
779             [[fallthrough]];
780         case lexer::TokenType::KEYW_STATIC:
781             [[fallthrough]];
782         case lexer::TokenType::KEYW_ABSTRACT:
783             [[fallthrough]];
784         case lexer::TokenType::KEYW_FINAL:
785             [[fallthrough]];
786         case lexer::TokenType::KEYW_ENUM:
787             [[fallthrough]];
788         case lexer::TokenType::KEYW_INTERFACE:
789             [[fallthrough]];
790         case lexer::TokenType::KEYW_CLASS: {
791             // NOLINTBEGIN(modernize-avoid-bind)
792             ParseTopLevelType(statements, defaultExport, currentPos,
793                               std::bind(&ETSParser::ParseTypeDeclaration, std::placeholders::_1, false));
794             // NOLINTEND(modernize-avoid-bind)
795             break;
796         }
797         case lexer::TokenType::KEYW_TYPE: {
798             ParseTopLevelType(statements, defaultExport, currentPos, &ETSParser::ParseTypeAliasDeclaration);
799             break;
800         }
801         default: {
802             // If struct is a soft keyword, handle it here, otherwise it's an identifier.
803             ParseTopLevelNextTokenDefault(statements, initFunction, currentPos, tokenType, defaultExport);
804         }
805     }
806     return startLoc;
807 }
808 
ParseTopLevelNextToken(ArenaVector<ir::Statement * > & statements,ArenaVector<ir::AstNode * > & globalProperties,ir::ScriptFunction * initFunction)809 void ETSParser::ParseTopLevelNextToken(ArenaVector<ir::Statement *> &statements,
810                                        ArenaVector<ir::AstNode *> &globalProperties, ir::ScriptFunction *initFunction)
811 {
812     bool defaultExport = false;
813 
814     while (Lexer()->GetToken().Type() != lexer::TokenType::EOS) {
815         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
816             Lexer()->NextToken();
817             continue;
818         }
819 
820         auto currentPos = std::numeric_limits<size_t>::max();
821         if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXPORT) {
822             Lexer()->NextToken();
823             currentPos = globalProperties.size();
824 
825             if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY ||
826                 Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
827                 ParseExport(Lexer()->GetToken().Start());
828                 continue;
829             }
830 
831             if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_DEFAULT) {
832                 defaultExport = true;
833                 Lexer()->NextToken();
834             }
835         }
836 
837         lexer::SourcePosition startLoc =
838             ParseTopLevelNextTokenResolution(statements, globalProperties, initFunction, currentPos, defaultExport);
839 
840         GetContext().Status() &= ~ParserStatus::IN_AMBIENT_CONTEXT;
841 
842         while (currentPos < globalProperties.size()) {
843             MarkNodeAsExported(globalProperties[currentPos], startLoc, defaultExport,
844                                globalProperties.size() - currentPos);
845             defaultExport = false;
846             currentPos++;
847         }
848     }
849 }
850 
ParseTokenOfNative(panda::es2panda::lexer::TokenType tokenType,ir::ModifierFlags & memberModifiers)851 void ETSParser::ParseTokenOfNative(panda::es2panda::lexer::TokenType tokenType, ir::ModifierFlags &memberModifiers)
852 {
853     bool isAsync = tokenType == lexer::TokenType::KEYW_ASYNC;
854 
855     if (isAsync) {
856         memberModifiers |= ir::ModifierFlags::ASYNC;
857     } else {
858         memberModifiers |= ir::ModifierFlags::NATIVE;
859     }
860 
861     Lexer()->NextToken();
862 
863     if (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_FUNCTION) {
864         ThrowSyntaxError({isAsync ? "'async'" : "'native'", " flags must be used for functions at top-level."});
865     }
866 }
867 
ParseTokenOfFunction(ir::ModifierFlags memberModifiers,lexer::SourcePosition startLoc,ArenaVector<ir::AstNode * > & globalProperties)868 void ETSParser::ParseTokenOfFunction(ir::ModifierFlags memberModifiers, lexer::SourcePosition startLoc,
869                                      ArenaVector<ir::AstNode *> &globalProperties)
870 {
871     Lexer()->NextToken();
872     // check whether it is an extension function
873     ir::Identifier *className = nullptr;
874     if (Lexer()->Lookahead() == lexer::LEX_CHAR_DOT) {
875         className = ExpectIdentifier();
876         Lexer()->NextToken();
877     }
878 
879     auto *memberName = ExpectIdentifier();
880     auto *classMethod = ParseClassMethodDefinition(memberName, memberModifiers, className);
881     classMethod->SetStart(startLoc);
882     if (!classMethod->Function()->IsOverload()) {
883         globalProperties.push_back(classMethod);
884     }
885 }
886 
887 // NOLINTNEXTLINE(google-default-arguments)
ParseTopLevelStatement(StatementParsingFlags flags)888 ir::Statement *ETSParser::ParseTopLevelStatement(StatementParsingFlags flags)
889 {
890     switch (auto const tokenType = Lexer()->GetToken().Type(); tokenType) {
891         case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
892             return ParseBlockStatement();
893         }
894         case lexer::TokenType::PUNCTUATOR_SEMI_COLON: {
895             return ParseEmptyStatement();
896         }
897         case lexer::TokenType::KEYW_ASSERT: {
898             return ParseAssertStatement();
899         }
900         case lexer::TokenType::KEYW_IF: {
901             return ParseIfStatement();
902         }
903         case lexer::TokenType::KEYW_DO: {
904             return ParseDoWhileStatement();
905         }
906         case lexer::TokenType::KEYW_FOR: {
907             return ParseForStatement();
908         }
909         case lexer::TokenType::KEYW_TRY: {
910             return ParseTryStatement();
911         }
912         case lexer::TokenType::KEYW_WHILE: {
913             return ParseWhileStatement();
914         }
915         case lexer::TokenType::KEYW_BREAK: {
916             return ParseBreakStatement();
917         }
918         case lexer::TokenType::KEYW_CONTINUE: {
919             return ParseContinueStatement();
920         }
921         case lexer::TokenType::KEYW_THROW: {
922             return ParseThrowStatement();
923         }
924         case lexer::TokenType::KEYW_SWITCH: {
925             return ParseSwitchStatement();
926         }
927         case lexer::TokenType::KEYW_DEBUGGER: {
928             return ParseDebuggerStatement();
929         }
930         case lexer::TokenType::LITERAL_IDENT: {
931             if (Lexer()->Lookahead() == lexer::LEX_CHAR_COLON) {
932                 const auto pos = Lexer()->Save();
933                 Lexer()->NextToken();
934                 return ParseLabelledStatement(pos);
935             }
936 
937             return ParseExpressionStatement(flags);
938         }
939         // These cases never can occur here!
940         case lexer::TokenType::KEYW_EXPORT:
941             [[fallthrough]];
942         case lexer::TokenType::KEYW_IMPORT:
943             [[fallthrough]];
944         case lexer::TokenType::KEYW_RETURN: {
945             ThrowUnexpectedToken(tokenType);
946         }
947         // Note: let's leave the default processing case separately, because it can be changed in the future.
948         default: {
949             ThrowUnexpectedToken(tokenType);
950             // like this `return ParseExpressionStatement(flags);`
951         }
952     }
953 }
954 
ParseTopLevelDeclaration(ArenaVector<ir::Statement * > & statements)955 void ETSParser::ParseTopLevelDeclaration(ArenaVector<ir::Statement *> &statements)
956 {
957     lexer::SourcePosition classBodyStartLoc = Lexer()->GetToken().Start();
958     auto globalProperties = ParseTopLevelStatements(statements);
959 
960     auto *classDef = GetProgram()->GlobalClass();
961 
962     if (classDef->IsGlobalInitialized()) {
963         classDef->AddProperties(std::move(globalProperties));
964         Lexer()->NextToken();
965         return;
966     }
967 
968     CreateCCtor(globalProperties, classBodyStartLoc, GetProgram()->Kind() != ScriptKind::STDLIB);
969     classDef->AddProperties(std::move(globalProperties));
970     auto *classDecl = classDef->Parent()->AsClassDeclaration();
971     classDef->SetGlobalInitialized();
972     classDef->SetRange(classDef->Range());
973 
974     statements.push_back(classDecl);
975     Lexer()->NextToken();
976 }
977 
978 // NOLINTNEXTLINE(google-default-arguments)
CreateCCtor(ArenaVector<ir::AstNode * > & properties,const lexer::SourcePosition & loc,const bool inGlobalClass)979 void ETSParser::CreateCCtor(ArenaVector<ir::AstNode *> &properties, const lexer::SourcePosition &loc,
980                             const bool inGlobalClass)
981 {
982     bool hasStaticField = false;
983     for (const auto *prop : properties) {
984         if (prop->IsClassStaticBlock()) {
985             return;
986         }
987 
988         if (!prop->IsClassProperty()) {
989             continue;
990         }
991 
992         const auto *field = prop->AsClassProperty();
993 
994         if (field->IsStatic()) {
995             hasStaticField = true;
996         }
997     }
998 
999     if (!hasStaticField && !inGlobalClass) {
1000         return;
1001     }
1002 
1003     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
1004 
1005     auto *id = AllocNode<ir::Identifier>(compiler::Signatures::CCTOR, Allocator());
1006 
1007     ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
1008 
1009     // Add the call to special '_$init$_' method containing all the top-level variable initializations (as assignments)
1010     // and statements to the end of static constructor of the global class.
1011     if (inGlobalClass) {
1012         if (auto const it = std::find_if(properties.begin(), properties.end(),
1013                                          [](ir::AstNode const *const item) {
1014                                              return item->IsMethodDefinition() &&
1015                                                     item->AsMethodDefinition()->Id()->Name() ==
1016                                                         compiler::Signatures::INIT_METHOD;
1017                                          });
1018             it != properties.end()) {
1019             if (!(*it)->AsMethodDefinition()->Function()->Body()->AsBlockStatement()->Statements().empty()) {
1020                 auto *const callee = AllocNode<ir::Identifier>(compiler::Signatures::INIT_METHOD, Allocator());
1021                 callee->SetReference();
1022 
1023                 auto *const callExpr = AllocNode<ir::CallExpression>(
1024                     callee, ArenaVector<ir::Expression *>(Allocator()->Adapter()), nullptr, false, false);
1025 
1026                 statements.emplace_back(AllocNode<ir::ExpressionStatement>(callExpr));
1027             }
1028         }
1029     }
1030 
1031     auto *body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
1032     auto *func = AllocNode<ir::ScriptFunction>(ir::FunctionSignature(nullptr, std::move(params), nullptr), body,
1033                                                ir::ScriptFunctionFlags::STATIC_BLOCK | ir::ScriptFunctionFlags::HIDDEN,
1034                                                ir::ModifierFlags::STATIC, false, GetContext().GetLanguge());
1035     func->SetIdent(id);
1036 
1037     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
1038     auto *staticBlock = AllocNode<ir::ClassStaticBlock>(funcExpr, Allocator());
1039     staticBlock->AddModifier(ir::ModifierFlags::STATIC);
1040     staticBlock->SetRange({loc, loc});
1041     properties.push_back(staticBlock);
1042 }
1043 
IsClassModifier(lexer::TokenType type)1044 static bool IsClassModifier(lexer::TokenType type)
1045 {
1046     return type == lexer::TokenType::KEYW_STATIC || type == lexer::TokenType::KEYW_ABSTRACT ||
1047            type == lexer::TokenType::KEYW_FINAL;
1048 }
1049 
ParseClassModifiers()1050 ir::ModifierFlags ETSParser::ParseClassModifiers()
1051 {
1052     ir::ModifierFlags flags = ir::ModifierFlags::NONE;
1053 
1054     while (IsClassModifier(Lexer()->GetToken().KeywordType())) {
1055         ir::ModifierFlags currentFlag = ir::ModifierFlags::NONE;
1056 
1057         lexer::TokenFlags tokenFlags = Lexer()->GetToken().Flags();
1058         if ((tokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) {
1059             ThrowSyntaxError("Keyword must not contain escaped characters");
1060         }
1061 
1062         switch (Lexer()->GetToken().KeywordType()) {
1063             case lexer::TokenType::KEYW_STATIC: {
1064                 currentFlag = ir::ModifierFlags::STATIC;
1065                 break;
1066             }
1067             case lexer::TokenType::KEYW_FINAL: {
1068                 currentFlag = ir::ModifierFlags::FINAL;
1069                 break;
1070             }
1071             case lexer::TokenType::KEYW_ABSTRACT: {
1072                 currentFlag = ir::ModifierFlags::ABSTRACT;
1073                 break;
1074             }
1075             default: {
1076                 UNREACHABLE();
1077             }
1078         }
1079 
1080         if ((flags & currentFlag) != 0) {
1081             ThrowSyntaxError("Duplicated modifier is not allowed");
1082         }
1083 
1084         Lexer()->NextToken();
1085         flags |= currentFlag;
1086     }
1087 
1088     return flags;
1089 }
1090 
ParseClassImplementsElement()1091 std::tuple<ir::Expression *, ir::TSTypeParameterInstantiation *> ETSParser::ParseClassImplementsElement()
1092 {
1093     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR |
1094                                            TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE |
1095                                            TypeAnnotationParsingOptions::ALLOW_WILDCARD;
1096     return {ParseTypeReference(&options), nullptr};
1097 }
1098 
ParseSuperClassReference()1099 ir::Expression *ETSParser::ParseSuperClassReference()
1100 {
1101     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
1102         Lexer()->NextToken();
1103 
1104         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR |
1105                                                TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE |
1106                                                TypeAnnotationParsingOptions::ALLOW_WILDCARD;
1107         return ParseTypeReference(&options);
1108     }
1109 
1110     return nullptr;
1111 }
1112 
ParseInterfaceExtendsElement()1113 ir::TypeNode *ETSParser::ParseInterfaceExtendsElement()
1114 {
1115     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR |
1116                                            TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE |
1117                                            TypeAnnotationParsingOptions::ALLOW_WILDCARD;
1118     return ParseTypeReference(&options);
1119 }
1120 
IsClassMemberAccessModifier(lexer::TokenType type)1121 static bool IsClassMemberAccessModifier(lexer::TokenType type)
1122 {
1123     return type == lexer::TokenType::KEYW_PUBLIC || type == lexer::TokenType::KEYW_PRIVATE ||
1124            type == lexer::TokenType::KEYW_PROTECTED || type == lexer::TokenType::KEYW_INTERNAL;
1125 }
1126 
ParseClassMemberAccessModifiers()1127 std::tuple<ir::ModifierFlags, bool> ETSParser::ParseClassMemberAccessModifiers()
1128 {
1129     if (IsClassMemberAccessModifier(Lexer()->GetToken().Type())) {
1130         char32_t nextCp = Lexer()->Lookahead();
1131         if (!(nextCp != lexer::LEX_CHAR_EQUALS && nextCp != lexer::LEX_CHAR_COLON &&
1132               nextCp != lexer::LEX_CHAR_LEFT_PAREN)) {
1133             return {ir::ModifierFlags::NONE, false};
1134         }
1135 
1136         lexer::TokenFlags tokenFlags = Lexer()->GetToken().Flags();
1137         if ((tokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) {
1138             ThrowSyntaxError("Keyword must not contain escaped characters");
1139         }
1140 
1141         ir::ModifierFlags accessFlag = ir::ModifierFlags::NONE;
1142 
1143         switch (Lexer()->GetToken().KeywordType()) {
1144             case lexer::TokenType::KEYW_PUBLIC: {
1145                 accessFlag = ir::ModifierFlags::PUBLIC;
1146                 break;
1147             }
1148             case lexer::TokenType::KEYW_PRIVATE: {
1149                 accessFlag = ir::ModifierFlags::PRIVATE;
1150                 break;
1151             }
1152             case lexer::TokenType::KEYW_PROTECTED: {
1153                 accessFlag = ir::ModifierFlags::PROTECTED;
1154                 break;
1155             }
1156             case lexer::TokenType::KEYW_INTERNAL: {
1157                 Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
1158                 if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_PROTECTED) {
1159                     accessFlag = ir::ModifierFlags::INTERNAL;
1160                     return {accessFlag, true};
1161                 }
1162                 accessFlag = ir::ModifierFlags::INTERNAL_PROTECTED;
1163                 break;
1164             }
1165             default: {
1166                 UNREACHABLE();
1167             }
1168         }
1169 
1170         Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
1171         return {accessFlag, true};
1172     }
1173 
1174     return {ir::ModifierFlags::PUBLIC, false};
1175 }
1176 
IsClassFieldModifier(lexer::TokenType type)1177 static bool IsClassFieldModifier(lexer::TokenType type)
1178 {
1179     return type == lexer::TokenType::KEYW_STATIC || type == lexer::TokenType::KEYW_READONLY;
1180 }
1181 
ParseClassFieldModifiers(bool seenStatic)1182 ir::ModifierFlags ETSParser::ParseClassFieldModifiers(bool seenStatic)
1183 {
1184     ir::ModifierFlags flags = seenStatic ? ir::ModifierFlags::STATIC : ir::ModifierFlags::NONE;
1185 
1186     while (IsClassFieldModifier(Lexer()->GetToken().KeywordType())) {
1187         char32_t nextCp = Lexer()->Lookahead();
1188         if (!(nextCp != lexer::LEX_CHAR_EQUALS && nextCp != lexer::LEX_CHAR_COLON)) {
1189             return flags;
1190         }
1191 
1192         ir::ModifierFlags currentFlag = ir::ModifierFlags::NONE;
1193 
1194         lexer::TokenFlags tokenFlags = Lexer()->GetToken().Flags();
1195         if ((tokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) {
1196             ThrowSyntaxError("Keyword must not contain escaped characters");
1197         }
1198 
1199         switch (Lexer()->GetToken().KeywordType()) {
1200             case lexer::TokenType::KEYW_STATIC: {
1201                 currentFlag = ir::ModifierFlags::STATIC;
1202                 break;
1203             }
1204             case lexer::TokenType::KEYW_READONLY: {
1205                 // NOTE(OCs): Use ir::ModifierFlags::READONLY once compiler is ready for it.
1206                 currentFlag = ir::ModifierFlags::CONST;
1207                 break;
1208             }
1209             default: {
1210                 UNREACHABLE();
1211             }
1212         }
1213 
1214         if ((flags & currentFlag) != 0) {
1215             ThrowSyntaxError("Duplicated modifier is not allowed");
1216         }
1217 
1218         Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
1219         flags |= currentFlag;
1220     }
1221 
1222     return flags;
1223 }
1224 
IsClassMethodModifier(lexer::TokenType type)1225 static bool IsClassMethodModifier(lexer::TokenType type)
1226 {
1227     switch (type) {
1228         case lexer::TokenType::KEYW_STATIC:
1229         case lexer::TokenType::KEYW_FINAL:
1230         case lexer::TokenType::KEYW_NATIVE:
1231         case lexer::TokenType::KEYW_ASYNC:
1232         case lexer::TokenType::KEYW_OVERRIDE:
1233         case lexer::TokenType::KEYW_ABSTRACT: {
1234             return true;
1235         }
1236         default: {
1237             break;
1238         }
1239     }
1240 
1241     return false;
1242 }
1243 
ParseClassMethodModifiers(bool seenStatic)1244 ir::ModifierFlags ETSParser::ParseClassMethodModifiers(bool seenStatic)
1245 {
1246     ir::ModifierFlags flags = seenStatic ? ir::ModifierFlags::STATIC : ir::ModifierFlags::NONE;
1247 
1248     while (IsClassMethodModifier(Lexer()->GetToken().KeywordType())) {
1249         char32_t nextCp = Lexer()->Lookahead();
1250         if (!(nextCp != lexer::LEX_CHAR_LEFT_PAREN)) {
1251             return flags;
1252         }
1253 
1254         ir::ModifierFlags currentFlag = ir::ModifierFlags::NONE;
1255 
1256         lexer::TokenFlags tokenFlags = Lexer()->GetToken().Flags();
1257         if ((tokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) {
1258             ThrowSyntaxError("Keyword must not contain escaped characters");
1259         }
1260 
1261         switch (Lexer()->GetToken().KeywordType()) {
1262             case lexer::TokenType::KEYW_STATIC: {
1263                 currentFlag = ir::ModifierFlags::STATIC;
1264                 break;
1265             }
1266             case lexer::TokenType::KEYW_FINAL: {
1267                 currentFlag = ir::ModifierFlags::FINAL;
1268                 break;
1269             }
1270             case lexer::TokenType::KEYW_NATIVE: {
1271                 currentFlag = ir::ModifierFlags::NATIVE;
1272                 break;
1273             }
1274             case lexer::TokenType::KEYW_ASYNC: {
1275                 currentFlag = ir::ModifierFlags::ASYNC;
1276                 break;
1277             }
1278             case lexer::TokenType::KEYW_OVERRIDE: {
1279                 currentFlag = ir::ModifierFlags::OVERRIDE;
1280                 break;
1281             }
1282             case lexer::TokenType::KEYW_ABSTRACT: {
1283                 currentFlag = ir::ModifierFlags::ABSTRACT;
1284                 break;
1285             }
1286             case lexer::TokenType::KEYW_DECLARE: {
1287                 currentFlag = ir::ModifierFlags::DECLARE;
1288                 break;
1289             }
1290             default: {
1291                 UNREACHABLE();
1292             }
1293         }
1294 
1295         if ((flags & currentFlag) != 0) {
1296             ThrowSyntaxError("Duplicated modifier is not allowed");
1297         }
1298 
1299         Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
1300         flags |= currentFlag;
1301         if ((flags & ir::ModifierFlags::ASYNC) != 0 && (flags & ir::ModifierFlags::NATIVE) != 0) {
1302             ThrowSyntaxError("Native method cannot be async");
1303         }
1304     }
1305 
1306     return flags;
1307 }
1308 
1309 // NOLINTNEXTLINE(google-default-arguments)
ParseClassFieldDefinition(ir::Identifier * fieldName,ir::ModifierFlags modifiers,ArenaVector<ir::AstNode * > * declarations,ir::ScriptFunction * initFunction,lexer::SourcePosition * letLoc)1310 void ETSParser::ParseClassFieldDefinition(ir::Identifier *fieldName, ir::ModifierFlags modifiers,
1311                                           ArenaVector<ir::AstNode *> *declarations, ir::ScriptFunction *initFunction,
1312                                           lexer::SourcePosition *letLoc)
1313 {
1314     lexer::SourcePosition startLoc = letLoc != nullptr ? *letLoc : Lexer()->GetToken().Start();
1315     lexer::SourcePosition endLoc = startLoc;
1316     ir::TypeNode *typeAnnotation = nullptr;
1317     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1318 
1319     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1320         Lexer()->NextToken();  // eat ':'
1321         typeAnnotation = ParseTypeAnnotation(&options);
1322     }
1323 
1324     ir::Expression *initializer = nullptr;
1325     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
1326         Lexer()->NextToken();  // eat '='
1327         initializer = ParseInitializer();
1328     } else if (typeAnnotation == nullptr) {
1329         ThrowSyntaxError("Field type annotation expected");
1330     }
1331 
1332     // Add initialization of top-level (global) variables to a special '_$init$_' function so that it could be
1333     // performed multiple times.
1334     if (initFunction != nullptr && (modifiers & ir::ModifierFlags::CONST) == 0U && initializer != nullptr &&
1335         !initializer->IsArrowFunctionExpression()) {
1336         endLoc = InitializeGlobalVariable(fieldName, initializer, initFunction, startLoc, typeAnnotation);
1337     }
1338 
1339     bool isDeclare = (modifiers & ir::ModifierFlags::DECLARE) != 0;
1340 
1341     if (isDeclare && initializer != nullptr) {
1342         ThrowSyntaxError("Initializers are not allowed in ambient contexts.");
1343     }
1344     auto *field = AllocNode<ir::ClassProperty>(fieldName, initializer, typeAnnotation, modifiers, Allocator(), false);
1345     startLoc = fieldName->Start();
1346     if (initializer != nullptr) {
1347         endLoc = initializer->End();
1348     } else {
1349         endLoc = typeAnnotation != nullptr ? typeAnnotation->End() : fieldName->End();
1350     }
1351     field->SetRange({startLoc, endLoc});
1352 
1353     fieldMap_.insert({fieldName->Name(), field});
1354     declarations->push_back(field);
1355 
1356     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
1357         Lexer()->NextToken();
1358         ir::Identifier *nextName = ExpectIdentifier(false, true);
1359         ParseClassFieldDefinition(nextName, modifiers, declarations);
1360     }
1361 }
1362 
InitializeGlobalVariable(ir::Identifier * fieldName,ir::Expression * & initializer,ir::ScriptFunction * initFunction,lexer::SourcePosition & startLoc,ir::TypeNode * typeAnnotation)1363 lexer::SourcePosition ETSParser::InitializeGlobalVariable(ir::Identifier *fieldName, ir::Expression *&initializer,
1364                                                           ir::ScriptFunction *initFunction,
1365                                                           lexer::SourcePosition &startLoc, ir::TypeNode *typeAnnotation)
1366 {
1367     lexer::SourcePosition endLoc = startLoc;
1368 
1369     if (auto *const funcBody = initFunction->Body(); funcBody != nullptr && funcBody->IsBlockStatement()) {
1370         auto *ident = AllocNode<ir::Identifier>(fieldName->Name(), Allocator());
1371         ident->SetReference();
1372         ident->SetRange(fieldName->Range());
1373 
1374         auto *assignmentExpression =
1375             AllocNode<ir::AssignmentExpression>(ident, initializer, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
1376         endLoc = initializer->End();
1377         assignmentExpression->SetRange({fieldName->Start(), endLoc});
1378         assignmentExpression->SetParent(funcBody);
1379 
1380         auto expressionStatement = AllocNode<ir::ExpressionStatement>(assignmentExpression);
1381         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) {
1382             endLoc = Lexer()->GetToken().End();
1383         }
1384         expressionStatement->SetRange({startLoc, endLoc});
1385         funcBody->AsBlockStatement()->Statements().emplace_back(expressionStatement);
1386 
1387         if (typeAnnotation != nullptr && !typeAnnotation->IsETSFunctionType()) {
1388             initializer = nullptr;
1389         }
1390     }
1391     return endLoc;
1392 }
1393 
ParseClassMethodDefinition(ir::Identifier * methodName,ir::ModifierFlags modifiers,ir::Identifier * className,ir::Identifier * identNode)1394 ir::MethodDefinition *ETSParser::ParseClassMethodDefinition(ir::Identifier *methodName, ir::ModifierFlags modifiers,
1395                                                             ir::Identifier *className, ir::Identifier *identNode)
1396 {
1397     auto newStatus = ParserStatus::NEED_RETURN_TYPE | ParserStatus::ALLOW_SUPER;
1398     auto methodKind = ir::MethodDefinitionKind::METHOD;
1399 
1400     if (className != nullptr) {
1401         methodKind = ir::MethodDefinitionKind::EXTENSION_METHOD;
1402         newStatus |= ParserStatus::IN_EXTENSION_FUNCTION;
1403     }
1404 
1405     if ((modifiers & ir::ModifierFlags::CONSTRUCTOR) != 0) {
1406         newStatus = ParserStatus::CONSTRUCTOR_FUNCTION | ParserStatus::ALLOW_SUPER | ParserStatus::ALLOW_SUPER_CALL;
1407         methodKind = ir::MethodDefinitionKind::CONSTRUCTOR;
1408     }
1409 
1410     if ((modifiers & ir::ModifierFlags::ASYNC) != 0) {
1411         newStatus |= ParserStatus::ASYNC_FUNCTION;
1412     }
1413 
1414     if ((modifiers & ir::ModifierFlags::STATIC) == 0) {
1415         newStatus |= ParserStatus::ALLOW_THIS_TYPE;
1416     }
1417 
1418     ir::ScriptFunction *func = ParseFunction(newStatus, className);
1419     func->SetIdent(methodName);
1420     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
1421     funcExpr->SetRange(func->Range());
1422     func->AddModifier(modifiers);
1423 
1424     if (className != nullptr) {
1425         func->AddFlag(ir::ScriptFunctionFlags::INSTANCE_EXTENSION_METHOD);
1426     }
1427     auto *method = AllocNode<ir::MethodDefinition>(methodKind, methodName, funcExpr, modifiers, Allocator(), false);
1428     method->SetRange(funcExpr->Range());
1429 
1430     fieldMap_.insert({methodName->Name(), method});
1431     AddProxyOverloadToMethodWithDefaultParams(method, identNode);
1432 
1433     return method;
1434 }
1435 
ParseFunction(ParserStatus newStatus,ir::Identifier * className)1436 ir::ScriptFunction *ETSParser::ParseFunction(ParserStatus newStatus, ir::Identifier *className)
1437 {
1438     FunctionContext functionContext(this, newStatus | ParserStatus::FUNCTION);
1439     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
1440     auto [signature, throwMarker] = ParseFunctionSignature(newStatus, className);
1441 
1442     ir::AstNode *body = nullptr;
1443     lexer::SourcePosition endLoc = startLoc;
1444     bool isOverload = false;
1445     bool isArrow = (newStatus & ParserStatus::ARROW_FUNCTION) != 0;
1446 
1447     if ((newStatus & ParserStatus::ASYNC_FUNCTION) != 0) {
1448         functionContext.AddFlag(ir::ScriptFunctionFlags::ASYNC);
1449     }
1450 
1451     if (isArrow) {
1452         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) {
1453             ThrowSyntaxError("'=>' expected");
1454         }
1455 
1456         functionContext.AddFlag(ir::ScriptFunctionFlags::ARROW);
1457         Lexer()->NextToken();
1458     }
1459 
1460     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
1461         std::tie(std::ignore, body, endLoc, isOverload) =
1462             ParseFunctionBody(signature.Params(), newStatus, GetContext().Status());
1463     } else if (isArrow) {
1464         body = ParseExpression();
1465         endLoc = body->AsExpression()->End();
1466         functionContext.AddFlag(ir::ScriptFunctionFlags::EXPRESSION);
1467     }
1468 
1469     if ((GetContext().Status() & ParserStatus::FUNCTION_HAS_RETURN_STATEMENT) != 0) {
1470         functionContext.AddFlag(ir::ScriptFunctionFlags::HAS_RETURN);
1471         GetContext().Status() ^= ParserStatus::FUNCTION_HAS_RETURN_STATEMENT;
1472     }
1473     functionContext.AddFlag(throwMarker);
1474 
1475     auto *funcNode = AllocNode<ir::ScriptFunction>(std::move(signature), body, functionContext.Flags(), false,
1476                                                    GetContext().GetLanguge());
1477     funcNode->SetRange({startLoc, endLoc});
1478 
1479     return funcNode;
1480 }
1481 
ParseClassMethod(ClassElementDescriptor * desc,const ArenaVector<ir::AstNode * > & properties,ir::Expression * propName,lexer::SourcePosition * propEnd)1482 ir::MethodDefinition *ETSParser::ParseClassMethod(ClassElementDescriptor *desc,
1483                                                   const ArenaVector<ir::AstNode *> &properties,
1484                                                   ir::Expression *propName, lexer::SourcePosition *propEnd)
1485 {
1486     if (desc->methodKind != ir::MethodDefinitionKind::SET &&
1487         (desc->newStatus & ParserStatus::CONSTRUCTOR_FUNCTION) == 0) {
1488         desc->newStatus |= ParserStatus::NEED_RETURN_TYPE;
1489     }
1490 
1491     ir::ScriptFunction *func = ParseFunction(desc->newStatus);
1492 
1493     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
1494     funcExpr->SetRange(func->Range());
1495 
1496     if (desc->methodKind == ir::MethodDefinitionKind::SET) {
1497         ValidateClassSetter(desc, properties, propName, func);
1498     } else if (desc->methodKind == ir::MethodDefinitionKind::GET) {
1499         ValidateClassGetter(desc, properties, propName, func);
1500     }
1501 
1502     *propEnd = func->End();
1503     func->AddFlag(ir::ScriptFunctionFlags::METHOD);
1504     auto *method = AllocNode<ir::MethodDefinition>(desc->methodKind, propName, funcExpr, desc->modifiers, Allocator(),
1505                                                    desc->isComputed);
1506     method->SetRange(funcExpr->Range());
1507 
1508     return method;
1509 }
1510 
ParseFunctionBody(const ArenaVector<ir::Expression * > & params,ParserStatus newStatus,ParserStatus contextStatus)1511 std::tuple<bool, ir::BlockStatement *, lexer::SourcePosition, bool> ETSParser::ParseFunctionBody(
1512     [[maybe_unused]] const ArenaVector<ir::Expression *> &params, [[maybe_unused]] ParserStatus newStatus,
1513     [[maybe_unused]] ParserStatus contextStatus)
1514 {
1515     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
1516 
1517     ir::BlockStatement *body = ParseBlockStatement();
1518 
1519     return {true, body, body->End(), false};
1520 }
1521 
ParseFunctionReturnType(ParserStatus status)1522 ir::TypeNode *ETSParser::ParseFunctionReturnType([[maybe_unused]] ParserStatus status)
1523 {
1524     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
1525         if ((status & ParserStatus::CONSTRUCTOR_FUNCTION) != 0U) {
1526             ThrowSyntaxError("Type annotation isn't allowed for constructor.");
1527         }
1528         Lexer()->NextToken();  // eat ':'
1529         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR |
1530                                                TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE |
1531                                                TypeAnnotationParsingOptions::RETURN_TYPE;
1532         return ParseTypeAnnotation(&options);
1533     }
1534 
1535     return nullptr;
1536 }
1537 
ParseFunctionThrowMarker(bool isRethrowsAllowed)1538 ir::ScriptFunctionFlags ETSParser::ParseFunctionThrowMarker(bool isRethrowsAllowed)
1539 {
1540     ir::ScriptFunctionFlags throwMarker = ir::ScriptFunctionFlags::NONE;
1541 
1542     if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
1543         if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_THROWS) {
1544             Lexer()->NextToken();  // eat 'throws'
1545             throwMarker = ir::ScriptFunctionFlags::THROWS;
1546         } else if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_RETHROWS) {
1547             if (isRethrowsAllowed) {
1548                 Lexer()->NextToken();  // eat 'rethrows'
1549                 throwMarker = ir::ScriptFunctionFlags::RETHROWS;
1550             } else {
1551                 ThrowSyntaxError("Only 'throws' can be used with function types");
1552             }
1553         }
1554     }
1555 
1556     return throwMarker;
1557 }
1558 
ValidateLabeledStatement(lexer::TokenType type)1559 void ETSParser::ValidateLabeledStatement(lexer::TokenType type)
1560 {
1561     if (type != lexer::TokenType::KEYW_DO && type != lexer::TokenType::KEYW_WHILE &&
1562         type != lexer::TokenType::KEYW_FOR && type != lexer::TokenType::KEYW_SWITCH) {
1563         ThrowSyntaxError("Label must be followed by a loop statement", Lexer()->GetToken().Start());
1564     }
1565 }
1566 
ParseInnerTypeDeclaration(ir::ModifierFlags memberModifiers,lexer::LexerPosition savedPos,bool isStepToken,bool seenStatic)1567 ir::AstNode *ETSParser::ParseInnerTypeDeclaration(ir::ModifierFlags memberModifiers, lexer::LexerPosition savedPos,
1568                                                   bool isStepToken, bool seenStatic)
1569 {
1570     if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) == 0) {
1571         ThrowSyntaxError("Local type declaration (class, struct, interface and enum) support is not yet implemented.");
1572     }
1573 
1574     // remove saved_pos nolint
1575     Lexer()->Rewind(savedPos);
1576     if (isStepToken) {
1577         Lexer()->NextToken();
1578     }
1579 
1580     Lexer()->GetToken().SetTokenType(Lexer()->GetToken().KeywordType());
1581     ir::AstNode *typeDecl = ParseTypeDeclaration(true);
1582     memberModifiers &= (ir::ModifierFlags::PUBLIC | ir::ModifierFlags::PROTECTED | ir::ModifierFlags::PRIVATE |
1583                         ir::ModifierFlags::INTERNAL);
1584     typeDecl->AddModifier(memberModifiers);
1585 
1586     if (!seenStatic) {
1587         if (typeDecl->IsClassDeclaration()) {
1588             typeDecl->AsClassDeclaration()->Definition()->AsClassDefinition()->SetInnerModifier();
1589         } else if (typeDecl->IsETSStructDeclaration()) {
1590             typeDecl->AsETSStructDeclaration()->Definition()->AsClassDefinition()->SetInnerModifier();
1591         }
1592     }
1593 
1594     return typeDecl;
1595 }
1596 
ParseInnerConstructorDeclaration(ir::ModifierFlags memberModifiers,const lexer::SourcePosition & startLoc)1597 ir::AstNode *ETSParser::ParseInnerConstructorDeclaration(ir::ModifierFlags memberModifiers,
1598                                                          const lexer::SourcePosition &startLoc)
1599 {
1600     if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) != 0) {
1601         ThrowSyntaxError({"Namespaces should not have a constructor"});
1602     }
1603     if ((memberModifiers & ir::ModifierFlags::ASYNC) != 0) {
1604         ThrowSyntaxError({"Constructor should not be async."});
1605     }
1606     auto *memberName = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
1607     memberModifiers |= ir::ModifierFlags::CONSTRUCTOR;
1608     Lexer()->NextToken();
1609     auto *classMethod = ParseClassMethodDefinition(memberName, memberModifiers);
1610     classMethod->SetStart(startLoc);
1611 
1612     return classMethod;
1613 }
1614 
ParseInnerRest(const ArenaVector<ir::AstNode * > & properties,ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags memberModifiers,ir::Identifier * identNode,const lexer::SourcePosition & startLoc)1615 ir::AstNode *ETSParser::ParseInnerRest(const ArenaVector<ir::AstNode *> &properties,
1616                                        ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags memberModifiers,
1617                                        ir::Identifier *identNode, const lexer::SourcePosition &startLoc)
1618 {
1619     if (Lexer()->Lookahead() != lexer::LEX_CHAR_LEFT_PAREN && Lexer()->Lookahead() != lexer::LEX_CHAR_LESS_THAN &&
1620         (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_GET ||
1621          Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_SET)) {
1622         return ParseClassGetterSetterMethod(properties, modifiers, memberModifiers);
1623     }
1624 
1625     if ((GetContext().Status() & ParserStatus::IN_NAMESPACE) != 0) {
1626         auto type = Lexer()->GetToken().Type();
1627         if (type == lexer::TokenType::KEYW_FUNCTION || type == lexer::TokenType::KEYW_LET ||
1628             type == lexer::TokenType::KEYW_CONST) {
1629             Lexer()->NextToken();
1630         }
1631     }
1632 
1633     auto *memberName = ExpectIdentifier();
1634 
1635     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS ||
1636         Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1637         auto *classMethod = ParseClassMethodDefinition(memberName, memberModifiers, nullptr, identNode);
1638         classMethod->SetStart(startLoc);
1639         return classMethod;
1640     }
1641 
1642     ArenaVector<ir::AstNode *> fieldDeclarations(Allocator()->Adapter());
1643     auto *placeholder = AllocNode<ir::TSInterfaceBody>(std::move(fieldDeclarations));
1644     ParseClassFieldDefinition(memberName, memberModifiers, placeholder->BodyPtr());
1645     return placeholder;
1646 }
1647 
1648 // NOLINTNEXTLINE(google-default-arguments)
ParseClassElement(const ArenaVector<ir::AstNode * > & properties,ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags,ir::Identifier * identNode)1649 ir::AstNode *ETSParser::ParseClassElement([[maybe_unused]] const ArenaVector<ir::AstNode *> &properties,
1650                                           [[maybe_unused]] ir::ClassDefinitionModifiers modifiers,
1651                                           [[maybe_unused]] ir::ModifierFlags flags,
1652                                           [[maybe_unused]] ir::Identifier *identNode)
1653 {
1654     auto startLoc = Lexer()->GetToken().Start();
1655     auto savedPos = Lexer()->Save();  // NOLINT(clang-analyzer-deadcode.DeadStores)
1656 
1657     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STATIC &&
1658         Lexer()->Lookahead() == lexer::LEX_CHAR_LEFT_BRACE) {
1659         return ParseClassStaticBlock();
1660     }
1661 
1662     auto [memberModifiers, isStepToken] = ParseClassMemberAccessModifiers();
1663 
1664     if (InAmbientContext()) {
1665         memberModifiers |= ir::ModifierFlags::DECLARE;
1666     }
1667 
1668     bool seenStatic = false;
1669     char32_t nextCp = Lexer()->Lookahead();
1670     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STATIC && nextCp != lexer::LEX_CHAR_EQUALS &&
1671         nextCp != lexer::LEX_CHAR_COLON && nextCp != lexer::LEX_CHAR_LEFT_PAREN &&
1672         nextCp != lexer::LEX_CHAR_LESS_THAN) {
1673         Lexer()->NextToken();
1674         memberModifiers |= ir::ModifierFlags::STATIC;
1675         seenStatic = true;
1676     }
1677 
1678     if (IsClassFieldModifier(Lexer()->GetToken().KeywordType())) {
1679         memberModifiers |= ParseClassFieldModifiers(seenStatic);
1680     } else if (IsClassMethodModifier(Lexer()->GetToken().Type())) {
1681         memberModifiers |= ParseClassMethodModifiers(seenStatic);
1682     }
1683 
1684     switch (Lexer()->GetToken().Type()) {
1685         case lexer::TokenType::KEYW_INTERFACE:
1686         case lexer::TokenType::KEYW_CLASS:
1687         case lexer::TokenType::KEYW_ENUM: {
1688             return ParseInnerTypeDeclaration(memberModifiers, savedPos, isStepToken, seenStatic);
1689         }
1690         case lexer::TokenType::KEYW_CONSTRUCTOR: {
1691             return ParseInnerConstructorDeclaration(memberModifiers, startLoc);
1692         }
1693         case lexer::TokenType::KEYW_PUBLIC:
1694         case lexer::TokenType::KEYW_PRIVATE:
1695         case lexer::TokenType::KEYW_PROTECTED: {
1696             ThrowSyntaxError("Access modifier must precede field and method modifiers.");
1697             break;
1698         }
1699         default: {
1700             break;
1701         }
1702     }
1703 
1704     return ParseInnerRest(properties, modifiers, memberModifiers, identNode, startLoc);
1705 }
1706 
ParseClassGetterSetterMethod(const ArenaVector<ir::AstNode * > & properties,const ir::ClassDefinitionModifiers modifiers,const ir::ModifierFlags memberModifiers)1707 ir::MethodDefinition *ETSParser::ParseClassGetterSetterMethod(const ArenaVector<ir::AstNode *> &properties,
1708                                                               const ir::ClassDefinitionModifiers modifiers,
1709                                                               const ir::ModifierFlags memberModifiers)
1710 {
1711     ClassElementDescriptor desc(Allocator());
1712     desc.methodKind = Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_GET ? ir::MethodDefinitionKind::GET
1713                                                                                       : ir::MethodDefinitionKind::SET;
1714     Lexer()->NextToken();  // eat get/set
1715     auto *methodName = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
1716     if (desc.methodKind == ir::MethodDefinitionKind::GET) {
1717         methodName->SetAccessor();
1718     } else {
1719         methodName->SetMutator();
1720     }
1721 
1722     Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);
1723 
1724     desc.newStatus = ParserStatus::ALLOW_SUPER;
1725     desc.hasSuperClass = (modifiers & ir::ClassDefinitionModifiers::HAS_SUPER) != 0U;
1726     desc.propStart = Lexer()->GetToken().Start();
1727     desc.modifiers = memberModifiers;
1728 
1729     lexer::SourcePosition propEnd = methodName->End();
1730     ir::MethodDefinition *method = ParseClassMethod(&desc, properties, methodName, &propEnd);
1731     method->Function()->SetIdent(methodName);
1732     method->Function()->AddModifier(desc.modifiers);
1733     method->SetRange({desc.propStart, propEnd});
1734     if (desc.methodKind == ir::MethodDefinitionKind::GET) {
1735         method->Function()->AddFlag(ir::ScriptFunctionFlags::GETTER);
1736     } else {
1737         method->Function()->AddFlag(ir::ScriptFunctionFlags::SETTER);
1738     }
1739 
1740     return method;
1741 }
1742 
ParseInterfaceGetterSetterMethod(const ir::ModifierFlags modifiers)1743 ir::MethodDefinition *ETSParser::ParseInterfaceGetterSetterMethod(const ir::ModifierFlags modifiers)
1744 {
1745     auto methodKind = Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_GET ? ir::MethodDefinitionKind::GET
1746                                                                                       : ir::MethodDefinitionKind::SET;
1747     Lexer()->NextToken();  // eat get/set
1748     ir::MethodDefinition *method = ParseInterfaceMethod(modifiers, methodKind);
1749     method->SetRange({Lexer()->GetToken().Start(), method->Id()->End()});
1750     if (methodKind == ir::MethodDefinitionKind::GET) {
1751         method->Id()->SetAccessor();
1752         method->Function()->AddFlag(ir::ScriptFunctionFlags::GETTER);
1753     } else {
1754         method->Id()->SetMutator();
1755         method->Function()->AddFlag(ir::ScriptFunctionFlags::SETTER);
1756     }
1757 
1758     method->Function()->SetIdent(method->Id());
1759     method->Function()->AddModifier(method->Modifiers());
1760 
1761     return method;
1762 }
1763 
ParseTypeDeclarationAbstractFinal(bool allowStatic,ir::ClassDefinitionModifiers modifiers)1764 ir::Statement *ETSParser::ParseTypeDeclarationAbstractFinal(bool allowStatic, ir::ClassDefinitionModifiers modifiers)
1765 {
1766     auto flags = ParseClassModifiers();
1767     if (allowStatic && (flags & ir::ModifierFlags::STATIC) == 0U) {
1768         modifiers |= ir::ClassDefinitionModifiers::INNER;
1769     }
1770 
1771     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS) {
1772         return ParseClassDeclaration(modifiers, flags);
1773     }
1774 
1775     if (IsStructKeyword()) {
1776         return ParseStructDeclaration(modifiers, flags);
1777     }
1778 
1779     ThrowUnexpectedToken(Lexer()->GetToken().Type());
1780 }
1781 
ParseTypeDeclaration(bool allowStatic)1782 ir::Statement *ETSParser::ParseTypeDeclaration(bool allowStatic)
1783 {
1784     auto savedPos = Lexer()->Save();
1785 
1786     auto modifiers = ir::ClassDefinitionModifiers::ID_REQUIRED | ir::ClassDefinitionModifiers::CLASS_DECL;
1787 
1788     auto tokenType = Lexer()->GetToken().Type();
1789     switch (tokenType) {
1790         case lexer::TokenType::KEYW_STATIC: {
1791             if (!allowStatic) {
1792                 ThrowUnexpectedToken(Lexer()->GetToken().Type());
1793             }
1794 
1795             Lexer()->NextToken();
1796 
1797             if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_INTERFACE) {
1798                 return ParseInterfaceDeclaration(true);
1799             }
1800 
1801             Lexer()->Rewind(savedPos);
1802             [[fallthrough]];
1803         }
1804         case lexer::TokenType::KEYW_ABSTRACT:
1805         case lexer::TokenType::KEYW_FINAL: {
1806             return ParseTypeDeclarationAbstractFinal(allowStatic, modifiers);
1807         }
1808         case lexer::TokenType::KEYW_ENUM: {
1809             return ParseEnumDeclaration(false);
1810         }
1811         case lexer::TokenType::KEYW_INTERFACE: {
1812             return ParseInterfaceDeclaration(false);
1813         }
1814         case lexer::TokenType::KEYW_NAMESPACE: {
1815             if (!InAmbientContext()) {
1816                 ThrowSyntaxError("Namespaces are declare only");
1817             }
1818             GetContext().Status() |= ParserStatus::IN_NAMESPACE;
1819             auto *ns = ParseClassDeclaration(modifiers, ir::ModifierFlags::STATIC);
1820             GetContext().Status() &= ~ParserStatus::IN_NAMESPACE;
1821             return ns;
1822         }
1823         case lexer::TokenType::KEYW_CLASS: {
1824             return ParseClassDeclaration(modifiers);
1825         }
1826         case lexer::TokenType::KEYW_TYPE: {
1827             return ParseTypeAliasDeclaration();
1828         }
1829         case lexer::TokenType::LITERAL_IDENT: {
1830             if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STRUCT) {
1831                 return ParseStructDeclaration(modifiers);
1832             }
1833             [[fallthrough]];
1834         }
1835         case lexer::TokenType::LITERAL_NUMBER:
1836         case lexer::TokenType::LITERAL_NULL:
1837         case lexer::TokenType::KEYW_UNDEFINED:
1838         case lexer::TokenType::LITERAL_STRING:
1839         case lexer::TokenType::LITERAL_FALSE:
1840         case lexer::TokenType::LITERAL_TRUE:
1841         case lexer::TokenType::LITERAL_CHAR: {
1842             std::string errMsg("Cannot used in global scope '");
1843 
1844             std::string text = tokenType == lexer::TokenType::LITERAL_CHAR
1845                                    ? util::Helpers::UTF16toUTF8(Lexer()->GetToken().Utf16())
1846                                    : Lexer()->GetToken().Ident().Mutf8();
1847 
1848             if ((Lexer()->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) == 0) {
1849                 errMsg.append(text);
1850             } else {
1851                 errMsg.append(util::Helpers::CreateEscapedString(text));
1852             }
1853 
1854             errMsg.append("'");
1855             ThrowSyntaxError(errMsg.c_str());
1856         }
1857         default: {
1858             ThrowUnexpectedToken(Lexer()->GetToken().Type());
1859         }
1860     }
1861 }
1862 
ParseTypeAliasDeclaration()1863 ir::TSTypeAliasDeclaration *ETSParser::ParseTypeAliasDeclaration()
1864 {
1865     ASSERT(Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPE);
1866 
1867     if ((GetContext().Status() & parser::ParserStatus::FUNCTION) != 0U) {
1868         ThrowSyntaxError("Type alias is allowed only as top-level declaration");
1869     }
1870 
1871     lexer::SourcePosition typeStart = Lexer()->GetToken().Start();
1872     Lexer()->NextToken();  // eat type keyword
1873 
1874     if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
1875         ThrowSyntaxError("Identifier expected");
1876     }
1877 
1878     if (Lexer()->GetToken().IsReservedTypeName()) {
1879         std::string errMsg("Type alias name cannot be '");
1880         errMsg.append(TokenToString(Lexer()->GetToken().KeywordType()));
1881         errMsg.append("'");
1882         ThrowSyntaxError(errMsg.c_str());
1883     }
1884 
1885     const util::StringView ident = Lexer()->GetToken().Ident();
1886     auto *id = AllocNode<ir::Identifier>(ident, Allocator());
1887     id->SetRange(Lexer()->GetToken().Loc());
1888 
1889     auto *typeAliasDecl = AllocNode<ir::TSTypeAliasDeclaration>(Allocator(), id);
1890 
1891     Lexer()->NextToken();  // eat alias name
1892 
1893     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1894         auto options =
1895             TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::ALLOW_DECLARATION_SITE_VARIANCE;
1896         ir::TSTypeParameterDeclaration *params = ParseTypeParameterDeclaration(&options);
1897         typeAliasDecl->SetTypeParameters(params);
1898         params->SetParent(typeAliasDecl);
1899     }
1900 
1901     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
1902         ThrowSyntaxError("'=' expected");
1903     }
1904 
1905     Lexer()->NextToken();  // eat '='
1906 
1907     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
1908     ir::TypeNode *typeAnnotation = ParseTypeAnnotation(&options);
1909     typeAliasDecl->SetTsTypeAnnotation(typeAnnotation);
1910     typeAliasDecl->SetRange({typeStart, Lexer()->GetToken().End()});
1911     typeAnnotation->SetParent(typeAliasDecl);
1912 
1913     return typeAliasDecl;
1914 }
1915 
ParseInterfaceBody(ir::Identifier * name,bool isStatic)1916 ir::TSInterfaceDeclaration *ETSParser::ParseInterfaceBody(ir::Identifier *name, bool isStatic)
1917 {
1918     GetContext().Status() |= ParserStatus::ALLOW_THIS_TYPE;
1919 
1920     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
1921     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
1922         auto options =
1923             TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::ALLOW_DECLARATION_SITE_VARIANCE;
1924         typeParamDecl = ParseTypeParameterDeclaration(&options);
1925     }
1926 
1927     ArenaVector<ir::TSInterfaceHeritage *> extends(Allocator()->Adapter());
1928     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
1929         extends = ParseInterfaceExtendsClause();
1930     }
1931 
1932     lexer::SourcePosition bodyStart = Lexer()->GetToken().Start();
1933     auto members = ParseTypeLiteralOrInterface();
1934 
1935     for (auto &member : members) {
1936         if (member->Type() == ir::AstNodeType::CLASS_DECLARATION ||
1937             member->Type() == ir::AstNodeType::STRUCT_DECLARATION ||
1938             member->Type() == ir::AstNodeType::TS_ENUM_DECLARATION ||
1939             member->Type() == ir::AstNodeType::TS_INTERFACE_DECLARATION) {
1940             ThrowSyntaxError(
1941                 "Local type declaration (class, struct, interface and enum) support is not yet implemented.");
1942         }
1943     }
1944 
1945     auto *body = AllocNode<ir::TSInterfaceBody>(std::move(members));
1946     body->SetRange({bodyStart, Lexer()->GetToken().End()});
1947 
1948     const auto isExternal = (GetContext().Status() & ParserStatus::IN_EXTERNAL);
1949     auto *interfaceDecl = AllocNode<ir::TSInterfaceDeclaration>(
1950         Allocator(), name, typeParamDecl, body, std::move(extends), isStatic, isExternal, GetContext().GetLanguge());
1951 
1952     Lexer()->NextToken();
1953     GetContext().Status() &= ~ParserStatus::ALLOW_THIS_TYPE;
1954 
1955     return interfaceDecl;
1956 }
1957 
ParseInterfaceDeclaration(bool isStatic)1958 ir::Statement *ETSParser::ParseInterfaceDeclaration(bool isStatic)
1959 {
1960     if ((GetContext().Status() & parser::ParserStatus::FUNCTION) != 0U) {
1961         ThrowSyntaxError("Local interface declaration support is not yet implemented.");
1962     }
1963 
1964     lexer::SourcePosition interfaceStart = Lexer()->GetToken().Start();
1965     Lexer()->NextToken();  // eat interface keyword
1966 
1967     auto *id = ExpectIdentifier(false, true);
1968 
1969     auto *declNode = ParseInterfaceBody(id, isStatic);
1970 
1971     declNode->SetRange({interfaceStart, Lexer()->GetToken().End()});
1972     return declNode;
1973 }
1974 
1975 // NOLINTNEXTLINE(google-default-arguments)
ParseEnumDeclaration(bool isConst,bool isStatic)1976 ir::Statement *ETSParser::ParseEnumDeclaration(bool isConst, bool isStatic)
1977 {
1978     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_ENUM);
1979 
1980     if ((GetContext().Status() & parser::ParserStatus::FUNCTION) != 0U) {
1981         ThrowSyntaxError("Local enum declaration support is not yet implemented.");
1982     }
1983 
1984     lexer::SourcePosition enumStart = Lexer()->GetToken().Start();
1985     Lexer()->NextToken();  // eat enum keyword
1986 
1987     auto *key = ExpectIdentifier(false, true);
1988 
1989     auto *declNode = ParseEnumMembers(key, enumStart, isConst, isStatic);
1990 
1991     return declNode;
1992 }
1993 
ParseLaunchExpression(ExpressionParseFlags flags)1994 ir::Expression *ETSParser::ParseLaunchExpression(ExpressionParseFlags flags)
1995 {
1996     lexer::SourcePosition start = Lexer()->GetToken().Start();
1997     Lexer()->NextToken();  // eat launch
1998 
1999     ir::Expression *expr = ParseLeftHandSideExpression(flags);
2000     if (!expr->IsCallExpression()) {
2001         ThrowSyntaxError("Only call expressions are allowed after 'launch'", expr->Start());
2002     }
2003     auto call = expr->AsCallExpression();
2004     auto *launchExpression = AllocNode<ir::ETSLaunchExpression>(call);
2005     launchExpression->SetRange({start, call->End()});
2006 
2007     return launchExpression;
2008 }
2009 
2010 // NOLINTNEXTLINE(google-default-arguments)
ParseClassDefinition(ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags flags)2011 ir::ClassDefinition *ETSParser::ParseClassDefinition(ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags flags)
2012 {
2013     Lexer()->NextToken();
2014 
2015     ir::Identifier *identNode = ParseClassIdent(modifiers);
2016 
2017     ir::TSTypeParameterDeclaration *typeParamDecl = nullptr;
2018     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
2019         auto options =
2020             TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::ALLOW_DECLARATION_SITE_VARIANCE;
2021         typeParamDecl = ParseTypeParameterDeclaration(&options);
2022     }
2023 
2024     // Parse SuperClass
2025     auto [superClass, superTypeParams] = ParseSuperClass();
2026 
2027     if (superClass != nullptr) {
2028         modifiers |= ir::ClassDefinitionModifiers::HAS_SUPER;
2029         GetContext().Status() |= ParserStatus::ALLOW_SUPER;
2030     }
2031 
2032     if (InAmbientContext()) {
2033         flags |= ir::ModifierFlags::DECLARE;
2034     }
2035 
2036     // Parse implements clause
2037     ArenaVector<ir::TSClassImplements *> implements(Allocator()->Adapter());
2038     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_IMPLEMENTS) {
2039         Lexer()->NextToken();
2040         implements = ParseClassImplementClause();
2041     }
2042 
2043     ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE, false);
2044 
2045     // Parse ClassBody
2046     auto [ctor, properties, bodyRange] = ParseClassBody(modifiers, flags, identNode);
2047     CreateCCtor(properties, bodyRange.start);
2048 
2049     auto *classDefinition = AllocNode<ir::ClassDefinition>(
2050         util::StringView(), identNode, typeParamDecl, superTypeParams, std::move(implements), ctor, superClass,
2051         std::move(properties), modifiers, flags, GetContext().GetLanguge());
2052 
2053     classDefinition->SetRange(bodyRange);
2054 
2055     GetContext().Status() &= ~ParserStatus::ALLOW_SUPER;
2056 
2057     return classDefinition;
2058 }
2059 
IsInterfaceMethodModifier(lexer::TokenType type)2060 static bool IsInterfaceMethodModifier(lexer::TokenType type)
2061 {
2062     return type == lexer::TokenType::KEYW_STATIC || type == lexer::TokenType::KEYW_PRIVATE;
2063 }
2064 
ParseInterfaceMethodModifiers()2065 ir::ModifierFlags ETSParser::ParseInterfaceMethodModifiers()
2066 {
2067     ir::ModifierFlags flags = ir::ModifierFlags::NONE;
2068 
2069     while (IsInterfaceMethodModifier(Lexer()->GetToken().Type())) {
2070         ir::ModifierFlags currentFlag = ir::ModifierFlags::NONE;
2071 
2072         switch (Lexer()->GetToken().Type()) {
2073             case lexer::TokenType::KEYW_STATIC: {
2074                 currentFlag = ir::ModifierFlags::STATIC;
2075                 break;
2076             }
2077             case lexer::TokenType::KEYW_PRIVATE: {
2078                 currentFlag = ir::ModifierFlags::PRIVATE;
2079                 break;
2080             }
2081             default: {
2082                 UNREACHABLE();
2083             }
2084         }
2085 
2086         char32_t nextCp = Lexer()->Lookahead();
2087         if (nextCp == lexer::LEX_CHAR_COLON || nextCp == lexer::LEX_CHAR_LEFT_PAREN ||
2088             nextCp == lexer::LEX_CHAR_EQUALS) {
2089             break;
2090         }
2091 
2092         if ((flags & currentFlag) != 0) {
2093             ThrowSyntaxError("Duplicated modifier is not allowed");
2094         }
2095 
2096         Lexer()->NextToken();
2097         flags |= currentFlag;
2098     }
2099 
2100     return flags;
2101 }
2102 
ParseInterfaceField()2103 ir::ClassProperty *ETSParser::ParseInterfaceField()
2104 {
2105     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT);
2106     auto *name = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
2107     name->SetRange(Lexer()->GetToken().Loc());
2108     Lexer()->NextToken();
2109 
2110     ir::TypeNode *typeAnnotation = nullptr;
2111     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COLON) {
2112         ThrowSyntaxError("Interface fields must have typeannotation.");
2113     }
2114     Lexer()->NextToken();  // eat ':'
2115     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
2116     typeAnnotation = ParseTypeAnnotation(&options);
2117 
2118     name->SetTsTypeAnnotation(typeAnnotation);
2119 
2120     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EQUAL) {
2121         ThrowSyntaxError("Initializers are not allowed on interface propertys.");
2122     }
2123 
2124     ir::ModifierFlags fieldModifiers = ir::ModifierFlags::PUBLIC;
2125 
2126     if (InAmbientContext()) {
2127         fieldModifiers |= ir::ModifierFlags::DECLARE;
2128     }
2129 
2130     auto *field = AllocNode<ir::ClassProperty>(name, nullptr, typeAnnotation, fieldModifiers, Allocator(), false);
2131     field->SetEnd(Lexer()->GetToken().End());
2132 
2133     return field;
2134 }
2135 
ParseInterfaceMethod(ir::ModifierFlags flags,ir::MethodDefinitionKind methodKind)2136 ir::MethodDefinition *ETSParser::ParseInterfaceMethod(ir::ModifierFlags flags, ir::MethodDefinitionKind methodKind)
2137 {
2138     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT);
2139     auto *name = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
2140     name->SetRange(Lexer()->GetToken().Loc());
2141     Lexer()->NextToken();
2142 
2143     FunctionContext functionContext(this, ParserStatus::FUNCTION);
2144 
2145     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
2146 
2147     auto [signature, throwMarker] = ParseFunctionSignature(ParserStatus::NEED_RETURN_TYPE);
2148 
2149     ir::BlockStatement *body = nullptr;
2150 
2151     bool isDeclare = InAmbientContext();
2152     if (isDeclare) {
2153         flags |= ir::ModifierFlags::DECLARE;
2154     }
2155 
2156     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
2157         if (methodKind == ir::MethodDefinitionKind::SET || methodKind == ir::MethodDefinitionKind::GET) {
2158             ThrowSyntaxError("Getter and setter methods must be abstracts in the interface body", startLoc);
2159         }
2160         body = ParseBlockStatement();
2161     } else if ((flags & (ir::ModifierFlags::PRIVATE | ir::ModifierFlags::STATIC)) != 0 && !isDeclare) {
2162         ThrowSyntaxError("Private or static interface methods must have body", startLoc);
2163     }
2164 
2165     functionContext.AddFlag(throwMarker);
2166 
2167     auto *func = AllocNode<ir::ScriptFunction>(std::move(signature), body, functionContext.Flags(), flags, true,
2168                                                GetContext().GetLanguge());
2169 
2170     if ((flags & ir::ModifierFlags::STATIC) == 0 && body == nullptr) {
2171         func->AddModifier(ir::ModifierFlags::ABSTRACT);
2172     }
2173     func->SetRange({startLoc, body != nullptr                           ? body->End()
2174                               : func->ReturnTypeAnnotation() != nullptr ? func->ReturnTypeAnnotation()->End()
2175                                                                         : (*func->Params().end())->End()});
2176 
2177     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
2178     funcExpr->SetRange(func->Range());
2179     func->AddFlag(ir::ScriptFunctionFlags::METHOD);
2180 
2181     func->SetIdent(name);
2182     auto *method =
2183         AllocNode<ir::MethodDefinition>(ir::MethodDefinitionKind::METHOD, name, funcExpr, flags, Allocator(), false);
2184     method->SetRange(funcExpr->Range());
2185 
2186     ConsumeSemicolon(method);
2187 
2188     return method;
2189 }
2190 
CheckDefaultParameters(const ir::ScriptFunction * const function) const2191 std::pair<bool, std::size_t> ETSParser::CheckDefaultParameters(const ir::ScriptFunction *const function) const
2192 {
2193     bool hasDefaultParameter = false;
2194     bool hasRestParameter = false;
2195     std::size_t requiredParametersNumber = 0U;
2196 
2197     for (auto *const it : function->Params()) {
2198         auto const *const param = it->AsETSParameterExpression();
2199 
2200         if (param->IsRestParameter()) {
2201             hasRestParameter = true;
2202             continue;
2203         }
2204 
2205         if (hasRestParameter) {
2206             ThrowSyntaxError("Rest parameter should be the last one.", param->Start());
2207         }
2208 
2209         if (param->IsDefault()) {
2210             hasDefaultParameter = true;
2211             continue;
2212         }
2213 
2214         if (hasDefaultParameter) {
2215             ThrowSyntaxError("Required parameter follows default parameter(s).", param->Start());
2216         }
2217 
2218         ++requiredParametersNumber;
2219     }
2220 
2221     if (hasDefaultParameter && hasRestParameter) {
2222         ThrowSyntaxError("Both optional and rest parameters are not allowed in function's parameter list.",
2223                          function->Start());
2224     }
2225 
2226     return std::make_pair(hasDefaultParameter, requiredParametersNumber);
2227 }
2228 
CreateProxyConstructorDefinition(ir::MethodDefinition const * const method)2229 ir::MethodDefinition *ETSParser::CreateProxyConstructorDefinition(ir::MethodDefinition const *const method)
2230 {
2231     ASSERT(method->IsConstructor());
2232 
2233     const auto *const function = method->Function();
2234     std::string proxyMethod = function->Id()->Name().Mutf8() + '(';
2235 
2236     for (const auto *const it : function->Params()) {
2237         auto const *const param = it->AsETSParameterExpression();
2238         proxyMethod += param->Ident()->Name().Mutf8() + ": " + GetNameForTypeNode(param->TypeAnnotation()) + ", ";
2239     }
2240 
2241     proxyMethod += ir::PROXY_PARAMETER_NAME;
2242     proxyMethod += ": int) { this(";
2243 
2244     auto const parametersNumber = function->Params().size();
2245     for (size_t i = 0U; i < parametersNumber; ++i) {
2246         if (auto const *const param = function->Params()[i]->AsETSParameterExpression(); param->IsDefault()) {
2247             std::string proxyIf = "(((" + std::string {ir::PROXY_PARAMETER_NAME} + " >> " + std::to_string(i) +
2248                                   ") & 0x1) == 0) ? " + param->Ident()->Name().Mutf8() + " : (" +
2249                                   param->LexerSaved().Mutf8() + "), ";
2250             proxyMethod += proxyIf;
2251         } else {
2252             proxyMethod += function->Params()[i]->AsETSParameterExpression()->Ident()->Name().Mutf8() + ", ";
2253         }
2254     }
2255 
2256     proxyMethod.pop_back();  // Note: at least one parameter always should present!
2257     proxyMethod.pop_back();
2258     proxyMethod += ") }";
2259 
2260     return CreateConstructorDefinition(method->Modifiers(), proxyMethod, DEFAULT_PROXY_FILE);
2261 }
2262 
CreateProxyMethodDefinition(ir::MethodDefinition const * const method,ir::Identifier const * const identNode)2263 ir::MethodDefinition *ETSParser::CreateProxyMethodDefinition(ir::MethodDefinition const *const method,
2264                                                              ir::Identifier const *const identNode)
2265 {
2266     ASSERT(!method->IsConstructor());
2267 
2268     const auto *const function = method->Function();
2269     std::string proxyMethod = function->Id()->Name().Mutf8() + "_proxy(";
2270 
2271     for (const auto *const it : function->Params()) {
2272         auto const *const param = it->AsETSParameterExpression();
2273         proxyMethod += param->Ident()->Name().Mutf8() + ": " + GetNameForTypeNode(param->TypeAnnotation()) + ", ";
2274     }
2275 
2276     const bool hasFunctionReturnType = function->ReturnTypeAnnotation() != nullptr;
2277     const std::string returnType = hasFunctionReturnType ? GetNameForTypeNode(function->ReturnTypeAnnotation()) : "";
2278 
2279     proxyMethod += ir::PROXY_PARAMETER_NAME;
2280     proxyMethod += ": int)";
2281     if (hasFunctionReturnType) {
2282         proxyMethod += ": " + returnType;
2283     }
2284     proxyMethod += " { ";
2285 
2286     auto const parametersNumber = function->Params().size();
2287     for (size_t i = 0U; i < parametersNumber; ++i) {
2288         if (auto const *const param = function->Params()[i]->AsETSParameterExpression(); param->IsDefault()) {
2289             std::string proxyIf = "if (((" + std::string {ir::PROXY_PARAMETER_NAME} + " >> " + std::to_string(i) +
2290                                   ") & 0x1) == 1) { " + param->Ident()->Name().Mutf8() + " = " +
2291                                   param->LexerSaved().Mutf8() + " } ";
2292             proxyMethod += proxyIf;
2293         }
2294     }
2295 
2296     proxyMethod += ' ';
2297     if (returnType != "void") {
2298         proxyMethod += "return ";
2299     }
2300 
2301     if (identNode != nullptr) {
2302         if (method->IsStatic()) {
2303             ASSERT(identNode != nullptr);
2304             proxyMethod += identNode->Name().Mutf8() + ".";
2305         } else {
2306             proxyMethod += "this.";
2307         }
2308     }
2309 
2310     proxyMethod += function->Id()->Name().Mutf8();
2311     proxyMethod += '(';
2312 
2313     for (const auto *const it : function->Params()) {
2314         proxyMethod += it->AsETSParameterExpression()->Ident()->Name().Mutf8() + ", ";
2315     }
2316     proxyMethod.pop_back();
2317     proxyMethod.pop_back();
2318     proxyMethod += ") }";
2319 
2320     return CreateMethodDefinition(method->Modifiers(), proxyMethod, DEFAULT_PROXY_FILE);
2321 }
2322 
AddProxyOverloadToMethodWithDefaultParams(ir::MethodDefinition * method,ir::Identifier * identNode)2323 void ETSParser::AddProxyOverloadToMethodWithDefaultParams(ir::MethodDefinition *method, ir::Identifier *identNode)
2324 {
2325     if (auto const [has_default_parameters, required_parameters] = CheckDefaultParameters(method->Function());
2326         has_default_parameters) {
2327         if (ir::MethodDefinition *proxyMethodDef = !method->IsConstructor()
2328                                                        ? CreateProxyMethodDefinition(method, identNode)
2329                                                        : CreateProxyConstructorDefinition(method);
2330             proxyMethodDef != nullptr) {
2331             auto *const proxyParam = proxyMethodDef->Function()->Params().back()->AsETSParameterExpression();
2332             proxyParam->SetRequiredParams(required_parameters);
2333 
2334             proxyMethodDef->Function()->SetDefaultParamProxy();
2335             proxyMethodDef->Function()->AddFlag(ir::ScriptFunctionFlags::OVERLOAD);
2336             method->AddOverload(proxyMethodDef);
2337             proxyMethodDef->SetParent(method);
2338         }
2339     }
2340 }
2341 
PrimitiveTypeToName(ir::PrimitiveType type)2342 std::string ETSParser::PrimitiveTypeToName(ir::PrimitiveType type)
2343 {
2344     switch (type) {
2345         case ir::PrimitiveType::BYTE:
2346             return "byte";
2347         case ir::PrimitiveType::INT:
2348             return "int";
2349         case ir::PrimitiveType::LONG:
2350             return "long";
2351         case ir::PrimitiveType::SHORT:
2352             return "short";
2353         case ir::PrimitiveType::FLOAT:
2354             return "float";
2355         case ir::PrimitiveType::DOUBLE:
2356             return "double";
2357         case ir::PrimitiveType::BOOLEAN:
2358             return "boolean";
2359         case ir::PrimitiveType::CHAR:
2360             return "char";
2361         case ir::PrimitiveType::VOID:
2362             return "void";
2363         default:
2364             UNREACHABLE();
2365     }
2366 }
GetNameForETSUnionType(const ir::TypeNode * typeAnnotation) const2367 std::string ETSParser::GetNameForETSUnionType(const ir::TypeNode *typeAnnotation) const
2368 {
2369     ASSERT(typeAnnotation->IsETSUnionType());
2370     std::string newstr;
2371     for (size_t i = 0; i < typeAnnotation->AsETSUnionType()->Types().size(); i++) {
2372         auto type = typeAnnotation->AsETSUnionType()->Types()[i];
2373         if (type->IsNullAssignable() || type->IsUndefinedAssignable()) {
2374             continue;
2375         }
2376         std::string str = GetNameForTypeNode(type, false);
2377         newstr += str;
2378         if (i != typeAnnotation->AsETSUnionType()->Types().size() - 1) {
2379             newstr += "|";
2380         }
2381     }
2382     if (typeAnnotation->IsNullAssignable()) {
2383         newstr += "|null";
2384     }
2385     if (typeAnnotation->IsUndefinedAssignable()) {
2386         newstr += "|undefined";
2387     }
2388     return newstr;
2389 }
2390 
GetNameForTypeNode(const ir::TypeNode * typeAnnotation,bool adjust) const2391 std::string ETSParser::GetNameForTypeNode(const ir::TypeNode *typeAnnotation, bool adjust) const
2392 {
2393     if (typeAnnotation->IsETSUnionType()) {
2394         return GetNameForETSUnionType(typeAnnotation);
2395     }
2396 
2397     const auto adjustNullish = [typeAnnotation, adjust](std::string const &s) {
2398         std::string newstr = s;
2399         if (typeAnnotation->IsNullAssignable() && adjust) {
2400             newstr += "|null";
2401         }
2402         if (typeAnnotation->IsUndefinedAssignable() && adjust) {
2403             newstr += "|undefined";
2404         }
2405         return newstr;
2406     };
2407 
2408     if (typeAnnotation->IsETSPrimitiveType()) {
2409         return adjustNullish(PrimitiveTypeToName(typeAnnotation->AsETSPrimitiveType()->GetPrimitiveType()));
2410     }
2411 
2412     if (typeAnnotation->IsETSTypeReference()) {
2413         std::string typeParamNames;
2414         auto typeParam = typeAnnotation->AsETSTypeReference()->Part()->TypeParams();
2415         if (typeParam != nullptr && typeParam->IsTSTypeParameterInstantiation()) {
2416             typeParamNames = "<";
2417             auto paramList = typeParam->Params();
2418             for (auto param : paramList) {
2419                 std::string typeParamName = GetNameForTypeNode(param);
2420                 typeParamNames += typeParamName + ",";
2421             }
2422             typeParamNames.pop_back();
2423             typeParamNames += ">";
2424         }
2425         return adjustNullish(typeAnnotation->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Name().Mutf8() +
2426                              typeParamNames);
2427     }
2428 
2429     if (typeAnnotation->IsETSFunctionType()) {
2430         std::string lambdaParams = " ";
2431 
2432         for (const auto *const param : typeAnnotation->AsETSFunctionType()->Params()) {
2433             lambdaParams += param->AsETSParameterExpression()->Ident()->Name().Mutf8();
2434             lambdaParams += ":";
2435             lambdaParams += GetNameForTypeNode(param->AsETSParameterExpression()->Ident()->TypeAnnotation());
2436             lambdaParams += ",";
2437         }
2438 
2439         lambdaParams.pop_back();
2440         const std::string returnTypeName = GetNameForTypeNode(typeAnnotation->AsETSFunctionType()->ReturnType());
2441 
2442         return adjustNullish("((" + lambdaParams + ") => " + returnTypeName + ")");
2443     }
2444 
2445     if (typeAnnotation->IsTSArrayType()) {
2446         // Note! array is required for the rest parameter.
2447         return GetNameForTypeNode(typeAnnotation->AsTSArrayType()->ElementType()) + "[]";
2448     }
2449 
2450     UNREACHABLE();
2451 }
2452 
ValidateRestParameter(ir::Expression * param)2453 void ETSParser::ValidateRestParameter(ir::Expression *param)
2454 {
2455     if (param->IsETSParameterExpression()) {
2456         if (param->AsETSParameterExpression()->IsRestParameter()) {
2457             GetContext().Status() |= ParserStatus::HAS_COMPLEX_PARAM;
2458 
2459             if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
2460                 ThrowSyntaxError("Rest parameter must be the last formal parameter.");
2461             }
2462         }
2463     }
2464 }
2465 
ParseTypeLiteralOrInterfaceMember()2466 ir::AstNode *ETSParser::ParseTypeLiteralOrInterfaceMember()
2467 {
2468     auto startLoc = Lexer()->GetToken().Start();
2469     ir::ModifierFlags methodFlags = ParseInterfaceMethodModifiers();
2470     if (methodFlags != ir::ModifierFlags::NONE) {
2471         if ((methodFlags & ir::ModifierFlags::PRIVATE) == 0) {
2472             methodFlags |= ir::ModifierFlags::PUBLIC;
2473         }
2474 
2475         auto *method = ParseInterfaceMethod(methodFlags, ir::MethodDefinitionKind::METHOD);
2476         method->SetStart(startLoc);
2477         return method;
2478     }
2479 
2480     if (Lexer()->Lookahead() != lexer::LEX_CHAR_LEFT_PAREN && Lexer()->Lookahead() != lexer::LEX_CHAR_LESS_THAN &&
2481         (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_GET ||
2482          Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_SET)) {
2483         return ParseInterfaceGetterSetterMethod(methodFlags);
2484     }
2485 
2486     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_READONLY) {
2487         Lexer()->NextToken();  // eat 'readonly' keyword
2488         auto *field = ParseInterfaceField();
2489         field->SetStart(startLoc);
2490         field->AddModifier(ir::ModifierFlags::READONLY);
2491         return field;
2492     }
2493 
2494     if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
2495         char32_t nextCp = Lexer()->Lookahead();
2496         if (nextCp == lexer::LEX_CHAR_LEFT_PAREN || nextCp == lexer::LEX_CHAR_LESS_THAN) {
2497             auto *method = ParseInterfaceMethod(ir::ModifierFlags::PUBLIC, ir::MethodDefinitionKind::METHOD);
2498             method->SetStart(startLoc);
2499             return method;
2500         }
2501 
2502         auto *field = ParseInterfaceField();
2503         field->SetStart(startLoc);
2504         return field;
2505     }
2506 
2507     return ParseTypeDeclaration(true);
2508 }
2509 
ParseTypeReferencePart(TypeAnnotationParsingOptions * options)2510 std::tuple<ir::Expression *, ir::TSTypeParameterInstantiation *> ETSParser::ParseTypeReferencePart(
2511     TypeAnnotationParsingOptions *options)
2512 {
2513     ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS;
2514 
2515     if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL) != 0) {
2516         flags |= ExpressionParseFlags::POTENTIAL_CLASS_LITERAL;
2517     }
2518 
2519     auto *typeName = ParseQualifiedName(flags);
2520     if (typeName == nullptr) {
2521         return {nullptr, nullptr};
2522     }
2523 
2524     if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL) != 0 &&
2525         (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS || IsStructKeyword())) {
2526         return {typeName, nullptr};
2527     }
2528 
2529     ir::TSTypeParameterInstantiation *typeParamInst = nullptr;
2530     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT ||
2531         Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
2532         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
2533             Lexer()->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
2534         }
2535         *options |= TypeAnnotationParsingOptions::ALLOW_WILDCARD;
2536         typeParamInst = ParseTypeParameterInstantiation(options);
2537         *options &= ~TypeAnnotationParsingOptions::ALLOW_WILDCARD;
2538     }
2539 
2540     return {typeName, typeParamInst};
2541 }
2542 
ParseTypeReference(TypeAnnotationParsingOptions * options)2543 ir::TypeNode *ETSParser::ParseTypeReference(TypeAnnotationParsingOptions *options)
2544 {
2545     auto startPos = Lexer()->GetToken().Start();
2546     ir::ETSTypeReferencePart *typeRefPart = nullptr;
2547 
2548     while (true) {
2549         auto partPos = Lexer()->GetToken().Start();
2550         auto [typeName, typeParams] = ParseTypeReferencePart(options);
2551         if (typeName == nullptr) {
2552             return nullptr;
2553         }
2554 
2555         typeRefPart = AllocNode<ir::ETSTypeReferencePart>(typeName, typeParams, typeRefPart);
2556         typeRefPart->SetRange({partPos, Lexer()->GetToken().End()});
2557 
2558         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_PERIOD) {
2559             break;
2560         }
2561 
2562         Lexer()->NextToken();
2563 
2564         if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL) != 0 &&
2565             (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS || IsStructKeyword())) {
2566             break;
2567         }
2568     }
2569 
2570     auto *typeReference = AllocNode<ir::ETSTypeReference>(typeRefPart);
2571     typeReference->SetRange({startPos, Lexer()->GetToken().End()});
2572     return typeReference;
2573 }
2574 
ParseBaseTypeReference(TypeAnnotationParsingOptions * options)2575 ir::TypeNode *ETSParser::ParseBaseTypeReference(TypeAnnotationParsingOptions *options)
2576 {
2577     ir::TypeNode *typeAnnotation = nullptr;
2578 
2579     switch (Lexer()->GetToken().KeywordType()) {
2580         case lexer::TokenType::KEYW_BOOLEAN: {
2581             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::BOOLEAN);
2582             break;
2583         }
2584         case lexer::TokenType::KEYW_BYTE: {
2585             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::BYTE);
2586             break;
2587         }
2588         case lexer::TokenType::KEYW_CHAR: {
2589             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::CHAR);
2590             break;
2591         }
2592         case lexer::TokenType::KEYW_DOUBLE: {
2593             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::DOUBLE);
2594             break;
2595         }
2596         case lexer::TokenType::KEYW_FLOAT: {
2597             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::FLOAT);
2598             break;
2599         }
2600         case lexer::TokenType::KEYW_INT: {
2601             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::INT);
2602             break;
2603         }
2604         case lexer::TokenType::KEYW_LONG: {
2605             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::LONG);
2606             break;
2607         }
2608         case lexer::TokenType::KEYW_SHORT: {
2609             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::SHORT);
2610             break;
2611         }
2612 
2613         default: {
2614             break;
2615         }
2616     }
2617 
2618     return typeAnnotation;
2619 }
2620 
ParsePrimitiveType(TypeAnnotationParsingOptions * options,ir::PrimitiveType type)2621 ir::TypeNode *ETSParser::ParsePrimitiveType(TypeAnnotationParsingOptions *options, ir::PrimitiveType type)
2622 {
2623     if (((*options) & TypeAnnotationParsingOptions::DISALLOW_PRIMARY_TYPE) != 0) {
2624         ThrowSyntaxError("Primitive type is not allowed here.");
2625     }
2626 
2627     auto *typeAnnotation = AllocNode<ir::ETSPrimitiveType>(type);
2628     typeAnnotation->SetRange(Lexer()->GetToken().Loc());
2629     Lexer()->NextToken();
2630     return typeAnnotation;
2631 }
2632 
ParseUnionType(ir::TypeNode * const firstType)2633 ir::TypeNode *ETSParser::ParseUnionType(ir::TypeNode *const firstType)
2634 {
2635     ArenaVector<ir::TypeNode *> types(Allocator()->Adapter());
2636     types.push_back(firstType->AsTypeNode());
2637 
2638     ir::ModifierFlags nullishModifiers {};
2639 
2640     while (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BITWISE_OR) {
2641         Lexer()->NextToken();  // eat '|'
2642 
2643         if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_NULL) {
2644             nullishModifiers |= ir::ModifierFlags::NULL_ASSIGNABLE;
2645             Lexer()->NextToken();
2646         } else if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_UNDEFINED) {
2647             nullishModifiers |= ir::ModifierFlags::UNDEFINED_ASSIGNABLE;
2648             Lexer()->NextToken();
2649         } else {
2650             auto options = TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::DISALLOW_UNION;
2651             types.push_back(ParseTypeAnnotation(&options));
2652         }
2653     }
2654 
2655     lexer::SourcePosition const endLoc = types.back()->End();
2656 
2657     if (types.size() == 1) {  // Workaround until nullability is a typeflag
2658         firstType->AddModifier(nullishModifiers);
2659         firstType->SetRange({firstType->Start(), endLoc});
2660         return firstType;
2661     }
2662 
2663     auto *const unionType = AllocNode<ir::ETSUnionType>(std::move(types));
2664     unionType->AddModifier(nullishModifiers);
2665     unionType->SetRange({firstType->Start(), endLoc});
2666     return unionType;
2667 }
2668 
ParseIntersectionType(ir::Expression * type)2669 ir::TSIntersectionType *ETSParser::ParseIntersectionType(ir::Expression *type)
2670 {
2671     auto startLoc = type->Start();
2672     ArenaVector<ir::Expression *> types(Allocator()->Adapter());
2673     types.push_back(type);
2674     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
2675 
2676     while (true) {
2677         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_BITWISE_AND) {
2678             break;
2679         }
2680 
2681         Lexer()->NextToken();  // eat '&'
2682         types.push_back(ParseTypeReference(&options));
2683     }
2684 
2685     lexer::SourcePosition endLoc = types.back()->End();
2686     auto *intersectionType = AllocNode<ir::TSIntersectionType>(std::move(types));
2687     intersectionType->SetRange({startLoc, endLoc});
2688     return intersectionType;
2689 }
2690 
GetTypeAnnotationOfPrimitiveType(lexer::TokenType tokenType,TypeAnnotationParsingOptions * options)2691 ir::TypeNode *ETSParser::GetTypeAnnotationOfPrimitiveType([[maybe_unused]] lexer::TokenType tokenType,
2692                                                           TypeAnnotationParsingOptions *options)
2693 {
2694     ir::TypeNode *typeAnnotation = nullptr;
2695     switch (tokenType) {
2696         case lexer::TokenType::KEYW_BOOLEAN:
2697             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::BOOLEAN);
2698             break;
2699         case lexer::TokenType::KEYW_DOUBLE:
2700             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::DOUBLE);
2701             break;
2702         case lexer::TokenType::KEYW_BYTE:
2703             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::BYTE);
2704             break;
2705         case lexer::TokenType::KEYW_FLOAT:
2706             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::FLOAT);
2707             break;
2708         case lexer::TokenType::KEYW_SHORT:
2709             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::SHORT);
2710             break;
2711         case lexer::TokenType::KEYW_INT:
2712             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::INT);
2713             break;
2714         case lexer::TokenType::KEYW_CHAR:
2715             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::CHAR);
2716             break;
2717         case lexer::TokenType::KEYW_LONG:
2718             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::LONG);
2719             break;
2720         default:
2721             typeAnnotation = ParseTypeReference(options);
2722             break;
2723     }
2724     return typeAnnotation;
2725 }
2726 
ParseWildcardType(TypeAnnotationParsingOptions * options)2727 ir::TypeNode *ETSParser::ParseWildcardType(TypeAnnotationParsingOptions *options)
2728 {
2729     const auto varianceStartLoc = Lexer()->GetToken().Start();
2730     const auto varianceEndLoc = Lexer()->GetToken().End();
2731     const auto varianceModifier = ParseTypeVarianceModifier(options);
2732 
2733     auto *typeReference = [this, &varianceModifier, options]() -> ir::ETSTypeReference * {
2734         if (varianceModifier == ir::ModifierFlags::OUT &&
2735             (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_GREATER_THAN ||
2736              Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA)) {
2737             // unbounded 'out'
2738             return nullptr;
2739         }
2740         return ParseTypeReference(options)->AsETSTypeReference();
2741     }();
2742 
2743     auto *wildcardType = AllocNode<ir::ETSWildcardType>(typeReference, varianceModifier);
2744     wildcardType->SetRange({varianceStartLoc, typeReference == nullptr ? varianceEndLoc : typeReference->End()});
2745 
2746     return wildcardType;
2747 }
2748 
ParseFunctionType()2749 ir::TypeNode *ETSParser::ParseFunctionType()
2750 {
2751     auto startLoc = Lexer()->GetToken().Start();
2752     auto params = ParseFunctionParams();
2753 
2754     auto *const returnTypeAnnotation = [this]() -> ir::TypeNode * {
2755         ExpectToken(lexer::TokenType::PUNCTUATOR_ARROW);
2756         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
2757         return ParseTypeAnnotation(&options);
2758     }();
2759 
2760     ir::ScriptFunctionFlags throwMarker = ParseFunctionThrowMarker(false);
2761 
2762     auto *funcType = AllocNode<ir::ETSFunctionType>(
2763         ir::FunctionSignature(nullptr, std::move(params), returnTypeAnnotation), throwMarker);
2764     const auto endLoc = returnTypeAnnotation->End();
2765     funcType->SetRange({startLoc, endLoc});
2766 
2767     return funcType;
2768 }
2769 
ParseETSTupleType(TypeAnnotationParsingOptions * const options)2770 ir::TypeNode *ETSParser::ParseETSTupleType(TypeAnnotationParsingOptions *const options)
2771 {
2772     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
2773 
2774     const auto startLoc = Lexer()->GetToken().Start();
2775     Lexer()->NextToken();  // eat '['
2776 
2777     ArenaVector<ir::TypeNode *> tupleTypeList(Allocator()->Adapter());
2778     auto *const tupleType = AllocNode<ir::ETSTuple>(Allocator());
2779 
2780     bool spreadTypePresent = false;
2781 
2782     while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
2783         // Parse named parameter if name presents
2784         if ((Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) &&
2785             (Lexer()->Lookahead() == lexer::LEX_CHAR_COLON)) {
2786             ExpectIdentifier();
2787             Lexer()->NextToken();  // eat ':'
2788         }
2789 
2790         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
2791             if (spreadTypePresent) {
2792                 ThrowSyntaxError("Only one spread type declaration allowed, at the last index");
2793             }
2794 
2795             spreadTypePresent = true;
2796             Lexer()->NextToken();  // eat '...'
2797         } else if (spreadTypePresent) {
2798             // This can't be implemented to any index, with type consistency. If a spread type is in the middle of the
2799             // tuple, then bounds check can't be made for element access, so the type of elements after the spread can't
2800             // be determined in compile time.
2801             ThrowSyntaxError("Spread type must be at the last index in the tuple type");
2802         }
2803 
2804         auto *const currentTypeAnnotation = ParseTypeAnnotation(options);
2805         currentTypeAnnotation->SetParent(tupleType);
2806 
2807         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
2808             // NOTE(mmartin): implement optional types for tuples
2809             ThrowSyntaxError("Optional types in tuples are not yet implemented.");
2810         }
2811 
2812         if (spreadTypePresent) {
2813             if (!currentTypeAnnotation->IsTSArrayType()) {
2814                 ThrowSyntaxError("Spread type must be an array type");
2815             }
2816 
2817             tupleType->SetSpreadType(currentTypeAnnotation);
2818         } else {
2819             tupleTypeList.push_back(currentTypeAnnotation);
2820         }
2821 
2822         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
2823             Lexer()->NextToken();  // eat comma
2824             continue;
2825         }
2826 
2827         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
2828             ThrowSyntaxError("Comma is mandatory between elements in a tuple type declaration");
2829         }
2830     }
2831 
2832     Lexer()->NextToken();  // eat ']'
2833 
2834     tupleType->SetTypeAnnotationsList(tupleTypeList);
2835     const auto endLoc = Lexer()->GetToken().End();
2836     tupleType->SetRange({startLoc, endLoc});
2837 
2838     return tupleType;
2839 }
2840 
2841 // Just to reduce the size of ParseTypeAnnotation(...) method
GetTypeAnnotationFromToken(TypeAnnotationParsingOptions * options)2842 std::pair<ir::TypeNode *, bool> ETSParser::GetTypeAnnotationFromToken(TypeAnnotationParsingOptions *options)
2843 {
2844     ir::TypeNode *typeAnnotation = nullptr;
2845 
2846     switch (Lexer()->GetToken().Type()) {
2847         case lexer::TokenType::LITERAL_IDENT: {
2848             typeAnnotation = ParseLiteralIdent(options);
2849             if (((*options) & TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL) != 0 &&
2850                 (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS || IsStructKeyword())) {
2851                 return std::make_pair(typeAnnotation, false);
2852             }
2853             break;
2854         }
2855         case lexer::TokenType::KEYW_BOOLEAN: {
2856             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::BOOLEAN);
2857             break;
2858         }
2859         case lexer::TokenType::KEYW_BYTE: {
2860             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::BYTE);
2861             break;
2862         }
2863         case lexer::TokenType::KEYW_CHAR: {
2864             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::CHAR);
2865             break;
2866         }
2867         case lexer::TokenType::KEYW_DOUBLE: {
2868             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::DOUBLE);
2869             break;
2870         }
2871         case lexer::TokenType::KEYW_FLOAT: {
2872             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::FLOAT);
2873             break;
2874         }
2875         case lexer::TokenType::KEYW_INT: {
2876             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::INT);
2877             break;
2878         }
2879         case lexer::TokenType::KEYW_LONG: {
2880             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::LONG);
2881             break;
2882         }
2883         case lexer::TokenType::KEYW_SHORT: {
2884             typeAnnotation = ParsePrimitiveType(options, ir::PrimitiveType::SHORT);
2885             break;
2886         }
2887         case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
2888             auto startLoc = Lexer()->GetToken().Start();
2889             lexer::LexerPosition savedPos = Lexer()->Save();
2890             Lexer()->NextToken();  // eat '('
2891 
2892             if (((*options) & TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE) == 0 &&
2893                 (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS ||
2894                  Lexer()->Lookahead() == lexer::LEX_CHAR_COLON)) {
2895                 typeAnnotation = ParseFunctionType();
2896                 typeAnnotation->SetStart(startLoc);
2897                 return std::make_pair(typeAnnotation, false);
2898             }
2899 
2900             typeAnnotation = ParseTypeAnnotation(options);
2901             typeAnnotation->SetStart(startLoc);
2902 
2903             if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BITWISE_OR) {
2904                 typeAnnotation = ParseUnionType(typeAnnotation);
2905             }
2906 
2907             ParseRightParenthesis(options, typeAnnotation, savedPos);
2908             break;
2909         }
2910         case lexer::TokenType::PUNCTUATOR_FORMAT: {
2911             typeAnnotation = ParseTypeFormatPlaceholder();
2912             break;
2913         }
2914         case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
2915             typeAnnotation = ParseETSTupleType(options);
2916             break;
2917         }
2918         case lexer::TokenType::KEYW_THIS: {
2919             typeAnnotation = ParseThisType(options);
2920             break;
2921         }
2922         default: {
2923             break;
2924         }
2925     }
2926 
2927     return std::make_pair(typeAnnotation, true);
2928 }
2929 
ParseLiteralIdent(TypeAnnotationParsingOptions * options)2930 ir::TypeNode *ETSParser::ParseLiteralIdent(TypeAnnotationParsingOptions *options)
2931 {
2932     if (const auto keyword = Lexer()->GetToken().KeywordType();
2933         keyword == lexer::TokenType::KEYW_IN || keyword == lexer::TokenType::KEYW_OUT) {
2934         return ParseWildcardType(options);
2935     }
2936 
2937     if (Lexer()->GetToken().IsDefinableTypeName()) {
2938         return GetTypeAnnotationOfPrimitiveType(Lexer()->GetToken().KeywordType(), options);
2939     }
2940 
2941     return ParseTypeReference(options);
2942 }
2943 
ParseRightParenthesis(TypeAnnotationParsingOptions * options,ir::TypeNode * & typeAnnotation,lexer::LexerPosition savedPos)2944 void ETSParser::ParseRightParenthesis(TypeAnnotationParsingOptions *options, ir::TypeNode *&typeAnnotation,
2945                                       lexer::LexerPosition savedPos)
2946 {
2947     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
2948         if (((*options) & TypeAnnotationParsingOptions::THROW_ERROR) != 0) {
2949             ThrowExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS);
2950         }
2951 
2952         Lexer()->Rewind(savedPos);
2953         typeAnnotation = nullptr;
2954     } else {
2955         Lexer()->NextToken();  // eat ')'
2956     }
2957 }
2958 
ParseThisType(TypeAnnotationParsingOptions * options)2959 ir::TypeNode *ETSParser::ParseThisType(TypeAnnotationParsingOptions *options)
2960 {
2961     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_THIS);
2962 
2963     // A syntax error should be thrown if
2964     // - the usage of 'this' as a type is not allowed in the current context, or
2965     // - 'this' is not used as a return type, or
2966     // - the current context is an arrow function (might be inside a method of a class where 'this' is allowed).
2967     if (((*options & TypeAnnotationParsingOptions::THROW_ERROR) != 0) &&
2968         (((GetContext().Status() & ParserStatus::ALLOW_THIS_TYPE) == 0) ||
2969          ((*options & TypeAnnotationParsingOptions::RETURN_TYPE) == 0) ||
2970          ((GetContext().Status() & ParserStatus::ARROW_FUNCTION) != 0))) {
2971         ThrowSyntaxError("A 'this' type is available only as return type in a non-static method of a class or struct.");
2972     }
2973 
2974     auto *thisType = AllocNode<ir::TSThisType>();
2975     thisType->SetRange(Lexer()->GetToken().Loc());
2976 
2977     Lexer()->NextToken();  // eat 'this'
2978 
2979     return thisType;
2980 }
2981 
ParseTypeAnnotation(TypeAnnotationParsingOptions * options)2982 ir::TypeNode *ETSParser::ParseTypeAnnotation(TypeAnnotationParsingOptions *options)
2983 {
2984     bool const throwError = ((*options) & TypeAnnotationParsingOptions::THROW_ERROR) != 0;
2985 
2986     auto [typeAnnotation, needFurtherProcessing] = GetTypeAnnotationFromToken(options);
2987 
2988     if (typeAnnotation == nullptr) {
2989         if (throwError) {
2990             ThrowSyntaxError("Invalid Type");
2991         }
2992         return nullptr;
2993     }
2994 
2995     if (!needFurtherProcessing) {
2996         return typeAnnotation;
2997     }
2998 
2999     const lexer::SourcePosition &startPos = Lexer()->GetToken().Start();
3000 
3001     if (((*options) & TypeAnnotationParsingOptions::ALLOW_INTERSECTION) != 0 &&
3002         Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BITWISE_AND) {
3003         if (typeAnnotation->IsETSPrimitiveType()) {
3004             if (throwError) {
3005                 ThrowSyntaxError("Invalid intersection type.");
3006             }
3007             return nullptr;
3008         }
3009 
3010         return ParseIntersectionType(typeAnnotation);
3011     }
3012 
3013     while (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
3014         Lexer()->NextToken();  // eat '['
3015 
3016         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
3017             if (throwError) {
3018                 ThrowExpectedToken(lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET);
3019             }
3020             return nullptr;
3021         }
3022 
3023         Lexer()->NextToken();  // eat ']'
3024         typeAnnotation = AllocNode<ir::TSArrayType>(typeAnnotation);
3025         typeAnnotation->SetRange({startPos, Lexer()->GetToken().End()});
3026     }
3027 
3028     if (((*options) & TypeAnnotationParsingOptions::DISALLOW_UNION) == 0 &&
3029         Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_BITWISE_OR) {
3030         return ParseUnionType(typeAnnotation);
3031     }
3032 
3033     return typeAnnotation;
3034 }
3035 
ThrowIfVarDeclaration(VariableParsingFlags flags)3036 void ETSParser::ThrowIfVarDeclaration(VariableParsingFlags flags)
3037 {
3038     if ((flags & VariableParsingFlags::VAR) != 0) {
3039         ThrowUnexpectedToken(lexer::TokenType::KEYW_VAR);
3040     }
3041 }
3042 
ValidateForInStatement()3043 void ETSParser::ValidateForInStatement()
3044 {
3045     ThrowUnexpectedToken(lexer::TokenType::KEYW_IN);
3046 }
3047 
ParseDebuggerStatement()3048 ir::DebuggerStatement *ETSParser::ParseDebuggerStatement()
3049 {
3050     ThrowUnexpectedToken(lexer::TokenType::KEYW_DEBUGGER);
3051 }
3052 
ParseExport(lexer::SourcePosition startLoc)3053 void ETSParser::ParseExport(lexer::SourcePosition startLoc)
3054 {
3055     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY ||
3056            Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
3057     ArenaVector<ir::AstNode *> specifiers(Allocator()->Adapter());
3058 
3059     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
3060         ParseNameSpaceSpecifier(&specifiers, true);
3061     } else {
3062         ParseNamedSpecifiers(&specifiers, true);
3063 
3064         if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) {
3065             // selective export directive
3066             return;
3067         }
3068     }
3069 
3070     // re-export directive
3071     ir::ImportSource *reExportSource = nullptr;
3072     std::vector<std::string> userPaths;
3073 
3074     std::tie(reExportSource, userPaths) = ParseFromClause(true);
3075 
3076     lexer::SourcePosition endLoc = reExportSource->Source()->End();
3077     auto *reExportDeclaration = AllocNode<ir::ETSImportDeclaration>(reExportSource, specifiers);
3078     reExportDeclaration->SetRange({startLoc, endLoc});
3079 
3080     auto varbinder = GetProgram()->VarBinder()->AsETSBinder();
3081     if (reExportDeclaration->Language().IsDynamic()) {
3082         varbinder->AddDynamicImport(reExportDeclaration);
3083     }
3084 
3085     ConsumeSemicolon(reExportDeclaration);
3086 
3087     auto *reExport = Allocator()->New<ir::ETSReExportDeclaration>(reExportDeclaration, userPaths,
3088                                                                   GetProgram()->SourceFilePath(), Allocator());
3089     varbinder->AddReExportImport(reExport);
3090 }
3091 
ParseFunctionStatement(const StatementParsingFlags flags)3092 ir::Statement *ETSParser::ParseFunctionStatement([[maybe_unused]] const StatementParsingFlags flags)
3093 {
3094     ASSERT((flags & StatementParsingFlags::GLOBAL) == 0);
3095     ThrowSyntaxError("Nested functions are not allowed");
3096 }
3097 
ParsePackageDeclaration(ArenaVector<ir::Statement * > & statements)3098 void ETSParser::ParsePackageDeclaration(ArenaVector<ir::Statement *> &statements)
3099 {
3100     auto startLoc = Lexer()->GetToken().Start();
3101 
3102     if (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_PACKAGE) {
3103         if (!IsETSModule() && GetProgram()->IsEntryPoint()) {
3104             return;
3105         }
3106 
3107         auto baseName = GetProgram()->SourceFilePath().Utf8();
3108         baseName = baseName.substr(baseName.find_last_of(panda::os::file::File::GetPathDelim()) + 1);
3109         const size_t idx = baseName.find_last_of('.');
3110         if (idx != std::string::npos) {
3111             baseName = baseName.substr(0, idx);
3112         }
3113 
3114         GetProgram()->SetPackageName(baseName);
3115 
3116         return;
3117     }
3118 
3119     Lexer()->NextToken();
3120 
3121     ir::Expression *name = ParseQualifiedName();
3122 
3123     auto *packageDeclaration = AllocNode<ir::ETSPackageDeclaration>(name);
3124     packageDeclaration->SetRange({startLoc, Lexer()->GetToken().End()});
3125 
3126     ConsumeSemicolon(packageDeclaration);
3127     statements.push_back(packageDeclaration);
3128 
3129     if (name->IsIdentifier()) {
3130         GetProgram()->SetPackageName(name->AsIdentifier()->Name());
3131     } else {
3132         GetProgram()->SetPackageName(name->AsTSQualifiedName()->ToString(Allocator()));
3133     }
3134 }
3135 
ParseFromClause(bool requireFrom)3136 std::tuple<ir::ImportSource *, std::vector<std::string>> ETSParser::ParseFromClause(bool requireFrom)
3137 {
3138     if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) {
3139         if (requireFrom) {
3140             ThrowSyntaxError("Unexpected token.");
3141         }
3142     } else {
3143         Lexer()->NextToken();  // eat `from`
3144     }
3145 
3146     if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
3147         ThrowSyntaxError("Unexpected token.");
3148     }
3149 
3150     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_STRING);
3151     std::vector<std::string> userPaths;
3152     bool isModule = false;
3153     auto importPath = Lexer()->GetToken().Ident();
3154     auto resolvedImportPath = ResolveImportPath(importPath.Mutf8());
3155     resolvedParsedSources_.emplace(importPath.Mutf8(), resolvedImportPath);
3156 
3157     ir::StringLiteral *resolvedSource;
3158     if (*importPath.Bytes() == '/') {
3159         resolvedSource = AllocNode<ir::StringLiteral>(util::UString(resolvedImportPath, Allocator()).View());
3160     } else {
3161         resolvedSource = AllocNode<ir::StringLiteral>(importPath);
3162     }
3163 
3164     auto importData = GetImportData(resolvedImportPath);
3165 
3166     if ((GetContext().Status() & ParserStatus::IN_DEFAULT_IMPORTS) == 0) {
3167         std::tie(userPaths, isModule) = CollectUserSources(importPath.Mutf8());
3168     }
3169 
3170     ir::StringLiteral *module = nullptr;
3171     if (isModule) {
3172         auto pos = importPath.Mutf8().find_last_of(panda::os::file::File::GetPathDelim());
3173 
3174         util::UString baseName(importPath.Mutf8().substr(0, pos), Allocator());
3175         if (baseName.View().Is(".") || baseName.View().Is("..")) {
3176             baseName.Append(panda::os::file::File::GetPathDelim());
3177         }
3178 
3179         module = AllocNode<ir::StringLiteral>(util::UString(importPath.Mutf8().substr(pos + 1), Allocator()).View());
3180         importPath = baseName.View();
3181     }
3182 
3183     auto *source = AllocNode<ir::StringLiteral>(importPath);
3184     source->SetRange(Lexer()->GetToken().Loc());
3185 
3186     Lexer()->NextToken();
3187 
3188     auto *importSource =
3189         Allocator()->New<ir::ImportSource>(source, resolvedSource, importData.lang, importData.hasDecl, module);
3190     return {importSource, userPaths};
3191 }
3192 
ParseImportDeclarations(ArenaVector<ir::Statement * > & statements)3193 std::vector<std::string> ETSParser::ParseImportDeclarations(ArenaVector<ir::Statement *> &statements)
3194 {
3195     std::vector<std::string> allUserPaths;
3196     std::vector<std::string> userPaths;
3197     ArenaVector<ir::ETSImportDeclaration *> imports(Allocator()->Adapter());
3198 
3199     while (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_IMPORT) {
3200         auto startLoc = Lexer()->GetToken().Start();
3201         Lexer()->NextToken();  // eat import
3202 
3203         ArenaVector<ir::AstNode *> specifiers(Allocator()->Adapter());
3204         ir::ImportSource *importSource = nullptr;
3205 
3206         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
3207             ParseNameSpaceSpecifier(&specifiers);
3208         } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
3209             ParseNamedSpecifiers(&specifiers);
3210         } else {
3211             ParseImportDefaultSpecifier(&specifiers);
3212         }
3213 
3214         std::tie(importSource, userPaths) = ParseFromClause(true);
3215 
3216         allUserPaths.insert(allUserPaths.end(), userPaths.begin(), userPaths.end());
3217         lexer::SourcePosition endLoc = importSource->Source()->End();
3218         auto *importDeclaration = AllocNode<ir::ETSImportDeclaration>(importSource, std::move(specifiers));
3219         importDeclaration->SetRange({startLoc, endLoc});
3220 
3221         ConsumeSemicolon(importDeclaration);
3222 
3223         statements.push_back(importDeclaration);
3224         imports.push_back(importDeclaration);
3225     }
3226 
3227     sort(statements.begin(), statements.end(), [](ir::Statement const *s1, ir::Statement const *s2) -> bool {
3228         return s1->IsETSImportDeclaration() && s2->IsETSImportDeclaration() &&
3229                s1->AsETSImportDeclaration()->Specifiers()[0]->IsImportNamespaceSpecifier() &&
3230                !s2->AsETSImportDeclaration()->Specifiers()[0]->IsImportNamespaceSpecifier();
3231     });
3232 
3233     if ((GetContext().Status() & ParserStatus::IN_DEFAULT_IMPORTS) != 0) {
3234         static_cast<varbinder::ETSBinder *>(GetProgram()->VarBinder())
3235             ->SetDefaultImports(std::move(imports));  // get rid of it
3236     }
3237 
3238     sort(allUserPaths.begin(), allUserPaths.end());
3239     allUserPaths.erase(unique(allUserPaths.begin(), allUserPaths.end()), allUserPaths.end());
3240 
3241     return allUserPaths;
3242 }
3243 
ParseNamedSpecifiers(ArenaVector<ir::AstNode * > * specifiers,bool isExport)3244 void ETSParser::ParseNamedSpecifiers(ArenaVector<ir::AstNode *> *specifiers, bool isExport)
3245 {
3246     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
3247     // NOTE(user): handle qualifiedName in file bindings: qualifiedName '.' '*'
3248     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
3249         ThrowExpectedToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE);
3250     }
3251     Lexer()->NextToken();  // eat '{'
3252 
3253     auto fileName = GetProgram()->SourceFilePath().Mutf8();
3254     std::vector<util::StringView> exportedIdents;
3255 
3256     while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
3257         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MULTIPLY) {
3258             ThrowSyntaxError("The '*' token is not allowed as a selective binding (between braces)");
3259         }
3260 
3261         if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
3262             ThrowSyntaxError("Unexpected token");
3263         }
3264 
3265         lexer::Token importedToken = Lexer()->GetToken();
3266         auto *imported = AllocNode<ir::Identifier>(importedToken.Ident(), Allocator());
3267         ir::Identifier *local = nullptr;
3268         imported->SetRange(Lexer()->GetToken().Loc());
3269 
3270         Lexer()->NextToken();  // eat import/export name
3271 
3272         if (CheckModuleAsModifier() && Lexer()->GetToken().Type() == lexer::TokenType::KEYW_AS) {
3273             Lexer()->NextToken();  // eat `as` literal
3274             local = ParseNamedImport(Lexer()->GetToken());
3275             Lexer()->NextToken();  // eat local name
3276         } else {
3277             local = ParseNamedImport(importedToken);
3278         }
3279 
3280         auto *specifier = AllocNode<ir::ImportSpecifier>(imported, local);
3281         specifier->SetRange({imported->Start(), local->End()});
3282 
3283         util::Helpers::CheckImportedName(specifiers, specifier, fileName);
3284 
3285         if (isExport) {
3286             util::StringView memberName = local->Name();
3287             exportedIdents.push_back(memberName);
3288         }
3289         specifiers->push_back(specifier);
3290 
3291         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3292             Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat comma
3293         }
3294     }
3295 
3296     Lexer()->NextToken();  // eat '}'
3297 
3298     if (isExport && Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) {
3299         // update exported idents to export name map when it is not the case of re-export
3300         for (auto memberName : exportedIdents) {
3301             exportNameMap_.insert({memberName, startLoc});
3302         }
3303     }
3304 }
3305 
ParseNameSpaceSpecifier(ArenaVector<ir::AstNode * > * specifiers,bool isReExport)3306 void ETSParser::ParseNameSpaceSpecifier(ArenaVector<ir::AstNode *> *specifiers, bool isReExport)
3307 {
3308     lexer::SourcePosition namespaceStart = Lexer()->GetToken().Start();
3309     Lexer()->NextToken();  // eat `*` character
3310 
3311     if (!CheckModuleAsModifier()) {
3312         ThrowSyntaxError("Unexpected token.");
3313     }
3314 
3315     auto *local = AllocNode<ir::Identifier>(util::StringView(""), Allocator());
3316     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA ||
3317         Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_FROM || isReExport) {
3318         auto *specifier = AllocNode<ir::ImportNamespaceSpecifier>(local);
3319         specifier->SetRange({namespaceStart, Lexer()->GetToken().End()});
3320         specifiers->push_back(specifier);
3321         return;
3322     }
3323 
3324     Lexer()->NextToken();  // eat `as` literal
3325     local = ParseNamedImport(Lexer()->GetToken());
3326 
3327     auto *specifier = AllocNode<ir::ImportNamespaceSpecifier>(local);
3328     specifier->SetRange({namespaceStart, Lexer()->GetToken().End()});
3329     specifiers->push_back(specifier);
3330 
3331     Lexer()->NextToken();  // eat local name
3332 }
3333 
ParseImportDefaultSpecifier(ArenaVector<ir::AstNode * > * specifiers)3334 ir::AstNode *ETSParser::ParseImportDefaultSpecifier(ArenaVector<ir::AstNode *> *specifiers)
3335 {
3336     if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
3337         ThrowSyntaxError("Unexpected token, expected an identifier");
3338     }
3339 
3340     auto *imported = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
3341     imported->SetRange(Lexer()->GetToken().Loc());
3342     Lexer()->NextToken();  // Eat import specifier.
3343 
3344     if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) {
3345         ThrowSyntaxError("Unexpected token, expected 'from'");
3346     }
3347 
3348     auto *specifier = AllocNode<ir::ImportDefaultSpecifier>(imported);
3349     specifier->SetRange({imported->Start(), imported->End()});
3350     specifiers->push_back(specifier);
3351 
3352     return nullptr;
3353 }
3354 
CheckModuleAsModifier()3355 bool ETSParser::CheckModuleAsModifier()
3356 {
3357     if ((Lexer()->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0U) {
3358         ThrowSyntaxError("Escape sequences are not allowed in 'as' keyword");
3359     }
3360 
3361     return true;
3362 }
3363 
GetAnnotatedExpressionFromParam()3364 ir::AnnotatedExpression *ETSParser::GetAnnotatedExpressionFromParam()
3365 {
3366     ir::AnnotatedExpression *parameter;
3367 
3368     switch (Lexer()->GetToken().Type()) {
3369         case lexer::TokenType::LITERAL_IDENT: {
3370             parameter = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
3371             if (parameter->AsIdentifier()->Decorators().empty()) {
3372                 parameter->SetRange(Lexer()->GetToken().Loc());
3373             } else {
3374                 parameter->SetRange(
3375                     {parameter->AsIdentifier()->Decorators().front()->Start(), Lexer()->GetToken().End()});
3376             }
3377             break;
3378         }
3379 
3380         case lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD: {
3381             const auto startLoc = Lexer()->GetToken().Start();
3382             Lexer()->NextToken();
3383 
3384             if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) {
3385                 ThrowSyntaxError("Unexpected token, expected an identifier.");
3386             }
3387 
3388             auto *const restIdent = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
3389             restIdent->SetRange(Lexer()->GetToken().Loc());
3390 
3391             parameter = AllocNode<ir::SpreadElement>(ir::AstNodeType::REST_ELEMENT, Allocator(), restIdent);
3392             parameter->SetRange({startLoc, Lexer()->GetToken().End()});
3393             break;
3394         }
3395 
3396         default: {
3397             ThrowSyntaxError("Unexpected token, expected an identifier.");
3398         }
3399     }
3400 
3401     Lexer()->NextToken();
3402     return parameter;
3403 }
3404 
3405 // NOLINTBEGIN(modernize-avoid-c-arrays)
3406 static constexpr char const NO_DEFAULT_FOR_REST[] = "Rest parameter cannot have the default value.";
3407 static constexpr char const ONLY_ARRAY_FOR_REST[] = "Rest parameter should be of an array type.";
3408 static constexpr char const EXPLICIT_PARAM_TYPE[] = "Parameter declaration should have an explicit type annotation.";
3409 // NOLINTEND(modernize-avoid-c-arrays)
3410 
ParseFunctionParameter()3411 ir::Expression *ETSParser::ParseFunctionParameter()
3412 {
3413     ir::ETSParameterExpression *paramExpression;
3414     auto *const paramIdent = GetAnnotatedExpressionFromParam();
3415 
3416     bool defaultUndefined = false;
3417     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) {
3418         if (paramIdent->IsRestElement()) {
3419             ThrowSyntaxError(NO_DEFAULT_FOR_REST);
3420         }
3421         defaultUndefined = true;
3422         Lexer()->NextToken();  // eat '?'
3423     }
3424 
3425     const bool isArrow = (GetContext().Status() & ParserStatus::ARROW_FUNCTION) != 0;
3426 
3427     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
3428         Lexer()->NextToken();  // eat ':'
3429 
3430         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
3431         ir::TypeNode *typeAnnotation = ParseTypeAnnotation(&options);
3432 
3433         if (paramIdent->IsRestElement() && !typeAnnotation->IsTSArrayType()) {
3434             ThrowSyntaxError(ONLY_ARRAY_FOR_REST);
3435         }
3436 
3437         typeAnnotation->SetParent(paramIdent);
3438         paramIdent->SetTsTypeAnnotation(typeAnnotation);
3439         paramIdent->SetEnd(typeAnnotation->End());
3440 
3441     } else if (!isArrow && !defaultUndefined) {
3442         ThrowSyntaxError(EXPLICIT_PARAM_TYPE);
3443     }
3444 
3445     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
3446         if (paramIdent->IsRestElement()) {
3447             ThrowSyntaxError(NO_DEFAULT_FOR_REST);
3448         }
3449 
3450         auto const lexerPos = Lexer()->Save().Iterator();
3451         Lexer()->NextToken();  // eat '='
3452 
3453         if (defaultUndefined) {
3454             ThrowSyntaxError("Not enable default value with default undefined");
3455         }
3456 
3457         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS ||
3458             Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3459             ThrowSyntaxError("You didn't set the value.");
3460         }
3461 
3462         paramExpression = AllocNode<ir::ETSParameterExpression>(paramIdent->AsIdentifier(), ParseExpression());
3463 
3464         std::string value = Lexer()->SourceView(lexerPos.Index(), Lexer()->Save().Iterator().Index()).Mutf8();
3465         while (value.back() == ' ') {
3466             value.pop_back();
3467         }
3468         if (value.back() == ')' || value.back() == ',') {
3469             value.pop_back();
3470         }
3471         paramExpression->SetLexerSaved(util::UString(value, Allocator()).View());
3472 
3473         paramExpression->SetRange({paramIdent->Start(), paramExpression->Initializer()->End()});
3474     } else if (paramIdent->IsIdentifier()) {
3475         auto *const typeAnnotation = paramIdent->AsIdentifier()->TypeAnnotation();
3476 
3477         const auto typeAnnotationValue = [this, typeAnnotation]() -> std::pair<ir::Expression *, std::string> {
3478             if (typeAnnotation == nullptr) {
3479                 return std::make_pair(nullptr, "");
3480             }
3481             if (!typeAnnotation->IsETSPrimitiveType()) {
3482                 return std::make_pair(AllocNode<ir::UndefinedLiteral>(), "undefined");
3483             }
3484             // NOTE(ttamas) : after nullable fix, fix this scope
3485             switch (typeAnnotation->AsETSPrimitiveType()->GetPrimitiveType()) {
3486                 case ir::PrimitiveType::BYTE:
3487                 case ir::PrimitiveType::INT:
3488                 case ir::PrimitiveType::LONG:
3489                 case ir::PrimitiveType::SHORT:
3490                 case ir::PrimitiveType::FLOAT:
3491                 case ir::PrimitiveType::DOUBLE:
3492                     return std::make_pair(AllocNode<ir::NumberLiteral>(lexer::Number(0)), "0");
3493                 case ir::PrimitiveType::BOOLEAN:
3494                     return std::make_pair(AllocNode<ir::BooleanLiteral>(false), "false");
3495                 case ir::PrimitiveType::CHAR:
3496                     return std::make_pair(AllocNode<ir::CharLiteral>(), "c'\\u0000'");
3497                 default: {
3498                     UNREACHABLE();
3499                 }
3500             }
3501         }();
3502 
3503         if (defaultUndefined && !typeAnnotation->IsETSPrimitiveType()) {
3504             typeAnnotation->AddModifier(ir::ModifierFlags::UNDEFINED_ASSIGNABLE);
3505         }
3506 
3507         paramExpression = AllocNode<ir::ETSParameterExpression>(
3508             paramIdent->AsIdentifier(), defaultUndefined ? std::get<0>(typeAnnotationValue) : nullptr);
3509 
3510         if (defaultUndefined) {
3511             paramExpression->SetLexerSaved(util::UString(std::get<1>(typeAnnotationValue), Allocator()).View());
3512         }
3513 
3514         paramExpression->SetRange({paramIdent->Start(), paramIdent->End()});
3515     } else {
3516         paramExpression = AllocNode<ir::ETSParameterExpression>(paramIdent->AsRestElement(), nullptr);
3517         paramExpression->SetRange({paramIdent->Start(), paramIdent->End()});
3518     }
3519 
3520     return paramExpression;
3521 }
3522 
CreateParameterThis(const util::StringView className)3523 ir::Expression *ETSParser::CreateParameterThis(const util::StringView className)
3524 {
3525     auto *paramIdent = AllocNode<ir::Identifier>(varbinder::TypedBinder::MANDATORY_PARAM_THIS, Allocator());
3526     paramIdent->SetRange(Lexer()->GetToken().Loc());
3527 
3528     ir::Expression *classTypeName = AllocNode<ir::Identifier>(className, Allocator());
3529     classTypeName->AsIdentifier()->SetReference();
3530     classTypeName->SetRange(Lexer()->GetToken().Loc());
3531 
3532     auto typeRefPart = AllocNode<ir::ETSTypeReferencePart>(classTypeName, nullptr, nullptr);
3533     ir::TypeNode *typeAnnotation = AllocNode<ir::ETSTypeReference>(typeRefPart);
3534 
3535     typeAnnotation->SetParent(paramIdent);
3536     paramIdent->SetTsTypeAnnotation(typeAnnotation);
3537 
3538     auto *paramExpression = AllocNode<ir::ETSParameterExpression>(paramIdent, nullptr);
3539     paramExpression->SetRange({paramIdent->Start(), paramIdent->End()});
3540 
3541     return paramExpression;
3542 }
3543 
ParseVariableDeclaratorKey(VariableParsingFlags flags)3544 ir::AnnotatedExpression *ETSParser::ParseVariableDeclaratorKey([[maybe_unused]] VariableParsingFlags flags)
3545 {
3546     ir::Identifier *init = ExpectIdentifier();
3547     ir::TypeNode *typeAnnotation = nullptr;
3548 
3549     if (auto const tokenType = Lexer()->GetToken().Type(); tokenType == lexer::TokenType::PUNCTUATOR_COLON) {
3550         Lexer()->NextToken();  // eat ':'
3551         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
3552         typeAnnotation = ParseTypeAnnotation(&options);
3553     } else if (tokenType != lexer::TokenType::PUNCTUATOR_SUBSTITUTION && (flags & VariableParsingFlags::FOR_OF) == 0U) {
3554         ThrowSyntaxError("Variable must be initialized or it's type must be declared");
3555     }
3556 
3557     if (typeAnnotation != nullptr) {
3558         init->SetTsTypeAnnotation(typeAnnotation);
3559         typeAnnotation->SetParent(init);
3560     }
3561 
3562     return init;
3563 }
3564 
ParseInitializer()3565 ir::Expression *ETSParser::ParseInitializer()
3566 {
3567     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
3568         return ParseArrayLiteral();
3569     }
3570 
3571     return ParseExpression();
3572 }
3573 
ParseArrayLiteral()3574 ir::ArrayExpression *ETSParser::ParseArrayLiteral()
3575 {
3576     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
3577 
3578     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
3579 
3580     ArenaVector<ir::Expression *> elements(Allocator()->Adapter());
3581 
3582     Lexer()->NextToken();
3583 
3584     while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
3585         elements.push_back(ParseInitializer());
3586 
3587         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
3588             Lexer()->NextToken();  // eat comma
3589             continue;
3590         }
3591 
3592         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET) {
3593             ThrowSyntaxError("Comma is mandatory between elements in an array literal");
3594         }
3595     }
3596 
3597     auto *arrayLiteral = AllocNode<ir::ArrayExpression>(std::move(elements), Allocator());
3598     arrayLiteral->SetRange({startLoc, Lexer()->GetToken().End()});
3599     Lexer()->NextToken();
3600 
3601     return arrayLiteral;
3602 }
3603 
ParseVariableDeclaratorInitializer(ir::Expression * init,VariableParsingFlags flags,const lexer::SourcePosition & startLoc)3604 ir::VariableDeclarator *ETSParser::ParseVariableDeclaratorInitializer(ir::Expression *init, VariableParsingFlags flags,
3605                                                                       const lexer::SourcePosition &startLoc)
3606 {
3607     if ((flags & VariableParsingFlags::DISALLOW_INIT) != 0) {
3608         ThrowSyntaxError("for-await-of loop variable declaration may not have an initializer");
3609     }
3610 
3611     Lexer()->NextToken();
3612 
3613     ir::Expression *initializer = ParseInitializer();
3614 
3615     lexer::SourcePosition endLoc = initializer->End();
3616 
3617     auto *declarator = AllocNode<ir::VariableDeclarator>(GetFlag(flags), init, initializer);
3618     declarator->SetRange({startLoc, endLoc});
3619 
3620     return declarator;
3621 }
3622 
ParseVariableDeclarator(ir::Expression * init,lexer::SourcePosition startLoc,VariableParsingFlags flags)3623 ir::VariableDeclarator *ETSParser::ParseVariableDeclarator(ir::Expression *init, lexer::SourcePosition startLoc,
3624                                                            VariableParsingFlags flags)
3625 {
3626     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
3627         return ParseVariableDeclaratorInitializer(init, flags, startLoc);
3628     }
3629 
3630     if ((flags & VariableParsingFlags::CONST) != 0 &&
3631         static_cast<uint32_t>(flags & VariableParsingFlags::ACCEPT_CONST_NO_INIT) == 0U) {
3632         ThrowSyntaxError("Missing initializer in const declaration");
3633     }
3634 
3635     if (init->AsIdentifier()->TypeAnnotation() == nullptr && (flags & VariableParsingFlags::FOR_OF) == 0U) {
3636         ThrowSyntaxError("Variable must be initialized or it's type must be declared");
3637     }
3638 
3639     lexer::SourcePosition endLoc = init->End();
3640     auto declarator = AllocNode<ir::VariableDeclarator>(GetFlag(flags), init);
3641     declarator->SetRange({startLoc, endLoc});
3642 
3643     return declarator;
3644 }
3645 
ParseAssertStatement()3646 ir::Statement *ETSParser::ParseAssertStatement()
3647 {
3648     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
3649     Lexer()->NextToken();
3650 
3651     ir::Expression *test = ParseExpression();
3652     lexer::SourcePosition endLoc = test->End();
3653     ir::Expression *second = nullptr;
3654 
3655     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
3656         Lexer()->NextToken();  // eat ':'
3657         second = ParseExpression();
3658         endLoc = second->End();
3659     }
3660 
3661     auto *asStatement = AllocNode<ir::AssertStatement>(test, second);
3662     asStatement->SetRange({startLoc, endLoc});
3663     ConsumeSemicolon(asStatement);
3664 
3665     return asStatement;
3666 }
3667 
ParseCatchParam()3668 ir::Expression *ETSParser::ParseCatchParam()
3669 {
3670     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
3671         ThrowSyntaxError("Unexpected token, expected '('");
3672     }
3673 
3674     ir::AnnotatedExpression *param = nullptr;
3675 
3676     Lexer()->NextToken();  // eat left paren
3677 
3678     if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) {
3679         CheckRestrictedBinding();
3680         param = ExpectIdentifier();
3681     } else {
3682         ThrowSyntaxError("Unexpected token in catch parameter, expected an identifier");
3683     }
3684 
3685     ParseCatchParamTypeAnnotation(param);
3686 
3687     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
3688         ThrowSyntaxError("Unexpected token, expected ')'");
3689     }
3690 
3691     Lexer()->NextToken();  // eat right paren
3692 
3693     return param;
3694 }
3695 
ParseCatchParamTypeAnnotation(ir::AnnotatedExpression * param)3696 void ETSParser::ParseCatchParamTypeAnnotation([[maybe_unused]] ir::AnnotatedExpression *param)
3697 {
3698     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) {
3699         Lexer()->NextToken();  // eat ':'
3700 
3701         TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
3702         param->SetTsTypeAnnotation(ParseTypeAnnotation(&options));
3703     }
3704 
3705     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
3706         ThrowSyntaxError("Catch clause variable cannot have an initializer");
3707     }
3708 }
3709 
ParseTryStatement()3710 ir::Statement *ETSParser::ParseTryStatement()
3711 {
3712     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
3713     Lexer()->NextToken();  // eat the 'try' keyword
3714 
3715     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
3716         ThrowSyntaxError("Unexpected token, expected '{'");
3717     }
3718 
3719     ir::BlockStatement *body = ParseBlockStatement();
3720 
3721     ArenaVector<ir::CatchClause *> catchClauses(Allocator()->Adapter());
3722 
3723     while (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_CATCH) {
3724         ir::CatchClause *clause {};
3725 
3726         clause = ParseCatchClause();
3727 
3728         catchClauses.push_back(clause);
3729     }
3730 
3731     ir::BlockStatement *finalizer = nullptr;
3732     if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_FINALLY) {
3733         Lexer()->NextToken();  // eat 'finally' keyword
3734 
3735         finalizer = ParseBlockStatement();
3736     }
3737 
3738     if (catchClauses.empty() && finalizer == nullptr) {
3739         ThrowSyntaxError("A try statement should contain either finally clause or at least one catch clause.",
3740                          startLoc);
3741     }
3742 
3743     lexer::SourcePosition endLoc = finalizer != nullptr ? finalizer->End() : catchClauses.back()->End();
3744 
3745     ArenaVector<std::pair<compiler::LabelPair, const ir::Statement *>> finalizerInsertions(Allocator()->Adapter());
3746 
3747     auto *tryStatement = AllocNode<ir::TryStatement>(body, std::move(catchClauses), finalizer, finalizerInsertions);
3748     tryStatement->SetRange({startLoc, endLoc});
3749     ConsumeSemicolon(tryStatement);
3750 
3751     return tryStatement;
3752 }
3753 
ParseImportDeclaration(StatementParsingFlags flags)3754 ir::Statement *ETSParser::ParseImportDeclaration([[maybe_unused]] StatementParsingFlags flags)
3755 {
3756     char32_t nextChar = Lexer()->Lookahead();
3757     if (nextChar == lexer::LEX_CHAR_LEFT_PAREN || nextChar == lexer::LEX_CHAR_DOT) {
3758         return ParseExpressionStatement();
3759     }
3760 
3761     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
3762     Lexer()->NextToken();  // eat import
3763 
3764     ArenaVector<ir::AstNode *> specifiers(Allocator()->Adapter());
3765 
3766     ir::ImportSource *importSource = nullptr;
3767     std::vector<std::string> userPaths;
3768 
3769     if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
3770         ir::AstNode *astNode = ParseImportSpecifiers(&specifiers);
3771         if (astNode != nullptr) {
3772             ASSERT(astNode->IsTSImportEqualsDeclaration());
3773             astNode->SetRange({startLoc, Lexer()->GetToken().End()});
3774             ConsumeSemicolon(astNode->AsTSImportEqualsDeclaration());
3775             return astNode->AsTSImportEqualsDeclaration();
3776         }
3777         std::tie(importSource, userPaths) = ParseFromClause(true);
3778     } else {
3779         std::tie(importSource, userPaths) = ParseFromClause(false);
3780     }
3781 
3782     lexer::SourcePosition endLoc = importSource->Source()->End();
3783     auto *importDeclaration = AllocNode<ir::ETSImportDeclaration>(importSource, std::move(specifiers));
3784     importDeclaration->SetRange({startLoc, endLoc});
3785 
3786     ConsumeSemicolon(importDeclaration);
3787 
3788     return importDeclaration;
3789 }
3790 
ParseExportDeclaration(StatementParsingFlags flags)3791 ir::Statement *ETSParser::ParseExportDeclaration([[maybe_unused]] StatementParsingFlags flags)
3792 {
3793     ThrowUnexpectedToken(lexer::TokenType::KEYW_EXPORT);
3794 }
3795 
3796 // NOLINTNEXTLINE(google-default-arguments)
ParseUnaryOrPrefixUpdateExpression(ExpressionParseFlags flags)3797 ir::Expression *ETSParser::ParseUnaryOrPrefixUpdateExpression(ExpressionParseFlags flags)
3798 {
3799     switch (Lexer()->GetToken().Type()) {
3800         case lexer::TokenType::PUNCTUATOR_PLUS_PLUS:
3801         case lexer::TokenType::PUNCTUATOR_MINUS_MINUS:
3802         case lexer::TokenType::PUNCTUATOR_PLUS:
3803         case lexer::TokenType::PUNCTUATOR_MINUS:
3804         case lexer::TokenType::PUNCTUATOR_TILDE:
3805         case lexer::TokenType::PUNCTUATOR_DOLLAR_DOLLAR:
3806         case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: {
3807             break;
3808         }
3809         case lexer::TokenType::KEYW_LAUNCH: {
3810             return ParseLaunchExpression(flags);
3811         }
3812         default: {
3813             return ParseLeftHandSideExpression(flags);
3814         }
3815     }
3816 
3817     lexer::TokenType operatorType = Lexer()->GetToken().Type();
3818     auto start = Lexer()->GetToken().Start();
3819     Lexer()->NextToken();
3820 
3821     ir::Expression *argument = nullptr;
3822     switch (Lexer()->GetToken().Type()) {
3823         case lexer::TokenType::PUNCTUATOR_PLUS:
3824         case lexer::TokenType::PUNCTUATOR_MINUS:
3825         case lexer::TokenType::PUNCTUATOR_TILDE:
3826         case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK:
3827         case lexer::TokenType::PUNCTUATOR_DOLLAR_DOLLAR:
3828         case lexer::TokenType::PUNCTUATOR_PLUS_PLUS:
3829         case lexer::TokenType::PUNCTUATOR_MINUS_MINUS: {
3830             argument = ParseUnaryOrPrefixUpdateExpression();
3831             break;
3832         }
3833         default: {
3834             argument = ParseLeftHandSideExpression(flags);
3835             break;
3836         }
3837     }
3838 
3839     if (lexer::Token::IsUpdateToken(operatorType)) {
3840         if (!argument->IsIdentifier() && !argument->IsMemberExpression()) {
3841             ThrowSyntaxError("Invalid left-hand side in prefix operation");
3842         }
3843     }
3844 
3845     lexer::SourcePosition end = argument->End();
3846 
3847     ir::Expression *returnExpr = nullptr;
3848     if (lexer::Token::IsUpdateToken(operatorType)) {
3849         returnExpr = AllocNode<ir::UpdateExpression>(argument, operatorType, true);
3850     } else {
3851         returnExpr = AllocNode<ir::UnaryExpression>(argument, operatorType);
3852     }
3853 
3854     returnExpr->SetRange({start, end});
3855 
3856     return returnExpr;
3857 }
3858 
3859 // NOLINTNEXTLINE(google-default-arguments)
ParseDefaultPrimaryExpression(ExpressionParseFlags flags)3860 ir::Expression *ETSParser::ParseDefaultPrimaryExpression(ExpressionParseFlags flags)
3861 {
3862     auto startLoc = Lexer()->GetToken().Start();
3863     auto savedPos = Lexer()->Save();
3864     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::POTENTIAL_CLASS_LITERAL |
3865                                            TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE |
3866                                            TypeAnnotationParsingOptions::DISALLOW_UNION;
3867     ir::TypeNode *potentialType = ParseTypeAnnotation(&options);
3868 
3869     if (potentialType != nullptr) {
3870         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) {
3871             Lexer()->NextToken();  // eat '.'
3872         }
3873 
3874         if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CLASS || IsStructKeyword()) {
3875             Lexer()->NextToken();  // eat 'class' and 'struct'
3876             auto *classLiteral = AllocNode<ir::ETSClassLiteral>(potentialType);
3877             classLiteral->SetRange({startLoc, Lexer()->GetToken().End()});
3878             return classLiteral;
3879         }
3880     }
3881 
3882     Lexer()->Rewind(savedPos);
3883 
3884     Lexer()->NextToken();
3885     bool pretendArrow = Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW;
3886     Lexer()->Rewind(savedPos);
3887 
3888     if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && !pretendArrow) {
3889         return ParsePrimaryExpressionIdent(flags);
3890     }
3891 
3892     ThrowSyntaxError({"Unexpected token '", lexer::TokenToString(Lexer()->GetToken().Type()), "'."});
3893     return nullptr;
3894 }
3895 
3896 // NOLINTNEXTLINE(google-default-arguments)
ParsePrimaryExpression(ExpressionParseFlags flags)3897 ir::Expression *ETSParser::ParsePrimaryExpression(ExpressionParseFlags flags)
3898 {
3899     switch (Lexer()->GetToken().Type()) {
3900         case lexer::TokenType::LITERAL_TRUE:
3901         case lexer::TokenType::LITERAL_FALSE: {
3902             return ParseBooleanLiteral();
3903         }
3904         case lexer::TokenType::LITERAL_NULL: {
3905             return ParseNullLiteral();
3906         }
3907         case lexer::TokenType::KEYW_UNDEFINED: {
3908             return ParseUndefinedLiteral();
3909         }
3910         case lexer::TokenType::LITERAL_NUMBER: {
3911             return ParseCoercedNumberLiteral();
3912         }
3913         case lexer::TokenType::LITERAL_STRING: {
3914             return ParseStringLiteral();
3915         }
3916         case lexer::TokenType::LITERAL_CHAR: {
3917             return ParseCharLiteral();
3918         }
3919         case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
3920             return ParseCoverParenthesizedExpressionAndArrowParameterList(flags);
3921         }
3922         case lexer::TokenType::KEYW_THIS: {
3923             return ParseThisExpression();
3924         }
3925         case lexer::TokenType::KEYW_SUPER: {
3926             return ParseSuperExpression();
3927         }
3928         case lexer::TokenType::KEYW_NEW: {
3929             return ParseNewExpression();
3930         }
3931         case lexer::TokenType::KEYW_ASYNC: {
3932             return ParseAsyncExpression();
3933         }
3934         case lexer::TokenType::KEYW_AWAIT: {
3935             return ParseAwaitExpression();
3936         }
3937         case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
3938             return ParseArrayExpression(CarryPatternFlags(flags));
3939         }
3940         case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: {
3941             return ParseObjectExpression(CarryPatternFlags(flags));
3942         }
3943         case lexer::TokenType::PUNCTUATOR_BACK_TICK: {
3944             return ParseTemplateLiteral();
3945         }
3946         case lexer::TokenType::KEYW_TYPE: {
3947             ThrowSyntaxError("Type alias is allowed only as top-level declaration");
3948         }
3949         case lexer::TokenType::PUNCTUATOR_FORMAT: {
3950             return ParseExpressionFormatPlaceholder();
3951         }
3952         default: {
3953             return ParseDefaultPrimaryExpression(flags);
3954         }
3955     }
3956 }
3957 
IsArrowFunctionExpressionStart()3958 bool ETSParser::IsArrowFunctionExpressionStart()
3959 {
3960     const auto savedPos = Lexer()->Save();
3961     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
3962     Lexer()->NextToken();
3963     auto tokenType = Lexer()->GetToken().Type();
3964 
3965     size_t openBrackets = 1;
3966     bool expectIdentifier = true;
3967     while (tokenType != lexer::TokenType::EOS && openBrackets > 0) {
3968         switch (tokenType) {
3969             case lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS:
3970                 --openBrackets;
3971                 break;
3972             case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS:
3973                 ++openBrackets;
3974                 break;
3975             case lexer::TokenType::PUNCTUATOR_COMMA:
3976                 expectIdentifier = true;
3977                 break;
3978             case lexer::TokenType::PUNCTUATOR_SEMI_COLON:
3979                 Lexer()->Rewind(savedPos);
3980                 return false;
3981             default:
3982                 if (!expectIdentifier) {
3983                     break;
3984                 }
3985                 if (tokenType != lexer::TokenType::LITERAL_IDENT &&
3986                     tokenType != lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) {
3987                     Lexer()->Rewind(savedPos);
3988                     return false;
3989                 }
3990                 expectIdentifier = false;
3991         }
3992         Lexer()->NextToken();
3993         tokenType = Lexer()->GetToken().Type();
3994     }
3995 
3996     while (tokenType != lexer::TokenType::EOS && tokenType != lexer::TokenType::PUNCTUATOR_ARROW) {
3997         if (lexer::Token::IsPunctuatorToken(tokenType) && tokenType != lexer::TokenType::PUNCTUATOR_COLON &&
3998             tokenType != lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET &&
3999             tokenType != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET &&
4000             tokenType != lexer::TokenType::PUNCTUATOR_LESS_THAN &&
4001             tokenType != lexer::TokenType::PUNCTUATOR_GREATER_THAN &&
4002             tokenType != lexer::TokenType::PUNCTUATOR_BITWISE_OR) {
4003             break;
4004         }
4005         Lexer()->NextToken();
4006         tokenType = Lexer()->GetToken().Type();
4007     }
4008     Lexer()->Rewind(savedPos);
4009     return tokenType == lexer::TokenType::PUNCTUATOR_ARROW;
4010 }
4011 
ParseArrowFunctionExpression()4012 ir::ArrowFunctionExpression *ETSParser::ParseArrowFunctionExpression()
4013 {
4014     auto newStatus = ParserStatus::ARROW_FUNCTION;
4015     auto *func = ParseFunction(newStatus);
4016     auto *arrowFuncNode = AllocNode<ir::ArrowFunctionExpression>(Allocator(), func);
4017     arrowFuncNode->SetRange(func->Range());
4018     return arrowFuncNode;
4019 }
4020 
4021 // NOLINTNEXTLINE(google-default-arguments)
ParseCoverParenthesizedExpressionAndArrowParameterList(ExpressionParseFlags flags)4022 ir::Expression *ETSParser::ParseCoverParenthesizedExpressionAndArrowParameterList(ExpressionParseFlags flags)
4023 {
4024     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS);
4025     if (IsArrowFunctionExpressionStart()) {
4026         return ParseArrowFunctionExpression();
4027     }
4028 
4029     lexer::SourcePosition start = Lexer()->GetToken().Start();
4030     Lexer()->NextToken();
4031 
4032     ExpressionParseFlags newFlags = ExpressionParseFlags::ACCEPT_COMMA;
4033     if ((flags & ExpressionParseFlags::INSTANCEOF) != 0) {
4034         newFlags |= ExpressionParseFlags::INSTANCEOF;
4035     };
4036 
4037     ir::Expression *expr = ParseExpression(newFlags);
4038 
4039     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
4040         ThrowSyntaxError("Unexpected token, expected ')'");
4041     }
4042 
4043     expr->SetGrouped();
4044     expr->SetRange({start, Lexer()->GetToken().End()});
4045     Lexer()->NextToken();
4046 
4047     return expr;
4048 }
4049 
ParsePotentialGenericFunctionCall(ir::Expression * primaryExpr,ir::Expression ** returnExpression,const lexer::SourcePosition & startLoc,bool ignoreCallExpression)4050 bool ETSParser::ParsePotentialGenericFunctionCall(ir::Expression *primaryExpr, ir::Expression **returnExpression,
4051                                                   [[maybe_unused]] const lexer::SourcePosition &startLoc,
4052                                                   bool ignoreCallExpression)
4053 {
4054     if (Lexer()->Lookahead() == lexer::LEX_CHAR_LESS_THAN ||
4055         (!primaryExpr->IsIdentifier() && !primaryExpr->IsMemberExpression())) {
4056         return true;
4057     }
4058 
4059     const auto savedPos = Lexer()->Save();
4060 
4061     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT) {
4062         Lexer()->BackwardToken(lexer::TokenType::PUNCTUATOR_LESS_THAN, 1);
4063     }
4064 
4065     TypeAnnotationParsingOptions options =
4066         TypeAnnotationParsingOptions::ALLOW_WILDCARD | TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE;
4067     ir::TSTypeParameterInstantiation *typeParams = ParseTypeParameterInstantiation(&options);
4068 
4069     if (typeParams == nullptr) {
4070         Lexer()->Rewind(savedPos);
4071         return true;
4072     }
4073 
4074     if (Lexer()->GetToken().Type() == lexer::TokenType::EOS) {
4075         ThrowSyntaxError("'(' expected");
4076     }
4077 
4078     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
4079         if (!ignoreCallExpression) {
4080             *returnExpression = ParseCallExpression(*returnExpression, false, false);
4081             (*returnExpression)->AsCallExpression()->SetTypeParams(typeParams);
4082             return false;
4083         }
4084 
4085         return true;
4086     }
4087 
4088     Lexer()->Rewind(savedPos);
4089     return true;
4090 }
4091 
ParsePostPrimaryExpression(ir::Expression * primaryExpr,lexer::SourcePosition startLoc,bool ignoreCallExpression,bool * isChainExpression)4092 ir::Expression *ETSParser::ParsePostPrimaryExpression(ir::Expression *primaryExpr, lexer::SourcePosition startLoc,
4093                                                       bool ignoreCallExpression,
4094                                                       [[maybe_unused]] bool *isChainExpression)
4095 {
4096     ir::Expression *returnExpression = primaryExpr;
4097 
4098     while (true) {
4099         switch (Lexer()->GetToken().Type()) {
4100             case lexer::TokenType::PUNCTUATOR_QUESTION_DOT: {
4101                 Lexer()->NextToken();  // eat ?.
4102 
4103                 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
4104                     returnExpression = ParseElementAccess(returnExpression, true);
4105                     continue;
4106                 }
4107 
4108                 if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
4109                     returnExpression = ParseCallExpression(returnExpression, true, false);
4110                     continue;
4111                 }
4112 
4113                 returnExpression = ParsePropertyAccess(returnExpression, true);
4114                 continue;
4115             }
4116             case lexer::TokenType::PUNCTUATOR_PERIOD: {
4117                 Lexer()->NextToken();  // eat period
4118 
4119                 returnExpression = ParsePropertyAccess(returnExpression);
4120                 continue;
4121             }
4122             case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: {
4123                 returnExpression = ParseElementAccess(returnExpression);
4124                 continue;
4125             }
4126             case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT:
4127             case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
4128                 if (ParsePotentialGenericFunctionCall(returnExpression, &returnExpression, startLoc,
4129                                                       ignoreCallExpression)) {
4130                     break;
4131                 }
4132 
4133                 continue;
4134             }
4135             case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: {
4136                 if (ignoreCallExpression) {
4137                     break;
4138                 }
4139 
4140                 returnExpression = ParseCallExpression(returnExpression, false, false);
4141                 continue;
4142             }
4143             case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: {
4144                 const bool shouldBreak = ParsePotentialNonNullExpression(&returnExpression, startLoc);
4145                 if (shouldBreak) {
4146                     break;
4147                 }
4148 
4149                 continue;
4150             }
4151             case lexer::TokenType::PUNCTUATOR_FORMAT: {
4152                 ThrowUnexpectedToken(lexer::TokenType::PUNCTUATOR_FORMAT);
4153             }
4154             default: {
4155                 break;
4156             }
4157         }
4158 
4159         break;
4160     }
4161 
4162     return returnExpression;
4163 }
4164 
ParsePotentialAsExpression(ir::Expression * primaryExpr)4165 ir::Expression *ETSParser::ParsePotentialAsExpression(ir::Expression *primaryExpr)
4166 {
4167     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_AS);
4168     Lexer()->NextToken();
4169 
4170     TypeAnnotationParsingOptions options =
4171         TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::ALLOW_INTERSECTION;
4172     ir::TypeNode *type = ParseTypeAnnotation(&options);
4173 
4174     auto *asExpression = AllocNode<ir::TSAsExpression>(primaryExpr, type, false);
4175     asExpression->SetRange(primaryExpr->Range());
4176     return asExpression;
4177 }
4178 
ParseNewExpression()4179 ir::Expression *ETSParser::ParseNewExpression()
4180 {
4181     lexer::SourcePosition start = Lexer()->GetToken().Start();
4182 
4183     Lexer()->NextToken();  // eat new
4184 
4185     TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR;
4186     ir::TypeNode *baseTypeReference = ParseBaseTypeReference(&options);
4187     ir::TypeNode *typeReference = baseTypeReference;
4188     if (typeReference == nullptr) {
4189         options |= TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE | TypeAnnotationParsingOptions::ALLOW_WILDCARD;
4190         typeReference = ParseTypeReference(&options);
4191     } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
4192         ThrowSyntaxError("Invalid { after base types.");
4193     }
4194 
4195     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
4196         Lexer()->NextToken();
4197         ir::Expression *dimension = ParseExpression();
4198 
4199         auto endLoc = Lexer()->GetToken().End();
4200         ExpectToken(lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET);
4201 
4202         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET) {
4203             auto *arrInstance = AllocNode<ir::ETSNewArrayInstanceExpression>(Allocator(), typeReference, dimension);
4204             arrInstance->SetRange({start, endLoc});
4205             return arrInstance;
4206         }
4207 
4208         ArenaVector<ir::Expression *> dimensions(Allocator()->Adapter());
4209         dimensions.push_back(dimension);
4210 
4211         do {
4212             Lexer()->NextToken();
4213             dimensions.push_back(ParseExpression());
4214 
4215             endLoc = Lexer()->GetToken().End();
4216             ExpectToken(lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET);
4217         } while (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET);
4218 
4219         auto *multiArray = AllocNode<ir::ETSNewMultiDimArrayInstanceExpression>(typeReference, std::move(dimensions));
4220         multiArray->SetRange({start, endLoc});
4221         return multiArray;
4222     }
4223 
4224     ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
4225     lexer::SourcePosition endLoc = typeReference->End();
4226 
4227     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) {
4228         if (baseTypeReference != nullptr) {
4229             ThrowSyntaxError("Can not use 'new' on primitive types.", baseTypeReference->Start());
4230         }
4231 
4232         Lexer()->NextToken();
4233 
4234         while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) {
4235             ir::Expression *argument = ParseExpression();
4236             arguments.push_back(argument);
4237 
4238             if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) {
4239                 Lexer()->NextToken();
4240                 continue;
4241             }
4242         }
4243 
4244         endLoc = Lexer()->GetToken().End();
4245         Lexer()->NextToken();
4246     }
4247 
4248     ir::ClassDefinition *classDefinition {};
4249 
4250     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
4251         ArenaVector<ir::TSClassImplements *> implements(Allocator()->Adapter());
4252         auto modifiers = ir::ClassDefinitionModifiers::ANONYMOUS | ir::ClassDefinitionModifiers::HAS_SUPER;
4253         auto [ctor, properties, bodyRange] = ParseClassBody(modifiers);
4254 
4255         auto newIdent = AllocNode<ir::Identifier>("#0", Allocator());
4256         classDefinition = AllocNode<ir::ClassDefinition>(
4257             "#0", newIdent, nullptr, nullptr, std::move(implements), ctor,  // remove name
4258             typeReference, std::move(properties), modifiers, ir::ModifierFlags::NONE, Language(Language::Id::ETS));
4259 
4260         classDefinition->SetRange(bodyRange);
4261     }
4262 
4263     auto *newExprNode =
4264         AllocNode<ir::ETSNewClassInstanceExpression>(typeReference, std::move(arguments), classDefinition);
4265     newExprNode->SetRange({start, Lexer()->GetToken().End()});
4266 
4267     return newExprNode;
4268 }
4269 
ParseAsyncExpression()4270 ir::Expression *ETSParser::ParseAsyncExpression()
4271 {
4272     Lexer()->NextToken();  // eat 'async'
4273     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS ||
4274         !IsArrowFunctionExpressionStart()) {
4275         ThrowSyntaxError("Unexpected token. expected '('");
4276     }
4277 
4278     auto newStatus = ParserStatus::NEED_RETURN_TYPE | ParserStatus::ARROW_FUNCTION | ParserStatus::ASYNC_FUNCTION;
4279     auto *func = ParseFunction(newStatus);
4280     auto *arrowFuncNode = AllocNode<ir::ArrowFunctionExpression>(Allocator(), func);
4281     arrowFuncNode->SetRange(func->Range());
4282     return arrowFuncNode;
4283 }
4284 
ParseAwaitExpression()4285 ir::Expression *ETSParser::ParseAwaitExpression()
4286 {
4287     lexer::SourcePosition start = Lexer()->GetToken().Start();
4288     Lexer()->NextToken();
4289     ir::Expression *argument = ParseExpression();
4290     auto *awaitExpression = AllocNode<ir::AwaitExpression>(argument);
4291     awaitExpression->SetRange({start, Lexer()->GetToken().End()});
4292     return awaitExpression;
4293 }
4294 
ParseTypeVarianceModifier(TypeAnnotationParsingOptions * const options)4295 ir::ModifierFlags ETSParser::ParseTypeVarianceModifier(TypeAnnotationParsingOptions *const options)
4296 {
4297     if ((*options & TypeAnnotationParsingOptions::ALLOW_WILDCARD) == 0 &&
4298         (*options & TypeAnnotationParsingOptions::ALLOW_DECLARATION_SITE_VARIANCE) == 0) {
4299         ThrowSyntaxError("Variance modifier is not allowed here.");
4300     }
4301 
4302     switch (Lexer()->GetToken().KeywordType()) {
4303         case lexer::TokenType::KEYW_IN: {
4304             Lexer()->NextToken();
4305             return ir::ModifierFlags::IN;
4306         }
4307         case lexer::TokenType::KEYW_OUT: {
4308             Lexer()->NextToken();
4309             return ir::ModifierFlags::OUT;
4310         }
4311         default: {
4312             return ir::ModifierFlags::NONE;
4313         }
4314     }
4315 }
4316 
ParseTypeParameter(TypeAnnotationParsingOptions * options)4317 ir::TSTypeParameter *ETSParser::ParseTypeParameter([[maybe_unused]] TypeAnnotationParsingOptions *options)
4318 {
4319     lexer::SourcePosition startLoc = Lexer()->GetToken().Start();
4320 
4321     const auto varianceModifier = [this, options] {
4322         switch (Lexer()->GetToken().KeywordType()) {
4323             case lexer::TokenType::KEYW_IN:
4324             case lexer::TokenType::KEYW_OUT:
4325                 return ParseTypeVarianceModifier(options);
4326             default:
4327                 return ir::ModifierFlags::NONE;
4328         }
4329     }();
4330 
4331     auto *paramIdent = ExpectIdentifier();
4332 
4333     ir::TypeNode *constraint = nullptr;
4334     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) {
4335         Lexer()->NextToken();
4336         TypeAnnotationParsingOptions newOptions = TypeAnnotationParsingOptions::THROW_ERROR |
4337                                                   TypeAnnotationParsingOptions::ALLOW_INTERSECTION |
4338                                                   TypeAnnotationParsingOptions::IGNORE_FUNCTION_TYPE;
4339         constraint = ParseTypeAnnotation(&newOptions);
4340     }
4341 
4342     ir::TypeNode *defaultType = nullptr;
4343 
4344     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
4345         Lexer()->NextToken();  // eat '='
4346         defaultType = ParseTypeAnnotation(options);
4347     }
4348 
4349     auto *typeParam = AllocNode<ir::TSTypeParameter>(paramIdent, constraint, defaultType, varianceModifier);
4350 
4351     typeParam->SetRange({startLoc, Lexer()->GetToken().End()});
4352     return typeParam;
4353 }
4354 
4355 // NOLINTBEGIN(cert-err58-cpp)
4356 static std::string const DUPLICATE_ENUM_VALUE = "Duplicate enum initialization value "s;
4357 static std::string const INVALID_ENUM_TYPE = "Invalid enum initialization type"s;
4358 static std::string const INVALID_ENUM_VALUE = "Invalid enum initialization value"s;
4359 static std::string const MISSING_COMMA_IN_ENUM = "Missing comma between enum constants"s;
4360 static std::string const TRAILING_COMMA_IN_ENUM = "Trailing comma is not allowed in enum constant list"s;
4361 // NOLINTEND(cert-err58-cpp)
4362 
ParseEnumMembers(ir::Identifier * const key,const lexer::SourcePosition & enumStart,const bool isConst,const bool isStatic)4363 ir::TSEnumDeclaration *ETSParser::ParseEnumMembers(ir::Identifier *const key, const lexer::SourcePosition &enumStart,
4364                                                    const bool isConst, const bool isStatic)
4365 {
4366     if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
4367         ThrowSyntaxError("'{' expected");
4368     }
4369 
4370     Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat '{'
4371 
4372     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
4373         ThrowSyntaxError("An enum must have at least one enum constant");
4374     }
4375 
4376     // Lambda to check if enum underlying type is string:
4377     auto const isStringEnum = [this]() -> bool {
4378         Lexer()->NextToken();
4379         auto tokenType = Lexer()->GetToken().Type();
4380         while (tokenType != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE &&
4381                tokenType != lexer::TokenType::PUNCTUATOR_COMMA) {
4382             if (tokenType == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
4383                 Lexer()->NextToken();
4384                 if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_STRING) {
4385                     return true;
4386                 }
4387             }
4388             Lexer()->NextToken();
4389             tokenType = Lexer()->GetToken().Type();
4390         }
4391         return false;
4392     };
4393 
4394     // Get the underlying type of enum (number or string). It is defined from the first element ONLY!
4395     auto const pos = Lexer()->Save();
4396     auto const stringTypeEnum = isStringEnum();
4397     Lexer()->Rewind(pos);
4398 
4399     ArenaVector<ir::AstNode *> members(Allocator()->Adapter());
4400 
4401     if (stringTypeEnum) {
4402         ParseStringEnum(members);
4403     } else {
4404         ParseNumberEnum(members);
4405     }
4406 
4407     auto *const enumDeclaration =
4408         AllocNode<ir::TSEnumDeclaration>(Allocator(), key, std::move(members), isConst, isStatic, InAmbientContext());
4409     enumDeclaration->SetRange({enumStart, Lexer()->GetToken().End()});
4410 
4411     Lexer()->NextToken();  // eat '}'
4412 
4413     return enumDeclaration;
4414 }
4415 
ParseNumberEnum(ArenaVector<ir::AstNode * > & members)4416 void ETSParser::ParseNumberEnum(ArenaVector<ir::AstNode *> &members)
4417 {
4418     checker::ETSEnumType::ValueType currentValue {};
4419 
4420     // Lambda to parse enum member (maybe with initializer)
4421     auto const parseMember = [this, &members, &currentValue]() {
4422         auto *const ident = ExpectIdentifier(false, true);
4423 
4424         ir::NumberLiteral *ordinal;
4425         lexer::SourcePosition endLoc;
4426 
4427         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
4428             // Case when user explicitly set the value for enumeration constant
4429 
4430             bool minusSign = false;
4431 
4432             Lexer()->NextToken();
4433             if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PLUS) {
4434                 Lexer()->NextToken();
4435             } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS) {
4436                 minusSign = true;
4437                 Lexer()->NextToken();
4438             }
4439 
4440             if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_NUMBER) {
4441                 ThrowSyntaxError(INVALID_ENUM_TYPE);
4442             }
4443 
4444             ordinal = ParseNumberLiteral()->AsNumberLiteral();
4445             if (!ordinal->Number().CanGetValue<checker::ETSEnumType::ValueType>()) {
4446                 ThrowSyntaxError(INVALID_ENUM_VALUE);
4447             } else if (minusSign) {
4448                 ordinal->Number().Negate();
4449             }
4450 
4451             currentValue = ordinal->Number().GetValue<checker::ETSEnumType::ValueType>();
4452 
4453             endLoc = ordinal->End();
4454         } else {
4455             // Default enumeration constant value. Equal to 0 for the first item and = previous_value + 1 for all
4456             // the others.
4457 
4458             ordinal = AllocNode<ir::NumberLiteral>(lexer::Number(currentValue));
4459 
4460             endLoc = ident->End();
4461         }
4462 
4463         auto *const member = AllocNode<ir::TSEnumMember>(ident, ordinal);
4464         member->SetRange({ident->Start(), endLoc});
4465         members.emplace_back(member);
4466 
4467         ++currentValue;
4468     };
4469 
4470     parseMember();
4471 
4472     while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
4473         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) {
4474             ThrowSyntaxError(MISSING_COMMA_IN_ENUM);
4475         }
4476 
4477         Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat ','
4478 
4479         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
4480             break;
4481         }
4482 
4483         parseMember();
4484     }
4485 }
4486 
ParseStringEnum(ArenaVector<ir::AstNode * > & members)4487 void ETSParser::ParseStringEnum(ArenaVector<ir::AstNode *> &members)
4488 {
4489     // Lambda to parse enum member (maybe with initializer)
4490     auto const parseMember = [this, &members]() {
4491         auto *const ident = ExpectIdentifier();
4492 
4493         ir::StringLiteral *itemValue;
4494 
4495         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
4496             // Case when user explicitly set the value for enumeration constant
4497 
4498             Lexer()->NextToken();
4499             if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_STRING) {
4500                 ThrowSyntaxError(INVALID_ENUM_TYPE);
4501             }
4502 
4503             itemValue = ParseStringLiteral();
4504         } else {
4505             // Default item value is not allowed for string type enumerations!
4506             ThrowSyntaxError("All items of string-type enumeration should be explicitly initialized.");
4507         }
4508 
4509         auto *const member = AllocNode<ir::TSEnumMember>(ident, itemValue);
4510         member->SetRange({ident->Start(), itemValue->End()});
4511         members.emplace_back(member);
4512     };
4513 
4514     parseMember();
4515 
4516     while (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
4517         if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA) {
4518             ThrowSyntaxError(MISSING_COMMA_IN_ENUM);
4519         }
4520 
4521         Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT);  // eat ','
4522 
4523         if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) {
4524             ThrowSyntaxError(TRAILING_COMMA_IN_ENUM);
4525         }
4526 
4527         parseMember();
4528     }
4529 }
4530 
ParseThisExpression()4531 ir::ThisExpression *ETSParser::ParseThisExpression()
4532 {
4533     auto *thisExpression = TypedParser::ParseThisExpression();
4534 
4535     if (Lexer()->GetToken().NewLine()) {
4536         return thisExpression;
4537     }
4538 
4539     switch (Lexer()->GetToken().Type()) {
4540         case lexer::TokenType::PUNCTUATOR_PERIOD:
4541         case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS:
4542         case lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS:
4543         case lexer::TokenType::PUNCTUATOR_SEMI_COLON:
4544         case lexer::TokenType::PUNCTUATOR_COLON:
4545         case lexer::TokenType::PUNCTUATOR_EQUAL:
4546         case lexer::TokenType::PUNCTUATOR_NOT_EQUAL:
4547         case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL:
4548         case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL:
4549         case lexer::TokenType::PUNCTUATOR_COMMA:
4550         case lexer::TokenType::PUNCTUATOR_QUESTION_MARK:
4551         case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET:
4552         case lexer::TokenType::KEYW_AS: {
4553             break;
4554         }
4555         default: {
4556             ThrowUnexpectedToken(Lexer()->GetToken().Type());
4557             break;
4558         }
4559     }
4560 
4561     return thisExpression;
4562 }
4563 
ParseClassIdent(ir::ClassDefinitionModifiers modifiers)4564 ir::Identifier *ETSParser::ParseClassIdent([[maybe_unused]] ir::ClassDefinitionModifiers modifiers)
4565 {
4566     return ExpectIdentifier(false, true);
4567 }
4568 
4569 // NOLINTNEXTLINE(google-default-arguments)
ParseClassStatement(StatementParsingFlags flags,ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags modFlags)4570 ir::ClassDeclaration *ETSParser::ParseClassStatement([[maybe_unused]] StatementParsingFlags flags,
4571                                                      [[maybe_unused]] ir::ClassDefinitionModifiers modifiers,
4572                                                      [[maybe_unused]] ir::ModifierFlags modFlags)
4573 {
4574     ThrowSyntaxError("Illegal start of expression", Lexer()->GetToken().Start());
4575 }
4576 
4577 // NOLINTNEXTLINE(google-default-arguments)
ParseStructStatement(StatementParsingFlags flags,ir::ClassDefinitionModifiers modifiers,ir::ModifierFlags modFlags)4578 ir::ETSStructDeclaration *ETSParser::ParseStructStatement([[maybe_unused]] StatementParsingFlags flags,
4579                                                           [[maybe_unused]] ir::ClassDefinitionModifiers modifiers,
4580                                                           [[maybe_unused]] ir::ModifierFlags modFlags)
4581 {
4582     ThrowSyntaxError("Illegal start of expression", Lexer()->GetToken().Start());
4583 }
4584 
CheckClassElement(ir::AstNode * property,ir::MethodDefinition * & ctor,ArenaVector<ir::AstNode * > & properties)4585 bool ETSParser::CheckClassElement(ir::AstNode *property, [[maybe_unused]] ir::MethodDefinition *&ctor,
4586                                   [[maybe_unused]] ArenaVector<ir::AstNode *> &properties)
4587 {
4588     if (property->IsClassStaticBlock()) {
4589         if (std::any_of(properties.cbegin(), properties.cend(),
4590                         [](const auto *prop) { return prop->IsClassStaticBlock(); })) {
4591             ThrowSyntaxError("Only one static block is allowed", property->Start());
4592         }
4593 
4594         auto *id = AllocNode<ir::Identifier>(compiler::Signatures::CCTOR, Allocator());
4595         property->AsClassStaticBlock()->Function()->SetIdent(id);
4596     }
4597 
4598     if (property->IsTSInterfaceBody()) {
4599         return CheckClassElementInterfaceBody(property, properties);
4600     }
4601 
4602     if (!property->IsMethodDefinition()) {
4603         return false;
4604     }
4605 
4606     auto const *const method = property->AsMethodDefinition();
4607     auto const *const function = method->Function();
4608 
4609     //  Check the special '$_get' and '$_set' methods using for object's index access
4610     if (method->Kind() == ir::MethodDefinitionKind::METHOD) {
4611         CheckIndexAccessMethod(function, property->Start());
4612     }
4613 
4614     return false;  // resolve overloads later on scopes stage
4615 }
4616 
CheckIndexAccessMethod(ir::ScriptFunction const * function,const lexer::SourcePosition & position) const4617 void ETSParser::CheckIndexAccessMethod(ir::ScriptFunction const *function, const lexer::SourcePosition &position) const
4618 {
4619     auto const name = function->Id()->Name();
4620     if (name.Is(compiler::Signatures::GET_INDEX_METHOD)) {
4621         if (function->IsAsyncFunc()) {
4622             ThrowSyntaxError(std::string {ir::INDEX_ACCESS_ERROR_1} + std::string {name.Utf8()} +
4623                                  std::string {ir::INDEX_ACCESS_ERROR_2},
4624                              position);
4625         }
4626 
4627         bool isValid = function->Params().size() == 1U;
4628         if (isValid) {
4629             auto const *const param = function->Params()[0]->AsETSParameterExpression();
4630             isValid = !param->IsDefault() && !param->IsRestParameter();
4631         }
4632 
4633         if (!isValid) {
4634             ThrowSyntaxError(std::string {ir::INDEX_ACCESS_ERROR_1} + std::string {name.Utf8()} +
4635                                  std::string {"' should have exactly one required parameter."},
4636                              position);
4637         }
4638     } else if (name.Is(compiler::Signatures::SET_INDEX_METHOD)) {
4639         if (function->IsAsyncFunc()) {
4640             ThrowSyntaxError(std::string {ir::INDEX_ACCESS_ERROR_1} + std::string {name.Utf8()} +
4641                                  std::string {ir::INDEX_ACCESS_ERROR_2},
4642                              position);
4643         }
4644 
4645         bool isValid = function->Params().size() == 2U;
4646         if (isValid) {
4647             auto const *const param1 = function->Params()[0]->AsETSParameterExpression();
4648             auto const *const param2 = function->Params()[1]->AsETSParameterExpression();
4649             isValid = !param1->IsDefault() && !param1->IsRestParameter() && !param2->IsDefault() &&
4650                       !param2->IsRestParameter();
4651         }
4652 
4653         if (!isValid) {
4654             ThrowSyntaxError(std::string {ir::INDEX_ACCESS_ERROR_1} + std::string {name.Utf8()} +
4655                                  std::string {"' should have exactly two required parameters."},
4656                              position);
4657         }
4658     }
4659 }
4660 
CreateImplicitConstructor(ir::MethodDefinition * & ctor,ArenaVector<ir::AstNode * > & properties,ir::ClassDefinitionModifiers modifiers,const lexer::SourcePosition & startLoc)4661 void ETSParser::CreateImplicitConstructor([[maybe_unused]] ir::MethodDefinition *&ctor,
4662                                           ArenaVector<ir::AstNode *> &properties,
4663                                           [[maybe_unused]] ir::ClassDefinitionModifiers modifiers,
4664                                           const lexer::SourcePosition &startLoc)
4665 {
4666     if (std::any_of(properties.cbegin(), properties.cend(), [](ir::AstNode *prop) {
4667             return prop->IsMethodDefinition() && prop->AsMethodDefinition()->IsConstructor();
4668         })) {
4669         return;
4670     }
4671 
4672     if ((modifiers & ir::ClassDefinitionModifiers::ANONYMOUS) != 0) {
4673         return;
4674     }
4675 
4676     auto *methodDef = BuildImplicitConstructor(ir::ClassDefinitionModifiers::SET_CTOR_ID, startLoc);
4677     properties.push_back(methodDef);
4678 }
4679 
ParsePotentialExpressionSequence(ir::Expression * expr,ExpressionParseFlags flags)4680 ir::Expression *ETSParser::ParsePotentialExpressionSequence(ir::Expression *expr, ExpressionParseFlags flags)
4681 {
4682     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA &&
4683         (flags & ExpressionParseFlags::ACCEPT_COMMA) != 0 && (flags & ExpressionParseFlags::IN_FOR) != 0U) {
4684         return ParseSequenceExpression(expr, (flags & ExpressionParseFlags::ACCEPT_REST) != 0);
4685     }
4686 
4687     return expr;
4688 }
4689 
ParsePotentialNonNullExpression(ir::Expression ** expression,const lexer::SourcePosition startLoc)4690 bool ETSParser::ParsePotentialNonNullExpression(ir::Expression **expression, const lexer::SourcePosition startLoc)
4691 {
4692     if (expression == nullptr || Lexer()->GetToken().NewLine()) {
4693         return true;
4694     }
4695 
4696     const auto nonNullExpr = AllocNode<ir::TSNonNullExpression>(*expression);
4697     nonNullExpr->SetRange({startLoc, Lexer()->GetToken().End()});
4698     nonNullExpr->SetParent(*expression);
4699 
4700     *expression = nonNullExpr;
4701 
4702     Lexer()->NextToken();
4703 
4704     return false;
4705 }
4706 
IsStructKeyword() const4707 bool ETSParser::IsStructKeyword() const
4708 {
4709     return (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT &&
4710             Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STRUCT);
4711 }
4712 
ValidateInstanceOfExpression(ir::Expression * expr)4713 void ETSParser::ValidateInstanceOfExpression(ir::Expression *expr)
4714 {
4715     ValidateGroupedExpression(expr);
4716     lexer::TokenType tokenType = Lexer()->GetToken().Type();
4717     if (tokenType == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
4718         auto options = TypeAnnotationParsingOptions::NO_OPTS;
4719 
4720         // Run checks to validate type declarations
4721         // Should provide helpful messages with incorrect declarations like the following:
4722         // `instanceof A<String;`
4723         ParseTypeParameterDeclaration(&options);
4724 
4725         // Display error message even when type declaration is correct
4726         // `instanceof A<String>;`
4727         ThrowSyntaxError("Invalid right-hand side in 'instanceof' expression");
4728     }
4729 }
4730 
4731 // NOLINTNEXTLINE(google-default-arguments)
ParseExpression(ExpressionParseFlags flags)4732 ir::Expression *ETSParser::ParseExpression(ExpressionParseFlags flags)
4733 {
4734     if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_YIELD &&
4735         (flags & ExpressionParseFlags::DISALLOW_YIELD) == 0U) {
4736         ir::YieldExpression *yieldExpr = ParseYieldExpression();
4737 
4738         return ParsePotentialExpressionSequence(yieldExpr, flags);
4739     }
4740 
4741     ir::Expression *unaryExpressionNode = ParseUnaryOrPrefixUpdateExpression(flags);
4742     if ((flags & ExpressionParseFlags::INSTANCEOF) != 0) {
4743         ValidateInstanceOfExpression(unaryExpressionNode);
4744     }
4745 
4746     ir::Expression *assignmentExpression = ParseAssignmentExpression(unaryExpressionNode, flags);
4747 
4748     if (Lexer()->GetToken().NewLine()) {
4749         return assignmentExpression;
4750     }
4751 
4752     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA &&
4753         (flags & ExpressionParseFlags::ACCEPT_COMMA) != 0U && (flags & ExpressionParseFlags::IN_FOR) != 0U) {
4754         return ParseSequenceExpression(assignmentExpression, (flags & ExpressionParseFlags::ACCEPT_REST) != 0U);
4755     }
4756 
4757     return assignmentExpression;
4758 }
4759 
ParseTrailingBlock(ir::CallExpression * callExpr)4760 void ETSParser::ParseTrailingBlock(ir::CallExpression *callExpr)
4761 {
4762     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_BRACE) {
4763         callExpr->SetIsTrailingBlockInNewLine(Lexer()->GetToken().NewLine());
4764         callExpr->SetTrailingBlock(ParseBlockStatement());
4765     }
4766 }
4767 
ParseCoercedNumberLiteral()4768 ir::Expression *ETSParser::ParseCoercedNumberLiteral()
4769 {
4770     if ((Lexer()->GetToken().Flags() & lexer::TokenFlags::NUMBER_FLOAT) != 0U) {
4771         auto *number = AllocNode<ir::NumberLiteral>(Lexer()->GetToken().GetNumber());
4772         number->SetRange(Lexer()->GetToken().Loc());
4773         auto *floatType = AllocNode<ir::ETSPrimitiveType>(ir::PrimitiveType::FLOAT);
4774         floatType->SetRange(Lexer()->GetToken().Loc());
4775         auto *asExpression = AllocNode<ir::TSAsExpression>(number, floatType, true);
4776         asExpression->SetRange(Lexer()->GetToken().Loc());
4777 
4778         Lexer()->NextToken();
4779         return asExpression;
4780     }
4781     return ParseNumberLiteral();
4782 }
4783 
CheckDeclare()4784 void ETSParser::CheckDeclare()
4785 {
4786     ASSERT(Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE);
4787 
4788     if (InAmbientContext()) {
4789         ThrowSyntaxError("A 'declare' modifier cannot be used in an already ambient context.");
4790     }
4791 
4792     GetContext().Status() |= ParserStatus::IN_AMBIENT_CONTEXT;
4793 
4794     Lexer()->NextToken();  // eat 'declare'
4795 
4796     switch (Lexer()->GetToken().KeywordType()) {
4797         case lexer::TokenType::KEYW_LET:
4798         case lexer::TokenType::KEYW_CONST:
4799         case lexer::TokenType::KEYW_FUNCTION:
4800         case lexer::TokenType::KEYW_CLASS:
4801         case lexer::TokenType::KEYW_NAMESPACE:
4802         case lexer::TokenType::KEYW_ENUM:
4803         case lexer::TokenType::KEYW_TYPE:
4804         case lexer::TokenType::KEYW_ABSTRACT:
4805         case lexer::TokenType::KEYW_INTERFACE: {
4806             return;
4807         }
4808         default: {
4809             ThrowSyntaxError("Unexpected token.");
4810         }
4811     }
4812 }
4813 
4814 //================================================================================================//
4815 //  Methods to create AST node(s) from the specified string (part of valid ETS-code!)
4816 //================================================================================================//
4817 
4818 // NOLINTBEGIN(modernize-avoid-c-arrays)
4819 static constexpr char const INVALID_NUMBER_NODE[] = "Invalid node number in format expression.";
4820 static constexpr char const INVALID_FORMAT_NODE[] = "Invalid node type in format expression.";
4821 static constexpr char const INSERT_NODE_ABSENT[] = "There is no any node to insert at the placeholder position.";
4822 static constexpr char const INVALID_INSERT_NODE[] =
4823     "Inserting node type differs from that required by format specification.";
4824 // NOLINTEND(modernize-avoid-c-arrays)
4825 
GetFormatPlaceholderIdent() const4826 ParserImpl::NodeFormatType ETSParser::GetFormatPlaceholderIdent() const
4827 {
4828     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_FORMAT);
4829     Lexer()->NextToken();
4830     ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT);
4831 
4832     char const *const identData = Lexer()->GetToken().Ident().Bytes();
4833 
4834     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic, cert-err34-c)
4835     auto identNumber = std::atoi(identData + 1U);
4836     if (identNumber <= 0) {
4837         ThrowSyntaxError(INVALID_NUMBER_NODE, Lexer()->GetToken().Start());
4838     }
4839 
4840     return {*identData, static_cast<decltype(std::declval<ParserImpl::NodeFormatType>().second)>(identNumber - 1)};
4841 }
4842 
ParseFormatPlaceholder()4843 ir::AstNode *ETSParser::ParseFormatPlaceholder()
4844 {
4845     if (insertingNodes_.empty()) {
4846         ThrowSyntaxError(INSERT_NODE_ABSENT, Lexer()->GetToken().Start());
4847     }
4848 
4849     if (auto nodeFormat = GetFormatPlaceholderIdent(); nodeFormat.first == EXPRESSION_FORMAT_NODE) {
4850         return ParseExpressionFormatPlaceholder(std::make_optional(nodeFormat));
4851     } else if (nodeFormat.first == IDENTIFIER_FORMAT_NODE) {  // NOLINT(readability-else-after-return)
4852         return ParseIdentifierFormatPlaceholder(std::make_optional(nodeFormat));
4853     } else if (nodeFormat.first == TYPE_FORMAT_NODE) {  // NOLINT(readability-else-after-return)
4854         return ParseTypeFormatPlaceholder(std::make_optional(nodeFormat));
4855     } else if (nodeFormat.first == STATEMENT_FORMAT_NODE) {  // NOLINT(readability-else-after-return)
4856         return ParseStatementFormatPlaceholder(std::make_optional(nodeFormat));
4857     }
4858 
4859     ThrowSyntaxError(INVALID_FORMAT_NODE, Lexer()->GetToken().Start());
4860 }
4861 
ParseExpressionFormatPlaceholder(std::optional<ParserImpl::NodeFormatType> nodeFormat)4862 ir::Expression *ETSParser::ParseExpressionFormatPlaceholder(std::optional<ParserImpl::NodeFormatType> nodeFormat)
4863 {
4864     if (!nodeFormat.has_value()) {
4865         if (insertingNodes_.empty()) {
4866             ThrowSyntaxError(INSERT_NODE_ABSENT, Lexer()->GetToken().Start());
4867         }
4868 
4869         if (nodeFormat = GetFormatPlaceholderIdent(); nodeFormat->first == TYPE_FORMAT_NODE) {
4870             return ParseTypeFormatPlaceholder(std::move(nodeFormat));
4871         } else if (nodeFormat->first == IDENTIFIER_FORMAT_NODE) {  // NOLINT(readability-else-after-return)
4872             return ParseIdentifierFormatPlaceholder(std::move(nodeFormat));
4873         } else if (nodeFormat->first != EXPRESSION_FORMAT_NODE) {  // NOLINT(readability-else-after-return)
4874             ThrowSyntaxError(INVALID_FORMAT_NODE, Lexer()->GetToken().Start());
4875         }
4876     }
4877 
4878     auto *const insertingNode =
4879         nodeFormat->second < insertingNodes_.size() ? insertingNodes_[nodeFormat->second] : nullptr;
4880     if (insertingNode == nullptr || !insertingNode->IsExpression()) {
4881         ThrowSyntaxError(INVALID_INSERT_NODE, Lexer()->GetToken().Start());
4882     }
4883 
4884     auto *const insertExpression = insertingNode->AsExpression();
4885     Lexer()->NextToken();
4886     return insertExpression;
4887 }
4888 
ParseTypeFormatPlaceholder(std::optional<ParserImpl::NodeFormatType> nodeFormat)4889 ir::TypeNode *ETSParser::ParseTypeFormatPlaceholder(std::optional<ParserImpl::NodeFormatType> nodeFormat)
4890 {
4891     if (!nodeFormat.has_value()) {
4892         if (insertingNodes_.empty()) {
4893             ThrowSyntaxError(INSERT_NODE_ABSENT, Lexer()->GetToken().Start());
4894         }
4895 
4896         if (nodeFormat = GetFormatPlaceholderIdent(); nodeFormat->first != TYPE_FORMAT_NODE) {
4897             ThrowSyntaxError(INVALID_FORMAT_NODE, Lexer()->GetToken().Start());
4898         }
4899     }
4900 
4901     auto *const insertingNode =
4902         nodeFormat->second < insertingNodes_.size() ? insertingNodes_[nodeFormat->second] : nullptr;
4903     if (insertingNode == nullptr || !insertingNode->IsExpression() || !insertingNode->AsExpression()->IsTypeNode()) {
4904         ThrowSyntaxError(INVALID_INSERT_NODE, Lexer()->GetToken().Start());
4905     }
4906 
4907     auto *const insertType = insertingNode->AsExpression()->AsTypeNode();
4908     Lexer()->NextToken();
4909     return insertType;
4910 }
4911 
4912 // NOLINTNEXTLINE(google-default-arguments)
ParseIdentifierFormatPlaceholder(std::optional<ParserImpl::NodeFormatType> nodeFormat)4913 ir::Identifier *ETSParser::ParseIdentifierFormatPlaceholder(std::optional<ParserImpl::NodeFormatType> nodeFormat)
4914 {
4915     if (!nodeFormat.has_value()) {
4916         if (insertingNodes_.empty()) {
4917             ThrowSyntaxError(INSERT_NODE_ABSENT, Lexer()->GetToken().Start());
4918         }
4919 
4920         if (nodeFormat = GetFormatPlaceholderIdent(); nodeFormat->first != IDENTIFIER_FORMAT_NODE) {
4921             ThrowSyntaxError(INVALID_FORMAT_NODE, Lexer()->GetToken().Start());
4922         }
4923     }
4924 
4925     auto *const insertingNode =
4926         nodeFormat->second < insertingNodes_.size() ? insertingNodes_[nodeFormat->second] : nullptr;
4927     if (insertingNode == nullptr || !insertingNode->IsExpression() || !insertingNode->AsExpression()->IsIdentifier()) {
4928         ThrowSyntaxError(INVALID_INSERT_NODE, Lexer()->GetToken().Start());
4929     }
4930 
4931     auto *const insertIdentifier = insertingNode->AsExpression()->AsIdentifier();
4932     Lexer()->NextToken();
4933     return insertIdentifier;
4934 }
4935 
ParseStatementFormatPlaceholder(std::optional<ParserImpl::NodeFormatType> nodeFormat)4936 ir::Statement *ETSParser::ParseStatementFormatPlaceholder(std::optional<ParserImpl::NodeFormatType> nodeFormat)
4937 {
4938     if (!nodeFormat.has_value()) {
4939         if (insertingNodes_.empty()) {
4940             ThrowSyntaxError(INSERT_NODE_ABSENT, Lexer()->GetToken().Start());
4941         }
4942 
4943         if (nodeFormat = GetFormatPlaceholderIdent(); nodeFormat->first != STATEMENT_FORMAT_NODE) {
4944             ThrowSyntaxError(INVALID_FORMAT_NODE, Lexer()->GetToken().Start());
4945         }
4946     }
4947 
4948     auto *const insertingNode =
4949         nodeFormat->second < insertingNodes_.size() ? insertingNodes_[nodeFormat->second] : nullptr;
4950     if (insertingNode == nullptr || !insertingNode->IsStatement()) {
4951         ThrowSyntaxError(INVALID_INSERT_NODE, Lexer()->GetToken().Start());
4952     }
4953 
4954     auto *const insertStatement = insertingNode->AsStatement();
4955     Lexer()->NextToken();
4956     return insertStatement;
4957 }
4958 
CreateStatement(std::string_view const sourceCode,std::string_view const fileName)4959 ir::Statement *ETSParser::CreateStatement(std::string_view const sourceCode, std::string_view const fileName)
4960 {
4961     util::UString source {sourceCode, Allocator()};
4962     auto const isp = InnerSourceParser(this);
4963     auto const lexer = InitLexer({fileName, source.View().Utf8()});
4964 
4965     lexer::SourcePosition const startLoc = lexer->GetToken().Start();
4966     lexer->NextToken();
4967 
4968     auto statements = ParseStatementList(StatementParsingFlags::STMT_GLOBAL_LEXICAL);
4969     auto const statementNumber = statements.size();
4970     if (statementNumber == 0U) {
4971         return nullptr;
4972     }
4973 
4974     if (statementNumber == 1U) {
4975         return statements[0U];
4976     }
4977 
4978     auto *const blockStmt = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
4979     blockStmt->SetRange({startLoc, lexer->GetToken().End()});
4980 
4981     return blockStmt;
4982 }
4983 
CreateFormattedStatement(std::string_view const sourceCode,std::vector<ir::AstNode * > & insertingNodes,std::string_view const fileName)4984 ir::Statement *ETSParser::CreateFormattedStatement(std::string_view const sourceCode,
4985                                                    std::vector<ir::AstNode *> &insertingNodes,
4986                                                    std::string_view const fileName)
4987 {
4988     insertingNodes_.swap(insertingNodes);
4989     auto const statement = CreateStatement(sourceCode, fileName);
4990     insertingNodes_.swap(insertingNodes);
4991     return statement;
4992 }
4993 
CreateStatements(std::string_view const sourceCode,std::string_view const fileName)4994 ArenaVector<ir::Statement *> ETSParser::CreateStatements(std::string_view const sourceCode,
4995                                                          std::string_view const fileName)
4996 {
4997     util::UString source {sourceCode, Allocator()};
4998     auto const isp = InnerSourceParser(this);
4999     auto const lexer = InitLexer({fileName, source.View().Utf8()});
5000 
5001     lexer->NextToken();
5002     return ParseStatementList(StatementParsingFlags::STMT_GLOBAL_LEXICAL);
5003 }
5004 
CreateFormattedStatements(std::string_view const sourceCode,std::vector<ir::AstNode * > & insertingNodes,std::string_view const fileName)5005 ArenaVector<ir::Statement *> ETSParser::CreateFormattedStatements(std::string_view const sourceCode,
5006                                                                   std::vector<ir::AstNode *> &insertingNodes,
5007                                                                   std::string_view const fileName)
5008 {
5009     insertingNodes_.swap(insertingNodes);
5010     auto statements = CreateStatements(sourceCode, fileName);
5011     insertingNodes_.swap(insertingNodes);
5012     return statements;
5013 }
5014 
CreateMethodDefinition(ir::ModifierFlags modifiers,std::string_view const sourceCode,std::string_view const fileName)5015 ir::MethodDefinition *ETSParser::CreateMethodDefinition(ir::ModifierFlags modifiers, std::string_view const sourceCode,
5016                                                         std::string_view const fileName)
5017 {
5018     util::UString source {sourceCode, Allocator()};
5019     auto const isp = InnerSourceParser(this);
5020     auto const lexer = InitLexer({fileName, source.View().Utf8()});
5021 
5022     auto const startLoc = Lexer()->GetToken().Start();
5023     Lexer()->NextToken();
5024 
5025     if (IsClassMethodModifier(Lexer()->GetToken().Type())) {
5026         modifiers |= ParseClassMethodModifiers(false);
5027     }
5028 
5029     ir::MethodDefinition *methodDefinition = nullptr;
5030     auto *methodName = ExpectIdentifier();
5031 
5032     if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS ||
5033         Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) {
5034         methodDefinition = ParseClassMethodDefinition(methodName, modifiers);
5035         methodDefinition->SetStart(startLoc);
5036     }
5037 
5038     return methodDefinition;
5039 }
5040 
CreateConstructorDefinition(ir::ModifierFlags modifiers,std::string_view const sourceCode,std::string_view const fileName)5041 ir::MethodDefinition *ETSParser::CreateConstructorDefinition(ir::ModifierFlags modifiers,
5042                                                              std::string_view const sourceCode,
5043                                                              std::string_view const fileName)
5044 {
5045     util::UString source {sourceCode, Allocator()};
5046     auto const isp = InnerSourceParser(this);
5047     auto const lexer = InitLexer({fileName, source.View().Utf8()});
5048 
5049     auto const startLoc = Lexer()->GetToken().Start();
5050     Lexer()->NextToken();
5051 
5052     if (IsClassMethodModifier(Lexer()->GetToken().Type())) {
5053         modifiers |= ParseClassMethodModifiers(false);
5054     }
5055 
5056     if (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_CONSTRUCTOR) {
5057         ThrowSyntaxError({"Unexpected token. 'Constructor' keyword is expected."});
5058     }
5059 
5060     if ((modifiers & ir::ModifierFlags::ASYNC) != 0) {
5061         ThrowSyntaxError({"Constructor should not be async."});
5062     }
5063 
5064     auto *memberName = AllocNode<ir::Identifier>(Lexer()->GetToken().Ident(), Allocator());
5065     modifiers |= ir::ModifierFlags::CONSTRUCTOR;
5066     Lexer()->NextToken();
5067 
5068     auto *const methodDefinition = ParseClassMethodDefinition(memberName, modifiers);
5069     methodDefinition->SetStart(startLoc);
5070 
5071     return methodDefinition;
5072 }
5073 
CreateExpression(std::string_view const sourceCode,ExpressionParseFlags const flags,std::string_view const fileName)5074 ir::Expression *ETSParser::CreateExpression(std::string_view const sourceCode, ExpressionParseFlags const flags,
5075                                             std::string_view const fileName)
5076 {
5077     util::UString source {sourceCode, Allocator()};
5078     auto const isp = InnerSourceParser(this);
5079     auto const lexer = InitLexer({fileName, source.View().Utf8()});
5080 
5081     lexer::SourcePosition const startLoc = lexer->GetToken().Start();
5082     lexer->NextToken();
5083 
5084     ir::Expression *returnExpression = ParseExpression(flags);
5085     returnExpression->SetRange({startLoc, lexer->GetToken().End()});
5086 
5087     return returnExpression;
5088 }
5089 
CreateFormattedExpression(std::string_view const sourceCode,std::vector<ir::AstNode * > & insertingNodes,std::string_view const fileName)5090 ir::Expression *ETSParser::CreateFormattedExpression(std::string_view const sourceCode,
5091                                                      std::vector<ir::AstNode *> &insertingNodes,
5092                                                      std::string_view const fileName)
5093 {
5094     ir::Expression *returnExpression;
5095     insertingNodes_.swap(insertingNodes);
5096 
5097     if (auto statements = CreateStatements(sourceCode, fileName);
5098         statements.size() == 1U && statements.back()->IsExpressionStatement()) {
5099         returnExpression = statements.back()->AsExpressionStatement()->GetExpression();
5100     } else {
5101         returnExpression = AllocNode<ir::BlockExpression>(std::move(statements));
5102     }
5103 
5104     insertingNodes_.swap(insertingNodes);
5105     return returnExpression;
5106 }
5107 
CreateTypeAnnotation(TypeAnnotationParsingOptions * options,std::string_view const sourceCode,std::string_view const fileName)5108 ir::TypeNode *ETSParser::CreateTypeAnnotation(TypeAnnotationParsingOptions *options, std::string_view const sourceCode,
5109                                               std::string_view const fileName)
5110 {
5111     util::UString source {sourceCode, Allocator()};
5112     auto const isp = InnerSourceParser(this);
5113     auto const lexer = InitLexer({fileName, source.View().Utf8()});
5114 
5115     lexer->NextToken();
5116     return ParseTypeAnnotation(options);
5117 }
5118 
5119 //================================================================================================//
5120 //  ExternalSourceParser class
5121 //================================================================================================//
5122 
ExternalSourceParser(ETSParser * parser,Program * newProgram)5123 ExternalSourceParser::ExternalSourceParser(ETSParser *parser, Program *newProgram)
5124     : parser_(parser),
5125       savedProgram_(parser_->GetProgram()),
5126       savedLexer_(parser_->Lexer()),
5127       savedTopScope_(parser_->GetProgram()->VarBinder()->TopScope())
5128 {
5129     parser_->SetProgram(newProgram);
5130     parser_->GetContext().SetProgram(newProgram);
5131 }
5132 
~ExternalSourceParser()5133 ExternalSourceParser::~ExternalSourceParser()
5134 {
5135     parser_->SetLexer(savedLexer_);
5136     parser_->SetProgram(savedProgram_);
5137     parser_->GetContext().SetProgram(savedProgram_);
5138     parser_->GetProgram()->VarBinder()->ResetTopScope(savedTopScope_);
5139 }
5140 
5141 //================================================================================================//
5142 //  InnerSourceParser class
5143 //================================================================================================//
5144 
InnerSourceParser(ETSParser * parser)5145 InnerSourceParser::InnerSourceParser(ETSParser *parser)
5146     : parser_(parser),
5147       savedLexer_(parser_->Lexer()),
5148       savedSourceCode_(parser_->GetProgram()->SourceCode()),
5149       savedSourceFile_(parser_->GetProgram()->SourceFilePath()),
5150       savedSourceFilePath_(parser_->GetProgram()->SourceFileFolder())
5151 {
5152 }
5153 
~InnerSourceParser()5154 InnerSourceParser::~InnerSourceParser()
5155 {
5156     parser_->SetLexer(savedLexer_);
5157     parser_->GetProgram()->SetSource(savedSourceCode_, savedSourceFile_, savedSourceFilePath_);
5158 }
5159 }  // namespace panda::es2panda::parser
5160 #undef USE_UNIX_SYSCALL
5161