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