From 073eb46824db39f1d321817b4f23176d7ea6c175 Mon Sep 17 00:00:00 2001 From: Sam Kravitz Date: Mon, 7 Aug 2023 21:38:46 -0500 Subject: [PATCH] LibJS: Apply the correct precedence for unary + and - operators When determining the precedence of the + and - operators, the parser always returned the precedence using these operators in a binary expression (lower than division!). The context of whether the operator is used in a unary or binary expression must be taken into account. --- Userland/Libraries/LibJS/Parser.cpp | 14 +++++++++++++- .../LibJS/Tests/parser-unary-associativity.js | 4 ++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibJS/Parser.cpp b/Userland/Libraries/LibJS/Parser.cpp index d51480e277..f4692573de 100644 --- a/Userland/Libraries/LibJS/Parser.cpp +++ b/Userland/Libraries/LibJS/Parser.cpp @@ -503,6 +503,18 @@ public: return p; } + constexpr int get_unary(TokenType token) const + { + constexpr int operator_precedence_unary_plus_minus = 17; + switch (token) { + case TokenType::Minus: + case TokenType::Plus: + return operator_precedence_unary_plus_minus; + default: + return get(token); + } + } + private: int m_token_precedence[cs_num_of_js_tokens]; @@ -1791,7 +1803,7 @@ static bool is_simple_assignment_target(Expression const& expression, bool allow NonnullRefPtr Parser::parse_unary_prefixed_expression() { auto rule_start = push_start(); - auto precedence = g_operator_precedence.get(m_state.current_token.type()); + auto precedence = g_operator_precedence.get_unary(m_state.current_token.type()); auto associativity = operator_associativity(m_state.current_token.type()); switch (m_state.current_token.type()) { case TokenType::PlusPlus: { diff --git a/Userland/Libraries/LibJS/Tests/parser-unary-associativity.js b/Userland/Libraries/LibJS/Tests/parser-unary-associativity.js index 25763eda6c..dc4201e72a 100644 --- a/Userland/Libraries/LibJS/Tests/parser-unary-associativity.js +++ b/Userland/Libraries/LibJS/Tests/parser-unary-associativity.js @@ -12,3 +12,7 @@ test("basic functionality", () => { expect((typeof "x" === "string") === true).toBeTrue(); expect(!(typeof "x" === "string") === false).toBeTrue(); }); + +test("unary +/- operators bind higher than binary", () => { + expect(10 ** -3 / 2).toEqual(0.0005); +});