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/main.rs | 241 ++---------------------------------------------------------- 1 file changed, 6 insertions(+), 235 deletions(-) (limited to 'src/main.rs') diff --git a/src/main.rs b/src/main.rs index 71251e2..63d0eb2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,57 +1,11 @@ +use std::io::{ stdin }; use std::f64; -#[derive(Debug, Copy, Clone, PartialEq)] -pub struct Operator { - token: char, - operation: fn(f64, f64) -> f64, - precedence: u8, - is_left_associative: bool, -} - -#[derive(Debug, Clone, PartialEq)] -pub struct Function { - token: String, - relation: fn(f64) -> f64, -} - -#[derive(Debug, Clone, PartialEq)] -pub enum Token { - Operator(Operator), - Num(f64), - Function(Function), - LParen, - RParen -} - -impl Operator { - fn token_from_op(token: char, operation: fn(f64, f64) -> f64, precedence: u8, is_left_associative: bool) -> Token { - Token::Operator( - Operator { - token, - operation, - precedence, - is_left_associative - } - ) - } - fn operate(self, x: f64, y: f64) -> f64 { - (self.operation)(x, y) - } -} +mod lex; +use crate::lex::*; -impl Function { - fn token_from_fn(token: String, relation: fn(f64) -> f64) -> Token { - Token::Function( - Function { - token, - relation - } - ) - } - fn apply(self, arg: f64) -> f64 { - (self.relation)(arg) - } -} +mod parse; +use crate::parse::*; fn main() { loop { @@ -69,191 +23,8 @@ fn main() { let postfixed = to_postfix(lexed.unwrap()); let evaled = eval_postfix(postfixed.unwrap()); println!("ans: {}", evaled.unwrap()); + println!(); } } -fn lexer(input: &str) -> Result, String> { - let mut num_vec: String = String::new(); - let mut char_vec: String = String::new(); - let mut result: Vec = vec![]; - for letter in input.chars() { - match letter { - '0'...'9' | '.' => { - num_vec.push(letter); - }, - 'a'...'z' | 'A'...'Z' => { - let parse_num = num_vec.parse::().ok(); - if let Some(x) = parse_num { - result.push(Token::Num(x)); - result.push(Operator::token_from_op('*', |x, y| x * y, 3, true)); - num_vec.clear(); - } - char_vec.push(letter); - }, - '+' | '-' | '/' | '*' | '^' => { - let parse_num = num_vec.parse::().ok(); - if let Some(x) = parse_num { - result.push(Token::Num(x)); - num_vec.clear(); - } - let operator_token: Token = match letter { - '+' => Operator::token_from_op('+', |x, y| x + y, 2, true), - '-' => Operator::token_from_op('-', |x, y| x - y, 2, true), - '/' => Operator::token_from_op('/', |x, y| x / y, 3, true), - '*' => Operator::token_from_op('*', |x, y| x * y, 3, true), - '^' => Operator::token_from_op('^', |x, y| x.powf(y), 4, false), - _ => panic!("unexpected op whuuu"), - }; - result.push(operator_token); - }, - '(' => { - if char_vec.len() > 0 { - let funct = char_vec.clone(); - match &funct[..] { - "sin" | "sine" => result.push(Function::token_from_fn("sin".into(), |x| x.to_radians().sin())), - "cos" | "cosine" => result.push(Function::token_from_fn("cos".into(), |x| x.to_radians().cos())), - "tan" | "tangent" => result.push(Function::token_from_fn("tan".into(), |x| x.to_radians().tan())), - "csc" | "cosec" => result.push(Function::token_from_fn("csc".into(), |x| 1f64 / x.to_radians().sin())), - "sec" | "secant" => result.push(Function::token_from_fn("sec".into(), |x| 1f64 / x.to_radians().cos())), - "cot" | "cotangent" => result.push(Function::token_from_fn("cot".into(), |x| 1f64 / x.to_radians().tan())), - "ln" => result.push(Function::token_from_fn("ln".into(), |x| x.ln())), - "log" => result.push(Function::token_from_fn("log".into(), |x| x.log10())), - _ => {} - } - char_vec.clear(); - } else { - let parse_num = num_vec.parse::().ok(); - if let Some(x) = parse_num { - result.push(Token::Num(x)); - result.push(Operator::token_from_op('*', |x, y| x * y, 3, true)); - num_vec.clear(); - } - } - if let Some(x) = result.last() { - match x { - Token::RParen => { - result.push(Operator::token_from_op('*', |x, y| x * y, 3, true)); - }, - _ => {} - }; - } - result.push(Token::LParen); - }, - ')' => { - let parse_num = num_vec.parse::().ok(); - if let Some(x) = parse_num { - result.push(Token::Num(x)); - num_vec.clear(); - } - result.push(Token::RParen); - } - ' ' => {} - _ => { - return Err(format!("Unexpected character: {}", letter)) - } - } - } - let parse_num = num_vec.parse::().ok(); - if let Some(x) = parse_num { - result.push(Token::Num(x)); - num_vec.clear(); - } - Ok(result) -} - -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) -} - -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