From a050178c692c59861cb0fb9666321fbef7578039 Mon Sep 17 00:00:00 2001 From: NerdyPepper Date: Thu, 21 Mar 2019 10:54:29 +0530 Subject: refactor into modules --- src/parse/mod.rs | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 src/parse/mod.rs (limited to 'src/parse') diff --git a/src/parse/mod.rs b/src/parse/mod.rs new file mode 100644 index 0000000..e5c28e6 --- /dev/null +++ b/src/parse/mod.rs @@ -0,0 +1,96 @@ +use crate::lex::Token; + +pub fn to_postfix(tokens: Vec) -> Result, String> { + let mut postfixed: Vec = vec![]; + let mut op_stack: Vec = vec![]; + for token in tokens { + match token { + Token::Num(_) => { + postfixed.push(token); + }, + Token::Function(_) => { + op_stack.push(token); + } + Token::Operator(current_op) => { + while let Some(top_op) = op_stack.last() { + match top_op { + Token::LParen => { + break; + } + Token::Operator(x) => { + let tp = x.precedence; + let cp = current_op.precedence; + if tp > cp || (tp == cp && x.is_left_associative) { + postfixed.push(op_stack.pop().unwrap()); + } else { + break; + } + } + Token::Function(_) => { + postfixed.push(op_stack.pop().unwrap()); + } + _ => { + return Err(format!("{:?} must not be on operator stack", top_op)) + } + } + } + op_stack.push(token); + }, + Token::LParen => { + op_stack.push(token); + }, + Token::RParen => { + let mut push_until_paren: bool = false; + while let Some(token) = op_stack.pop() { + if token == Token::LParen { + push_until_paren = true; + break; + } + postfixed.push(token) + } + if !push_until_paren { + return Err(String::from("Mismatched ')'")); + } + } + } + } + while let Some(op) = op_stack.pop() { + postfixed.push(op); + } + Ok(postfixed) +} + +pub fn eval_postfix(postfixed: Vec) -> Result { + let mut num_stack: Vec = vec![]; + for token in postfixed { + match token { + Token::Num(n) => { + num_stack.push(n); + }, + Token::Operator(op) => { + if let Some(n2) = num_stack.pop() { + if let Some(n1) = num_stack.pop() { + num_stack.push(op.operate(n1, n2)) + } else { + return Err(format!("Too many operators, Too little operands")) + } + } else { + return Err(format!("Too many operators, Too little operands")) + } + }, + Token::Function(funct) => { + if let Some(arg) = num_stack.pop() { + num_stack.push(funct.apply(arg)) + } + } + _ => { + return Err(format!("Yo nibba how did this get here")) + } + } + } + if num_stack.len() == 1 { + Ok(num_stack.pop().unwrap()) + } else { + Err(format!("Parser Error")) + } +} -- cgit v1.2.3