From 051f0e40bdd3157902fd5e94f71f9747ad2fb72c Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sat, 3 Aug 2019 13:56:32 +0800 Subject: Add constants (e, pi) --- readme.md | 17 +++++++++++++++-- src/lex/mod.rs | 23 +++++++++++++++++++---- src/main.rs | 5 +++++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/readme.md b/readme.md index 10f1e18..eed3789 100644 --- a/readme.md +++ b/readme.md @@ -72,6 +72,19 @@ $ cargo install --force --path /path/to/eva - binary operators: `+ - * / ^` - unary operators: `+ -` +### constants + +some constants avaliable in rust standard library. + +``` +e pi +``` + +examples: +``` +pi * 5^2 # πr² +``` + ### functions all trignometric functions expect input in degrees. @@ -85,7 +98,7 @@ deg(x) - convert x to degrees rad(x) - convert x to radians ``` -examples: +examples: ``` sqrt(sin(30)) # parentheses are mandatory for functions @@ -117,7 +130,7 @@ Domain Error: Out of bounds! ### todo - - add support for variables (ans, pi, e) + - ~~add support for variables (pi, e, _ (previous answer))~~ - ~~syntax highlighting~~ - multiple arg functions - ~~screenshots~~ diff --git a/src/lex/mod.rs b/src/lex/mod.rs index caafd4b..2793699 100644 --- a/src/lex/mod.rs +++ b/src/lex/mod.rs @@ -77,6 +77,13 @@ pub enum Token { RParen } +fn get_constants() -> HashMap<&'static str, Token> { + return [ + ("e", Token::Num(std::f64::consts::E)), + ("pi", Token::Num(std::f64::consts::PI)), + ].iter().cloned().collect(); +} + fn get_functions() -> HashMap<&'static str, Token> { return [ ("sin", Function::token_from_fn("sin".into(), |x| is_radian_mode(x, CONFIGURATION.radian_mode).sin())), @@ -123,6 +130,7 @@ fn factorial (n: f64) -> f64 { } pub fn lexer(input: &str, prev_ans: f64) -> Result, CalcError> { + let constants: HashMap<&str, Token> = get_constants(); let functions: HashMap<&str, Token> = get_functions(); let operators: HashMap = get_operators(); @@ -179,6 +187,10 @@ pub fn lexer(input: &str, prev_ans: f64) -> Result, CalcError> { 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 { @@ -189,7 +201,7 @@ pub fn lexer(input: &str, prev_ans: f64) -> Result, CalcError> { } }, '/' | '*' | '%' | '^' | '!' => { - drain_num_stack(&mut num_vec, &mut result); + drain_stack(&mut num_vec, &mut char_vec, &mut result); let operator_token: Token = operators.get(&letter).unwrap().clone(); result.push(operator_token); last_char_is_op = true; @@ -227,7 +239,7 @@ pub fn lexer(input: &str, prev_ans: f64) -> Result, CalcError> { last_char_is_op = true; }, ')' => { - drain_num_stack(&mut num_vec, &mut result); + drain_stack(&mut num_vec, &mut char_vec, &mut result); result.push(Token::RParen); last_char_is_op = false; }, @@ -238,15 +250,18 @@ pub fn lexer(input: &str, prev_ans: f64) -> Result, CalcError> { } } // println!("{:?}", result); - drain_num_stack(&mut num_vec, &mut result); + drain_stack(&mut num_vec, &mut char_vec, &mut result); Ok(result) } -fn drain_num_stack(num_vec: &mut String, result: &mut Vec) { +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) = get_constants().get(&char_vec[..]) { + result.push(token.clone()); + char_vec.clear(); } } diff --git a/src/main.rs b/src/main.rs index 99d2059..c3f3342 100644 --- a/src/main.rs +++ b/src/main.rs @@ -192,6 +192,11 @@ mod tests { assert_eq!(90., evaled); } #[test] + fn sigmoid_fns() { + let evaled = eval_math_expression("1 / (1 + e^-7)", 0f64).unwrap(); + assert_eq!(0.9990889488, evaled); + } + #[test] fn prev_ans() { let evaled = eval_math_expression("_ + 9", 9f64).unwrap(); assert_eq!(18.0, evaled); -- cgit v1.2.3