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