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 *> ¶ms, [[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, ¤tValue]() {
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