diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lex/mod.rs | 57 |
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 | ||
80 | fn get_functions() -> HashMap<&'static str, Token> { | 80 | fn 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 | ||
109 | fn get_operators() -> HashMap<char, Token> { | 109 | pub 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 | ||
121 | fn factorial (n: f64) -> f64 { | ||
122 | n.signum() * (1.. n.abs() as u64 +1).fold(1, |p, n| p*n) as f64 | ||
123 | } | ||
124 | |||
120 | pub fn lexer(input: &str) -> Result<Vec<Token>, CalcError> { | 125 | pub 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 { |