--- /dev/null
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "aho-corasick"
+version = "0.7.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "evpf"
+version = "0.1.0"
+dependencies = [
+ "regex",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "memchr"
+version = "2.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
+
+[[package]]
+name = "regex"
+version = "1.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "226ddd1197737bcb937489322ec1b9edaac1709d46792886e70f2113923585a6"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+ "thread_local",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
+
+[[package]]
+name = "thread_local"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
+dependencies = [
+ "lazy_static",
+]
--- /dev/null
+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::<Expression>) {
+ // 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::<Expression>::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);
+ }
+}