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/lex/mod.rs | 283 --------------------------------------------------------- 1 file changed, 283 deletions(-) delete mode 100644 src/lex/mod.rs (limited to 'src/lex') diff --git a/src/lex/mod.rs b/src/lex/mod.rs deleted file mode 100644 index 3222c12..0000000 --- a/src/lex/mod.rs +++ /dev/null @@ -1,283 +0,0 @@ -/* Copyright (C) 2019 Akshay Oppiliappan - * Refer to LICENCE for more information. - * */ - -use lazy_static::lazy_static; -use std::collections::HashMap; - -use crate::CONFIGURATION; - -use crate::error::{CalcError, Math}; - -#[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) -> Result { - if self.token == '/' && y == 0. { - Err(CalcError::Math(Math::DivideByZero)) - } else { - Ok((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) -> Result { - let result = (self.relation)(arg); - if !result.is_finite() { - Err(CalcError::Math(Math::OutOfBounds)) - } else { - Ok(result) - } - } -} - -#[derive(Debug, Clone, PartialEq)] -pub enum Token { - Operator(Operator), - Num(f64), - Function(Function), - LParen, - RParen, -} - -lazy_static! { - static ref CONSTANTS: HashMap<&'static str, Token> = { - let mut m = HashMap::new(); - m.insert("e", Token::Num(std::f64::consts::E)); - m.insert("pi", Token::Num(std::f64::consts::PI)); - m - }; - - static ref FUNCTIONS: HashMap<&'static str, Token> = { - let mut m = HashMap::new(); - m.insert("sin", Function::token_from_fn("sin".into(), |x| is_radian_mode(x, CONFIGURATION.radian_mode).sin())); - m.insert("cos", Function::token_from_fn("cos".into(), |x| is_radian_mode(x, CONFIGURATION.radian_mode).cos())); - m.insert("tan", Function::token_from_fn("tan".into(), |x| is_radian_mode(x, CONFIGURATION.radian_mode).tan())); - m.insert("csc", Function::token_from_fn("csc".into(), |x| is_radian_mode(x, CONFIGURATION.radian_mode).sin().recip())); - m.insert("sec", Function::token_from_fn("sec".into(), |x| is_radian_mode(x, CONFIGURATION.radian_mode).cos().recip())); - m.insert("cot", Function::token_from_fn("cot".into(), |x| is_radian_mode(x, CONFIGURATION.radian_mode).tan().recip())); - m.insert("sinh", Function::token_from_fn("sinh".into(), |x| x.sinh())); - m.insert("cosh", Function::token_from_fn("cosh".into(), |x| x.cosh())); - m.insert("tanh", Function::token_from_fn("tanh".into(), |x| x.tanh())); - m.insert("ln", Function::token_from_fn("ln".into(), |x| x.ln())); - m.insert("log", Function::token_from_fn("log".into(), |x| x.log10())); - m.insert("sqrt", Function::token_from_fn("sqrt".into(), |x| x.sqrt())); - m.insert("ceil", Function::token_from_fn("ceil".into(), |x| x.ceil())); - m.insert("floor", Function::token_from_fn("floor".into(), |x| x.floor())); - m.insert("rad", Function::token_from_fn("rad".into(), |x| x.to_radians())); - m.insert("deg", Function::token_from_fn("deg".into(), |x| x.to_degrees())); - m.insert("abs", Function::token_from_fn("abs".into(), |x| x.abs())); - m.insert("asin", Function::token_from_fn("asin".into(), |x| x.asin())); - m.insert("acos", Function::token_from_fn("acos".into(), |x| x.acos())); - m.insert("atan", Function::token_from_fn("atan".into(), |x| x.atan())); - m.insert("acsc", Function::token_from_fn("acsc".into(), |x| (1./x).asin())); - m.insert("asec", Function::token_from_fn("asec".into(), |x| (1./x).acos())); - m.insert("acot", Function::token_from_fn("acot".into(), |x| (1./x).atan())); - // single arg function s can be added here - m - }; - - static ref OPERATORS: HashMap = { - let mut m = HashMap::new(); - m.insert('+', Operator::token_from_op('+', |x, y| x + y, 2, true)); - m.insert('-', Operator::token_from_op('-', |x, y| x - y, 2, true)); - m.insert('*', Operator::token_from_op('*', |x, y| x * y, 3, true)); - m.insert('/', Operator::token_from_op('/', |x, y| x / y, 3, true)); - m.insert('%', Operator::token_from_op('%', |x, y| x % y, 3, true)); - m.insert('^', Operator::token_from_op('^', |x, y| x.powf(y) , 4, false)); - m.insert('!', Operator::token_from_op('!', |x, _| factorial(x) , 4, true)); - m - }; -} - -fn factorial(n: f64) -> f64 { - n.signum() * (1..=n.abs() as u64).fold(1, |p, n| p * n) as f64 -} - -pub fn lexer(input: &str, prev_ans: Option) -> Result, CalcError> { - let mut num_vec: String = String::new(); - let mut char_vec: String = String::new(); - let mut result: Vec = vec![]; - let mut last_char_is_op = true; - - let mut chars = input.chars().peekable(); - while let Some(mut letter) = chars.next() { - match letter { - '0'..='9' | '.' => { - if !char_vec.is_empty() { - if FUNCTIONS.get(&char_vec[..]).is_some() { - return Err(CalcError::Syntax(format!( - "Function '{}' expected parentheses", - char_vec - ))); - } else { - return Err(CalcError::Syntax(format!( - "Unexpected character '{}'", - char_vec - ))); - } - } - num_vec.push(letter); - last_char_is_op = false; - } - '_' => { - if prev_ans.is_none() { - return Err(CalcError::Syntax("No previous answer!".into())); - } - if !char_vec.is_empty() { - if FUNCTIONS.get(&char_vec[..]).is_some() { - return Err(CalcError::Syntax(format!( - "Function '{}' expected parentheses", - char_vec - ))); - } else { - return Err(CalcError::Syntax(format!( - "Unexpected character '{}'", - char_vec - ))); - } - } - let parse_num = num_vec.parse::().ok(); - if let Some(x) = parse_num { - result.push(Token::Num(x)); - result.push(OPERATORS.get(&'*').unwrap().clone()); - num_vec.clear(); - } - last_char_is_op = false; - result.push(Token::Num(prev_ans.unwrap())); - } - 'a'..='z' | 'A'..='Z' => { - let parse_num = num_vec.parse::().ok(); - if let Some(x) = parse_num { - result.push(Token::Num(x)); - result.push(OPERATORS.get(&'*').unwrap().clone()); - num_vec.clear(); - } - char_vec.push(letter); - last_char_is_op = false; - } - '+' | '-' => { - let op_token = OPERATORS.get(&letter).unwrap().clone(); - let parse_num = num_vec.parse::().ok(); - if !last_char_is_op { - if let Some(x) = parse_num { - result.push(Token::Num(x)); - num_vec.clear(); - last_char_is_op = true; - } else if let Some(token) = CONSTANTS.get(&char_vec[..]) { - result.push(token.clone()); - char_vec.clear(); - last_char_is_op = true; - } - result.push(op_token); - } else if last_char_is_op { - result.push(Token::LParen); - result.push(Token::Num( - (letter.to_string() + "1").parse::().unwrap(), - )); - result.push(Token::RParen); - result.push(Operator::token_from_op('*', |x, y| x * y, 10, true)); - } - } - '/' | '*' | '%' | '^' | '!' => { - drain_stack(&mut num_vec, &mut char_vec, &mut result); - if letter == '*' && chars.peek() == Some(&'*') { - // Accept `**` operator as meaning `^` (exponentation). - let _ = chars.next(); - letter = '^'; - } - let operator_token: Token = OPERATORS.get(&letter).unwrap().clone(); - result.push(operator_token); - last_char_is_op = true; - if letter == '!' { - result.push(Token::Num(1.)); - last_char_is_op = false; - } - } - '(' => { - if !char_vec.is_empty() { - if let Some(res) = FUNCTIONS.get(&char_vec[..]) { - result.push(res.clone()); - } else { - return Err(CalcError::Syntax(format!( - "Unknown function '{}'", - char_vec - ))); - } - char_vec.clear(); - } else { - let parse_num = num_vec.parse::().ok(); - if let Some(x) = parse_num { - result.push(Token::Num(x)); - result.push(OPERATORS.get(&'*').unwrap().clone()); - num_vec.clear(); - } - } - - if let Some(Token::RParen) = result.last() { - result.push(OPERATORS.get(&'*').unwrap().clone()); - } - result.push(Token::LParen); - last_char_is_op = true; - } - ')' => { - drain_stack(&mut num_vec, &mut char_vec, &mut result); - result.push(Token::RParen); - last_char_is_op = false; - } - ' ' => {} - _ => return Err(CalcError::Syntax(format!("Unexpected token: '{}'", letter))), - } - } - // println!("{:?}", result); - drain_stack(&mut num_vec, &mut char_vec, &mut result); - Ok(result) -} - -fn drain_stack(num_vec: &mut String, char_vec: &mut String, result: &mut Vec) { - let parse_num = num_vec.parse::().ok(); - if let Some(x) = parse_num { - result.push(Token::Num(x)); - num_vec.clear(); - } else if let Some(token) = CONSTANTS.get(&char_vec[..]) { - result.push(token.clone()); - char_vec.clear(); - } -} - -fn is_radian_mode(x: f64, is_radian: bool) -> f64 { - if is_radian { - x - } else { - x.to_radians() - } -} -- cgit v1.2.3