clc_engine/
calculator.rs

1use crate::errors::Error;
2use crate::eval::Eval;
3use crate::parse::Parser;
4
5/// Calculator provide calculation api.
6pub struct Calculator {
7    parser: Parser,
8    eval: Eval,
9}
10
11impl Calculator {
12    /// Construct Calculator.
13    pub fn new() -> Self {
14        Self {
15            parser: Parser::new(),
16            eval: Eval::new(),
17        }
18    }
19
20    /// Calculate single line.
21    pub fn calculate_line(&self, input: &str) -> Result<f64, Error> {
22        self.parser
23            .parse_line(input)
24            .and_then(|exp| self.eval.eval(&exp))
25    }
26}
27
28impl Default for Calculator {
29    fn default() -> Self {
30        Calculator::new()
31    }
32}
33
34#[cfg(test)]
35mod tests {
36    use super::*;
37    use crate::errors::EvalError;
38
39    #[test]
40    fn calculate_line() {
41        let c = calculator();
42
43        assert_eq!(c.calculate_line("1 + 2"), Ok(3.));
44        assert_eq!(c.calculate_line("-2 * -2"), Ok(4.));
45        assert_eq!(c.calculate_line("sqrt(sqrt(16)) + 10"), Ok(12.));
46        assert_eq!(c.calculate_line("sqrt(pow(-2, 2)) - abs(-2)"), Ok(0.));
47        assert_eq!(c.calculate_line("pow(2,3) - 2 ^ 3"), Ok(0.));
48        assert_eq!(c.calculate_line("sig(1,3 |x| sig(1,3 |y| x*y ))"), Ok(36.));
49    }
50
51    #[test]
52    fn divide_by_zero() {
53        let c = calculator();
54
55        assert_eq!(
56            c.calculate_line("1 / 0"),
57            Err(Error::Eval(EvalError::DivisionByZero))
58        );
59    }
60
61    fn calculator() -> Calculator {
62        Calculator::new()
63    }
64}