rpn_calc_hellojaewon/
lib.rs

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