From 8b49603f0c6d06bcb444bd0ee14aa5c1fbc4648c Mon Sep 17 00:00:00 2001 From: NerdyPepper Date: Tue, 9 Jul 2019 12:44:35 +0530 Subject: add previous answer access --- src/lex/mod.rs | 22 ++++++++++++++++++++-- src/main.rs | 27 ++++++++++++++++++--------- src/parse/mod.rs | 2 +- src/readline/mod.rs | 25 ++++--------------------- 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 { n.signum() * (1.. n.abs() as u64 +1).fold(1, |p, n| p*n) as f64 } -pub fn lexer(input: &str) -> Result, CalcError> { +pub fn lexer(input: &str, prev_ans: &mut f64) -> Result, CalcError> { let functions: HashMap<&str, Token> = get_functions(); let operators: HashMap = get_operators(); @@ -144,6 +144,23 @@ pub fn lexer(input: &str) -> Result, CalcError> { num_vec.push(letter); last_char_is_op = false; }, + '_' => { + if char_vec.len() > 0 { + if let Some(_) = functions.get(&char_vec[..]) { + return Err(CalcError::Syntax(format!("Function '{}' expected parentheses", char_vec))) + } else { + return Err(CalcError::Syntax(format!("Unexpected character '{}'", char_vec))) + } + } + let parse_num = num_vec.parse::().ok(); + if let Some(x) = parse_num { + result.push(Token::Num(x)); + result.push(operators.get(&'*').unwrap().clone()); + num_vec.clear(); + } + last_char_is_op = false; + result.push(Token::Num(*prev_ans)); + } 'a'...'z' | 'A'...'Z' => { let parse_num = num_vec.parse::().ok(); if let Some(x) = parse_num { @@ -216,10 +233,11 @@ pub fn lexer(input: &str) -> Result, CalcError> { }, ' ' => {}, _ => { - return Err(CalcError::Syntax(format!("Unexpected character: '{}'", letter))) + return Err(CalcError::Syntax(format!("Unexpected token: '{}'", letter))) } } } + // println!("{:?}", result); drain_num_stack(&mut num_vec, &mut result); Ok(result) } 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! { fn main() { if CONFIGURATION.input.len() > 0 { // command mode // - let evaled = eval_math_expression(&CONFIGURATION.input[..]); + let evaled = eval_math_expression(&CONFIGURATION.input[..], &mut 0f64); match evaled { Ok(ans) => pprint(ans), Err(e) => { @@ -56,6 +56,9 @@ fn main() { // create fancy readline let mut rl = create_readline(); + // previous answer + let mut prev_ans = 0f64; + // handle history storage let eva_dirs = ProjectDirs::from("com", "NerdyPepper", "eva").unwrap(); let eva_data_dir = eva_dirs.data_dir(); @@ -75,7 +78,7 @@ fn main() { match readline { Ok(line) => { rl.add_history_entry(line.as_str()); - let evaled = eval_math_expression(&line[..]); + let evaled = eval_math_expression(&line[..], &mut prev_ans); match evaled { Ok(ans) => pprint(ans), Err(e) => println!("{}", handler(e)), @@ -142,16 +145,17 @@ fn parse_arguments() -> Configuration { } } -pub fn eval_math_expression(input: &str) -> Result { +pub fn eval_math_expression(input: &str, prev_ans: &mut f64) -> Result { let input = input.trim(); let input = input.replace(" ", ""); if input.len() == 0 { return Ok(0.) } let input = format::autobalance_parens(&input[..])?; - let lexed = lexer(&input[..])?; + let lexed = lexer(&input[..], prev_ans)?; let postfixed = to_postfix(lexed)?; let evaled = eval_postfix(postfixed)?; + *prev_ans = evaled; let evaled_fixed = format!("{:.*}", CONFIGURATION.fix, evaled).parse::().unwrap(); Ok(evaled_fixed) } @@ -162,27 +166,32 @@ mod tests { #[test] fn basic_ops() { - let evaled = eval_math_expression("6*2 + 3 + 12 -3").unwrap(); + let evaled = eval_math_expression("6*2 + 3 + 12 -3", &0f64).unwrap(); assert_eq!(24., evaled); } #[test] fn trignometric_fns() { - let evaled = eval_math_expression("sin(30) + tan(45").unwrap(); + let evaled = eval_math_expression("sin(30) + tan(45", &0f64).unwrap(); assert_eq!(1.5, evaled); } #[test] fn brackets() { - let evaled = eval_math_expression("(((1 + 2 + 3) ^ 2 ) - 4)").unwrap(); + let evaled = eval_math_expression("(((1 + 2 + 3) ^ 2 ) - 4)", &0f64).unwrap(); assert_eq!(32., evaled); } #[test] fn floating_ops() { - let evaled = eval_math_expression("1.2816 + 1 + 1.2816/1.2").unwrap(); + let evaled = eval_math_expression("1.2816 + 1 + 1.2816/1.2", &0f64).unwrap(); assert_eq!(3.3496, evaled); } #[test] fn inverse_trignometric_fns() { - let evaled = eval_math_expression("deg(asin(1) + acos(1))").unwrap(); + let evaled = eval_math_expression("deg(asin(1) + acos(1))", &0f64).unwrap(); assert_eq!(90., evaled); } + #[test] + fn prev_ans() { + let evaled = eval_math_expression("_ + 9", &9f64).unwrap(); + assert_eq!(18.0, evaled); + } } 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) -> Result { } } _ => { - unreachable!("nah nigga") + unreachable!("wut") } } } 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}; use rustyline::error::ReadlineError; use rustyline::{ Editor, Context, Helper }; use rustyline::config::{ Builder, ColorMode, EditMode, CompletionType }; -use rustyline::hint::Hinter; +use rustyline::hint::{ Hinter, HistoryHinter }; use rustyline::completion::{ FilenameCompleter, Completer, Pair }; use rustyline::highlight::Highlighter; @@ -14,33 +14,16 @@ use crate::eval_math_expression; pub struct RLHelper { completer: FilenameCompleter, highlighter: LineHighlighter, - hinter: AnswerHinter, + hinter: HistoryHinter, } -struct AnswerHinter { } -impl Hinter for AnswerHinter { - fn hint(&self, line: &str, _: usize, _: &Context) -> Option { - let input = line.trim(); - let input = input.replace(" ", ""); - if input.len() == 0 { - return Some("".into()) - } - let dry_run = eval_math_expression(&input); - match dry_run { - Ok(ans) => return Some(format!(" = {}", ans)), - Err(_) => return Some(format!("")) - }; - } -} - - struct LineHighlighter { } impl Highlighter for LineHighlighter { fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> { Owned(format!("\x1b[90m{}\x1b[0m", hint)) } fn highlight<'l>(&self, line: &'l str, _: usize) -> Cow<'l, str> { - let op = eval_math_expression(line); + let op = eval_math_expression(line, &mut 0f64); match op { Ok(_) => { let functions = [ @@ -108,7 +91,7 @@ pub fn create_readline() -> Editor { let h = RLHelper { completer: FilenameCompleter::new(), highlighter: LineHighlighter {}, - hinter: AnswerHinter {} + hinter: HistoryHinter {} }; rl.set_helper(Some(h)); return rl; -- cgit v1.2.3