diff --git a/ets2panda/parser/expressionParser.cpp b/ets2panda/parser/expressionParser.cpp index 67468ab682f9c20e069afa94914cc9ab66112ab5..6d54cc21432a65354c4e794b25d4854ec4c79d0f 100644 --- a/ets2panda/parser/expressionParser.cpp +++ b/ets2panda/parser/expressionParser.cpp @@ -214,6 +214,13 @@ ir::ArrayExpression *ParserImpl::ParseArrayExpression(ExpressionParseFlags flags arrayExpressionNode->SetDeclaration(); } + ParseArrayExpressionErrorCheck(arrayExpressionNode, flags, inPattern); + return arrayExpressionNode; +} + +void ParserImpl::ParseArrayExpressionErrorCheck(ir::ArrayExpression *arrayExpressionNode, + const ExpressionParseFlags flags, const bool inPattern) +{ if ((flags & ExpressionParseFlags::POTENTIALLY_IN_PATTERN) == 0) { if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION && !arrayExpressionNode->ConvertibleToArrayPattern()) { @@ -225,8 +232,6 @@ ir::ArrayExpression *ParserImpl::ParseArrayExpression(ExpressionParseFlags flags } } } - - return arrayExpressionNode; } ParserStatus ParserImpl::ValidateArrowParameter(ir::Expression *expr, [[maybe_unused]] bool *seenOptional) @@ -248,9 +253,8 @@ ParserStatus ParserImpl::ValidateArrowParameter(ir::Expression *expr, [[maybe_un return ParserStatus::NO_OPTS; } case ir::AstNodeType::OBJECT_EXPRESSION: { - ir::ObjectExpression *objectPattern = expr->AsObjectExpression(); - - if (!objectPattern->ConvertibleToObjectPattern()) { + if (ir::ObjectExpression *objectPattern = expr->AsObjectExpression(); + !objectPattern->ConvertibleToObjectPattern()) { ThrowSyntaxError("Invalid destructuring assignment target"); } @@ -258,9 +262,8 @@ ParserStatus ParserImpl::ValidateArrowParameter(ir::Expression *expr, [[maybe_un return ParserStatus::HAS_COMPLEX_PARAM; } case ir::AstNodeType::ARRAY_EXPRESSION: { - ir::ArrayExpression *arrayPattern = expr->AsArrayExpression(); - - if (!arrayPattern->ConvertibleToArrayPattern()) { + if (ir::ArrayExpression *arrayPattern = expr->AsArrayExpression(); + !arrayPattern->ConvertibleToArrayPattern()) { ThrowSyntaxError("Invalid destructuring assignment target"); } @@ -268,19 +271,7 @@ ParserStatus ParserImpl::ValidateArrowParameter(ir::Expression *expr, [[maybe_un return ParserStatus::HAS_COMPLEX_PARAM; } case ir::AstNodeType::ASSIGNMENT_EXPRESSION: { - auto *assignmentExpr = expr->AsAssignmentExpression(); - if (assignmentExpr->Right()->IsYieldExpression()) { - ThrowSyntaxError("yield is not allowed in arrow function parameters"); - } - - if (assignmentExpr->Right()->IsAwaitExpression()) { - ThrowSyntaxError("await is not allowed in arrow function parameters"); - } - - if (!assignmentExpr->ConvertibleToAssignmentPattern()) { - ThrowSyntaxError("Invalid destructuring assignment target"); - } - + ValidateArrowParameterAssignment(expr->AsAssignmentExpression()); ValidateArrowParameterBindings(expr); return ParserStatus::HAS_COMPLEX_PARAM; } @@ -292,6 +283,17 @@ ParserStatus ParserImpl::ValidateArrowParameter(ir::Expression *expr, [[maybe_un return ParserStatus::NO_OPTS; } +void ParserImpl::ValidateArrowParameterAssignment(ir::AssignmentExpression *expr) +{ + if (expr->Right()->IsYieldExpression()) { + ThrowSyntaxError("yield is not allowed in arrow function parameters"); + } else if (expr->Right()->IsAwaitExpression()) { + ThrowSyntaxError("await is not allowed in arrow function parameters"); + } else if (!expr->ConvertibleToAssignmentPattern()) { + ThrowSyntaxError("Invalid destructuring assignment target"); + } +} + ir::ArrowFunctionExpression *ParserImpl::ParseArrowFunctionExpressionBody(ArrowFunctionContext *arrowFunctionContext, ArrowFunctionDescriptor *desc, ir::TSTypeParameterDeclaration *typeParamDecl, @@ -592,6 +594,46 @@ ir::Expression *ParserImpl::ParseAssignmentExpression(ir::Expression *lhsExpress return ParseArrowFunctionExpression(lhsExpression, nullptr, nullptr, false); } + case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: { + ValidateAssignmentTarget(flags, lhsExpression); + + lexer_->NextToken(); + ir::Expression *assignmentExpression = ParseExpression(CarryPatternFlags(flags)); + + auto *binaryAssignmentExpression = + AllocNode(lhsExpression, assignmentExpression, tokenType); + + binaryAssignmentExpression->SetRange({lhsExpression->Start(), assignmentExpression->End()}); + return binaryAssignmentExpression; + } + case lexer::TokenType::KEYW_AS: { + if (auto asExpression = ParsePotentialAsExpression(lhsExpression); asExpression != nullptr) { + return ParseAssignmentExpression(asExpression); + } + break; + } + default: { + auto expression = ParseAssignmentBinaryExpression(tokenType, lhsExpression, flags); + if (expression == nullptr) { + expression = ParseAssignmentEqualExpression(tokenType, lhsExpression, flags); + } + + if (expression != nullptr) { + return expression; + } + + break; + } + } + + return lhsExpression; +} + +ir::Expression *ParserImpl::ParseAssignmentBinaryExpression(const lexer::TokenType tokenType, + ir::Expression *lhsExpression, + const ExpressionParseFlags flags) +{ + switch (tokenType) { case lexer::TokenType::KEYW_IN: { if ((flags & ExpressionParseFlags::STOP_AT_IN) != 0) { break; @@ -623,22 +665,20 @@ ir::Expression *ParserImpl::ParseAssignmentExpression(ir::Expression *lhsExpress case lexer::TokenType::PUNCTUATOR_MOD: case lexer::TokenType::KEYW_INSTANCEOF: case lexer::TokenType::PUNCTUATOR_EXPONENTIATION: { - ir::Expression *binaryExpression = ParseBinaryExpression(lhsExpression); - - return ParseAssignmentExpression(binaryExpression); + return ParseAssignmentExpression(ParseBinaryExpression(lhsExpression)); } - case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: { - ValidateAssignmentTarget(flags, lhsExpression); - - lexer_->NextToken(); - ir::Expression *assignmentExpression = ParseExpression(CarryPatternFlags(flags)); + default: + break; + } - auto *binaryAssignmentExpression = - AllocNode(lhsExpression, assignmentExpression, tokenType); + return nullptr; +} - binaryAssignmentExpression->SetRange({lhsExpression->Start(), assignmentExpression->End()}); - return binaryAssignmentExpression; - } +ir::Expression *ParserImpl::ParseAssignmentEqualExpression(const lexer::TokenType tokenType, + ir::Expression *lhsExpression, + const ExpressionParseFlags flags) +{ + switch (tokenType) { case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL: case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL: case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL: @@ -665,18 +705,11 @@ ir::Expression *ParserImpl::ParseAssignmentExpression(ir::Expression *lhsExpress binaryAssignmentExpression->SetRange({lhsExpression->Start(), assignmentExpression->End()}); return binaryAssignmentExpression; } - case lexer::TokenType::KEYW_AS: { - auto asExpression = ParsePotentialAsExpression(lhsExpression); - if (asExpression != nullptr) { - return ParseAssignmentExpression(asExpression); - } - break; - } default: break; } - return lhsExpression; + return nullptr; } ir::TemplateLiteral *ParserImpl::ParseTemplateLiteral() @@ -1092,7 +1125,43 @@ ir::Expression *ParserImpl::ParsePrimaryExpression(ExpressionParseFlags flags) return ParsePrimaryExpressionWithLiterals(flags); } -static size_t GetOperatorPrecedence(const lexer::TokenType operatorType) +static constexpr size_t GetOperatorPrecedenceArithmeticAndComparison(const lexer::TokenType operatorType) +{ + switch (operatorType) { + case lexer::TokenType::PUNCTUATOR_EQUAL: + case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: + case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL: + case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: { + constexpr auto PRECEDENCE = 8; + return PRECEDENCE; + } + case lexer::TokenType::PUNCTUATOR_LESS_THAN: + case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: + case lexer::TokenType::PUNCTUATOR_GREATER_THAN: + case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: + case lexer::TokenType::KEYW_INSTANCEOF: + case lexer::TokenType::KEYW_IN: { + constexpr auto PRECEDENCE = 9; + return PRECEDENCE; + } + case lexer::TokenType::PUNCTUATOR_PLUS: + case lexer::TokenType::PUNCTUATOR_MINUS: { + constexpr auto PRECEDENCE = 12; + return PRECEDENCE; + } + case lexer::TokenType::PUNCTUATOR_MULTIPLY: + case lexer::TokenType::PUNCTUATOR_DIVIDE: + case lexer::TokenType::PUNCTUATOR_MOD: { + constexpr auto PRECEDENCE = 13; + return PRECEDENCE; + } + default: { + UNREACHABLE(); + } + } +} + +static constexpr size_t GetOperatorPrecedence(const lexer::TokenType operatorType) { ASSERT(operatorType == lexer::TokenType::KEYW_AS || lexer::Token::IsBinaryToken(operatorType)); @@ -1121,22 +1190,6 @@ static size_t GetOperatorPrecedence(const lexer::TokenType operatorType) constexpr auto PRECEDENCE = 7; return PRECEDENCE; } - case lexer::TokenType::PUNCTUATOR_EQUAL: - case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: - case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL: - case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: { - constexpr auto PRECEDENCE = 8; - return PRECEDENCE; - } - case lexer::TokenType::PUNCTUATOR_LESS_THAN: - case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: - case lexer::TokenType::PUNCTUATOR_GREATER_THAN: - case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: - case lexer::TokenType::KEYW_INSTANCEOF: - case lexer::TokenType::KEYW_IN: { - constexpr auto PRECEDENCE = 9; - return PRECEDENCE; - } case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT: case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: { @@ -1147,23 +1200,12 @@ static size_t GetOperatorPrecedence(const lexer::TokenType operatorType) constexpr auto PRECEDENCE = 11; return PRECEDENCE; } - case lexer::TokenType::PUNCTUATOR_PLUS: - case lexer::TokenType::PUNCTUATOR_MINUS: { - constexpr auto PRECEDENCE = 12; - return PRECEDENCE; - } - case lexer::TokenType::PUNCTUATOR_MULTIPLY: - case lexer::TokenType::PUNCTUATOR_DIVIDE: - case lexer::TokenType::PUNCTUATOR_MOD: { - const auto precedence = 13; - return precedence; - } case lexer::TokenType::PUNCTUATOR_EXPONENTIATION: { constexpr auto PRECEDENCE = 14; return PRECEDENCE; } default: { - UNREACHABLE(); + return GetOperatorPrecedenceArithmeticAndComparison(operatorType); } } } @@ -1565,32 +1607,14 @@ ir::Expression *ParserImpl::ParsePostPrimaryExpression(ir::Expression *primaryEx ir::Expression *returnExpression = primaryExpr; while (true) { - switch (lexer_->GetToken().Type()) { - case lexer::TokenType::PUNCTUATOR_QUESTION_DOT: { - *isChainExpression = true; - lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); // eat ?. - returnExpression = ParseOptionalChain(returnExpression); - continue; - } - case lexer::TokenType::PUNCTUATOR_PERIOD: { - lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); // eat period - - if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_HASH_MARK) { - returnExpression = ParsePrivatePropertyAccess(returnExpression); - continue; - } - - returnExpression = ParsePropertyAccess(returnExpression); - continue; - } + auto tokenType = lexer_->GetToken().Type(); + switch (tokenType) { case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: { returnExpression = ParseElementAccess(returnExpression); continue; } case lexer::TokenType::LITERAL_IDENT: { - auto *asExpression = ParsePotentialAsExpression(returnExpression); - - if (asExpression != nullptr) { + if (auto *asExpression = ParsePotentialAsExpression(returnExpression); asExpression != nullptr) { return asExpression; } break; @@ -1600,15 +1624,10 @@ ir::Expression *ParserImpl::ParsePostPrimaryExpression(ir::Expression *primaryEx if (ParsePotentialGenericFunctionCall(primaryExpr, &returnExpression, startLoc, ignoreCallExpression)) { break; } - continue; } case lexer::TokenType::PUNCTUATOR_BACK_TICK: { - ir::TemplateLiteral *propertyNode = ParseTemplateLiteral(); - lexer::SourcePosition endLoc = propertyNode->End(); - - returnExpression = AllocNode(returnExpression, propertyNode, nullptr); - returnExpression->SetRange({startLoc, endLoc}); + returnExpression = ParsePostPrimaryExpressionBackTick(returnExpression, startLoc); continue; } case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: { @@ -1619,15 +1638,17 @@ ir::Expression *ParserImpl::ParsePostPrimaryExpression(ir::Expression *primaryEx continue; } case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: { - const bool shouldBreak = ParsePotentialNonNullExpression(&returnExpression, startLoc); - if (shouldBreak) { + if (ParsePotentialNonNullExpression(&returnExpression, startLoc)) { break; } - continue; } default: { - break; + if (auto tmp = ParsePostPrimaryExpressionDot(returnExpression, tokenType, isChainExpression); + tmp != nullptr) { + returnExpression = tmp; + continue; + } } } @@ -1637,6 +1658,44 @@ ir::Expression *ParserImpl::ParsePostPrimaryExpression(ir::Expression *primaryEx return returnExpression; } +ir::Expression *ParserImpl::ParsePostPrimaryExpressionBackTick(ir::Expression *returnExpression, + const lexer::SourcePosition startLoc) +{ + ir::TemplateLiteral *propertyNode = ParseTemplateLiteral(); + lexer::SourcePosition endLoc = propertyNode->End(); + + returnExpression = AllocNode(returnExpression, propertyNode, nullptr); + returnExpression->SetRange({startLoc, endLoc}); + + return returnExpression; +} + +ir::Expression *ParserImpl::ParsePostPrimaryExpressionDot(ir::Expression *returnExpression, + const lexer::TokenType tokenType, bool *isChainExpression) +{ + switch (tokenType) { + case lexer::TokenType::PUNCTUATOR_QUESTION_DOT: { + *isChainExpression = true; + lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); // eat ?. + return ParseOptionalChain(returnExpression); + } + case lexer::TokenType::PUNCTUATOR_PERIOD: { + lexer_->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); // eat period + + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_HASH_MARK) { + return ParsePrivatePropertyAccess(returnExpression); + } + + return ParsePropertyAccess(returnExpression); + } + default: { + break; + } + } + + return nullptr; +} + void ParserImpl::ValidateUpdateExpression(ir::Expression *returnExpression, bool isChainExpression) { if ((!returnExpression->IsMemberExpression() && !returnExpression->IsIdentifier() && @@ -1761,6 +1820,19 @@ ir::Expression *ParserImpl::ParsePatternElement(ExpressionParseFlags flags, bool return returnNode; } + ParsePatternElementErrorCheck(flags, allowDefault); + + 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; +} + +void ParserImpl::ParsePatternElementErrorCheck(const ExpressionParseFlags flags, const bool allowDefault) +{ if ((flags & ExpressionParseFlags::IN_REST) != 0) { ThrowSyntaxError("Unexpected token, expected ')'"); } @@ -1778,14 +1850,6 @@ ir::Expression *ParserImpl::ParsePatternElement(ExpressionParseFlags flags, bool if (context_.IsAsync() && lexer_->GetToken().Type() == lexer::TokenType::KEYW_AWAIT) { ThrowSyntaxError("Illegal await-expression in formal parameters of async function"); } - - 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; } void ParserImpl::CheckPropertyKeyAsyncModifier(ParserStatus *methodStatus) diff --git a/ets2panda/parser/parserImpl.h b/ets2panda/parser/parserImpl.h index 0fa1bfbd1133ba0e8f790452adb479a04cf01c07..585b1be3e5a61610e1ff54d15113aad18daddfbc 100644 --- a/ets2panda/parser/parserImpl.h +++ b/ets2panda/parser/parserImpl.h @@ -316,6 +316,10 @@ protected: ir::TypeNode *returnTypeAnnotation); ir::Expression *ParseAssignmentExpression(ir::Expression *lhsExpression, ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS); + ir::Expression *ParseAssignmentBinaryExpression(lexer::TokenType tokenType, ir::Expression *lhsExpression, + ExpressionParseFlags flags); + ir::Expression *ParseAssignmentEqualExpression(lexer::TokenType tokenType, ir::Expression *lhsExpression, + ExpressionParseFlags flags); ir::SequenceExpression *ParseSequenceExpression(ir::Expression *startExpr, bool acceptRest = false); ir::FunctionExpression *ParseFunctionExpression(ParserStatus newStatus = ParserStatus::NO_OPTS); ir::ArrowFunctionExpression *ParseArrowFunctionExpression(ir::Expression *expr, @@ -422,6 +426,7 @@ protected: // NOLINTNEXTLINE(google-default-arguments) virtual ir::Expression *ParsePatternElement(ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS, bool allowDefault = true); + void ParsePatternElementErrorCheck(ExpressionParseFlags flags, bool allowDefault); virtual bool ParsePotentialNonNullExpression(ir::Expression **returnExpression, lexer::SourcePosition startLoc); virtual ir::AstNode *ParseImportSpecifiers(ArenaVector *specifiers); virtual ir::Statement *ParseImportDeclaration(StatementParsingFlags flags); @@ -432,6 +437,8 @@ protected: virtual ir::ObjectExpression *ParseObjectExpression(ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS); // NOLINTNEXTLINE(google-default-arguments) virtual ir::ArrayExpression *ParseArrayExpression(ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS); + void ParseArrayExpressionErrorCheck(ir::ArrayExpression *arrayExpressionNode, ExpressionParseFlags flags, + bool inPattern); virtual ir::ArrowFunctionExpression *ParsePotentialArrowExpression(ir::Expression **returnExpression, const lexer::SourcePosition &startLoc); virtual bool ParsePotentialGenericFunctionCall(ir::Expression *primaryExpr, ir::Expression **returnExpression, @@ -497,8 +504,13 @@ protected: virtual ir::Expression *ParsePrimaryExpression(ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS); virtual ir::Expression *ParsePostPrimaryExpression(ir::Expression *primaryExpr, lexer::SourcePosition startLoc, bool ignoreCallExpression, bool *isChainExpression); + ir::Expression *ParsePostPrimaryExpressionBackTick(ir::Expression *returnExpression, + lexer::SourcePosition startLoc); + ir::Expression *ParsePostPrimaryExpressionDot(ir::Expression *returnExpression, lexer::TokenType tokenType, + bool *isChainExpression); virtual ir::ClassElement *ParseClassStaticBlock(); virtual ParserStatus ValidateArrowParameter(ir::Expression *expr, bool *seenOptional); + void ValidateArrowParameterAssignment(ir::AssignmentExpression *expr); virtual ArrowFunctionDescriptor ConvertToArrowParameter(ir::Expression *expr, bool isAsync); virtual ir::Expression *ParseNewExpression();