use std::io; use regex::Regex; // describe the operators enum Operator { NUM, ADD, SUB, MUL, DIV, } // structure to hold an expression in the stack struct Expression { value : f32, operator : Operator, } // function to compute a result by popping the stack and // pushing back the result fn get_result (t : &mut Vec::) { // pop the stack to get the operator // if nothing - panic with error let op = match t.pop () { Some(x) => x, None => panic! ("Illegal expression!"), }; // pop the stack for last operand // if nothing - panic with error let n1 = match t.pop () { Some (x) => x, None => panic! ("Illegal expression!"), }; // pop the stack for the first operand // if nothing - panic with error let n2 = match t.pop () { Some (x) => x, None => panic! ("Illegal expression!"), }; let mut res : f32 = 0.0; // depending on the operation, set the result match op.operator { Operator::ADD => res = n1.value + n2.value, Operator::SUB => res = n2.value - n1.value, Operator::MUL => res = n1.value * n2.value, Operator::DIV => res = n2.value / n1.value, _ => panic! ("Illegal operator in expression!"), } // push the result back to the stack t.push (Expression {value : res, operator : Operator::NUM }); } // evaluation function fn evaluate (expr : &str) { let mut ops = Vec::::new (); // tokenize the individual words by splitting at whitespace let words = expr.split_whitespace (); // regular expression to match a number let match_num = Regex::new (r"^\d+?.*?\d*?$").unwrap (); // iterate over the words for word in words { match word { // if the word matches one of +, -, *, / then push it on the stack // and immediately evaluate the expression by popping the operator // and the last two operands and push the result back on to the stack "+" => {ops.push (Expression{ value: 0.0, operator: Operator::ADD }); get_result (&mut ops) }, "-" => {ops.push (Expression{ value: 0.0, operator: Operator::SUB }); get_result (&mut ops) }, "*" => {ops.push (Expression{ value: 0.0, operator: Operator::MUL}); get_result (&mut ops)}, "/" => {ops.push (Expression{ value: 0.0, operator: Operator::DIV}); get_result (&mut ops) }, // if word matches a number, push it on to the stack _ => if match_num.is_match (word) { let num : f32 = word.parse ().unwrap (); ops.push (Expression {value: num, operator: Operator::NUM }); } // if word doesn't match either operator or number then panic. else { panic! ("Error parsing expression! Must be a number or operator (+,-,* or /)"); } } } // if the stack has more than one value, it means that the postfix // expression is not complete - so display the stack status if ops.len () > 1 { println! ("Postfix Expression not complete. Current stack: "); for exp in ops { println! ("{}", exp.value); } } // stack has only one item which is the result so display it else { println! ("Result: {}", ops[0].value); } println! (); } fn main() { // get a line from input and evaluate it let mut expr = String::new (); // loop until a blank line is received loop { expr.clear (); println!("Enter an expression (postfix) (blank to quit): "); // read a line of text io::stdin().read_line (&mut expr).expect ("Error reading line!"); // trim the text let expr = expr.trim (); // quit if the expression is blank if expr == "" { break; } evaluate (&expr); } }