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