fix: correctly evaluate unary operators with parenthesis
This commit is contained in:
parent
a520177183
commit
7182e29512
3 changed files with 37 additions and 12 deletions
|
|
@ -41,6 +41,31 @@ fn collapse_toplevel(nodes: &mut Vec<Node>, mut end: usize) -> Result<(), Error>
|
|||
.rposition(|n| *n == Node::ParenthesisStart)
|
||||
.unwrap_or(0);
|
||||
|
||||
let mut i = start;
|
||||
while i < end {
|
||||
if let Node::Operator(operator) = nodes[i]
|
||||
&& matches!(operator, Operator::Plus | Operator::Minus)
|
||||
&& matches!(
|
||||
i.checked_sub(1).and_then(|i| nodes.get(i)),
|
||||
None | Some(Node::ParenthesisStart)
|
||||
)
|
||||
{
|
||||
match nodes.get_mut(i + 1) {
|
||||
None => return Err(Error::OutOfBounds(Nodes(nodes.clone()), i + 1)),
|
||||
|
||||
Some(Node::Number(n)) => {
|
||||
if operator == Operator::Minus {
|
||||
n.mul_from(-1);
|
||||
}
|
||||
nodes.remove(i);
|
||||
end -= 1;
|
||||
}
|
||||
Some(n) => return Err(Error::InvalidOperand(n.clone())),
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
while let Some((index, function)) = nodes[start..end]
|
||||
.iter()
|
||||
.enumerate()
|
||||
|
|
|
|||
|
|
@ -157,17 +157,9 @@ impl FromStr for Nodes {
|
|||
} else if c == ')' {
|
||||
nodes.push(Node::ParenthesisEnd);
|
||||
} else {
|
||||
if matches!(
|
||||
nodes.last(),
|
||||
Some(Node::Operator(_) | Node::ParenthesisStart) | None
|
||||
) {
|
||||
// it must be a unary operator
|
||||
state = ParsingState::ReadingNumber(i);
|
||||
} else {
|
||||
nodes.push(Node::Operator(
|
||||
c.try_into().map_err(Error::InvalidOperator)?,
|
||||
));
|
||||
}
|
||||
nodes.push(Node::Operator(
|
||||
c.try_into().map_err(Error::InvalidOperator)?,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -241,7 +233,8 @@ mod tests {
|
|||
Node::from(5),
|
||||
Node::Operator(Operator::Mult),
|
||||
Node::ParenthesisStart,
|
||||
Node::from(-5),
|
||||
Node::Operator(Operator::Minus),
|
||||
Node::from(5),
|
||||
Node::ParenthesisEnd,
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -38,6 +38,13 @@ fn unary_operators() {
|
|||
assert_eq!(eval("-10"), -10.);
|
||||
assert_eq!(eval("+10"), 10.);
|
||||
}
|
||||
#[test]
|
||||
fn unary_operators_with_parenthesis() {
|
||||
assert_eq!(eval("-(10)"), -10.);
|
||||
assert_eq!(eval("+(10)"), 10.);
|
||||
assert_eq!(eval("(-10)"), -10.);
|
||||
assert_eq!(eval("(+10)"), 10.);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn constant_implicit_mult() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue