First commit
authorHarishankar <v.harishankar@gmail.com>
Thu, 28 May 2020 16:27:56 +0000 (21:57 +0530)
committerHarishankar <v.harishankar@gmail.com>
Thu, 28 May 2020 16:27:56 +0000 (21:57 +0530)
first commit of postfix expression evaluator

Cargo.lock [new file with mode: 0644]
Cargo.toml [new file with mode: 0644]
src/main.rs [new file with mode: 0644]

diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644 (file)
index 0000000..1f7d091
--- /dev/null
@@ -0,0 +1,56 @@
+# 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",
+]
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644 (file)
index 0000000..8615725
--- /dev/null
@@ -0,0 +1,10 @@
+[package]
+name = "evpf"
+version = "0.1.0"
+authors = ["Harishankar <v.harishankar@gmail.com>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+regex="1"
diff --git a/src/main.rs b/src/main.rs
new file mode 100644 (file)
index 0000000..dcf215f
--- /dev/null
@@ -0,0 +1,117 @@
+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);
+       }
+}