From 0bace013a1f4eff29e2dc0c550d117c33474b0c3 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Thu, 16 Nov 2023 21:23:58 +0100 Subject: [PATCH] fix: Unary operators not working correctly in math evaluator --- .../content/helpers/math_evaluator.hpp | 7 ++- .../source/content/helpers/math_evaluator.cpp | 52 +++++++++++++++---- 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/plugins/builtin/include/content/helpers/math_evaluator.hpp b/plugins/builtin/include/content/helpers/math_evaluator.hpp index 1bbdc04b3..4a58dc464 100644 --- a/plugins/builtin/include/content/helpers/math_evaluator.hpp +++ b/plugins/builtin/include/content/helpers/math_evaluator.hpp @@ -79,8 +79,10 @@ namespace hex { Modulus = 0x0C2, Exponentiation = 0x1D0, Combine = 0x0E0, - BitwiseNot = 0x0F0, - Not = 0x0F1 + BitwiseNot = 0x2F0, + Not = 0x2F1, + Plus = 0x2F2, + Minus = 0x2F3 }; enum class BracketType : std::uint8_t @@ -104,6 +106,7 @@ namespace hex { static i16 comparePrecedence(const Operator &a, const Operator &b); static bool isLeftAssociative(const Operator &op); + static bool isUnary(const Operator &op); static std::pair toOperator(const std::string &input); private: diff --git a/plugins/builtin/source/content/helpers/math_evaluator.cpp b/plugins/builtin/source/content/helpers/math_evaluator.cpp index c5a1bde52..86841c17d 100644 --- a/plugins/builtin/source/content/helpers/math_evaluator.cpp +++ b/plugins/builtin/source/content/helpers/math_evaluator.cpp @@ -19,7 +19,12 @@ namespace hex { template bool MathEvaluator::isLeftAssociative(const Operator &op) { - return (static_cast(op) & 0xF00) == 0; + return (static_cast(op) & 0x100) == 0; + } + + template + bool MathEvaluator::isUnary(const Operator &op) { + return (static_cast(op) & 0x200) != 0; } template @@ -143,10 +148,18 @@ namespace hex { } else { auto [op, width] = toOperator(pos); - if (op != Operator::Invalid) { - if (inputQueue.empty() || inputQueue.back().type == TokenType::Bracket || inputQueue.back().type == TokenType::Operator) - inputQueue.push(Token { .type = TokenType::Number, .number = 0, .name = "", .arguments = { } }); + if (!inputQueue.empty()) { + auto token = inputQueue.back(); + if (token.type == TokenType::Operator || (token.type == TokenType::Bracket && token.bracketType == BracketType::Left)) { + if (op == Operator::Addition) + op = Operator::Plus; + else if (op == Operator::Subtraction) + op = Operator::Minus; + } + } + + if (op != Operator::Invalid) { inputQueue.push(Token { .type = TokenType::Operator, .op = op, .name = "", .arguments = { } }); pos += width; } else { @@ -241,14 +254,25 @@ namespace hex { evaluationStack.push(front.number); else if (front.type == TokenType::Operator) { T rightOperand, leftOperand; - if (evaluationStack.size() < 2) { - this->setError("Not enough operands for operator!"); - return std::nullopt; + if (isUnary(front.op)) { + if (evaluationStack.size() < 1) { + this->setError("Not enough operands for operator!"); + return std::nullopt; + } else { + rightOperand = evaluationStack.top(); + evaluationStack.pop(); + leftOperand = 0; + } } else { - rightOperand = evaluationStack.top(); - evaluationStack.pop(); - leftOperand = evaluationStack.top(); - evaluationStack.pop(); + if (evaluationStack.size() < 2) { + this->setError("Not enough operands for operator!"); + return std::nullopt; + } else { + rightOperand = evaluationStack.top(); + evaluationStack.pop(); + leftOperand = evaluationStack.top(); + evaluationStack.pop(); + } } T result = [] { @@ -337,6 +361,12 @@ namespace hex { case Operator::Combine: result = (static_cast(leftOperand) << (64 - __builtin_clzll(static_cast(rightOperand)))) | static_cast(rightOperand); break; + case Operator::Plus: + result = +rightOperand; + break; + case Operator::Minus: + result = -rightOperand; + break; } evaluationStack.push(result);