1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
use std::error::Error; use token::{Operator, RPNToken}; pub fn parse(code: &str) -> Result<Vec<RPNToken>, String> { let tokens = code.chars().filter(|c| !c.is_whitespace()); let mut output: Vec<RPNToken> = Vec::new(); let mut stack: Vec<Operator> = Vec::new(); let mut num: String = String::new(); let mut neg = true; for tok in tokens { if tok.is_numeric() { num.push(tok); neg = false; } else { if tok == '-' && neg { num.push('-'); neg = false; continue; } if !num.is_empty() { let rpnt = RPNToken::Operand(num.parse::<i32>().map_err(|err| err.description().to_string())?); output.push(rpnt); num.clear(); } match Operator::try_from_char(tok) { Some(Operator::LPAREN) => { stack.push(Operator::LPAREN); neg = true; }, Some(Operator::RPAREN) => { while let Some(v) = stack.pop() { if v == Operator::LPAREN { break } assert!(v != Operator::RPAREN); output.push(RPNToken::Operator(v)); } }, Some(tokop) => { while { if let Some(&qe) = stack.last() { tokop.value() <= qe.value() } else { false } } { output.push(RPNToken::Operator(stack.pop().unwrap())); } stack.push(tokop); neg = true; }, None => return Err(format!("Unexpected character: {}", tok)), } } } if !num.is_empty() { let rpnt = RPNToken::Operand(num.parse::<i32>().map_err(|err| err.description().to_string())?); output.push(rpnt); } while let Some(v) = stack.pop() { output.push(RPNToken::Operator(v)); } Ok(output) }