1
0
mirror of synced 2024-11-12 02:00:52 +01:00

fix: Unary operators not working correctly in math evaluator

This commit is contained in:
WerWolv 2023-11-16 21:23:58 +01:00
parent 1df8d19399
commit 0bace013a1
2 changed files with 46 additions and 13 deletions

View File

@ -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<Operator, size_t> toOperator(const std::string &input);
private:

View File

@ -19,7 +19,12 @@ namespace hex {
template<typename T>
bool MathEvaluator<T>::isLeftAssociative(const Operator &op) {
return (static_cast<u32>(op) & 0xF00) == 0;
return (static_cast<u32>(op) & 0x100) == 0;
}
template<typename T>
bool MathEvaluator<T>::isUnary(const Operator &op) {
return (static_cast<u32>(op) & 0x200) != 0;
}
template<typename T>
@ -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<u64>(leftOperand) << (64 - __builtin_clzll(static_cast<u64>(rightOperand)))) | static_cast<u64>(rightOperand);
break;
case Operator::Plus:
result = +rightOperand;
break;
case Operator::Minus:
result = -rightOperand;
break;
}
evaluationStack.push(result);