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