diff --git a/ets2panda/parser/ASparser.cpp b/ets2panda/parser/ASparser.cpp index b74d7243cfdcd8b053f88e653d2fe4f53ef430c0..e3e06504f702132fb15fe003ac85825555be43e9 100644 --- a/ets2panda/parser/ASparser.cpp +++ b/ets2panda/parser/ASparser.cpp @@ -15,6 +15,7 @@ #include "ASparser.h" +#include "parserFlags.h" #include "util/helpers.h" #include "varbinder/privateBinding.h" #include "varbinder/scope.h" @@ -1350,7 +1351,9 @@ ir::AstNode *ASParser::ParseImportDefaultSpecifier(ArenaVector *s return nullptr; } -ir::Expression *ASParser::ParseCoverParenthesizedExpressionAndArrowParameterList() +// NOLINTNEXTLINE(google-default-arguments) +ir::Expression *ASParser::ParseCoverParenthesizedExpressionAndArrowParameterList( + [[maybe_unused]] ExpressionParseFlags flags) { ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); lexer::SourcePosition start = Lexer()->GetToken().Start(); diff --git a/ets2panda/parser/ASparser.h b/ets2panda/parser/ASparser.h index dbbf869c47b5cd21e5c28977b10a79b1d1a5fea0..fc7cdf98b60312ef2e4aa410d0f3dcc64e0415ed 100644 --- a/ets2panda/parser/ASparser.h +++ b/ets2panda/parser/ASparser.h @@ -17,6 +17,7 @@ #define ES2PANDA_PARSER_CORE_AS_PARSER_H #include "TypedParser.h" +#include "parserFlags.h" namespace panda::es2panda::parser { class ASParser : public TypedParser { @@ -74,7 +75,9 @@ private: const ArenaVector ¶ms, ParserStatus new_status, ParserStatus context_status) override; ir::AstNode *ParseImportDefaultSpecifier(ArenaVector *specifiers) override; std::tuple ParseInterfacePropertyKey() override; - ir::Expression *ParseCoverParenthesizedExpressionAndArrowParameterList() override; + // NOLINTNEXTLINE(google-default-arguments) + ir::Expression *ParseCoverParenthesizedExpressionAndArrowParameterList( + ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS) override; ir::Expression *ParsePrefixAssertionExpression() override; ir::Statement *ParseConstStatement(StatementParsingFlags flags) override; ir::AnnotatedExpression *ParseVariableDeclaratorKey(VariableParsingFlags flags) override; diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index ddee2a5b06514926610d8ffe45d9256cf5730b28..5d7b9c9be99e0ef51d6f6387b994e415858c7fad 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -3700,7 +3700,7 @@ ir::Expression *ETSParser::ParsePrimaryExpression(ExpressionParseFlags flags) return ParseCharLiteral(); } case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: { - return ParseCoverParenthesizedExpressionAndArrowParameterList(); + return ParseCoverParenthesizedExpressionAndArrowParameterList(flags); } case lexer::TokenType::KEYW_THIS: { return ParseThisExpression(); @@ -3801,7 +3801,8 @@ ir::ArrowFunctionExpression *ETSParser::ParseArrowFunctionExpression() return arrow_func_node; } -ir::Expression *ETSParser::ParseCoverParenthesizedExpressionAndArrowParameterList() +// NOLINTNEXTLINE(google-default-arguments) +ir::Expression *ETSParser::ParseCoverParenthesizedExpressionAndArrowParameterList(ExpressionParseFlags flags) { ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); if (IsArrowFunctionExpressionStart()) { @@ -3811,7 +3812,12 @@ ir::Expression *ETSParser::ParseCoverParenthesizedExpressionAndArrowParameterLis lexer::SourcePosition start = Lexer()->GetToken().Start(); Lexer()->NextToken(); - ir::Expression *expr = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); + ExpressionParseFlags new_flags = ExpressionParseFlags::ACCEPT_COMMA; + if ((flags & ExpressionParseFlags::INSTANCEOF) != 0) { + new_flags |= ExpressionParseFlags::INSTANCEOF; + }; + + ir::Expression *expr = ParseExpression(new_flags); if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { ThrowSyntaxError("Unexpected token, expected ')'"); @@ -4481,6 +4487,24 @@ bool ETSParser::IsStructKeyword() const Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_STRUCT); } +void ETSParser::ValidateInstanceOfExpression(ir::Expression *expr) +{ + ValidateGroupedExpression(expr); + lexer::TokenType token_type = Lexer()->GetToken().Type(); + if (token_type == lexer::TokenType::PUNCTUATOR_LESS_THAN) { + auto options = TypeAnnotationParsingOptions::NO_OPTS; + + // Run checks to validate type declarations + // Should provide helpful messages with incorrect declarations like the following: + // instanceof A; + ThrowSyntaxError("Invalid right-hand side in 'instanceof' expression"); + } +} + // NOLINTNEXTLINE(google-default-arguments) ir::Expression *ETSParser::ParseExpression(ExpressionParseFlags flags) { @@ -4492,6 +4516,10 @@ ir::Expression *ETSParser::ParseExpression(ExpressionParseFlags flags) } ir::Expression *unary_expression_node = ParseUnaryOrPrefixUpdateExpression(flags); + if ((flags & ExpressionParseFlags::INSTANCEOF) != 0) { + ValidateInstanceOfExpression(unary_expression_node); + } + ir::Expression *assignment_expression = ParseAssignmentExpression(unary_expression_node, flags); if (Lexer()->GetToken().NewLine()) { diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index 84d7503c257e61f4fe88858a33c9e13d17e5c58a..bc4d0ccf9b94e9713f0251e1023d6e01e533a1bd 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -17,6 +17,7 @@ #define ES2PANDA_PARSER_CORE_ETS_PARSER_H #include +#include "parserFlags.h" #include "util/arktsconfig.h" #include "TypedParser.h" @@ -186,7 +187,9 @@ private: void ValidateForInStatement() override; - ir::Expression *ParseCoverParenthesizedExpressionAndArrowParameterList() override; + // NOLINTNEXTLINE(google-default-arguments) + ir::Expression *ParseCoverParenthesizedExpressionAndArrowParameterList( + ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS) override; ir::Statement *ParseTryStatement() override; ir::DebuggerStatement *ParseDebuggerStatement() override; void ParseReExport(lexer::SourcePosition start_loc); @@ -257,6 +260,7 @@ private: // NOLINTNEXTLINE(google-default-arguments) ir::Statement *ParseEnumDeclaration(bool is_const = false, bool is_static = false) override; ir::Expression *ParseLaunchExpression(ExpressionParseFlags flags); + void ValidateInstanceOfExpression(ir::Expression *expr); void ValidateRestParameter(ir::Expression *param) override; void CheckIndexAccessMethod(ir::ScriptFunction const *function, const lexer::SourcePosition &position) const; @@ -312,7 +316,6 @@ private: ir::Statement *CreateStatement(std::string_view source_code, std::string_view file_name = DEFAULT_SOURCE_FILE); ir::Statement *CreateFormattedStatement(std::string_view source_code, std::vector &inserting_nodes, std::string_view file_name = DEFAULT_SOURCE_FILE); - // NOLINTEND(google-default-arguments) template ir::Statement *CreateFormattedStatement(std::string_view const source_code, std::string_view const file_name, @@ -329,7 +332,6 @@ private: std::string_view file_name = DEFAULT_SOURCE_FILE); ir::TypeNode *CreateTypeAnnotation(TypeAnnotationParsingOptions *options, std::string_view source_code, std::string_view file_name = DEFAULT_SOURCE_FILE); - // NOLINTEND(google-default-arguments) friend class ExternalSourceParser; friend class InnerSourceParser; diff --git a/ets2panda/parser/TSparser.cpp b/ets2panda/parser/TSparser.cpp index 29781c637d7d2150844d17df54056bc6c62d30b3..3204d0899d76ed71132839279d886c6058a419b4 100644 --- a/ets2panda/parser/TSparser.cpp +++ b/ets2panda/parser/TSparser.cpp @@ -15,6 +15,7 @@ #include "TSparser.h" +#include "parserFlags.h" #include "util/helpers.h" #include "varbinder/privateBinding.h" #include "varbinder/scope.h" @@ -2600,7 +2601,9 @@ ir::Statement *TSParser::ParseExportDeclaration(StatementParsingFlags flags) } } -ir::Expression *TSParser::ParseCoverParenthesizedExpressionAndArrowParameterList() +// 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(); diff --git a/ets2panda/parser/TSparser.h b/ets2panda/parser/TSparser.h index 376f7f0a2e01c7cc97b2351ee61206e29892fc6a..3e660ea9a05fe04b05dc79326fd7eff901e8560d 100644 --- a/ets2panda/parser/TSparser.h +++ b/ets2panda/parser/TSparser.h @@ -17,6 +17,7 @@ #define ES2PANDA_PARSER_CORE_TS_PARSER_H #include "TypedParser.h" +#include "parserFlags.h" namespace panda::es2panda::ir { class Decorator; @@ -123,7 +124,9 @@ private: const ArenaVector ¶ms, ParserStatus new_status, ParserStatus context_status) override; ir::AstNode *ParseImportDefaultSpecifier(ArenaVector *specifiers) override; ir::Statement *ParseExportDeclaration(StatementParsingFlags flags) override; - ir::Expression *ParseCoverParenthesizedExpressionAndArrowParameterList() override; + // NOLINTNEXTLINE(google-default-arguments) + ir::Expression *ParseCoverParenthesizedExpressionAndArrowParameterList( + ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS) override; ir::Statement *ParseConstStatement(StatementParsingFlags flags) override; ir::Statement *ParsePotentialConstEnum(VariableParsingFlags flags) override; void ParseCatchParamTypeAnnotation(ir::AnnotatedExpression *param) override; diff --git a/ets2panda/parser/expressionParser.cpp b/ets2panda/parser/expressionParser.cpp index 09d10d86420b3643c2eb22ddbd82dfd9f3ae0726..ecfdfd2f8322f71a25530bd8504a1a551483f0e3 100644 --- a/ets2panda/parser/expressionParser.cpp +++ b/ets2panda/parser/expressionParser.cpp @@ -420,7 +420,9 @@ void ParserImpl::ValidateArrowFunctionRestParameter([[maybe_unused]] ir::SpreadE } } -ir::Expression *ParserImpl::ParseCoverParenthesizedExpressionAndArrowParameterList() +// NOLINTNEXTLINE(google-default-arguments) +ir::Expression *ParserImpl::ParseCoverParenthesizedExpressionAndArrowParameterList( + [[maybe_unused]] ExpressionParseFlags flags) { ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); lexer::SourcePosition start = lexer_->GetToken().Start(); @@ -492,6 +494,20 @@ void ParserImpl::CheckInvalidDestructuring(const ir::AstNode *object) const }); } +void ParserImpl::ValidateGroupedExpression(ir::Expression *lhs_expression) +{ + lexer::TokenType token_type = lexer_->GetToken().Type(); + if (lhs_expression->IsGrouped() && token_type != lexer::TokenType::PUNCTUATOR_ARROW) { + if (lhs_expression->IsSequenceExpression()) { + for (auto *seq : lhs_expression->AsSequenceExpression()->Sequence()) { + ValidateParenthesizedExpression(seq); + } + } else { + ValidateParenthesizedExpression(lhs_expression); + } + } +} + void ParserImpl::ValidateParenthesizedExpression(ir::Expression *lhs_expression) { switch (lhs_expression->Type()) { @@ -542,17 +558,9 @@ ir::Expression *ParserImpl::ParsePrefixAssertionExpression() ir::Expression *ParserImpl::ParseAssignmentExpression(ir::Expression *lhs_expression, ExpressionParseFlags flags) { - lexer::TokenType token_type = lexer_->GetToken().Type(); - if (lhs_expression->IsGrouped() && token_type != lexer::TokenType::PUNCTUATOR_ARROW) { - if (lhs_expression->IsSequenceExpression()) { - for (auto *seq : lhs_expression->AsSequenceExpression()->Sequence()) { - ValidateParenthesizedExpression(seq); - } - } else { - ValidateParenthesizedExpression(lhs_expression); - } - } + ValidateGroupedExpression(lhs_expression); + lexer::TokenType token_type = lexer_->GetToken().Type(); switch (token_type) { case lexer::TokenType::PUNCTUATOR_QUESTION_MARK: { lexer_->NextToken(); @@ -1191,7 +1199,7 @@ void ParserImpl::CreateAmendedBinaryExpression(ir::Expression *const left, ir::E SetAmendedChildExpression(right, binary_expr); } -ir::Expression *ParserImpl::ParseBinaryExpression(ir::Expression *left) +ir::Expression *ParserImpl::ParseBinaryExpression(ir::Expression *left, ExpressionParseFlags flags) { lexer::TokenType operator_type = lexer_->GetToken().Type(); ASSERT(lexer::Token::IsBinaryToken(operator_type)); @@ -1206,7 +1214,12 @@ ir::Expression *ParserImpl::ParseBinaryExpression(ir::Expression *left) lexer_->NextToken(); - ir::Expression *right_expr = ParseExpression(ExpressionParseFlags::DISALLOW_YIELD); + ExpressionParseFlags new_flags = ExpressionParseFlags::DISALLOW_YIELD; + if ((operator_type == lexer::TokenType::KEYW_INSTANCEOF) || ((flags & ExpressionParseFlags::INSTANCEOF) != 0)) { + new_flags |= ExpressionParseFlags::INSTANCEOF; + } + + ir::Expression *right_expr = ParseExpression(new_flags); ir::ConditionalExpression *conditional_expr = nullptr; if (right_expr->IsConditionalExpression() && !right_expr->IsGrouped()) { diff --git a/ets2panda/parser/parserFlags.h b/ets2panda/parser/parserFlags.h index 792114ad56d706b46972c37cd16270c3df4620e1..6d71e66beb91d4ecb995e92a8deac4f4a3304269 100644 --- a/ets2panda/parser/parserFlags.h +++ b/ets2panda/parser/parserFlags.h @@ -60,6 +60,7 @@ enum class ExpressionParseFlags : uint32_t { IMPORT = 1U << 10U, POTENTIAL_CLASS_LITERAL = 1U << 11U, IN_FOR = 1U << 12U, + INSTANCEOF = 1U << 13U, }; DEFINE_BITOPS(ExpressionParseFlags) diff --git a/ets2panda/parser/parserImpl.h b/ets2panda/parser/parserImpl.h index b6f43c047163d472e6f34e8547e23f66545060de..7d0d74e3d98931fc13b5191690aa639ef5f7b369 100644 --- a/ets2panda/parser/parserImpl.h +++ b/ets2panda/parser/parserImpl.h @@ -229,13 +229,15 @@ protected: // ExpressionParser.Cpp ir::Expression *ParseKeywordExpression(); - ir::Expression *ParseBinaryExpression(ir::Expression *left); + ir::Expression *ParseBinaryExpression(ir::Expression *left, + ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS); void ValidateUpdateExpression(ir::Expression *return_expression, bool is_chain_expression); ir::Expression *ParseMemberExpression(bool ignore_call_expression = false, ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS); ir::MetaProperty *ParsePotentialNewTarget(); void CheckInvalidDestructuring(const ir::AstNode *object) const; void ValidateParenthesizedExpression(ir::Expression *lhs_expression); + void ValidateGroupedExpression(ir::Expression *lhs_expression); ir::Expression *ParseImportExpression(); ir::Expression *ParseOptionalChain(ir::Expression *left_side_expr); ir::Expression *ParsePropertyKey(ExpressionParseFlags flags); @@ -482,7 +484,9 @@ protected: virtual void ThrowIllegalNewLineErrorAfterThrow(); virtual void ThrowIfVarDeclaration(VariableParsingFlags flags); virtual ir::Expression *ParsePrefixAssertionExpression(); - virtual ir::Expression *ParseCoverParenthesizedExpressionAndArrowParameterList(); + // NOLINTNEXTLINE(google-default-arguments) + virtual ir::Expression *ParseCoverParenthesizedExpressionAndArrowParameterList( + ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS); virtual void ThrowErrorIfStaticConstructor(ir::ModifierFlags flags); virtual std::tuple ParseComputedClassFieldOrIndexSignature(ir::Expression **prop_name); // NOLINTNEXTLINE(google-default-arguments)