aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Tham <[email protected]>2019-08-03 06:56:32 +0100
committerIvan Tham <[email protected]>2019-08-03 07:15:43 +0100
commit051f0e40bdd3157902fd5e94f71f9747ad2fb72c (patch)
treea31cb6711c4aed59216d8fdd2956d9069a62c3d6
parent6c38d9b13b8e1cc976f9b22d15d100fd03ee54d4 (diff)
Add constants (e, pi)
-rw-r--r--readme.md17
-rw-r--r--src/lex/mod.rs23
-rw-r--r--src/main.rs5
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
72 - binary operators: `+ - * / ^` 72 - binary operators: `+ - * / ^`
73 - unary operators: `+ -` 73 - unary operators: `+ -`
74 74
75### constants
76
77some constants avaliable in rust standard library.
78
79```
80e pi
81```
82
83examples:
84```
85pi * 5^2 # πr²
86```
87
75### functions 88### functions
76 89
77all trignometric functions expect input in degrees. 90all trignometric functions expect input in degrees.
@@ -85,7 +98,7 @@ deg(x) - convert x to degrees
85rad(x) - convert x to radians 98rad(x) - convert x to radians
86``` 99```
87 100
88examples: 101examples:
89``` 102```
90sqrt(sin(30)) # parentheses are mandatory for functions 103sqrt(sin(30)) # parentheses are mandatory for functions
91 104
@@ -117,7 +130,7 @@ Domain Error: Out of bounds!
117 130
118### todo 131### todo
119 132
120 - add support for variables (ans, pi, e) 133 - ~~add support for variables (pi, e, _ (previous answer))~~
121 - ~~syntax highlighting~~ 134 - ~~syntax highlighting~~
122 - multiple arg functions 135 - multiple arg functions
123 - ~~screenshots~~ 136 - ~~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 {
77 RParen 77 RParen
78} 78}
79 79
80fn get_constants() -> HashMap<&'static str, Token> {
81 return [
82 ("e", Token::Num(std::f64::consts::E)),
83 ("pi", Token::Num(std::f64::consts::PI)),
84 ].iter().cloned().collect();
85}
86
80fn get_functions() -> HashMap<&'static str, Token> { 87fn get_functions() -> HashMap<&'static str, Token> {
81 return [ 88 return [
82 ("sin", Function::token_from_fn("sin".into(), |x| is_radian_mode(x, CONFIGURATION.radian_mode).sin())), 89 ("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 {
123} 130}
124 131
125pub fn lexer(input: &str, prev_ans: f64) -> Result<Vec<Token>, CalcError> { 132pub fn lexer(input: &str, prev_ans: f64) -> Result<Vec<Token>, CalcError> {
133 let constants: HashMap<&str, Token> = get_constants();
126 let functions: HashMap<&str, Token> = get_functions(); 134 let functions: HashMap<&str, Token> = get_functions();
127 let operators: HashMap<char, Token> = get_operators(); 135 let operators: HashMap<char, Token> = get_operators();
128 136
@@ -179,6 +187,10 @@ pub fn lexer(input: &str, prev_ans: f64) -> Result<Vec<Token>, CalcError> {
179 result.push(Token::Num(x)); 187 result.push(Token::Num(x));
180 num_vec.clear(); 188 num_vec.clear();
181 last_char_is_op = true; 189 last_char_is_op = true;
190 } else if let Some(token) = constants.get(&char_vec[..]) {
191 result.push(token.clone());
192 char_vec.clear();
193 last_char_is_op = true;
182 } 194 }
183 result.push(op_token); 195 result.push(op_token);
184 } else if last_char_is_op { 196 } else if last_char_is_op {
@@ -189,7 +201,7 @@ pub fn lexer(input: &str, prev_ans: f64) -> Result<Vec<Token>, CalcError> {
189 } 201 }
190 }, 202 },
191 '/' | '*' | '%' | '^' | '!' => { 203 '/' | '*' | '%' | '^' | '!' => {
192 drain_num_stack(&mut num_vec, &mut result); 204 drain_stack(&mut num_vec, &mut char_vec, &mut result);
193 let operator_token: Token = operators.get(&letter).unwrap().clone(); 205 let operator_token: Token = operators.get(&letter).unwrap().clone();
194 result.push(operator_token); 206 result.push(operator_token);
195 last_char_is_op = true; 207 last_char_is_op = true;
@@ -227,7 +239,7 @@ pub fn lexer(input: &str, prev_ans: f64) -> Result<Vec<Token>, CalcError> {
227 last_char_is_op = true; 239 last_char_is_op = true;
228 }, 240 },
229 ')' => { 241 ')' => {
230 drain_num_stack(&mut num_vec, &mut result); 242 drain_stack(&mut num_vec, &mut char_vec, &mut result);
231 result.push(Token::RParen); 243 result.push(Token::RParen);
232 last_char_is_op = false; 244 last_char_is_op = false;
233 }, 245 },
@@ -238,15 +250,18 @@ pub fn lexer(input: &str, prev_ans: f64) -> Result<Vec<Token>, CalcError> {
238 } 250 }
239 } 251 }
240 // println!("{:?}", result); 252 // println!("{:?}", result);
241 drain_num_stack(&mut num_vec, &mut result); 253 drain_stack(&mut num_vec, &mut char_vec, &mut result);
242 Ok(result) 254 Ok(result)
243} 255}
244 256
245fn drain_num_stack(num_vec: &mut String, result: &mut Vec<Token>) { 257fn drain_stack(num_vec: &mut String, char_vec: &mut String, result: &mut Vec<Token>) {
246 let parse_num = num_vec.parse::<f64>().ok(); 258 let parse_num = num_vec.parse::<f64>().ok();
247 if let Some(x) = parse_num { 259 if let Some(x) = parse_num {
248 result.push(Token::Num(x)); 260 result.push(Token::Num(x));
249 num_vec.clear(); 261 num_vec.clear();
262 } else if let Some(token) = get_constants().get(&char_vec[..]) {
263 result.push(token.clone());
264 char_vec.clear();
250 } 265 }
251} 266}
252 267
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 {
192 assert_eq!(90., evaled); 192 assert_eq!(90., evaled);
193 } 193 }
194 #[test] 194 #[test]
195 fn sigmoid_fns() {
196 let evaled = eval_math_expression("1 / (1 + e^-7)", 0f64).unwrap();
197 assert_eq!(0.9990889488, evaled);
198 }
199 #[test]
195 fn prev_ans() { 200 fn prev_ans() {
196 let evaled = eval_math_expression("_ + 9", 9f64).unwrap(); 201 let evaled = eval_math_expression("_ + 9", 9f64).unwrap();
197 assert_eq!(18.0, evaled); 202 assert_eq!(18.0, evaled);