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