use alloc::vec::Vec;
use calc_common::Character;
use calc_parser::Evaluator;
pub struct CalcEvaluator;
impl Evaluator for CalcEvaluator {
type Item = i32;
type Error = ();
fn evaluate(expr: calc_parser::Expression<Self::Item>) -> Result<Self::Item, Self::Error> {
if let Some(first_argument) = expr.first_argument {
match expr.operator {
calc_parser::Operator::Add => Ok(first_argument + expr.second_argument),
calc_parser::Operator::Subtract => Ok(first_argument - expr.second_argument),
calc_parser::Operator::Multiply => Ok(first_argument * expr.second_argument),
calc_parser::Operator::Divide => Ok(first_argument / expr.second_argument),
calc_parser::Operator::Exponentiate => {
Ok(first_argument.pow(expr.second_argument.unsigned_abs()))
}
}
} else {
match expr.operator {
calc_parser::Operator::Subtract => Ok(expr.second_argument),
_ => Err(()),
}
}
}
fn add_digit(mut number_so_far: Self::Item, next_digit: u8) -> Self::Item {
number_so_far *= 10;
number_so_far += i32::from(next_digit);
number_so_far
}
fn zero() -> Self::Item {
0
}
}
pub fn number_to_chars(mut num: i32) -> Vec<Character> {
const MAX_DEC: u32 = 10u32.pow((i32::MAX as u32).ilog10());
let mut div = MAX_DEC;
let mut chars = Vec::new();
let mut hit_nonzero_digit = false;
if num < 0 {
chars.push(Character::Minus);
num = -num;
}
let mut num = num as u32;
if num == 0 {
chars.push(Character::Zero);
return chars;
}
while div > 0 {
let digit = num / div;
num -= digit * div;
if digit != 0 {
hit_nonzero_digit = true;
}
if hit_nonzero_digit {
let Some(digit) = Character::from_digit(digit as u8) else {
unreachable!()
};
chars.push(digit);
}
div /= 10;
}
chars
}