From 72789dff9c52cf2c5ef7772b301a1d5cfd90e272 Mon Sep 17 00:00:00 2001 From: Akshay Date: Mon, 2 Nov 2020 20:00:42 +0530 Subject: fixes for nix --- src/parse.rs | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 src/parse.rs (limited to 'src/parse.rs') diff --git a/src/parse.rs b/src/parse.rs new file mode 100644 index 0000000..aa8bd4b --- /dev/null +++ b/src/parse.rs @@ -0,0 +1,105 @@ +/* Copyright (C) 2019 Akshay Oppiliappan + * Refer to LICENCE for more information. + * */ + +use crate::error::CalcError; +use crate::lex::Token; + +pub fn to_postfix(tokens: Vec) -> Result, CalcError> { + 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()); + } + _ => { + unreachable!(); + } + } + } + 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(CalcError::Syntax("Mismatched parentheses!".into())); + } + } + } + } + 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(CalcError::Parser( + "Too many operators, Too little operands".to_string(), + )); + } + } else { + return Err(CalcError::Parser( + "Too many operators, Too little operands".to_string(), + )); + } + } + Token::Function(funct) => { + if let Some(arg) = num_stack.pop() { + num_stack.push(funct.apply(arg)?) + } + } + _ => unreachable!("wut"), + } + } + if num_stack.len() == 1 { + Ok(num_stack.pop().unwrap()) + } else { + Err(CalcError::Parser( + "Too many operators, Too little operands".to_string(), + )) + } +} -- cgit v1.2.3