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 {
|
impl Expression {
|
||||||
pub async fn compute(
|
pub async fn compute(
|
||||||
&self,
|
&self,
|
||||||
|
@ -96,14 +125,11 @@ pub fn expression(i: &str) -> IResult<&str, Expression> {
|
||||||
let (i, l) = single(i)?;
|
let (i, l) = single(i)?;
|
||||||
let (i, o) = operator(i)?;
|
let (i, o) = operator(i)?;
|
||||||
let (i, r) = value(i)?;
|
let (i, r) = value(i)?;
|
||||||
Ok((
|
let v = match r {
|
||||||
i,
|
Value::Expression(r) => r.augment(l, o),
|
||||||
Expression {
|
_ => Expression::new(l, o, r),
|
||||||
l,
|
};
|
||||||
o,
|
Ok((i, v))
|
||||||
r,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[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 {
|
impl fmt::Display for Operator {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
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 {
|
impl From<i8> for Value {
|
||||||
fn from(v: i8) -> Self {
|
fn from(v: i8) -> Self {
|
||||||
Value::Number(Number::from(v))
|
Value::Number(Number::from(v))
|
||||||
|
|
Loading…
Reference in a new issue