Fix unary operator precedence.
Before, unary operators that appeared after an operator with higher precedence would be executed after that operator. However, in evalexpr, the two unary operators are prefix operators negation and not, and prefix operators always happen before operators directly left of them.
This commit is contained in:
parent
9d0a776346
commit
4fd86751dc
@ -173,6 +173,11 @@ impl Operator {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if this operator is unary, i.e. it requires exactly one argument.
|
||||
pub(crate) fn is_unary(&self) -> bool {
|
||||
self.max_argument_amount() == Some(1) && *self != Operator::RootNode
|
||||
}
|
||||
|
||||
/// Evaluates the operator with the given arguments and context.
|
||||
pub(crate) fn eval<C: Context>(
|
||||
&self,
|
||||
|
@ -459,8 +459,13 @@ impl Node {
|
||||
}
|
||||
|
||||
fn insert_back_prioritized(&mut self, node: Node, is_root_node: bool) -> EvalexprResult<()> {
|
||||
// println!("Inserting {:?} into {:?}", node.operator, self.operator());
|
||||
if self.operator().precedence() < node.operator().precedence() || is_root_node
|
||||
println!(
|
||||
"Inserting {:?} into {:?}, is_root_node = {is_root_node}",
|
||||
node.operator(),
|
||||
self.operator()
|
||||
);
|
||||
println!("Self is {:?}", self);
|
||||
if self.operator().precedence() < node.operator().precedence() || node.operator().is_unary() || is_root_node
|
||||
// Right-to-left chaining
|
||||
|| (self.operator().precedence() == node.operator().precedence() && !self.operator().is_left_to_right() && !node.operator().is_left_to_right())
|
||||
{
|
||||
@ -471,19 +476,22 @@ impl Node {
|
||||
let last_child_operator = self.children.last().unwrap().operator();
|
||||
|
||||
if last_child_operator.precedence()
|
||||
< node.operator().precedence()
|
||||
< node.operator().precedence() || node.operator().is_unary()
|
||||
// Right-to-left chaining
|
||||
|| (last_child_operator.precedence()
|
||||
== node.operator().precedence() && !last_child_operator.is_left_to_right() && !node.operator().is_left_to_right())
|
||||
{
|
||||
// println!("Recursing into {:?}", self.children.last().unwrap().operator());
|
||||
println!(
|
||||
"Recursing into {:?}",
|
||||
self.children.last().unwrap().operator()
|
||||
);
|
||||
// Unwrap cannot fail because is_leaf being false and has_enough_children being true implies that the operator wants and has at least one child
|
||||
self.children
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.insert_back_prioritized(node, false)
|
||||
} else {
|
||||
// println!("Rotating");
|
||||
println!("Rotating");
|
||||
if node.operator().is_leaf() {
|
||||
return Err(EvalexprError::AppendedToLeafNode);
|
||||
}
|
||||
@ -521,7 +529,7 @@ impl Node {
|
||||
Ok(())
|
||||
}
|
||||
} else {
|
||||
// println!("Inserting as specified");
|
||||
println!("Inserting as specified");
|
||||
self.children.push(node);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -2148,10 +2148,11 @@ fn test_variable_assignment_and_iteration() {
|
||||
|
||||
#[test]
|
||||
fn test_negative_power() {
|
||||
assert_eq!(eval("3^-2"), Ok(Value::Float(1.0/9.0)));
|
||||
assert_eq!(eval("3^(-2)"), Ok(Value::Float(1.0/9.0)));
|
||||
println!("{:?}", build_operator_tree("3^-2").unwrap());
|
||||
assert_eq!(eval("3^-2"), Ok(Value::Float(1.0 / 9.0)));
|
||||
assert_eq!(eval("3^(-2)"), Ok(Value::Float(1.0 / 9.0)));
|
||||
assert_eq!(eval("-3^2"), Ok(Value::Float(-9.0)));
|
||||
assert_eq!(eval("-(3)^2"), Ok(Value::Float(-9.0)));
|
||||
assert_eq!(eval("(-3)^-2"), Ok(Value::Float(1.0/9.0)));
|
||||
assert_eq!(eval("-(3^-2)"), Ok(Value::Float(-1.0/9.0)));
|
||||
assert_eq!(eval("(-3)^-2"), Ok(Value::Float(1.0 / 9.0)));
|
||||
assert_eq!(eval("-(3^-2)"), Ok(Value::Float(-1.0 / 9.0)));
|
||||
}
|
Loading…
Reference in New Issue
Block a user