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