Skip to content

Commit

Permalink
feat: expression evaluation
Browse files Browse the repository at this point in the history
  • Loading branch information
jcornaz committed Sep 14, 2022
1 parent 7331610 commit 03226fb
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 1 deletion.
34 changes: 34 additions & 0 deletions src/amount/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,30 @@ impl Expression {
fn minus(left: Self, right: Self) -> Self {
Self::operation(Operator::Substract, left, right)
}

/// Evaluate the expression
#[must_use]
pub fn evaluate(&self) -> Value {
match self {
Expression::Value(value) => *value,
Expression::Operation(Operation {
operator,
left,
right,
}) => operator.evaluate(left.evaluate(), right.evaluate()),
}
}
}

impl Operator {
fn evaluate(self, Value(left): Value, Value(right): Value) -> Value {
Value(match self {
Operator::Divide => left / right,
Operator::Multiply => left * right,
Operator::Add => left + right,
Operator::Substract => left - right,
})
}
}

pub(super) fn parse(input: &str) -> IResult<&str, Expression> {
Expand Down Expand Up @@ -213,4 +237,14 @@ mod tests {
fn parse_expression(#[case] input: &str, #[case] expected: Expression) {
assert_eq!(parse(input), Ok(("", expected)));
}

#[rstest]
#[case(Expression::value(1), 1)]
#[case(Expression::plus(Expression::value(1), Expression::value(1)), 2)]
#[case(Expression::minus(Expression::value(5), Expression::value(2)), 3)]
#[case(Expression::div(Expression::value(12), Expression::value(3)), 4)]
#[case(Expression::mul(Expression::value(2), Expression::value(3)), 6)]
fn evaluate(#[case] expression: Expression, #[case] expected_result: impl Into<Decimal>) {
assert_eq!(expression.evaluate(), Value(expected_result.into()));
}
}
7 changes: 6 additions & 1 deletion src/amount/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use nom::{
sequence::separated_pair, IResult,
};

pub use self::expression::Expression;
pub use self::expression::{Expression, Value};

mod expression;

Expand All @@ -27,6 +27,11 @@ impl<'a> Amount<'a> {
&self.expression
}

#[must_use]
pub fn value(&self) -> Value {
self.expression.evaluate()
}

#[must_use]
pub fn currency(&self) -> &str {
self.currency
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![deny(future_incompatible, unsafe_code)]
#![warn(nonstandard_style, rust_2018_idioms, clippy::pedantic)]
#![cfg_attr(test, allow(clippy::needless_pass_by_value))]

//! A rust parsing library for [beancount](https://beancount.github.io/docs/) files
//!
Expand Down Expand Up @@ -34,6 +35,7 @@ mod string;
mod transaction;

use crate::directive::directive;

pub use crate::{
account::Account,
amount::{Amount, Expression},
Expand Down

0 comments on commit 03226fb

Please sign in to comment.