clc-core 0.1.0

Provide calculation api for calculator ui
Documentation
use crate::errors::EvalError;
use crate::parse::{Expression, Node, Operator};
use crate::Error;

pub(crate) struct Eval {}

impl Eval {
    pub(crate) fn new() -> Self {
        Self {}
    }

    pub(crate) fn eval(&self, exp: &Expression) -> Result<f64, Error> {
        eval_exp(exp).map_err(Error::Eval)
    }
}

fn eval_exp(exp: &Expression) -> Result<f64, EvalError> {
    match exp {
        Expression::Literal(lit) => Ok(*lit),
        Expression::FuncCall(_fc) => unimplemented!(),
        Expression::Ast(node) => eval_node(node.as_ref()),
    }
}

fn eval_node(node: &Node) -> Result<f64, EvalError> {
    let left = eval_exp(&node.left)?;
    let right = eval_exp(&node.right)?;

    apply_operator(left, node.operator, right)
}

fn apply_operator(left: f64, op: Operator, right: f64) -> Result<f64, EvalError> {
    let eval = match op {
        Operator::Add => left + right,
        Operator::Sub => left - right,
        Operator::Mul => left * right,
        Operator::Div => {
            if right == 0. {
                return Err(EvalError::ZeroDivision);
            }
            left / right
        }
    };
    Ok(eval)
}