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 *> ¶ms, [[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