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/lex/mod.rs | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 src/lex/mod.rs (limited to 'src/lex/mod.rs') diff --git a/src/lex/mod.rs b/src/lex/mod.rs new file mode 100644 index 0000000..af5ff06 --- /dev/null +++ b/src/lex/mod.rs @@ -0,0 +1,145 @@ +use std::f64; +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct Operator { + token: char, + pub operation: fn(f64, f64) -> f64, + pub precedence: u8, + pub is_left_associative: bool, +} + +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 + } + ) + } + pub fn operate(self, x: f64, y: f64) -> f64 { + (self.operation)(x, y) + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct Function { + token: String, + relation: fn(f64) -> f64, +} + +impl Function { + fn token_from_fn(token: String, relation: fn(f64) -> f64) -> Token { + Token::Function( + Function { + token, + relation + } + ) + } + pub fn apply(self, arg: f64) -> f64 { + (self.relation)(arg) + } +} + + +#[derive(Debug, Clone, PartialEq)] +pub enum Token { + Operator(Operator), + Num(f64), + Function(Function), + LParen, + RParen +} + +pub 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())), + "sqrt" => result.push(Function::token_from_fn("sqrt".into(), |x| x.sqrt())), + _ => return Err(format!("Unexpected function {}", funct)) + } + 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) +} -- cgit v1.2.3