From 2ffb5357e0e35d415311a40eea14e9cc99dd54ab Mon Sep 17 00:00:00 2001 From: Dominick Allen Date: Sun, 28 Jun 2020 19:50:35 -0500 Subject: Improve read functionality. --- src/main.rs | 92 ++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 29 deletions(-) (limited to 'src/main.rs') diff --git a/src/main.rs b/src/main.rs index c2f9881..0116f78 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,33 +8,59 @@ use rustyline::Editor; use lib::environment::Environment; -fn read(rl: &mut Editor) -> Option { - let readline = rl.readline(">> "); - match readline { - Ok(line) => { - rl.add_history_entry(line.as_str()); - Some(line) - }, - Err(ReadlineError::Interrupted) => { - println!("CTRL-C"); - None - }, - Err(ReadlineError::Eof) => { - println!("CTRL-D"); - None - }, - Err(err) => { - println!("Error: {:?}", err); - None +const EXIT_STRINGS: &[&str; 3] = &[",q", "exit", "quit"]; + +fn read(rl: &mut Editor) -> Result { + let mut readline = rl.readline(">> "); + let mut full_line = String::new(); + + fn count_parens(s: &str) -> Result { + let mut lcount = 0; + let mut rcount = 0; + for c in s.chars() { + match c { + '(' => lcount += 1, + ')' => rcount += 1, + _ => {} + } + if rcount > lcount { + return Err(()) + } + } + return Ok(lcount == rcount) + } + + let mut loop_count = 0; + loop { + match readline { + Ok(line) => { + full_line.push_str(&line); + match count_parens(&full_line) { + Ok(true) => return Ok(full_line), + Ok(false) => readline = rl.readline("... "), + Err(_) => return Err("unexpected \")\"".to_string()) + } + }, + Err(ReadlineError::Interrupted) => { + return Err("user interrupt".to_string()) + }, + Err(ReadlineError::Eof) => { + if loop_count > 0 { + return Err("end of file".to_string()); + } else { + return Ok(EXIT_STRINGS[0].to_string()); + } + }, + Err(err) => { + return Err(format!("{:?}", err)); + } } + loop_count += 1 } } fn means_exit(input: &str) -> bool { - match input { - "exit" | "quit" | ",q" => true, - _ => false - } + EXIT_STRINGS.iter().any(|&s| s == input) } fn eval(env: &mut Environment, input: &str) -> String { @@ -45,8 +71,8 @@ fn eval(env: &mut Environment, input: &str) -> String { let res = lib::eval::eval(&sexp, env); match res { - Ok(x) => format!("{:?}", x), - Err(f) => f + Ok(x) => format!("{}", x), + Err(f) => format!("Error: {}", f) } } @@ -61,12 +87,20 @@ fn main() { } loop { let input_line = read(&mut rl); - let line = match input_line { - None => break, - Some(expr) if means_exit(&expr) => break, - Some(expr) => expr + match input_line { + Err(e) => { + println!("Error: {}", e); + continue; + } + Ok(expr) => { + if means_exit(&expr) { + break; + } + rl.add_history_entry(expr.as_str()); + println!("{}", eval(&mut env, &expr)); + } }; - println!("{}", eval(&mut env, &line)); + } rl.save_history(hist_file).unwrap(); } -- cgit v1.2.3