aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNerdyPepper <[email protected]>2019-04-01 17:40:13 +0100
committerNerdyPepper <[email protected]>2019-04-01 17:40:13 +0100
commit3546c82fb9cd2495340adbd6aadc4099d293e83e (patch)
tree8e62506ce669d85e66ca8cfcc057568514a48184
parenta4b60c736bd74a21c276dbbbb814625dd84b507a (diff)
add factorial operator
-rw-r--r--src/lex/mod.rs57
1 files changed, 33 insertions, 24 deletions
diff --git a/src/lex/mod.rs b/src/lex/mod.rs
index bd69885..5e7a346 100644
--- a/src/lex/mod.rs
+++ b/src/lex/mod.rs
@@ -79,34 +79,34 @@ pub enum Token {
79 79
80fn get_functions() -> HashMap<&'static str, Token> { 80fn get_functions() -> HashMap<&'static str, Token> {
81 return [ 81 return [
82 ("sin", Function::token_from_fn("sin".into(), |x| is_radian_mode(x, CONFIGURATION.radian_mode).sin())), 82 ("sin", Function::token_from_fn("sin".into(), |x| is_radian_mode(x, CONFIGURATION.radian_mode).sin())),
83 ("cos", Function::token_from_fn("cos".into(), |x| is_radian_mode(x, CONFIGURATION.radian_mode).cos())), 83 ("cos", Function::token_from_fn("cos".into(), |x| is_radian_mode(x, CONFIGURATION.radian_mode).cos())),
84 ("tan", Function::token_from_fn("tan".into(), |x| is_radian_mode(x, CONFIGURATION.radian_mode).tan())), 84 ("tan", Function::token_from_fn("tan".into(), |x| is_radian_mode(x, CONFIGURATION.radian_mode).tan())),
85 ("csc", Function::token_from_fn("csc".into(), |x| is_radian_mode(x, CONFIGURATION.radian_mode).sin().recip())), 85 ("csc", Function::token_from_fn("csc".into(), |x| is_radian_mode(x, CONFIGURATION.radian_mode).sin().recip())),
86 ("sec", Function::token_from_fn("sec".into(), |x| is_radian_mode(x, CONFIGURATION.radian_mode).cos().recip())), 86 ("sec", Function::token_from_fn("sec".into(), |x| is_radian_mode(x, CONFIGURATION.radian_mode).cos().recip())),
87 ("cot", Function::token_from_fn("cot".into(), |x| is_radian_mode(x, CONFIGURATION.radian_mode).tan().recip())), 87 ("cot", Function::token_from_fn("cot".into(), |x| is_radian_mode(x, CONFIGURATION.radian_mode).tan().recip())),
88 ("sinh", Function::token_from_fn("sinh".into(), |x| x.sinh())), 88 ("sinh", Function::token_from_fn("sinh".into(), |x| x.sinh())),
89 ("cosh", Function::token_from_fn("cosh".into(), |x| x.cosh())), 89 ("cosh", Function::token_from_fn("cosh".into(), |x| x.cosh())),
90 ("tanh", Function::token_from_fn("tanh".into(), |x| x.tanh())), 90 ("tanh", Function::token_from_fn("tanh".into(), |x| x.tanh())),
91 ("ln", Function::token_from_fn("ln".into(), |x| x.ln())), 91 ("ln", Function::token_from_fn("ln".into(), |x| x.ln())),
92 ("log", Function::token_from_fn("log".into(), |x| x.log10())), 92 ("log", Function::token_from_fn("log".into(), |x| x.log10())),
93 ("sqrt", Function::token_from_fn("sqrt".into(), |x| x.sqrt())), 93 ("sqrt", Function::token_from_fn("sqrt".into(), |x| x.sqrt())),
94 ("ceil", Function::token_from_fn("ceil".into(), |x| x.ceil())), 94 ("ceil", Function::token_from_fn("ceil".into(), |x| x.ceil())),
95 ("floor", Function::token_from_fn("floor".into(), |x| x.floor())), 95 ("floor", Function::token_from_fn("floor".into(), |x| x.floor())),
96 ("rad", Function::token_from_fn("rad".into(), |x| x.to_radians())), 96 ("rad", Function::token_from_fn("rad".into(), |x| x.to_radians())),
97 ("deg", Function::token_from_fn("deg".into(), |x| x.to_degrees())), 97 ("deg", Function::token_from_fn("deg".into(), |x| x.to_degrees())),
98 ("abs", Function::token_from_fn("abs".into(), |x| x.abs())), 98 ("abs", Function::token_from_fn("abs".into(), |x| x.abs())),
99 ("asin", Function::token_from_fn("asin".into(), |x| x.asin())), 99 ("asin", Function::token_from_fn("asin".into(), |x| x.asin())),
100 ("acos", Function::token_from_fn("acos".into(), |x| x.acos())), 100 ("acos", Function::token_from_fn("acos".into(), |x| x.acos())),
101 ("atan", Function::token_from_fn("atan".into(), |x| x.atan())), 101 ("atan", Function::token_from_fn("atan".into(), |x| x.atan())),
102 ("acsc", Function::token_from_fn("acsc".into(), |x| (1./x).asin())), 102 ("acsc", Function::token_from_fn("acsc".into(), |x| (1./x).asin())),
103 ("asec", Function::token_from_fn("asec".into(), |x| (1./x).acos())), 103 ("asec", Function::token_from_fn("asec".into(), |x| (1./x).acos())),
104 ("acot", Function::token_from_fn("acot".into(), |x| (1./x).atan())), 104 ("acot", Function::token_from_fn("acot".into(), |x| (1./x).atan())),
105 // single arg function s can be added here 105 // single arg function s can be added here
106 ].iter().cloned().collect(); 106 ].iter().cloned().collect();
107} 107}
108 108
109fn get_operators() -> HashMap<char, Token> { 109pub fn get_operators() -> HashMap<char, Token> {
110 return [ 110 return [
111 ('+', Operator::token_from_op('+', |x, y| x + y, 2, true)), 111 ('+', Operator::token_from_op('+', |x, y| x + y, 2, true)),
112 ('-', Operator::token_from_op('-', |x, y| x - y, 2, true)), 112 ('-', Operator::token_from_op('-', |x, y| x - y, 2, true)),
@@ -114,9 +114,14 @@ fn get_operators() -> HashMap<char, Token> {
114 ('/', Operator::token_from_op('/', |x, y| x / y, 3, true)), 114 ('/', Operator::token_from_op('/', |x, y| x / y, 3, true)),
115 ('%', Operator::token_from_op('%', |x, y| x % y, 3, true)), 115 ('%', Operator::token_from_op('%', |x, y| x % y, 3, true)),
116 ('^', Operator::token_from_op('^', |x, y| x.powf(y) , 4, false)), 116 ('^', Operator::token_from_op('^', |x, y| x.powf(y) , 4, false)),
117 ('!', Operator::token_from_op('!', |x, _| factorial(x) , 4, true)),
117 ].iter().cloned().collect(); 118 ].iter().cloned().collect();
118} 119}
119 120
121fn factorial (n: f64) -> f64 {
122 n.signum() * (1.. n.abs() as u64 +1).fold(1, |p, n| p*n) as f64
123}
124
120pub fn lexer(input: &str) -> Result<Vec<Token>, CalcError> { 125pub fn lexer(input: &str) -> Result<Vec<Token>, CalcError> {
121 let functions: HashMap<&str, Token> = get_functions(); 126 let functions: HashMap<&str, Token> = get_functions();
122 let operators: HashMap<char, Token> = get_operators(); 127 let operators: HashMap<char, Token> = get_operators();
@@ -166,11 +171,15 @@ pub fn lexer(input: &str) -> Result<Vec<Token>, CalcError> {
166 result.push(Operator::token_from_op('*', |x, y| x * y, 10, true)); 171 result.push(Operator::token_from_op('*', |x, y| x * y, 10, true));
167 } 172 }
168 }, 173 },
169 '/' | '*' | '%' | '^' => { 174 '/' | '*' | '%' | '^' | '!' => {
170 drain_num_stack(&mut num_vec, &mut result); 175 drain_num_stack(&mut num_vec, &mut result);
171 let operator_token: Token = operators.get(&letter).unwrap().clone(); 176 let operator_token: Token = operators.get(&letter).unwrap().clone();
172 result.push(operator_token); 177 result.push(operator_token);
173 last_char_is_op = true; 178 last_char_is_op = true;
179 if letter == '!' {
180 result.push(Token::Num(1.));
181 last_char_is_op = false;
182 }
174 }, 183 },
175 '(' => { 184 '(' => {
176 if char_vec.len() > 0 { 185 if char_vec.len() > 0 {