From e06da2f637a0dfa47af3c837867a1ee657738645 Mon Sep 17 00:00:00 2001 From: Boglarka Haag Date: Mon, 22 Jul 2024 14:15:29 +0200 Subject: [PATCH] [ETS] Title Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/IAES77 Reason: Code style fixes required in TSparser.cpp Description: Refactoring some methods to align with the style requirements and separating the file to macth the requirements Signed-off-by: Haag Boglarka --- ets2panda/BUILD.gn | 2 + ets2panda/CMakeLists.txt | 2 + ets2panda/parser/TSparser.cpp | 1201 +++-------------- ets2panda/parser/TSparser.h | 5 + ets2panda/parser/expressionTSParser.cpp | 676 ++++++++++ ets2panda/parser/statementTSParser.cpp | 373 +++++ .../parser/ts/test_import_type-expected.txt | 8 +- 7 files changed, 1277 insertions(+), 990 deletions(-) create mode 100644 ets2panda/parser/expressionTSParser.cpp create mode 100644 ets2panda/parser/statementTSParser.cpp diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index c7a2c0f773..8e8597a68f 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -388,9 +388,11 @@ libes2panda_sources = [ "parser/context/classPrivateContext.cpp", "parser/context/parserContext.cpp", "parser/expressionParser.cpp", + "parser/expressionTSParser.cpp", "parser/parserImpl.cpp", "parser/program/program.cpp", "parser/statementParser.cpp", + "parser/statementTSParser.cpp", "util/arktsconfig.cpp", "util/bitset.cpp", "util/errorHandler.cpp", diff --git a/ets2panda/CMakeLists.txt b/ets2panda/CMakeLists.txt index f6f77d63f6..561119ddb8 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -373,6 +373,7 @@ set(ES2PANDA_LIB_SRC parser/context/classPrivateContext.cpp parser/context/parserContext.cpp parser/expressionParser.cpp + parser/expressionTSParser.cpp parser/ASparser.cpp parser/JSparser.cpp parser/parserImpl.cpp @@ -383,6 +384,7 @@ set(ES2PANDA_LIB_SRC parser/TypedParser.cpp parser/program/program.cpp parser/statementParser.cpp + parser/statementTSParser.cpp checker/checker.cpp checker/checkerContext.cpp checker/ETSAnalyzer.cpp diff --git a/ets2panda/parser/TSparser.cpp b/ets2panda/parser/TSparser.cpp index f15dd0d940..d7f0bda065 100644 --- a/ets2panda/parser/TSparser.cpp +++ b/ets2panda/parser/TSparser.cpp @@ -15,6 +15,7 @@ #include "TSparser.h" +#include "macros.h" #include "parserFlags.h" #include "util/helpers.h" #include "varbinder/privateBinding.h" @@ -222,201 +223,6 @@ ir::TSTypeAliasDeclaration *TSParser::ParseTypeAliasDeclaration() return typeAliasDecl; } -// NOLINTNEXTLINE(google-default-arguments) -ir::Statement *TSParser::ParseStatement(StatementParsingFlags flags) -{ - return ParseDeclareAndDecorators(flags); -} - -ir::Expression *TSParser::ParsePotentialAsExpression(ir::Expression *expr) -{ - if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_AS) { - return nullptr; - } - - Lexer()->NextToken(); // eat 'as' - TypeAnnotationParsingOptions options = - TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::ALLOW_CONST; - ir::TypeNode *typeAnnotation = ParseTypeAnnotation(&options); - - bool isConst = false; - if (typeAnnotation->IsTSTypeReference() && typeAnnotation->AsTSTypeReference()->TypeName()->IsIdentifier()) { - const util::StringView &refName = typeAnnotation->AsTSTypeReference()->TypeName()->AsIdentifier()->Name(); - if (refName.Is("const")) { - isConst = true; - } - } - - lexer::SourcePosition startLoc = expr->Start(); - auto *asExpr = AllocNode(expr, typeAnnotation, isConst); - asExpr->SetRange({startLoc, Lexer()->GetToken().End()}); - - if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) { - return ParsePotentialAsExpression(asExpr); - } - - return asExpr; -} - -void TSParser::ParseOptionalFunctionParameter(ir::AnnotatedExpression *returnNode, bool isRest) -{ - bool isOptional = false; - - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) { - if (isRest) { - ThrowSyntaxError("A rest parameter cannot be optional"); - } - - switch (returnNode->Type()) { - case ir::AstNodeType::IDENTIFIER: { - returnNode->AsIdentifier()->SetOptional(true); - break; - } - case ir::AstNodeType::OBJECT_PATTERN: - case ir::AstNodeType::ARRAY_PATTERN: { - if (!InAmbientContext() && ((GetContext().Status() & ParserStatus::FUNCTION) != 0)) { - ThrowSyntaxError("A binding pattern parameter cannot be optional in an implementation signature."); - } - - if (returnNode->IsObjectPattern()) { - returnNode->AsObjectPattern()->SetOptional(true); - break; - } - - returnNode->AsArrayPattern()->SetOptional(true); - break; - } - case ir::AstNodeType::REST_ELEMENT: { - returnNode->AsRestElement()->SetOptional(true); - break; - } - default: { - UNREACHABLE(); - } - } - - isOptional = true; - Lexer()->NextToken(); // eat '?' - } - - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { - Lexer()->NextToken(); // eat ':' - TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; - returnNode->SetTsTypeAnnotation(ParseTypeAnnotation(&options)); - } - - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { - return; - } - - if (isRest) { - ThrowSyntaxError("A rest parameter cannot have an initializer"); - } - - if (returnNode->IsIdentifier() && isOptional) { - ThrowSyntaxError("Parameter cannot have question mark and initializer"); - } -} - -// NOLINTNEXTLINE(google-default-arguments) -ir::Expression *TSParser::ParsePatternElement(ExpressionParseFlags flags, bool allowDefault) -{ - ir::AnnotatedExpression *returnNode = nullptr; - bool isOptional = false; - - switch (Lexer()->GetToken().Type()) { - case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: { - returnNode = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN); - isOptional = returnNode->AsArrayPattern()->IsOptional(); - break; - } - case lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD: { - if ((flags & ExpressionParseFlags::IN_REST) != 0) { - ThrowSyntaxError("Unexpected token"); - } - - returnNode = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN); - break; - } - case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { - returnNode = - ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN | ExpressionParseFlags::OBJECT_PATTERN); - isOptional = returnNode->AsObjectPattern()->IsOptional(); - break; - } - case lexer::TokenType::LITERAL_IDENT: { - returnNode = AllocNode(Lexer()->GetToken().Ident(), Allocator()); - returnNode->AsIdentifier()->SetReference(); - - if (returnNode->AsIdentifier()->Decorators().empty()) { - returnNode->SetRange(Lexer()->GetToken().Loc()); - } else { - returnNode->SetRange( - {returnNode->AsIdentifier()->Decorators().front()->Start(), Lexer()->GetToken().End()}); - } - - Lexer()->NextToken(); - - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) { - isOptional = true; - - if ((flags & ExpressionParseFlags::IN_REST) != 0) { - ThrowSyntaxError("A rest parameter cannot be optional"); - } - - returnNode->AsIdentifier()->SetOptional(true); - Lexer()->NextToken(); - } - - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { - Lexer()->NextToken(); // eat ':' - TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; - returnNode->SetTsTypeAnnotation(ParseTypeAnnotation(&options)); - } - break; - } - default: { - ThrowSyntaxError("Unexpected token, expected an identifier."); - } - } - - if ((returnNode->IsObjectPattern() || returnNode->IsArrayPattern()) && !InAmbientContext() && - ((GetContext().Status() & ParserStatus::FUNCTION) != 0) && isOptional) { - ThrowSyntaxError("A binding pattern parameter cannot be optional in an implementation signature."); - } - - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { - return returnNode; - } - - if ((flags & ExpressionParseFlags::IN_REST) != 0) { - ThrowSyntaxError("A rest parameter cannot have an initializer."); - } - - if (!allowDefault) { - ThrowSyntaxError("Invalid destructuring assignment target"); - } - - if (isOptional) { - ThrowSyntaxError("Parameter cannot have question mark and initializer"); - } - - Lexer()->NextToken(); - - if (((GetContext().Status() & ParserStatus::GENERATOR_FUNCTION) != 0) && - Lexer()->GetToken().Type() == lexer::TokenType::KEYW_YIELD) { - ThrowSyntaxError("Yield is not allowed in generator parameters"); - } - - ir::Expression *rightNode = ParseExpression(); - - auto *assignmentExpression = AllocNode( - ir::AstNodeType::ASSIGNMENT_PATTERN, returnNode, rightNode, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); - assignmentExpression->SetRange({returnNode->Start(), rightNode->End()}); - - return assignmentExpression; -} - bool TSParser::CurrentLiteralIsBasicType() const { switch (Lexer()->GetToken().KeywordType()) { @@ -906,29 +712,18 @@ ir::TypeNode *TSParser::ParseTypeReferenceOrQuery(bool parseQuery) if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET && Lexer()->Lookahead() != lexer::LEX_CHAR_RIGHT_SQUARE) { - ir::TypeNode *typeRef {}; - if (parseQuery) { - typeRef = AllocNode(typeName); - } else { - typeRef = AllocNode(typeName, typeParamInst); - } + ir::TypeNode *typeRef = parseQuery ? AllocNode(typeName)->AsTypeNode() + : AllocNode(typeName, typeParamInst)->AsTypeNode(); typeRef->SetRange({referenceStartLoc, Lexer()->GetToken().End()}); return ParseIndexAccessType(typeRef); } - ir::TypeNode *returnNode = nullptr; - - lexer::SourcePosition referenceEndLoc = typeName->End(); - - if (parseQuery) { - returnNode = AllocNode(typeName); - } else { - returnNode = AllocNode(typeName, typeParamInst); - } + ir::TypeNode *returnNode = parseQuery ? AllocNode(typeName)->AsTypeNode() + : AllocNode(typeName, typeParamInst)->AsTypeNode(); - returnNode->SetRange({referenceStartLoc, referenceEndLoc}); + returnNode->SetRange({referenceStartLoc, typeName->End()}); return returnNode; } @@ -1230,130 +1025,116 @@ ir::TSIntersectionType *TSParser::ParseIntersectionType(ir::Expression *type, bo return intersectionType; } -ir::TypeNode *TSParser::ParseBasicType() -{ - ir::TypeNode *typeAnnotation = nullptr; +class TSParser::ParseBasicTypeHelper { + friend ir::TypeNode *TSParser::ParseBasicType(); - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS) { - Lexer()->NextToken(); +private: + static ir::TypeNode *GetTypeAnnotationFromLiteral(TSParser *parser, lexer::Lexer *lexer) + { + switch (lexer->GetToken().KeywordType()) { + case lexer::TokenType::LITERAL_NUMBER: { + if ((lexer->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) != 0) { + auto *bigintNode = parser->AllocNode(lexer->GetToken().BigInt()); + bigintNode->SetRange(lexer->GetToken().Loc()); - if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_NUMBER) { - ThrowSyntaxError("Type expected"); - } - } - switch (Lexer()->GetToken().KeywordType()) { - case lexer::TokenType::LITERAL_NUMBER: { - if ((Lexer()->GetToken().Flags() & lexer::TokenFlags::NUMBER_BIGINT) != 0) { - auto *bigintNode = AllocNode(Lexer()->GetToken().BigInt()); - bigintNode->SetRange(Lexer()->GetToken().Loc()); + return parser->AllocNode(bigintNode); + } + auto *numberNode = parser->AllocNode(lexer->GetToken().GetNumber()); + numberNode->SetRange(lexer->GetToken().Loc()); - typeAnnotation = AllocNode(bigintNode); - } else { - auto *numberNode = AllocNode(Lexer()->GetToken().GetNumber()); - numberNode->SetRange(Lexer()->GetToken().Loc()); + return parser->AllocNode(numberNode); + } + case lexer::TokenType::LITERAL_STRING: { + auto *stringNode = parser->AllocNode(lexer->GetToken().String()); + stringNode->SetRange(lexer->GetToken().Loc()); - typeAnnotation = AllocNode(numberNode); + return parser->AllocNode(stringNode); } - break; - } - case lexer::TokenType::LITERAL_STRING: { - auto *stringNode = AllocNode(Lexer()->GetToken().String()); - stringNode->SetRange(Lexer()->GetToken().Loc()); + case lexer::TokenType::LITERAL_TRUE: { + auto *booleanLiteral = parser->AllocNode(true); + booleanLiteral->SetRange(lexer->GetToken().Loc()); - typeAnnotation = AllocNode(stringNode); - break; - } - case lexer::TokenType::LITERAL_TRUE: { - auto *booleanLiteral = AllocNode(true); - booleanLiteral->SetRange(Lexer()->GetToken().Loc()); + return parser->AllocNode(booleanLiteral); + } + case lexer::TokenType::LITERAL_FALSE: { + auto *booleanLiteral = parser->AllocNode(false); + booleanLiteral->SetRange(lexer->GetToken().Loc()); - typeAnnotation = AllocNode(booleanLiteral); - break; + return parser->AllocNode(booleanLiteral); + } + case lexer::TokenType::LITERAL_NULL: { + return parser->AllocNode(); + } + default: { + return nullptr; + } } - case lexer::TokenType::LITERAL_FALSE: { - auto *booleanLiteral = AllocNode(false); - booleanLiteral->SetRange(Lexer()->GetToken().Loc()); + } - typeAnnotation = AllocNode(booleanLiteral); - break; - } - case lexer::TokenType::KEYW_ANY: { - typeAnnotation = AllocNode(); - break; - } - case lexer::TokenType::KEYW_BOOLEAN: { - typeAnnotation = AllocNode(); - break; - } - case lexer::TokenType::KEYW_NUMBER: { - typeAnnotation = AllocNode(); - break; - } - case lexer::TokenType::KEYW_STRING: { - typeAnnotation = AllocNode(); - break; - } - case lexer::TokenType::KEYW_UNKNOWN: { - typeAnnotation = AllocNode(); - break; - } - case lexer::TokenType::KEYW_VOID: { - typeAnnotation = AllocNode(); - break; - } - case lexer::TokenType::LITERAL_NULL: { - typeAnnotation = AllocNode(); - break; - } - case lexer::TokenType::KEYW_UNDEFINED: { - typeAnnotation = AllocNode(); - break; - } - case lexer::TokenType::KEYW_NEVER: { - typeAnnotation = AllocNode(); - break; - } - case lexer::TokenType::KEYW_OBJECT: { - typeAnnotation = AllocNode(); - break; - } - case lexer::TokenType::KEYW_BIGINT: { - typeAnnotation = AllocNode(); - break; + static ir::TypeNode *GetTypeAnnotation(TSParser *parser, lexer::Lexer *lexer) + { + switch (lexer->GetToken().KeywordType()) { + case lexer::TokenType::LITERAL_NUMBER: + case lexer::TokenType::LITERAL_STRING: + case lexer::TokenType::LITERAL_TRUE: + case lexer::TokenType::LITERAL_FALSE: + case lexer::TokenType::LITERAL_NULL: { + return GetTypeAnnotationFromLiteral(parser, lexer); + } + case lexer::TokenType::KEYW_ANY: { + return parser->AllocNode(); + } + case lexer::TokenType::KEYW_BOOLEAN: { + return parser->AllocNode(); + } + case lexer::TokenType::KEYW_NUMBER: { + return parser->AllocNode(); + } + case lexer::TokenType::KEYW_STRING: { + return parser->AllocNode(); + } + case lexer::TokenType::KEYW_UNKNOWN: { + return parser->AllocNode(); + } + case lexer::TokenType::KEYW_VOID: { + return parser->AllocNode(); + } + case lexer::TokenType::KEYW_UNDEFINED: { + return parser->AllocNode(); + } + case lexer::TokenType::KEYW_NEVER: { + return parser->AllocNode(); + } + case lexer::TokenType::KEYW_OBJECT: { + return parser->AllocNode(); + } + case lexer::TokenType::KEYW_BIGINT: { + return parser->AllocNode(); + } + default: { + parser->ThrowSyntaxError("Unexpected type"); + } } - default: { - ThrowSyntaxError("Unexpected type"); + } +}; +ir::TypeNode *TSParser::ParseBasicType() +{ + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_MINUS) { + Lexer()->NextToken(); + + if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_NUMBER) { + ThrowSyntaxError("Type expected"); } } + ir::TypeNode *typeAnnotation = ParseBasicTypeHelper::GetTypeAnnotation(this, Lexer()); + typeAnnotation->SetRange(Lexer()->GetToken().Loc()); Lexer()->NextToken(); return typeAnnotation; } -ir::TSTypeReference *TSParser::ParseConstExpression() -{ - auto *identRef = AllocNode(Lexer()->GetToken().Ident(), Allocator()); - identRef->SetReference(); - identRef->SetRange(Lexer()->GetToken().Loc()); - - auto *typeReference = AllocNode(identRef, nullptr); - typeReference->SetRange(Lexer()->GetToken().Loc()); - - Lexer()->NextToken(); - - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA && - Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON && - Lexer()->GetToken().Type() != lexer::TokenType::EOS && - Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET && - ((Lexer()->GetToken().Flags() & lexer::TokenFlags::NEW_LINE) == 0)) { - ThrowSyntaxError("Unexpected token."); - } - - return typeReference; -} - ir::TypeNode *TSParser::ParseParenthesizedOrFunctionType(ir::TypeNode *typeAnnotation, bool throwError) { if (typeAnnotation != nullptr) { @@ -1467,80 +1248,130 @@ ir::TypeNode *TSParser::ParseFunctionType(lexer::SourcePosition startLoc, bool i return funcType; } -ir::TypeNode *TSParser::ParseTypeAnnotationElement(ir::TypeNode *typeAnnotation, TypeAnnotationParsingOptions *options) -{ - switch (Lexer()->GetToken().Type()) { - case lexer::TokenType::PUNCTUATOR_BITWISE_OR: { - if (((*options) & - (TypeAnnotationParsingOptions::IN_UNION | TypeAnnotationParsingOptions::IN_INTERSECTION)) != 0) { - break; - } +class TSParser::ParseTypeAnnotationElementHelper { + friend ir::TypeNode *TSParser::ParseTypeAnnotationElement(ir::TypeNode *typeAnnotation, + TypeAnnotationParsingOptions *options); - return ParseUnionType(typeAnnotation, ((*options) & TypeAnnotationParsingOptions::RESTRICT_EXTENDS) != 0); - } - case lexer::TokenType::PUNCTUATOR_BITWISE_AND: { - if (((*options) & TypeAnnotationParsingOptions::IN_INTERSECTION) != 0) { - break; +private: + static ir::TypeNode *ParseKeywordTokens(TSParser *parser, lexer::Lexer *lexer, ir::TypeNode *typeAnnotation, + TypeAnnotationParsingOptions *options) + { + switch (lexer->GetToken().Type()) { + case lexer::TokenType::KEYW_NEW: { + return parser->ParseParenthesizedOrFunctionType( + typeAnnotation, ((*options) & TypeAnnotationParsingOptions::THROW_ERROR) != 0); } + case lexer::TokenType::KEYW_TYPEOF: { + if (typeAnnotation != nullptr) { + break; + } - return ParseIntersectionType(typeAnnotation, ((*options) & TypeAnnotationParsingOptions::IN_UNION) != 0, - ((*options) & TypeAnnotationParsingOptions::RESTRICT_EXTENDS) != 0); - } - case lexer::TokenType::PUNCTUATOR_LESS_THAN: - case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: - case lexer::TokenType::KEYW_NEW: { - return ParseParenthesizedOrFunctionType(typeAnnotation, - ((*options) & TypeAnnotationParsingOptions::THROW_ERROR) != 0); - } - case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: { - if (typeAnnotation != nullptr) { - if (Lexer()->Lookahead() == lexer::LEX_CHAR_RIGHT_SQUARE) { - return ParseArrayType(typeAnnotation); + return parser->ParseTypeReferenceOrQuery(true); + } + case lexer::TokenType::KEYW_IMPORT: { + if (typeAnnotation != nullptr) { + break; + } + return parser->ParseImportType(lexer->GetToken().Start()); + } + case lexer::TokenType::KEYW_CONST: { + if (((*options) & TypeAnnotationParsingOptions::ALLOW_CONST) == 0) { + break; } - return ParseIndexAccessType(typeAnnotation); + (*options) &= ~TypeAnnotationParsingOptions::ALLOW_CONST; + return parser->ParseConstExpression(); } + case lexer::TokenType::KEYW_EXTENDS: { + if (((*options) & + (TypeAnnotationParsingOptions::IN_UNION | TypeAnnotationParsingOptions::IN_INTERSECTION)) != 0) { + break; + } - return ParseTupleType(); - } - case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { - return ParseTypeLiteralOrMappedType(typeAnnotation); - } - case lexer::TokenType::PUNCTUATOR_MINUS: - case lexer::TokenType::LITERAL_NUMBER: - case lexer::TokenType::LITERAL_STRING: - case lexer::TokenType::LITERAL_FALSE: - case lexer::TokenType::LITERAL_TRUE: - case lexer::TokenType::LITERAL_NULL: - case lexer::TokenType::KEYW_VOID: { - if (typeAnnotation != nullptr) { + if (typeAnnotation == nullptr) { + return parser->ParseIdentifierReference(); + } + + return parser->ParseConditionalType(typeAnnotation, + ((*options) & TypeAnnotationParsingOptions::RESTRICT_EXTENDS) != 0); + } + case lexer::TokenType::KEYW_THIS: { + return parser->ParseThisTypeOrTypePredicate( + typeAnnotation, ((*options) & TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE) != 0, + ((*options) & TypeAnnotationParsingOptions::THROW_ERROR) != 0); + } + default: { break; } - - return ParseBasicType(); } - case lexer::TokenType::KEYW_TYPEOF: { - if (typeAnnotation != nullptr) { - break; + return nullptr; + } + + static ir::TypeNode *ParsePunctuatorTokens(TSParser *parser, lexer::Lexer *lexer, ir::TypeNode *typeAnnotation, + TypeAnnotationParsingOptions *options) + { + switch (lexer->GetToken().Type()) { + case lexer::TokenType::PUNCTUATOR_BITWISE_OR: { + if (((*options) & + (TypeAnnotationParsingOptions::IN_UNION | TypeAnnotationParsingOptions::IN_INTERSECTION)) != 0) { + break; + } + + return parser->ParseUnionType(typeAnnotation, + ((*options) & TypeAnnotationParsingOptions::RESTRICT_EXTENDS) != 0); } + case lexer::TokenType::PUNCTUATOR_BITWISE_AND: { + if (((*options) & TypeAnnotationParsingOptions::IN_INTERSECTION) != 0) { + break; + } - return ParseTypeReferenceOrQuery(true); - } - case lexer::TokenType::KEYW_IMPORT: { - if (typeAnnotation != nullptr) { - break; + return parser->ParseIntersectionType( + typeAnnotation, ((*options) & TypeAnnotationParsingOptions::IN_UNION) != 0, + ((*options) & TypeAnnotationParsingOptions::RESTRICT_EXTENDS) != 0); + } + case lexer::TokenType::PUNCTUATOR_LESS_THAN: + case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: { + return parser->ParseParenthesizedOrFunctionType( + typeAnnotation, ((*options) & TypeAnnotationParsingOptions::THROW_ERROR) != 0); } + case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: { + if (typeAnnotation != nullptr) { + if (lexer->Lookahead() == lexer::LEX_CHAR_RIGHT_SQUARE) { + return parser->ParseArrayType(typeAnnotation); + } - lexer::SourcePosition startLoc = Lexer()->GetToken().Start(); - return ParseImportType(startLoc); + return parser->ParseIndexAccessType(typeAnnotation); + } + + return parser->ParseTupleType(); + } + case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { + return parser->ParseTypeLiteralOrMappedType(typeAnnotation); + } + default: { + break; + } } - case lexer::TokenType::KEYW_CONST: { - if (((*options) & TypeAnnotationParsingOptions::ALLOW_CONST) == 0) { + + return nullptr; + } +}; + +ir::TypeNode *TSParser::ParseTypeAnnotationElement(ir::TypeNode *typeAnnotation, TypeAnnotationParsingOptions *options) +{ + switch (Lexer()->GetToken().Type()) { + case lexer::TokenType::PUNCTUATOR_MINUS: + case lexer::TokenType::LITERAL_NUMBER: + case lexer::TokenType::LITERAL_STRING: + case lexer::TokenType::LITERAL_FALSE: + case lexer::TokenType::LITERAL_TRUE: + case lexer::TokenType::LITERAL_NULL: + case lexer::TokenType::KEYW_VOID: { + if (typeAnnotation != nullptr) { break; } - (*options) &= ~TypeAnnotationParsingOptions::ALLOW_CONST; - return ParseConstExpression(); + return ParseBasicType(); } case lexer::TokenType::LITERAL_IDENT: { if (IsStartOfAbstractConstructorType()) { @@ -1551,25 +1382,19 @@ ir::TypeNode *TSParser::ParseTypeAnnotationElement(ir::TypeNode *typeAnnotation, return ParseTypeReferenceOrTypePredicate( typeAnnotation, ((*options) & TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE) != 0); } - case lexer::TokenType::KEYW_EXTENDS: { - if (((*options) & - (TypeAnnotationParsingOptions::IN_UNION | TypeAnnotationParsingOptions::IN_INTERSECTION)) != 0) { - break; + default: { + ir::TypeNode *parsedValue = + ParseTypeAnnotationElementHelper::ParseKeywordTokens(this, Lexer(), typeAnnotation, options); + if (parsedValue != nullptr) { + return parsedValue; } - if (typeAnnotation == nullptr) { - return ParseIdentifierReference(); + parsedValue = + ParseTypeAnnotationElementHelper::ParsePunctuatorTokens(this, Lexer(), typeAnnotation, options); + if (parsedValue != nullptr) { + return parsedValue; } - return ParseConditionalType(typeAnnotation, - ((*options) & TypeAnnotationParsingOptions::RESTRICT_EXTENDS) != 0); - } - case lexer::TokenType::KEYW_THIS: { - return ParseThisTypeOrTypePredicate( - typeAnnotation, ((*options) & TypeAnnotationParsingOptions::CAN_BE_TS_TYPE_PREDICATE) != 0, - ((*options) & TypeAnnotationParsingOptions::THROW_ERROR) != 0); - } - default: { break; } } @@ -1581,101 +1406,6 @@ ir::TypeNode *TSParser::ParseTypeAnnotationElement(ir::TypeNode *typeAnnotation, return nullptr; } -// NOLINTNEXTLINE(google-default-arguments) -ir::ObjectExpression *TSParser::ParseObjectExpression(ExpressionParseFlags flags) -{ - ir::ObjectExpression *objExpression = ParserImpl::ParseObjectExpression(flags); - ParsePotentialOptionalFunctionParameter(objExpression); - return objExpression; -} - -// NOLINTNEXTLINE(google-default-arguments) -ir::ArrayExpression *TSParser::ParseArrayExpression(ExpressionParseFlags flags) -{ - ir::ArrayExpression *arrayExpression = ParserImpl::ParseArrayExpression(flags); - ParsePotentialOptionalFunctionParameter(arrayExpression); - return arrayExpression; -} - -ir::ArrowFunctionExpression *TSParser::ParsePotentialArrowExpression(ir::Expression **returnExpression, - const lexer::SourcePosition &startLoc) -{ - ir::TSTypeParameterDeclaration *typeParamDecl = nullptr; - - switch (Lexer()->GetToken().Type()) { - case lexer::TokenType::KEYW_FUNCTION: { - *returnExpression = ParseFunctionExpression(ParserStatus::ASYNC_FUNCTION); - (*returnExpression)->SetStart(startLoc); - break; - } - case lexer::TokenType::LITERAL_IDENT: { - ir::Expression *identRef = ParsePrimaryExpression(); - ASSERT(identRef->IsIdentifier()); - - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { - ThrowSyntaxError("Unexpected token, expected '=>'"); - } - - ir::ArrowFunctionExpression *arrowFuncExpr = ParseArrowFunctionExpression(identRef, nullptr, nullptr, true); - arrowFuncExpr->SetStart(startLoc); - - return arrowFuncExpr; - } - case lexer::TokenType::PUNCTUATOR_ARROW: { - ir::ArrowFunctionExpression *arrowFuncExpr = - ParseArrowFunctionExpression(*returnExpression, nullptr, nullptr, true); - arrowFuncExpr->SetStart(startLoc); - return arrowFuncExpr; - } - case lexer::TokenType::PUNCTUATOR_LESS_THAN: { - const auto savedPos = Lexer()->Save(); - - auto options = TypeAnnotationParsingOptions::NO_OPTS; - typeParamDecl = ParseTypeParameterDeclaration(&options); - if (typeParamDecl == nullptr) { - Lexer()->Rewind(savedPos); - return nullptr; - } - - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { - ThrowSyntaxError("'(' expected"); - } - - [[fallthrough]]; - } - case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: { - ir::CallExpression *callExpression = ParseCallExpression(*returnExpression, false); - - ir::TypeNode *returnTypeAnnotation = nullptr; - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { - Lexer()->NextToken(); // eat ':' - TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; - returnTypeAnnotation = ParseTypeAnnotation(&options); - } - - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW) { - ir::ArrowFunctionExpression *arrowFuncExpr = - ParseArrowFunctionExpression(callExpression, typeParamDecl, returnTypeAnnotation, true); - arrowFuncExpr->SetStart(startLoc); - - return arrowFuncExpr; - } - - if (returnTypeAnnotation != nullptr || typeParamDecl != nullptr) { - ThrowSyntaxError("'=>' expected"); - } - - *returnExpression = callExpression; - break; - } - default: { - break; - } - } - - return nullptr; -} - bool TSParser::ParsePotentialGenericFunctionCall(ir::Expression *primaryExpr, ir::Expression **returnExpression, const lexer::SourcePosition &startLoc, bool ignoreCallExpression) { @@ -1725,18 +1455,6 @@ bool TSParser::ParsePotentialGenericFunctionCall(ir::Expression *primaryExpr, ir return true; } -bool TSParser::ParsePotentialNonNullExpression(ir::Expression **returnExpression, lexer::SourcePosition startLoc) -{ - if (returnExpression == nullptr || Lexer()->GetToken().NewLine()) { - return true; - } - - *returnExpression = AllocNode(*returnExpression); - (*returnExpression)->SetRange({startLoc, Lexer()->GetToken().End()}); - Lexer()->NextToken(); - return false; -} - bool TSParser::IsNamedFunctionExpression() { return Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS && @@ -1756,15 +1474,6 @@ ir::Identifier *TSParser::ParsePrimaryExpressionIdent([[maybe_unused]] Expressio return identNode; } -void TSParser::ValidateArrowFunctionRestParameter(ir::SpreadElement *restElement) -{ - ParseOptionalFunctionParameter(restElement, true); - - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { - ThrowSyntaxError("')' expected"); - } -} - ir::TSSignatureDeclaration *TSParser::ParseSignatureMember(bool isCallSignature) { lexer::SourcePosition memberStartLoc = Lexer()->GetToken().Start(); @@ -1945,21 +1654,13 @@ void TSParser::CreateTSVariableForProperty(ir::AstNode *node, const ir::Expressi ir::AstNode *TSParser::ParsePropertyOrMethodSignature(const lexer::SourcePosition &startLoc, bool isReadonly) { auto [key, isComputed] = ParseInterfacePropertyKey(); + varbinder::VariableFlags flags = isReadonly ? varbinder::VariableFlags::READONLY : varbinder::VariableFlags::NONE; bool isOptional = false; if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) { isOptional = true; - Lexer()->NextToken(); // eat '?' - } - - varbinder::VariableFlags flags = varbinder::VariableFlags::NONE; - - if (isOptional) { flags |= varbinder::VariableFlags::OPTIONAL; - } - - if (isReadonly) { - flags |= varbinder::VariableFlags::READONLY; + Lexer()->NextToken(); // eat '?' } if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS || @@ -1975,9 +1676,7 @@ ir::AstNode *TSParser::ParsePropertyOrMethodSignature(const lexer::SourcePositio typeParamDecl = ParseTypeParameterDeclaration(&options); } - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { - ThrowExpectedToken(lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); - } + ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS, false); FunctionParameterContext funcParamContext(&GetContext()); auto params = ParseFunctionParams(); @@ -2133,73 +1832,6 @@ ArenaVector TSParser::ParseFunctionParams() return params; } -ir::TSParameterProperty *TSParser::CreateParameterProperty(ir::Expression *parameter, ir::ModifierFlags modifiers) -{ - auto accessibility = ir::AccessibilityOption::NO_OPTS; - bool readonly = false; - bool isStatic = false; - bool isExport = false; - - if ((modifiers & ir::ModifierFlags::PRIVATE) != 0) { - accessibility = ir::AccessibilityOption::PRIVATE; - } else if ((modifiers & ir::ModifierFlags::PUBLIC) != 0) { - accessibility = ir::AccessibilityOption::PUBLIC; - } else if ((modifiers & ir::ModifierFlags::PROTECTED) != 0) { - accessibility = ir::AccessibilityOption::PROTECTED; - } - - if ((modifiers & ir::ModifierFlags::READONLY) != 0) { - readonly = true; - } - - if ((modifiers & ir::ModifierFlags::STATIC) != 0) { - isStatic = true; - } - - // NOTE(Csaba Repasi): Handle export property of TSParameterProperty - - return AllocNode(accessibility, parameter, readonly, isStatic, isExport); -} - -ir::Expression *TSParser::ParseFunctionParameter() -{ - if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_THIS) { - Lexer()->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT); - } - - lexer::SourcePosition parameterStart = Lexer()->GetToken().Start(); - ir::ModifierFlags modifiers = ParseModifiers(); - // NOTE(Csaba Repasi): throw error if using strick mode reserved keyword here - if (((GetContext().Status() & ParserStatus::CONSTRUCTOR_FUNCTION) == 0) && modifiers != ir::ModifierFlags::NONE) { - ThrowSyntaxError("A parameter property is only allowed in a constructor implementation.", parameterStart); - } - - if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) { - CheckRestrictedBinding(); - } - - ir::Expression *functionParameter = ParsePatternElement(ExpressionParseFlags::NO_OPTS, true); - - if (modifiers != ir::ModifierFlags::NONE && functionParameter->IsRestElement()) { - ThrowSyntaxError("A parameter property cannot be declared using a rest parameter.", parameterStart); - } - - if (modifiers != ir::ModifierFlags::NONE && - (functionParameter->IsArrayPattern() || functionParameter->IsObjectPattern() || - (functionParameter->IsAssignmentPattern() && - (functionParameter->AsAssignmentPattern()->Left()->IsArrayPattern() || - functionParameter->AsAssignmentPattern()->Left()->IsObjectPattern())))) { - ThrowSyntaxError("A parameter property may not be declared using a binding pattern.", parameterStart); - } - - if (modifiers != ir::ModifierFlags::NONE) { - functionParameter = CreateParameterProperty(functionParameter, modifiers); - functionParameter->SetRange({parameterStart, functionParameter->AsTSParameterProperty()->Parameter()->End()}); - } - - return functionParameter; -} - ir::TypeNode *TSParser::ParseClassKeyAnnotation() { if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { @@ -2466,44 +2098,6 @@ std::tuple TSParser::Pa return {letDeclare, body, endLoc, isOverload}; } -ir::Expression *TSParser::ParseModuleReference() -{ - ir::Expression *result = nullptr; - - if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_REQUIRE && - Lexer()->Lookahead() == lexer::LEX_CHAR_LEFT_PAREN) { - lexer::SourcePosition start = Lexer()->GetToken().Start(); - Lexer()->NextToken(); // eat 'require' - Lexer()->NextToken(); // eat '(' - - if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_STRING) { - ThrowSyntaxError("String literal expected."); - } - - result = AllocNode(Lexer()->GetToken().String()); - result->SetRange(Lexer()->GetToken().Loc()); - Lexer()->NextToken(); - - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { - ThrowSyntaxError("')' expected."); - } - - result = AllocNode(result); - result->SetRange({start, Lexer()->GetToken().End()}); - Lexer()->NextToken(); // eat ')' - } else { - result = AllocNode(Lexer()->GetToken().Ident(), Allocator()); - result->SetRange(Lexer()->GetToken().Loc()); - Lexer()->NextToken(); - - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) { - result = ParseQualifiedReference(result); - } - } - - return result; -} - ir::AstNode *TSParser::ParseImportDefaultSpecifier(ArenaVector *specifiers) { ir::Identifier *local = ParseNamedImport(Lexer()->GetToken()); @@ -2533,197 +2127,6 @@ ir::AstNode *TSParser::ParseImportDefaultSpecifier(ArenaVector *s return nullptr; } -ir::TSImportEqualsDeclaration *TSParser::ParseTsImportEqualsDeclaration(const lexer::SourcePosition &startLoc, - bool isExport) -{ - ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_IMPORT); - Lexer()->NextToken(); - if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { - ThrowSyntaxError("Unexpected token"); - } - - auto *id = AllocNode(Lexer()->GetToken().Ident(), Allocator()); - id->SetRange(Lexer()->GetToken().Loc()); - Lexer()->NextToken(); // eat id name - - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { - ThrowSyntaxError("'=' expected"); - } - Lexer()->NextToken(); // eat substitution - - if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { - ThrowSyntaxError("identifier expected"); - } - - auto *importEqualsDecl = AllocNode(id, ParseModuleReference(), isExport); - importEqualsDecl->SetRange({startLoc, Lexer()->GetToken().End()}); - - ConsumeSemicolon(importEqualsDecl); - - return importEqualsDecl; -} - -ir::Statement *TSParser::ParseExportDeclaration(StatementParsingFlags flags) -{ - lexer::SourcePosition startLoc = Lexer()->GetToken().Start(); - Lexer()->NextToken(); // eat `export` keyword - - switch (Lexer()->GetToken().Type()) { - case lexer::TokenType::KEYW_DEFAULT: { - return ParseExportDefaultDeclaration(startLoc); - } - case lexer::TokenType::PUNCTUATOR_MULTIPLY: { - return ParseExportAllDeclaration(startLoc); - } - case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { - return ParseExportNamedSpecifiers(startLoc); - } - case lexer::TokenType::KEYW_IMPORT: { - return ParseTsImportEqualsDeclaration(startLoc, true); - } - case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: { - return ParseExportDefaultDeclaration(startLoc, true); - } - default: { - ir::ExportNamedDeclaration *exportDecl = ParseNamedExportDeclaration(startLoc); - - if (exportDecl->Decl()->IsVariableDeclaration() && ((flags & StatementParsingFlags::GLOBAL) == 0) && - exportDecl->Parent() != nullptr && !exportDecl->Parent()->IsTSModuleBlock() && - !GetContext().IsModule()) { - ThrowSyntaxError("Modifiers cannot appear here'"); - } - - return exportDecl; - } - } -} - -ir::Expression *TSParser::ParseArrowFunctionRestParameter(lexer::SourcePosition start) -{ - ir::SpreadElement *restElement = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN); - - restElement->SetGrouped(); - restElement->SetStart(start); - - ValidateArrowFunctionRestParameter(restElement); - - Lexer()->NextToken(); - - TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; - ir::TypeNode *returnTypeAnnotation = nullptr; - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { - Lexer()->NextToken(); // eat ':' - returnTypeAnnotation = ParseTypeAnnotation(&options); - } - - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { - ThrowSyntaxError("Unexpected token"); - } - - return ParseArrowFunctionExpression(restElement, nullptr, returnTypeAnnotation, false); -} - -ir::Expression *TSParser::ParseArrowFunctionNoParameter(lexer::SourcePosition start) -{ - Lexer()->NextToken(); - - TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; - ir::TypeNode *returnTypeAnnotation = nullptr; - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { - Lexer()->NextToken(); // eat ':' - returnTypeAnnotation = ParseTypeAnnotation(&options); - } - - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { - ThrowSyntaxError("Unexpected token"); - } - - auto *arrowExpr = ParseArrowFunctionExpression(nullptr, nullptr, returnTypeAnnotation, false); - arrowExpr->SetStart(start); - arrowExpr->AsArrowFunctionExpression()->Function()->SetStart(start); - - return arrowExpr; -} - -// NOLINTNEXTLINE(google-default-arguments) -ir::Expression *TSParser::ParseCoverParenthesizedExpressionAndArrowParameterList( - [[maybe_unused]] ExpressionParseFlags flags) -{ - ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); - lexer::SourcePosition start = Lexer()->GetToken().Start(); - Lexer()->NextToken(); - TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; - - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) { - return ParseArrowFunctionRestParameter(start); - } - - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { - return ParseArrowFunctionNoParameter(start); - } - - ir::Expression *expr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::ACCEPT_REST | - ExpressionParseFlags::POTENTIALLY_IN_PATTERN); - - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { - ThrowSyntaxError("Unexpected token, expected ')'"); - } - - expr->SetGrouped(); - expr->SetRange({start, Lexer()->GetToken().End()}); - Lexer()->NextToken(); - - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { - auto savedPos = Lexer()->Save(); - Lexer()->NextToken(); // eat ':' - options = TypeAnnotationParsingOptions::NO_OPTS; - ir::TypeNode *returnTypeAnnotation = ParseTypeAnnotation(&options); - - if (returnTypeAnnotation == nullptr) { - Lexer()->Rewind(savedPos); - return expr; - } - - if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { - Lexer()->Rewind(savedPos); - return expr; - } - - return ParseArrowFunctionExpression(expr, nullptr, returnTypeAnnotation, false); - } - - return expr; -} - -ir::Statement *TSParser::ParseConstStatement(StatementParsingFlags flags) -{ - lexer::SourcePosition constVarStar = Lexer()->GetToken().Start(); - Lexer()->NextToken(); - - if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_ENUM) { - return ParseEnumDeclaration(true); - } - - if ((flags & StatementParsingFlags::ALLOW_LEXICAL) == 0) { - ThrowSyntaxError("Lexical declaration is not allowed in single statement context"); - } - - auto *variableDecl = ParseVariableDeclaration(VariableParsingFlags::CONST | VariableParsingFlags::NO_SKIP_VAR_KIND); - variableDecl->SetStart(constVarStar); - ConsumeSemicolon(variableDecl); - - return variableDecl; -} - -ir::Statement *TSParser::ParsePotentialConstEnum(VariableParsingFlags flags) -{ - if ((flags & VariableParsingFlags::CONST) == 0) { - ThrowSyntaxError("Variable declaration expected."); - } - - return ParseEnumDeclaration(true); -} - void TSParser::ParseCatchParamTypeAnnotation([[maybe_unused]] ir::AnnotatedExpression *param) { if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { @@ -2738,19 +2141,6 @@ void TSParser::ParseCatchParamTypeAnnotation([[maybe_unused]] ir::AnnotatedExpre } } -ir::AnnotatedExpression *TSParser::ParseVariableDeclaratorKey(VariableParsingFlags flags) -{ - ir::AnnotatedExpression *init = ParserImpl::ParseVariableDeclaratorKey(flags); - - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { - Lexer()->NextToken(); // eat ':' - TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; - init->SetTsTypeAnnotation(ParseTypeAnnotation(&options)); - } - - return init; -} - void TSParser::ThrowPossibleOutOfBoundaryJumpError(bool allowBreak) { if (((GetContext().Status() & ParserStatus::FUNCTION) != 0) && !allowBreak) { @@ -2785,165 +2175,4 @@ void TSParser::ThrowIfBodyEmptyError(ir::Statement *consequent) } } -// NOLINTNEXTLINE(google-default-arguments) -ir::ExportDefaultDeclaration *TSParser::ParseExportDefaultDeclaration(const lexer::SourcePosition &startLoc, - bool isExportEquals) -{ - Lexer()->NextToken(); // eat `default` keyword or `=` - - ir::AstNode *declNode = nullptr; - bool eatSemicolon = false; - - switch (Lexer()->GetToken().KeywordType()) { - case lexer::TokenType::KEYW_FUNCTION: { - declNode = ParseFunctionDeclaration(true); - break; - } - case lexer::TokenType::KEYW_CLASS: { - declNode = ParseClassDeclaration(ir::ClassDefinitionModifiers::ID_REQUIRED); - break; - } - case lexer::TokenType::KEYW_INTERFACE: { - declNode = ParseInterfaceDeclaration(false); - break; - } - case lexer::TokenType::KEYW_ASYNC: { - if ((Lexer()->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) == 0) { - Lexer()->NextToken(); // eat `async` - declNode = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION); - break; - } - [[fallthrough]]; - } - default: { - declNode = ParseExpression(); - eatSemicolon = true; - break; - } - } - - lexer::SourcePosition endLoc = declNode->End(); - auto *exportDeclaration = AllocNode(declNode, isExportEquals); - exportDeclaration->SetRange({startLoc, endLoc}); - - if (eatSemicolon) { - ConsumeSemicolon(exportDeclaration); - } - - return exportDeclaration; -} - -ir::ExportNamedDeclaration *TSParser::ParseNamedExportDeclaration(const lexer::SourcePosition &startLoc) -{ - ir::Statement *decl = nullptr; - - ir::ClassDefinitionModifiers classModifiers = ir::ClassDefinitionModifiers::ID_REQUIRED; - ir::ModifierFlags flags = ir::ModifierFlags::NONE; - - if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) { - CheckDeclare(); - } - - if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT) { - Lexer()->NextToken(); // eat 'abstract' - flags |= ir::ModifierFlags::ABSTRACT; - } - - switch (Lexer()->GetToken().KeywordType()) { - case lexer::TokenType::KEYW_VAR: { - decl = ParseVariableDeclaration(VariableParsingFlags::VAR); - break; - } - case lexer::TokenType::KEYW_CONST: { - decl = ParseVariableDeclaration(VariableParsingFlags::CONST); - break; - } - case lexer::TokenType::KEYW_LET: { - decl = ParseVariableDeclaration(VariableParsingFlags::LET); - break; - } - case lexer::TokenType::KEYW_FUNCTION: { - decl = ParseFunctionDeclaration(false, ParserStatus::NO_OPTS); - break; - } - case lexer::TokenType::KEYW_CLASS: { - decl = ParseClassDeclaration(classModifiers, flags); - break; - } - case lexer::TokenType::KEYW_ENUM: { - decl = ParseEnumDeclaration(); - break; - } - case lexer::TokenType::KEYW_INTERFACE: { - decl = ParseInterfaceDeclaration(false); - break; - } - case lexer::TokenType::KEYW_TYPE: { - decl = ParseTypeAliasDeclaration(); - break; - } - case lexer::TokenType::KEYW_GLOBAL: - case lexer::TokenType::KEYW_MODULE: - case lexer::TokenType::KEYW_NAMESPACE: { - decl = ParseModuleDeclaration(); - break; - } - default: { - if (!Lexer()->GetToken().IsAsyncModifier()) { - ThrowSyntaxError("Unexpected token"); - } - - Lexer()->NextToken(); // eat `async` keyword - decl = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION); - } - } - - if (decl->IsVariableDeclaration()) { - ConsumeSemicolon(decl); - } - - lexer::SourcePosition endLoc = decl->End(); - ArenaVector specifiers(Allocator()->Adapter()); - auto *exportDeclaration = AllocNode(Allocator(), decl, std::move(specifiers)); - exportDeclaration->SetRange({startLoc, endLoc}); - - return exportDeclaration; -} - -ir::Statement *TSParser::ParseImportDeclaration([[maybe_unused]] StatementParsingFlags flags) -{ - char32_t nextChar = Lexer()->Lookahead(); - if (nextChar == lexer::LEX_CHAR_LEFT_PAREN || nextChar == lexer::LEX_CHAR_DOT) { - return ParseExpressionStatement(); - } - - lexer::SourcePosition startLoc = Lexer()->GetToken().Start(); - Lexer()->NextToken(); // eat import - - ArenaVector specifiers(Allocator()->Adapter()); - - ir::StringLiteral *source = nullptr; - - if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_STRING) { - ir::AstNode *astNode = ParseImportSpecifiers(&specifiers); - if (astNode != nullptr) { - ASSERT(astNode->IsTSImportEqualsDeclaration()); - astNode->SetRange({startLoc, Lexer()->GetToken().End()}); - ConsumeSemicolon(astNode->AsTSImportEqualsDeclaration()); - return astNode->AsTSImportEqualsDeclaration(); - } - source = ParseFromClause(true); - } else { - source = ParseFromClause(false); - } - - lexer::SourcePosition endLoc = source->End(); - auto *importDeclaration = AllocNode(source, std::move(specifiers)); - importDeclaration->SetRange({startLoc, endLoc}); - - ConsumeSemicolon(importDeclaration); - - return importDeclaration; -} - } // namespace ark::es2panda::parser diff --git a/ets2panda/parser/TSparser.h b/ets2panda/parser/TSparser.h index 4c492cf97b..971d4b42ef 100644 --- a/ets2panda/parser/TSparser.h +++ b/ets2panda/parser/TSparser.h @@ -39,8 +39,11 @@ private: bool IsStartOfAbstractConstructorType() const; bool CurrentLiteralIsBasicType() const; ir::TypeNode *ParseTypeAnnotationElement(ir::TypeNode *typeAnnotation, TypeAnnotationParsingOptions *options); + class ParseTypeAnnotationElementHelper; + class ParsePotentialArrowExpressionHelper; ir::TypeNode *ParseTypeOperatorOrTypeReference(); ir::TypeNode *ParseIdentifierReference(); + class ParseBasicTypeHelper; ir::TypeNode *ParseBasicType(); ir::TSTypeReference *ParseConstExpression(); ir::TSIntersectionType *ParseIntersectionType(ir::Expression *type, bool inUnion, bool restrictExtends); @@ -78,6 +81,7 @@ private: // NOLINTNEXTLINE(google-default-arguments) ir::Statement *ParseStatement(StatementParsingFlags flags = StatementParsingFlags::NONE) override; + ir::AnnotatedExpression *ParsePatternElementGetReturnNode(ExpressionParseFlags &flags, bool &isOptional); // NOLINTNEXTLINE(google-default-arguments) ir::Expression *ParsePatternElement(ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS, bool allowDefault = true) override; @@ -140,6 +144,7 @@ private: // NOLINTNEXTLINE(google-default-arguments) ir::ExportDefaultDeclaration *ParseExportDefaultDeclaration(const lexer::SourcePosition &startLoc, bool isExportEquals = false) override; + ir::Statement *GetDeclarationForNamedExport(ir::ClassDefinitionModifiers &classModifiers, ir::ModifierFlags &flags); ir::ExportNamedDeclaration *ParseNamedExportDeclaration(const lexer::SourcePosition &startLoc) override; ir::Statement *ParseImportDeclaration(StatementParsingFlags flags) override; void ValidateIndexSignatureTypeAnnotation(ir::TypeNode *typeAnnotation) override; diff --git a/ets2panda/parser/expressionTSParser.cpp b/ets2panda/parser/expressionTSParser.cpp new file mode 100644 index 0000000000..006a4b5fd0 --- /dev/null +++ b/ets2panda/parser/expressionTSParser.cpp @@ -0,0 +1,676 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "TSparser.h" + +#include "parserFlags.h" +#include "util/helpers.h" +#include "varbinder/privateBinding.h" +#include "varbinder/scope.h" +#include "varbinder/tsBinding.h" +#include "lexer/TSLexer.h" +#include "ir/base/spreadElement.h" +#include "ir/base/decorator.h" +#include "ir/base/classElement.h" +#include "ir/base/classDefinition.h" +#include "ir/base/methodDefinition.h" +#include "ir/base/scriptFunction.h" +#include "ir/module/importDefaultSpecifier.h" +#include "ir/module/exportDefaultDeclaration.h" +#include "ir/module/exportAllDeclaration.h" +#include "ir/module/exportNamedDeclaration.h" +#include "ir/module/importDeclaration.h" +#include "ir/expressions/memberExpression.h" +#include "ir/expressions/sequenceExpression.h" +#include "ir/expressions/templateLiteral.h" +#include "ir/expressions/taggedTemplateExpression.h" +#include "ir/expressions/callExpression.h" +#include "ir/expressions/functionExpression.h" +#include "ir/expressions/arrowFunctionExpression.h" +#include "ir/expressions/yieldExpression.h" +#include "ir/expressions/assignmentExpression.h" +#include "ir/expressions/identifier.h" +#include "ir/expressions/objectExpression.h" +#include "ir/expressions/arrayExpression.h" +#include "ir/expressions/literals/bigIntLiteral.h" +#include "ir/expressions/literals/booleanLiteral.h" +#include "ir/expressions/literals/nullLiteral.h" +#include "ir/expressions/literals/numberLiteral.h" +#include "ir/expressions/literals/stringLiteral.h" +#include "ir/statements/emptyStatement.h" +#include "ir/statements/blockStatement.h" +#include "ir/statements/ifStatement.h" +#include "ir/statements/doWhileStatement.h" +#include "ir/statements/whileStatement.h" +#include "ir/statements/tryStatement.h" +#include "ir/statements/breakStatement.h" +#include "ir/statements/continueStatement.h" +#include "ir/statements/throwStatement.h" +#include "ir/statements/switchStatement.h" +#include "ir/statements/returnStatement.h" +#include "ir/statements/debuggerStatement.h" +#include "ir/statements/classDeclaration.h" +#include "ir/statements/labelledStatement.h" +#include "ir/statements/variableDeclarator.h" +#include "ir/statements/functionDeclaration.h" +#include "ir/ts/tsLiteralType.h" +#include "ir/ts/tsMappedType.h" +#include "ir/ts/tsImportType.h" +#include "ir/ts/tsThisType.h" +#include "ir/ts/tsConditionalType.h" +#include "ir/ts/tsTypeOperator.h" +#include "ir/ts/tsInferType.h" +#include "ir/ts/tsTupleType.h" +#include "ir/ts/tsNamedTupleMember.h" +#include "ir/ts/tsQualifiedName.h" +#include "ir/ts/tsIndexedAccessType.h" +#include "ir/ts/tsTypeQuery.h" +#include "ir/ts/tsTypeReference.h" +#include "ir/ts/tsTypePredicate.h" +#include "ir/ts/tsTypeLiteral.h" +#include "ir/ts/tsArrayType.h" +#include "ir/ts/tsUnionType.h" +#include "ir/ts/tsIntersectionType.h" +#include "ir/ts/tsAnyKeyword.h" +#include "ir/ts/tsUndefinedKeyword.h" +#include "ir/ts/tsVoidKeyword.h" +#include "ir/ts/tsNumberKeyword.h" +#include "ir/ts/tsStringKeyword.h" +#include "ir/ts/tsBooleanKeyword.h" +#include "ir/ts/tsBigintKeyword.h" +#include "ir/ts/tsUnknownKeyword.h" +#include "ir/ts/tsNullKeyword.h" +#include "ir/ts/tsNeverKeyword.h" +#include "ir/ts/tsObjectKeyword.h" +#include "ir/ts/tsFunctionType.h" +#include "ir/ts/tsConstructorType.h" +#include "ir/ts/tsParenthesizedType.h" +#include "ir/ts/tsTypeAssertion.h" +#include "ir/ts/tsAsExpression.h" +#include "ir/ts/tsNonNullExpression.h" +#include "ir/ts/tsEnumDeclaration.h" +#include "ir/ts/tsInterfaceDeclaration.h" +#include "ir/ts/tsTypeAliasDeclaration.h" +#include "ir/ts/tsModuleDeclaration.h" +#include "ir/ts/tsTypeParameterInstantiation.h" +#include "ir/ts/tsInterfaceHeritage.h" +#include "ir/base/tsSignatureDeclaration.h" +#include "ir/base/tsIndexSignature.h" +#include "ir/base/tsMethodSignature.h" +#include "ir/base/tsPropertySignature.h" +#include "ir/ts/tsParameterProperty.h" +#include "ir/ts/tsClassImplements.h" +#include "ir/ts/tsImportEqualsDeclaration.h" +#include "ir/ts/tsExternalModuleReference.h" + +namespace ark::es2panda::parser { +ir::Expression *TSParser::ParsePotentialAsExpression(ir::Expression *expr) +{ + if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_AS) { + return nullptr; + } + + Lexer()->NextToken(); // eat 'as' + TypeAnnotationParsingOptions options = + TypeAnnotationParsingOptions::THROW_ERROR | TypeAnnotationParsingOptions::ALLOW_CONST; + ir::TypeNode *typeAnnotation = ParseTypeAnnotation(&options); + + bool isConst = false; + if (typeAnnotation->IsTSTypeReference() && typeAnnotation->AsTSTypeReference()->TypeName()->IsIdentifier()) { + const util::StringView &refName = typeAnnotation->AsTSTypeReference()->TypeName()->AsIdentifier()->Name(); + if (refName.Is("const")) { + isConst = true; + } + } + + lexer::SourcePosition startLoc = expr->Start(); + auto *asExpr = AllocNode(expr, typeAnnotation, isConst); + asExpr->SetRange({startLoc, Lexer()->GetToken().End()}); + + if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_AS) { + return ParsePotentialAsExpression(asExpr); + } + + return asExpr; +} + +ir::AnnotatedExpression *TSParser::ParsePatternElementGetReturnNode(ExpressionParseFlags &flags, bool &isOptional) +{ + switch (Lexer()->GetToken().Type()) { + case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: { + ir::AnnotatedExpression *returnNode = ParseArrayExpression(ExpressionParseFlags::MUST_BE_PATTERN); + isOptional = returnNode->AsArrayPattern()->IsOptional(); + return returnNode; + } + case lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD: { + if ((flags & ExpressionParseFlags::IN_REST) != 0) { + ThrowSyntaxError("Unexpected token"); + } + + return ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN); + } + case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { + ir::AnnotatedExpression *returnNode = + ParseObjectExpression(ExpressionParseFlags::MUST_BE_PATTERN | ExpressionParseFlags::OBJECT_PATTERN); + isOptional = returnNode->AsObjectPattern()->IsOptional(); + return returnNode; + } + case lexer::TokenType::LITERAL_IDENT: { + ir::AnnotatedExpression *returnNode = AllocNode(Lexer()->GetToken().Ident(), Allocator()); + returnNode->AsIdentifier()->SetReference(); + + if (returnNode->AsIdentifier()->Decorators().empty()) { + returnNode->SetRange(Lexer()->GetToken().Loc()); + } else { + returnNode->SetRange( + {returnNode->AsIdentifier()->Decorators().front()->Start(), Lexer()->GetToken().End()}); + } + + Lexer()->NextToken(); + + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) { + isOptional = true; + + if ((flags & ExpressionParseFlags::IN_REST) != 0) { + ThrowSyntaxError("A rest parameter cannot be optional"); + } + + returnNode->AsIdentifier()->SetOptional(true); + Lexer()->NextToken(); + } + + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { + Lexer()->NextToken(); // eat ':' + TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; + returnNode->SetTsTypeAnnotation(ParseTypeAnnotation(&options)); + } + return returnNode; + } + default: { + ThrowSyntaxError("Unexpected token, expected an identifier."); + } + } +} +// NOLINTNEXTLINE(google-default-arguments) +ir::Expression *TSParser::ParsePatternElement(ExpressionParseFlags flags, bool allowDefault) +{ + bool isOptional = false; + ir::AnnotatedExpression *returnNode = ParsePatternElementGetReturnNode(flags, isOptional); + + if ((returnNode->IsObjectPattern() || returnNode->IsArrayPattern()) && !InAmbientContext() && + ((GetContext().Status() & ParserStatus::FUNCTION) != 0) && isOptional) { + ThrowSyntaxError("A binding pattern parameter cannot be optional in an implementation signature."); + } + + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { + return returnNode; + } + + if ((flags & ExpressionParseFlags::IN_REST) != 0) { + ThrowSyntaxError("A rest parameter cannot have an initializer."); + } + + if (!allowDefault) { + ThrowSyntaxError("Invalid destructuring assignment target"); + } + + if (isOptional) { + ThrowSyntaxError("Parameter cannot have question mark and initializer"); + } + + Lexer()->NextToken(); + + if (((GetContext().Status() & ParserStatus::GENERATOR_FUNCTION) != 0) && + Lexer()->GetToken().Type() == lexer::TokenType::KEYW_YIELD) { + ThrowSyntaxError("Yield is not allowed in generator parameters"); + } + + ir::Expression *rightNode = ParseExpression(); + + auto *assignmentExpression = AllocNode( + ir::AstNodeType::ASSIGNMENT_PATTERN, returnNode, rightNode, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + assignmentExpression->SetRange({returnNode->Start(), rightNode->End()}); + + return assignmentExpression; +} + +ir::TSParameterProperty *TSParser::CreateParameterProperty(ir::Expression *parameter, ir::ModifierFlags modifiers) +{ + auto accessibilityOption = ir::AccessibilityOption::NO_OPTS; + bool readonly = false; + bool isStatic = false; + bool isExport = false; + + if ((modifiers & ir::ModifierFlags::PRIVATE) != 0) { + accessibilityOption = ir::AccessibilityOption::PRIVATE; + } else if ((modifiers & ir::ModifierFlags::PUBLIC) != 0) { + accessibilityOption = ir::AccessibilityOption::PUBLIC; + } else if ((modifiers & ir::ModifierFlags::PROTECTED) != 0) { + accessibilityOption = ir::AccessibilityOption::PROTECTED; + } + + if ((modifiers & ir::ModifierFlags::READONLY) != 0) { + readonly = true; + } + + if ((modifiers & ir::ModifierFlags::STATIC) != 0) { + isStatic = true; + } + + // NOTE(Csaba Repasi): Handle export property of TSParameterProperty + + return AllocNode(accessibilityOption, parameter, readonly, isStatic, isExport); +} + +ir::Expression *TSParser::ParseFunctionParameter() +{ + if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_THIS) { + Lexer()->GetToken().SetTokenType(lexer::TokenType::LITERAL_IDENT); + } + + lexer::SourcePosition parameterStart = Lexer()->GetToken().Start(); + ir::ModifierFlags modifiers = ParseModifiers(); + // NOTE(Csaba Repasi): throw error if using strick mode reserved keyword here + if (((GetContext().Status() & ParserStatus::CONSTRUCTOR_FUNCTION) == 0) && modifiers != ir::ModifierFlags::NONE) { + ThrowSyntaxError("A parameter property is only allowed in a constructor implementation.", parameterStart); + } + + if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) { + CheckRestrictedBinding(); + } + + ir::Expression *functionParameter = ParsePatternElement(ExpressionParseFlags::NO_OPTS, true); + + if (modifiers != ir::ModifierFlags::NONE && functionParameter->IsRestElement()) { + ThrowSyntaxError("A parameter property cannot be declared using a rest parameter.", parameterStart); + } + + if (modifiers != ir::ModifierFlags::NONE && + (functionParameter->IsArrayPattern() || functionParameter->IsObjectPattern() || + (functionParameter->IsAssignmentPattern() && + (functionParameter->AsAssignmentPattern()->Left()->IsArrayPattern() || + functionParameter->AsAssignmentPattern()->Left()->IsObjectPattern())))) { + ThrowSyntaxError("A parameter property may not be declared using a binding pattern.", parameterStart); + } + + if (modifiers != ir::ModifierFlags::NONE) { + functionParameter = CreateParameterProperty(functionParameter, modifiers); + functionParameter->SetRange({parameterStart, functionParameter->AsTSParameterProperty()->Parameter()->End()}); + } + + return functionParameter; +} + +ir::Expression *TSParser::ParseModuleReference() +{ + ir::Expression *result = nullptr; + + if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_REQUIRE && + Lexer()->Lookahead() == lexer::LEX_CHAR_LEFT_PAREN) { + lexer::SourcePosition start = Lexer()->GetToken().Start(); + Lexer()->NextToken(); // eat 'require' + Lexer()->NextToken(); // eat '(' + + if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_STRING) { + ThrowSyntaxError("String literal expected."); + } + + result = AllocNode(Lexer()->GetToken().String()); + result->SetRange(Lexer()->GetToken().Loc()); + Lexer()->NextToken(); + + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { + ThrowSyntaxError("')' expected."); + } + + result = AllocNode(result); + result->SetRange({start, Lexer()->GetToken().End()}); + Lexer()->NextToken(); // eat ')' + } else { + result = AllocNode(Lexer()->GetToken().Ident(), Allocator()); + result->SetRange(Lexer()->GetToken().Loc()); + Lexer()->NextToken(); + + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD) { + result = ParseQualifiedReference(result); + } + } + + return result; +} + +ir::TSTypeReference *TSParser::ParseConstExpression() +{ + auto *identRef = AllocNode(Lexer()->GetToken().Ident(), Allocator()); + identRef->SetReference(); + identRef->SetRange(Lexer()->GetToken().Loc()); + + auto *typeReference = AllocNode(identRef, nullptr); + typeReference->SetRange(Lexer()->GetToken().Loc()); + + Lexer()->NextToken(); + + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_COMMA && + Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SEMI_COLON && + Lexer()->GetToken().Type() != lexer::TokenType::EOS && + Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_SQUARE_BRACKET && + ((Lexer()->GetToken().Flags() & lexer::TokenFlags::NEW_LINE) == 0)) { + ThrowSyntaxError("Unexpected token."); + } + + return typeReference; +} + +bool TSParser::ParsePotentialNonNullExpression(ir::Expression **returnExpression, lexer::SourcePosition startLoc) +{ + if (returnExpression == nullptr || Lexer()->GetToken().NewLine()) { + return true; + } + + *returnExpression = AllocNode(*returnExpression); + (*returnExpression)->SetRange({startLoc, Lexer()->GetToken().End()}); + Lexer()->NextToken(); + return false; +} + +// NOLINTNEXTLINE(google-default-arguments) +ir::ObjectExpression *TSParser::ParseObjectExpression(ExpressionParseFlags flags) +{ + ir::ObjectExpression *objExpression = ParserImpl::ParseObjectExpression(flags); + ParsePotentialOptionalFunctionParameter(objExpression); + return objExpression; +} + +// NOLINTNEXTLINE(google-default-arguments) +ir::ArrayExpression *TSParser::ParseArrayExpression(ExpressionParseFlags flags) +{ + ir::ArrayExpression *arrayExpression = ParserImpl::ParseArrayExpression(flags); + ParsePotentialOptionalFunctionParameter(arrayExpression); + return arrayExpression; +} +class TSParser::ParsePotentialArrowExpressionHelper { + friend ir::ArrowFunctionExpression *TSParser::ParsePotentialArrowExpression(ir::Expression **returnExpression, + const lexer::SourcePosition &startLoc); + +private: + static ir::ArrowFunctionExpression *CreateCallExpression(TSParser *parser, lexer::Lexer *lexer, + ir::Expression **returnExpression, + ir::TSTypeParameterDeclaration *typeParamDecl, + const lexer::SourcePosition &startLoc) + { + ir::CallExpression *callExpression = parser->ParseCallExpression(*returnExpression, false); + + ir::TypeNode *returnTypeAnnotation = nullptr; + if (lexer->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { + lexer->NextToken(); // eat ':' + TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; + returnTypeAnnotation = parser->ParseTypeAnnotation(&options); + } + + if (lexer->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW) { + ir::ArrowFunctionExpression *arrowFuncExpr = + parser->ParseArrowFunctionExpression(callExpression, typeParamDecl, returnTypeAnnotation, true); + arrowFuncExpr->SetStart(startLoc); + + return arrowFuncExpr; + } + + if (returnTypeAnnotation != nullptr || typeParamDecl != nullptr) { + parser->ThrowSyntaxError("'=>' expected"); + } + + *returnExpression = callExpression; + return nullptr; + } +}; + +ir::ArrowFunctionExpression *TSParser::ParsePotentialArrowExpression(ir::Expression **returnExpression, + const lexer::SourcePosition &startLoc) +{ + ir::TSTypeParameterDeclaration *typeParamDecl = nullptr; + + switch (Lexer()->GetToken().Type()) { + case lexer::TokenType::KEYW_FUNCTION: { + *returnExpression = ParseFunctionExpression(ParserStatus::ASYNC_FUNCTION); + (*returnExpression)->SetStart(startLoc); + break; + } + case lexer::TokenType::LITERAL_IDENT: { + ir::Expression *identRef = ParsePrimaryExpression(); + ASSERT(identRef->IsIdentifier()); + + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { + ThrowSyntaxError("Unexpected token, expected '=>'"); + } + + ir::ArrowFunctionExpression *arrowFuncExpr = ParseArrowFunctionExpression(identRef, nullptr, nullptr, true); + arrowFuncExpr->SetStart(startLoc); + + return arrowFuncExpr; + } + case lexer::TokenType::PUNCTUATOR_ARROW: { + ir::ArrowFunctionExpression *arrowFuncExpr = + ParseArrowFunctionExpression(*returnExpression, nullptr, nullptr, true); + arrowFuncExpr->SetStart(startLoc); + return arrowFuncExpr; + } + case lexer::TokenType::PUNCTUATOR_LESS_THAN: { + const auto savedPos = Lexer()->Save(); + + auto options = TypeAnnotationParsingOptions::NO_OPTS; + typeParamDecl = ParseTypeParameterDeclaration(&options); + if (typeParamDecl == nullptr) { + Lexer()->Rewind(savedPos); + return nullptr; + } + + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { + ThrowSyntaxError("'(' expected"); + } + + [[fallthrough]]; + } + case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: { + return ParsePotentialArrowExpressionHelper::CreateCallExpression(this, Lexer(), returnExpression, + typeParamDecl, startLoc); + } + default: { + break; + } + } + + return nullptr; +} + +ir::AnnotatedExpression *TSParser::ParseVariableDeclaratorKey(VariableParsingFlags flags) +{ + ir::AnnotatedExpression *init = ParserImpl::ParseVariableDeclaratorKey(flags); + + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { + Lexer()->NextToken(); // eat ':' + TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; + init->SetTsTypeAnnotation(ParseTypeAnnotation(&options)); + } + + return init; +} + +void TSParser::ParseOptionalFunctionParameter(ir::AnnotatedExpression *returnNode, bool isRest) +{ + bool isOptional = false; + + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_QUESTION_MARK) { + if (isRest) { + ThrowSyntaxError("A rest parameter cannot be optional"); + } + + switch (returnNode->Type()) { + case ir::AstNodeType::IDENTIFIER: { + returnNode->AsIdentifier()->SetOptional(true); + break; + } + case ir::AstNodeType::OBJECT_PATTERN: + case ir::AstNodeType::ARRAY_PATTERN: { + if (!InAmbientContext() && ((GetContext().Status() & ParserStatus::FUNCTION) != 0)) { + ThrowSyntaxError("A binding pattern parameter cannot be optional in an implementation signature."); + } + + if (returnNode->IsObjectPattern()) { + returnNode->AsObjectPattern()->SetOptional(true); + break; + } + + returnNode->AsArrayPattern()->SetOptional(true); + break; + } + case ir::AstNodeType::REST_ELEMENT: { + returnNode->AsRestElement()->SetOptional(true); + break; + } + default: { + UNREACHABLE(); + } + } + + isOptional = true; + Lexer()->NextToken(); // eat '?' + } + + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { + Lexer()->NextToken(); // eat ':' + TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; + returnNode->SetTsTypeAnnotation(ParseTypeAnnotation(&options)); + } + + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { + return; + } + + if (isRest) { + ThrowSyntaxError("A rest parameter cannot have an initializer"); + } + + if (returnNode->IsIdentifier() && isOptional) { + ThrowSyntaxError("Parameter cannot have question mark and initializer"); + } +} + +void TSParser::ValidateArrowFunctionRestParameter(ir::SpreadElement *restElement) +{ + ParseOptionalFunctionParameter(restElement, true); + + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { + ThrowSyntaxError("')' expected"); + } +} + +ir::Expression *TSParser::ParseArrowFunctionRestParameter(lexer::SourcePosition start) +{ + ir::SpreadElement *restElement = ParseSpreadElement(ExpressionParseFlags::MUST_BE_PATTERN); + + restElement->SetGrouped(); + restElement->SetStart(start); + + ValidateArrowFunctionRestParameter(restElement); + + Lexer()->NextToken(); + + TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; + ir::TypeNode *returnTypeAnnotation = nullptr; + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { + Lexer()->NextToken(); // eat ':' + returnTypeAnnotation = ParseTypeAnnotation(&options); + } + + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { + ThrowSyntaxError("Unexpected token"); + } + + return ParseArrowFunctionExpression(restElement, nullptr, returnTypeAnnotation, false); +} + +ir::Expression *TSParser::ParseArrowFunctionNoParameter(lexer::SourcePosition start) +{ + Lexer()->NextToken(); + + TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; + ir::TypeNode *returnTypeAnnotation = nullptr; + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { + Lexer()->NextToken(); // eat ':' + returnTypeAnnotation = ParseTypeAnnotation(&options); + } + + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { + ThrowSyntaxError("Unexpected token"); + } + + auto *arrowExpr = ParseArrowFunctionExpression(nullptr, nullptr, returnTypeAnnotation, false); + arrowExpr->SetStart(start); + arrowExpr->AsArrowFunctionExpression()->Function()->SetStart(start); + + return arrowExpr; +} + +// NOLINTNEXTLINE(google-default-arguments) +ir::Expression *TSParser::ParseCoverParenthesizedExpressionAndArrowParameterList( + [[maybe_unused]] ExpressionParseFlags flags) +{ + ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); + lexer::SourcePosition start = Lexer()->GetToken().Start(); + Lexer()->NextToken(); + TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::THROW_ERROR; + + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_PERIOD_PERIOD_PERIOD) { + return ParseArrowFunctionRestParameter(start); + } + + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { + return ParseArrowFunctionNoParameter(start); + } + + ir::Expression *expr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA | ExpressionParseFlags::ACCEPT_REST | + ExpressionParseFlags::POTENTIALLY_IN_PATTERN); + + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { + ThrowSyntaxError("Unexpected token, expected ')'"); + } + + expr->SetGrouped(); + expr->SetRange({start, Lexer()->GetToken().End()}); + Lexer()->NextToken(); + + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { + auto savedPos = Lexer()->Save(); + Lexer()->NextToken(); // eat ':' + options = TypeAnnotationParsingOptions::NO_OPTS; + ir::TypeNode *returnTypeAnnotation = ParseTypeAnnotation(&options); + + if (returnTypeAnnotation == nullptr) { + Lexer()->Rewind(savedPos); + return expr; + } + + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { + Lexer()->Rewind(savedPos); + return expr; + } + + return ParseArrowFunctionExpression(expr, nullptr, returnTypeAnnotation, false); + } + + return expr; +} + +} // namespace ark::es2panda::parser \ No newline at end of file diff --git a/ets2panda/parser/statementTSParser.cpp b/ets2panda/parser/statementTSParser.cpp new file mode 100644 index 0000000000..4ce03fbe2f --- /dev/null +++ b/ets2panda/parser/statementTSParser.cpp @@ -0,0 +1,373 @@ +/** + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "TSparser.h" + +#include "parserFlags.h" +#include "util/helpers.h" +#include "varbinder/privateBinding.h" +#include "varbinder/scope.h" +#include "varbinder/tsBinding.h" +#include "lexer/TSLexer.h" +#include "ir/base/spreadElement.h" +#include "ir/base/decorator.h" +#include "ir/base/classElement.h" +#include "ir/base/classDefinition.h" +#include "ir/base/methodDefinition.h" +#include "ir/base/scriptFunction.h" +#include "ir/module/importDefaultSpecifier.h" +#include "ir/module/exportDefaultDeclaration.h" +#include "ir/module/exportAllDeclaration.h" +#include "ir/module/exportNamedDeclaration.h" +#include "ir/module/importDeclaration.h" +#include "ir/expressions/memberExpression.h" +#include "ir/expressions/sequenceExpression.h" +#include "ir/expressions/templateLiteral.h" +#include "ir/expressions/taggedTemplateExpression.h" +#include "ir/expressions/callExpression.h" +#include "ir/expressions/functionExpression.h" +#include "ir/expressions/arrowFunctionExpression.h" +#include "ir/expressions/yieldExpression.h" +#include "ir/expressions/assignmentExpression.h" +#include "ir/expressions/identifier.h" +#include "ir/expressions/objectExpression.h" +#include "ir/expressions/arrayExpression.h" +#include "ir/expressions/literals/bigIntLiteral.h" +#include "ir/expressions/literals/booleanLiteral.h" +#include "ir/expressions/literals/nullLiteral.h" +#include "ir/expressions/literals/numberLiteral.h" +#include "ir/expressions/literals/stringLiteral.h" +#include "ir/statements/emptyStatement.h" +#include "ir/statements/blockStatement.h" +#include "ir/statements/ifStatement.h" +#include "ir/statements/doWhileStatement.h" +#include "ir/statements/whileStatement.h" +#include "ir/statements/tryStatement.h" +#include "ir/statements/breakStatement.h" +#include "ir/statements/continueStatement.h" +#include "ir/statements/throwStatement.h" +#include "ir/statements/switchStatement.h" +#include "ir/statements/returnStatement.h" +#include "ir/statements/debuggerStatement.h" +#include "ir/statements/classDeclaration.h" +#include "ir/statements/labelledStatement.h" +#include "ir/statements/variableDeclarator.h" +#include "ir/statements/functionDeclaration.h" +#include "ir/ts/tsLiteralType.h" +#include "ir/ts/tsMappedType.h" +#include "ir/ts/tsImportType.h" +#include "ir/ts/tsThisType.h" +#include "ir/ts/tsConditionalType.h" +#include "ir/ts/tsTypeOperator.h" +#include "ir/ts/tsInferType.h" +#include "ir/ts/tsTupleType.h" +#include "ir/ts/tsNamedTupleMember.h" +#include "ir/ts/tsQualifiedName.h" +#include "ir/ts/tsIndexedAccessType.h" +#include "ir/ts/tsTypeQuery.h" +#include "ir/ts/tsTypeReference.h" +#include "ir/ts/tsTypePredicate.h" +#include "ir/ts/tsTypeLiteral.h" +#include "ir/ts/tsArrayType.h" +#include "ir/ts/tsUnionType.h" +#include "ir/ts/tsIntersectionType.h" +#include "ir/ts/tsAnyKeyword.h" +#include "ir/ts/tsUndefinedKeyword.h" +#include "ir/ts/tsVoidKeyword.h" +#include "ir/ts/tsNumberKeyword.h" +#include "ir/ts/tsStringKeyword.h" +#include "ir/ts/tsBooleanKeyword.h" +#include "ir/ts/tsBigintKeyword.h" +#include "ir/ts/tsUnknownKeyword.h" +#include "ir/ts/tsNullKeyword.h" +#include "ir/ts/tsNeverKeyword.h" +#include "ir/ts/tsObjectKeyword.h" +#include "ir/ts/tsFunctionType.h" +#include "ir/ts/tsConstructorType.h" +#include "ir/ts/tsParenthesizedType.h" +#include "ir/ts/tsTypeAssertion.h" +#include "ir/ts/tsAsExpression.h" +#include "ir/ts/tsNonNullExpression.h" +#include "ir/ts/tsEnumDeclaration.h" +#include "ir/ts/tsInterfaceDeclaration.h" +#include "ir/ts/tsTypeAliasDeclaration.h" +#include "ir/ts/tsModuleDeclaration.h" +#include "ir/ts/tsTypeParameterInstantiation.h" +#include "ir/ts/tsInterfaceHeritage.h" +#include "ir/base/tsSignatureDeclaration.h" +#include "ir/base/tsIndexSignature.h" +#include "ir/base/tsMethodSignature.h" +#include "ir/base/tsPropertySignature.h" +#include "ir/ts/tsParameterProperty.h" +#include "ir/ts/tsClassImplements.h" +#include "ir/ts/tsImportEqualsDeclaration.h" +#include "ir/ts/tsExternalModuleReference.h" + +namespace ark::es2panda::parser { +// NOLINTNEXTLINE(google-default-arguments) +ir::Statement *TSParser::ParseStatement(StatementParsingFlags flags) +{ + return ParseDeclareAndDecorators(flags); +} +ir::TSImportEqualsDeclaration *TSParser::ParseTsImportEqualsDeclaration(const lexer::SourcePosition &startLoc, + bool isExport) +{ + ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_IMPORT); + Lexer()->NextToken(); + if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { + ThrowSyntaxError("Unexpected token"); + } + + auto *id = AllocNode(Lexer()->GetToken().Ident(), Allocator()); + id->SetRange(Lexer()->GetToken().Loc()); + Lexer()->NextToken(); // eat id name + + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { + ThrowSyntaxError("'=' expected"); + } + Lexer()->NextToken(); // eat substitution + + if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { + ThrowSyntaxError("identifier expected"); + } + + auto *importEqualsDecl = AllocNode(id, ParseModuleReference(), isExport); + importEqualsDecl->SetRange({startLoc, Lexer()->GetToken().End()}); + + ConsumeSemicolon(importEqualsDecl); + + return importEqualsDecl; +} + +// NOLINTNEXTLINE(google-default-arguments) +ir::ExportDefaultDeclaration *TSParser::ParseExportDefaultDeclaration(const lexer::SourcePosition &startLoc, + bool isExportEquals) +{ + Lexer()->NextToken(); // eat `default` keyword or `=` + + ir::AstNode *declNode = nullptr; + bool eatSemicolon = false; + + switch (Lexer()->GetToken().KeywordType()) { + case lexer::TokenType::KEYW_FUNCTION: { + declNode = ParseFunctionDeclaration(true); + break; + } + case lexer::TokenType::KEYW_CLASS: { + declNode = ParseClassDeclaration(ir::ClassDefinitionModifiers::ID_REQUIRED); + break; + } + case lexer::TokenType::KEYW_INTERFACE: { + declNode = ParseInterfaceDeclaration(false); + break; + } + case lexer::TokenType::KEYW_ASYNC: { + if ((Lexer()->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) == 0) { + Lexer()->NextToken(); // eat `async` + declNode = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION); + break; + } + [[fallthrough]]; + } + default: { + declNode = ParseExpression(); + eatSemicolon = true; + break; + } + } + + lexer::SourcePosition endLoc = declNode->End(); + auto *exportDeclaration = AllocNode(declNode, isExportEquals); + exportDeclaration->SetRange({startLoc, endLoc}); + + if (eatSemicolon) { + ConsumeSemicolon(exportDeclaration); + } + + return exportDeclaration; +} + +ir::Statement *TSParser::GetDeclarationForNamedExport(ir::ClassDefinitionModifiers &classModifiers, + ir::ModifierFlags &flags) +{ + switch (Lexer()->GetToken().KeywordType()) { + case lexer::TokenType::KEYW_VAR: { + return ParseVariableDeclaration(VariableParsingFlags::VAR); + } + case lexer::TokenType::KEYW_CONST: { + return ParseVariableDeclaration(VariableParsingFlags::CONST); + } + case lexer::TokenType::KEYW_LET: { + return ParseVariableDeclaration(VariableParsingFlags::LET); + } + case lexer::TokenType::KEYW_FUNCTION: { + return ParseFunctionDeclaration(false, ParserStatus::NO_OPTS); + } + case lexer::TokenType::KEYW_CLASS: { + return ParseClassDeclaration(classModifiers, flags); + } + case lexer::TokenType::KEYW_ENUM: { + return ParseEnumDeclaration(); + } + case lexer::TokenType::KEYW_INTERFACE: { + return ParseInterfaceDeclaration(false); + } + case lexer::TokenType::KEYW_TYPE: { + return ParseTypeAliasDeclaration(); + } + case lexer::TokenType::KEYW_GLOBAL: + case lexer::TokenType::KEYW_MODULE: + case lexer::TokenType::KEYW_NAMESPACE: { + return ParseModuleDeclaration(); + } + default: { + if (!Lexer()->GetToken().IsAsyncModifier()) { + ThrowSyntaxError("Unexpected token"); + } + + Lexer()->NextToken(); // eat `async` keyword + return ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION); + } + } +} +ir::ExportNamedDeclaration *TSParser::ParseNamedExportDeclaration(const lexer::SourcePosition &startLoc) +{ + ir::ClassDefinitionModifiers classModifiers = ir::ClassDefinitionModifiers::ID_REQUIRED; + ir::ModifierFlags flags = ir::ModifierFlags::NONE; + + if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_DECLARE) { + CheckDeclare(); + } + + if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_ABSTRACT) { + Lexer()->NextToken(); // eat 'abstract' + flags |= ir::ModifierFlags::ABSTRACT; + } + + ir::Statement *decl = GetDeclarationForNamedExport(classModifiers, flags); + + if (decl->IsVariableDeclaration()) { + ConsumeSemicolon(decl); + } + + lexer::SourcePosition endLoc = decl->End(); + ArenaVector specifiers(Allocator()->Adapter()); + auto *exportDeclaration = AllocNode(Allocator(), decl, std::move(specifiers)); + exportDeclaration->SetRange({startLoc, endLoc}); + + return exportDeclaration; +} + +ir::Statement *TSParser::ParseExportDeclaration(StatementParsingFlags flags) +{ + lexer::SourcePosition startLoc = Lexer()->GetToken().Start(); + Lexer()->NextToken(); // eat `export` keyword + + switch (Lexer()->GetToken().Type()) { + case lexer::TokenType::KEYW_DEFAULT: { + return ParseExportDefaultDeclaration(startLoc); + } + case lexer::TokenType::PUNCTUATOR_MULTIPLY: { + return ParseExportAllDeclaration(startLoc); + } + case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { + return ParseExportNamedSpecifiers(startLoc); + } + case lexer::TokenType::KEYW_IMPORT: { + return ParseTsImportEqualsDeclaration(startLoc, true); + } + case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: { + return ParseExportDefaultDeclaration(startLoc, true); + } + default: { + ir::ExportNamedDeclaration *exportDecl = ParseNamedExportDeclaration(startLoc); + + if (exportDecl->Decl()->IsVariableDeclaration() && ((flags & StatementParsingFlags::GLOBAL) == 0) && + exportDecl->Parent() != nullptr && !exportDecl->Parent()->IsTSModuleBlock() && + !GetContext().IsModule()) { + ThrowSyntaxError("Modifiers cannot appear here'"); + } + + return exportDecl; + } + } +} + +ir::Statement *TSParser::ParseConstStatement(StatementParsingFlags flags) +{ + lexer::SourcePosition constVarStar = Lexer()->GetToken().Start(); + Lexer()->NextToken(); + + if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_ENUM) { + return ParseEnumDeclaration(true); + } + + if ((flags & StatementParsingFlags::ALLOW_LEXICAL) == 0) { + ThrowSyntaxError("Lexical declaration is not allowed in single statement context"); + } + + auto *variableDecl = ParseVariableDeclaration(VariableParsingFlags::CONST | VariableParsingFlags::NO_SKIP_VAR_KIND); + variableDecl->SetStart(constVarStar); + ConsumeSemicolon(variableDecl); + + return variableDecl; +} + +ir::Statement *TSParser::ParsePotentialConstEnum(VariableParsingFlags flags) +{ + if ((flags & VariableParsingFlags::CONST) == 0) { + ThrowSyntaxError("Variable declaration expected."); + } + + return ParseEnumDeclaration(true); +} + +ir::Statement *TSParser::ParseImportDeclaration([[maybe_unused]] StatementParsingFlags flags) +{ + char32_t nextChar = Lexer()->Lookahead(); + if (nextChar == lexer::LEX_CHAR_LEFT_PAREN || nextChar == lexer::LEX_CHAR_DOT) { + return ParseExpressionStatement(); + } + + lexer::SourcePosition startLoc = Lexer()->GetToken().Start(); + Lexer()->NextToken(); // eat import + + ArenaVector specifiers(Allocator()->Adapter()); + + ir::StringLiteral *source = nullptr; + + if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_STRING) { + ir::AstNode *astNode = ParseImportSpecifiers(&specifiers); + if (astNode != nullptr) { + ASSERT(astNode->IsTSImportEqualsDeclaration()); + astNode->SetRange({startLoc, Lexer()->GetToken().End()}); + ConsumeSemicolon(astNode->AsTSImportEqualsDeclaration()); + return astNode->AsTSImportEqualsDeclaration(); + } + source = ParseFromClause(true); + } else { + source = ParseFromClause(false); + } + + lexer::SourcePosition endLoc = source->End(); + auto *importDeclaration = AllocNode(source, std::move(specifiers)); + importDeclaration->SetRange({startLoc, endLoc}); + + ConsumeSemicolon(importDeclaration); + + return importDeclaration; +} + +} // namespace ark::es2panda::parser \ No newline at end of file diff --git a/ets2panda/test/parser/ts/test_import_type-expected.txt b/ets2panda/test/parser/ts/test_import_type-expected.txt index 1f19c1b27a..67c7aee67d 100644 --- a/ets2panda/test/parser/ts/test_import_type-expected.txt +++ b/ets2panda/test/parser/ts/test_import_type-expected.txt @@ -42,7 +42,7 @@ "loc": { "start": { "line": 17, - "column": 8 + "column": 21 }, "end": { "line": 17, @@ -160,7 +160,7 @@ "loc": { "start": { "line": 20, - "column": 10 + "column": 25 }, "end": { "line": 20, @@ -446,7 +446,7 @@ "loc": { "start": { "line": 24, - "column": 15 + "column": 34 }, "end": { "line": 24, @@ -781,7 +781,7 @@ "loc": { "start": { "line": 24, - "column": 37 + "column": 132 }, "end": { "line": 24, -- Gitee