wikibooks_rpn_calc_test_ver_gw/
lib.rs

1// 문서용 설명 작성
2//! # RPN Calc
3//! REvers Polist notation (RPN) Calc.
4//! ```
5//! let src = String::from("1 2 + 3 * ");
6//! let a = rpn_calc::eval(src).unwrap();
7//! ```
8
9pub fn eval(src: String) -> Result<f64, String> {
10    let tokens = src.split_whitespace();
11    let mut stack:Vec<f64> = vec![];
12    for tok in tokens {
13        let t = tok.trim();
14        if t == "" { continue; }
15        match t.parse::<f64>() {
16            Ok(v) => { stack.push(v); continue; },
17            Err(_) => 0.0,
18        };
19        let b = stack.pop().unwrap_or(0.0);
20        let a = stack.pop().unwrap_or(0.0);
21        match t {
22            "+" => stack.push(a + b),
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    if stack.len() == 0 { return Err(format!("no result")); }
31    if stack.len() > 1 {
32        return Err(format!("too many value in stack"));
33    }
34    Ok(stack.pop().unwrap_or(0.0))
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40    #[test]
41    fn it_works() {
42        assert_eq!(eval("1 3 +".to_string()), Ok(4.0));
43        assert_eq!(eval("2 3 *".to_string()), Ok(6.0));
44        assert_eq!(eval("6 3 /".to_string()), Ok(2.0));
45        assert_eq!(eval("6 3 - 1 - ".to_string()), Ok(2.0));
46    }
47}