Fix arithmetic and boolean binary expression order
Previously the expression operations happened right-to-left so `1 - 2 - 3 - 4 - 5` was actually calculated as `(1 - (2 - (3 - (4 - (5)))))`. Now the expressions are calculated according to BODMAS, with boolean expressions calculated last.
This commit is contained in:
parent
0f6d700f6b
commit
03af33796a
3 changed files with 55 additions and 8 deletions
|
@ -27,6 +27,35 @@ impl Default for Expression {
|
|||
}
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
// Create a new expression
|
||||
pub fn new(l: Value, o: Operator, r: Value) -> Expression {
|
||||
Expression {
|
||||
l,
|
||||
o,
|
||||
r,
|
||||
}
|
||||
}
|
||||
// Augment an existing expression
|
||||
pub fn augment(mut self, l: Value, o: Operator) -> Expression {
|
||||
if o.precedence() >= self.o.precedence() {
|
||||
match self.l {
|
||||
Value::Expression(x) => {
|
||||
self.l = x.augment(l, o).into();
|
||||
self
|
||||
}
|
||||
_ => {
|
||||
self.l = Expression::new(l, o, self.l).into();
|
||||
self
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let r = Value::from(self);
|
||||
Expression::new(l, o, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
pub async fn compute(
|
||||
&self,
|
||||
|
@ -96,14 +125,11 @@ pub fn expression(i: &str) -> IResult<&str, Expression> {
|
|||
let (i, l) = single(i)?;
|
||||
let (i, o) = operator(i)?;
|
||||
let (i, r) = value(i)?;
|
||||
Ok((
|
||||
i,
|
||||
Expression {
|
||||
l,
|
||||
o,
|
||||
r,
|
||||
},
|
||||
))
|
||||
let v = match r {
|
||||
Value::Expression(r) => r.augment(l, o),
|
||||
_ => Expression::new(l, o, r),
|
||||
};
|
||||
Ok((i, v))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -56,6 +56,21 @@ impl Default for Operator {
|
|||
}
|
||||
}
|
||||
|
||||
impl Operator {
|
||||
#[inline]
|
||||
pub fn precedence(&self) -> u8 {
|
||||
match self {
|
||||
Operator::Or => 1,
|
||||
Operator::And => 2,
|
||||
Operator::Sub => 4,
|
||||
Operator::Add => 5,
|
||||
Operator::Mul => 6,
|
||||
Operator::Div => 7,
|
||||
_ => 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Operator {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
|
|
|
@ -201,6 +201,12 @@ impl From<Expression> for Value {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Box<Expression>> for Value {
|
||||
fn from(v: Box<Expression>) -> Self {
|
||||
Value::Expression(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i8> for Value {
|
||||
fn from(v: i8) -> Self {
|
||||
Value::Number(Number::from(v))
|
||||
|
|
Loading…
Reference in a new issue