aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNerdyPepper <[email protected]>2019-07-09 08:14:35 +0100
committerNerdyPepper <[email protected]>2019-07-09 08:14:35 +0100
commit8b49603f0c6d06bcb444bd0ee14aa5c1fbc4648c (patch)
treeff5fd41b489538f80b22930e4d8365505b610b8a /src
parentc6b03d82daa4d6b4856c4b33244f5261b0bbdaeb (diff)
add previous answer access
Diffstat (limited to 'src')
-rw-r--r--src/lex/mod.rs22
-rw-r--r--src/main.rs27
-rw-r--r--src/parse/mod.rs2
-rw-r--r--src/readline/mod.rs25
4 files changed, 43 insertions, 33 deletions
diff --git a/src/lex/mod.rs b/src/lex/mod.rs
index 5e7a346..cac16ca 100644
--- a/src/lex/mod.rs
+++ b/src/lex/mod.rs
@@ -122,7 +122,7 @@ fn factorial (n: f64) -> f64 {
122 n.signum() * (1.. n.abs() as u64 +1).fold(1, |p, n| p*n) as f64 122 n.signum() * (1.. n.abs() as u64 +1).fold(1, |p, n| p*n) as f64
123} 123}
124 124
125pub fn lexer(input: &str) -> Result<Vec<Token>, CalcError> { 125pub fn lexer(input: &str, prev_ans: &mut f64) -> Result<Vec<Token>, CalcError> {
126 let functions: HashMap<&str, Token> = get_functions(); 126 let functions: HashMap<&str, Token> = get_functions();
127 let operators: HashMap<char, Token> = get_operators(); 127 let operators: HashMap<char, Token> = get_operators();
128 128
@@ -144,6 +144,23 @@ pub fn lexer(input: &str) -> Result<Vec<Token>, CalcError> {
144 num_vec.push(letter); 144 num_vec.push(letter);
145 last_char_is_op = false; 145 last_char_is_op = false;
146 }, 146 },
147 '_' => {
148 if char_vec.len() > 0 {
149 if let Some(_) = functions.get(&char_vec[..]) {
150 return Err(CalcError::Syntax(format!("Function '{}' expected parentheses", char_vec)))
151 } else {
152 return Err(CalcError::Syntax(format!("Unexpected character '{}'", char_vec)))
153 }
154 }
155 let parse_num = num_vec.parse::<f64>().ok();
156 if let Some(x) = parse_num {
157 result.push(Token::Num(x));
158 result.push(operators.get(&'*').unwrap().clone());
159 num_vec.clear();
160 }
161 last_char_is_op = false;
162 result.push(Token::Num(*prev_ans));
163 }
147 'a'...'z' | 'A'...'Z' => { 164 'a'...'z' | 'A'...'Z' => {
148 let parse_num = num_vec.parse::<f64>().ok(); 165 let parse_num = num_vec.parse::<f64>().ok();
149 if let Some(x) = parse_num { 166 if let Some(x) = parse_num {
@@ -216,10 +233,11 @@ pub fn lexer(input: &str) -> Result<Vec<Token>, CalcError> {
216 }, 233 },
217 ' ' => {}, 234 ' ' => {},
218 _ => { 235 _ => {
219 return Err(CalcError::Syntax(format!("Unexpected character: '{}'", letter))) 236 return Err(CalcError::Syntax(format!("Unexpected token: '{}'", letter)))
220 } 237 }
221 } 238 }
222 } 239 }
240 // println!("{:?}", result);
223 drain_num_stack(&mut num_vec, &mut result); 241 drain_num_stack(&mut num_vec, &mut result);
224 Ok(result) 242 Ok(result)
225} 243}
diff --git a/src/main.rs b/src/main.rs
index 91d91e5..0742ee8 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -43,7 +43,7 @@ lazy_static! {
43fn main() { 43fn main() {
44 if CONFIGURATION.input.len() > 0 { 44 if CONFIGURATION.input.len() > 0 {
45 // command mode // 45 // command mode //
46 let evaled = eval_math_expression(&CONFIGURATION.input[..]); 46 let evaled = eval_math_expression(&CONFIGURATION.input[..], &mut 0f64);
47 match evaled { 47 match evaled {
48 Ok(ans) => pprint(ans), 48 Ok(ans) => pprint(ans),
49 Err(e) => { 49 Err(e) => {
@@ -56,6 +56,9 @@ fn main() {
56 // create fancy readline 56 // create fancy readline
57 let mut rl = create_readline(); 57 let mut rl = create_readline();
58 58
59 // previous answer
60 let mut prev_ans = 0f64;
61
59 // handle history storage 62 // handle history storage
60 let eva_dirs = ProjectDirs::from("com", "NerdyPepper", "eva").unwrap(); 63 let eva_dirs = ProjectDirs::from("com", "NerdyPepper", "eva").unwrap();
61 let eva_data_dir = eva_dirs.data_dir(); 64 let eva_data_dir = eva_dirs.data_dir();
@@ -75,7 +78,7 @@ fn main() {
75 match readline { 78 match readline {
76 Ok(line) => { 79 Ok(line) => {
77 rl.add_history_entry(line.as_str()); 80 rl.add_history_entry(line.as_str());
78 let evaled = eval_math_expression(&line[..]); 81 let evaled = eval_math_expression(&line[..], &mut prev_ans);
79 match evaled { 82 match evaled {
80 Ok(ans) => pprint(ans), 83 Ok(ans) => pprint(ans),
81 Err(e) => println!("{}", handler(e)), 84 Err(e) => println!("{}", handler(e)),
@@ -142,16 +145,17 @@ fn parse_arguments() -> Configuration {
142 } 145 }
143} 146}
144 147
145pub fn eval_math_expression(input: &str) -> Result<f64, CalcError> { 148pub fn eval_math_expression(input: &str, prev_ans: &mut f64) -> Result<f64, CalcError> {
146 let input = input.trim(); 149 let input = input.trim();
147 let input = input.replace(" ", ""); 150 let input = input.replace(" ", "");
148 if input.len() == 0 { 151 if input.len() == 0 {
149 return Ok(0.) 152 return Ok(0.)
150 } 153 }
151 let input = format::autobalance_parens(&input[..])?; 154 let input = format::autobalance_parens(&input[..])?;
152 let lexed = lexer(&input[..])?; 155 let lexed = lexer(&input[..], prev_ans)?;
153 let postfixed = to_postfix(lexed)?; 156 let postfixed = to_postfix(lexed)?;
154 let evaled = eval_postfix(postfixed)?; 157 let evaled = eval_postfix(postfixed)?;
158 *prev_ans = evaled;
155 let evaled_fixed = format!("{:.*}", CONFIGURATION.fix, evaled).parse::<f64>().unwrap(); 159 let evaled_fixed = format!("{:.*}", CONFIGURATION.fix, evaled).parse::<f64>().unwrap();
156 Ok(evaled_fixed) 160 Ok(evaled_fixed)
157} 161}
@@ -162,27 +166,32 @@ mod tests {
162 166
163 #[test] 167 #[test]
164 fn basic_ops() { 168 fn basic_ops() {
165 let evaled = eval_math_expression("6*2 + 3 + 12 -3").unwrap(); 169 let evaled = eval_math_expression("6*2 + 3 + 12 -3", &0f64).unwrap();
166 assert_eq!(24., evaled); 170 assert_eq!(24., evaled);
167 } 171 }
168 #[test] 172 #[test]
169 fn trignometric_fns() { 173 fn trignometric_fns() {
170 let evaled = eval_math_expression("sin(30) + tan(45").unwrap(); 174 let evaled = eval_math_expression("sin(30) + tan(45", &0f64).unwrap();
171 assert_eq!(1.5, evaled); 175 assert_eq!(1.5, evaled);
172 } 176 }
173 #[test] 177 #[test]
174 fn brackets() { 178 fn brackets() {
175 let evaled = eval_math_expression("(((1 + 2 + 3) ^ 2 ) - 4)").unwrap(); 179 let evaled = eval_math_expression("(((1 + 2 + 3) ^ 2 ) - 4)", &0f64).unwrap();
176 assert_eq!(32., evaled); 180 assert_eq!(32., evaled);
177 } 181 }
178 #[test] 182 #[test]
179 fn floating_ops() { 183 fn floating_ops() {
180 let evaled = eval_math_expression("1.2816 + 1 + 1.2816/1.2").unwrap(); 184 let evaled = eval_math_expression("1.2816 + 1 + 1.2816/1.2", &0f64).unwrap();
181 assert_eq!(3.3496, evaled); 185 assert_eq!(3.3496, evaled);
182 } 186 }
183 #[test] 187 #[test]
184 fn inverse_trignometric_fns() { 188 fn inverse_trignometric_fns() {
185 let evaled = eval_math_expression("deg(asin(1) + acos(1))").unwrap(); 189 let evaled = eval_math_expression("deg(asin(1) + acos(1))", &0f64).unwrap();
186 assert_eq!(90., evaled); 190 assert_eq!(90., evaled);
187 } 191 }
192 #[test]
193 fn prev_ans() {
194 let evaled = eval_math_expression("_ + 9", &9f64).unwrap();
195 assert_eq!(18.0, evaled);
196 }
188} 197}
diff --git a/src/parse/mod.rs b/src/parse/mod.rs
index b74df4c..5c85172 100644
--- a/src/parse/mod.rs
+++ b/src/parse/mod.rs
@@ -95,7 +95,7 @@ pub fn eval_postfix(postfixed: Vec<Token>) -> Result<f64, CalcError> {
95 } 95 }
96 } 96 }
97 _ => { 97 _ => {
98 unreachable!("nah nigga") 98 unreachable!("wut")
99 } 99 }
100 } 100 }
101 } 101 }
diff --git a/src/readline/mod.rs b/src/readline/mod.rs
index 34bce56..9ae14ba 100644
--- a/src/readline/mod.rs
+++ b/src/readline/mod.rs
@@ -3,7 +3,7 @@ use std::borrow::Cow::{self,Owned};
3use rustyline::error::ReadlineError; 3use rustyline::error::ReadlineError;
4use rustyline::{ Editor, Context, Helper }; 4use rustyline::{ Editor, Context, Helper };
5use rustyline::config::{ Builder, ColorMode, EditMode, CompletionType }; 5use rustyline::config::{ Builder, ColorMode, EditMode, CompletionType };
6use rustyline::hint::Hinter; 6use rustyline::hint::{ Hinter, HistoryHinter };
7use rustyline::completion::{ FilenameCompleter, Completer, Pair }; 7use rustyline::completion::{ FilenameCompleter, Completer, Pair };
8use rustyline::highlight::Highlighter; 8use rustyline::highlight::Highlighter;
9 9
@@ -14,33 +14,16 @@ use crate::eval_math_expression;
14pub struct RLHelper { 14pub struct RLHelper {
15 completer: FilenameCompleter, 15 completer: FilenameCompleter,
16 highlighter: LineHighlighter, 16 highlighter: LineHighlighter,
17 hinter: AnswerHinter, 17 hinter: HistoryHinter,
18} 18}
19 19
20struct AnswerHinter { }
21impl Hinter for AnswerHinter {
22 fn hint(&self, line: &str, _: usize, _: &Context) -> Option<String> {
23 let input = line.trim();
24 let input = input.replace(" ", "");
25 if input.len() == 0 {
26 return Some("".into())
27 }
28 let dry_run = eval_math_expression(&input);
29 match dry_run {
30 Ok(ans) => return Some(format!(" = {}", ans)),
31 Err(_) => return Some(format!(""))
32 };
33 }
34}
35
36
37struct LineHighlighter { } 20struct LineHighlighter { }
38impl Highlighter for LineHighlighter { 21impl Highlighter for LineHighlighter {
39 fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> { 22 fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
40 Owned(format!("\x1b[90m{}\x1b[0m", hint)) 23 Owned(format!("\x1b[90m{}\x1b[0m", hint))
41 } 24 }
42 fn highlight<'l>(&self, line: &'l str, _: usize) -> Cow<'l, str> { 25 fn highlight<'l>(&self, line: &'l str, _: usize) -> Cow<'l, str> {
43 let op = eval_math_expression(line); 26 let op = eval_math_expression(line, &mut 0f64);
44 match op { 27 match op {
45 Ok(_) => { 28 Ok(_) => {
46 let functions = [ 29 let functions = [
@@ -108,7 +91,7 @@ pub fn create_readline() -> Editor<RLHelper> {
108 let h = RLHelper { 91 let h = RLHelper {
109 completer: FilenameCompleter::new(), 92 completer: FilenameCompleter::new(),
110 highlighter: LineHighlighter {}, 93 highlighter: LineHighlighter {},
111 hinter: AnswerHinter {} 94 hinter: HistoryHinter {}
112 }; 95 };
113 rl.set_helper(Some(h)); 96 rl.set_helper(Some(h));
114 return rl; 97 return rl;