kengos_test_rpn_calc/
lib.rs

1/// Eval RPN
2/// # Example
3/// ```
4/// let src = String::from("1 2 + 3 *");
5/// let a = kengos_test_rpn_calc::eval(src).unwrap();
6/// println!("{}", a); // => 9
7/// ```
8pub fn eval(src: String) -> Result<f64, String> {
9    let tokens = src.split_whitespace();
10    let mut stack: Vec<f64> = vec![];
11    for token in tokens {
12        let t = token.trim();
13        match t.parse::<f64>() {
14            Ok(v) => {
15                stack.push(v);
16                continue;
17            }
18            Err(_) => 0.0,
19        };
20        let b = stack.pop().unwrap();
21        let a = stack.pop().unwrap();
22        match t {
23            "+" => stack.push(a + b),
24            "-" => stack.push(a - b),
25            "*" => stack.push(a * b),
26            "/" => stack.push(a / b),
27            _ => return Err(format!("invalid operator: {}", t)),
28        };
29    }
30
31    if stack.len() == 0 {
32        return Err(format!("no result"));
33    }
34    if stack.len() > 1 {
35        return Err(format!("too many value in stack"));
36    }
37    Ok(stack.pop().unwrap_or(0.0))
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn it_works() {
46        assert_eq!(eval("1 3 +".to_string()), Ok(4.0));
47        assert_eq!(eval("2.22 4.2 -".to_string()), Ok(-1.98));
48        assert_eq!(eval("2 3 *".to_string()), Ok(6.0));
49        assert_eq!(eval("6 3 /".to_string()), Ok(2.0));
50        assert_eq!(eval("6 3 - 1 -".to_string()), Ok(2.0));
51        assert_eq!(
52            eval("6 6".to_string()),
53            Err("too many value in stack".to_string())
54        );
55        assert_eq!(
56            eval("6 6 + 3 !".to_string()),
57            Err("invalid operator: !".to_string())
58        );
59        assert_eq!(eval("".to_string()), Err("no result".to_string()));
60    }
61}