diff options
-rw-r--r-- | readme.md | 17 | ||||
-rw-r--r-- | src/lex/mod.rs | 23 | ||||
-rw-r--r-- | src/main.rs | 5 |
3 files changed, 39 insertions, 6 deletions
@@ -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 | |||
77 | some constants avaliable in rust standard library. | ||
78 | |||
79 | ``` | ||
80 | e pi | ||
81 | ``` | ||
82 | |||
83 | examples: | ||
84 | ``` | ||
85 | pi * 5^2 # πr² | ||
86 | ``` | ||
87 | |||
75 | ### functions | 88 | ### functions |
76 | 89 | ||
77 | all trignometric functions expect input in degrees. | 90 | all trignometric functions expect input in degrees. |
@@ -85,7 +98,7 @@ deg(x) - convert x to degrees | |||
85 | rad(x) - convert x to radians | 98 | rad(x) - convert x to radians |
86 | ``` | 99 | ``` |
87 | 100 | ||
88 | examples: | 101 | examples: |
89 | ``` | 102 | ``` |
90 | sqrt(sin(30)) # parentheses are mandatory for functions | 103 | sqrt(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 | ||
80 | fn 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 | |||
80 | fn get_functions() -> HashMap<&'static str, Token> { | 87 | fn 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 | ||
125 | pub fn lexer(input: &str, prev_ans: f64) -> Result<Vec<Token>, CalcError> { | 132 | pub 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 | ||
245 | fn drain_num_stack(num_vec: &mut String, result: &mut Vec<Token>) { | 257 | fn 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); |