summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs92
1 files changed, 63 insertions, 29 deletions
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<T: rustyline::Helper>(rl: &mut Editor<T>) -> Option<String> {
- 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<T: rustyline::Helper>(rl: &mut Editor<T>) -> Result<String, String> {
+ let mut readline = rl.readline(">> ");
+ let mut full_line = String::new();
+
+ fn count_parens(s: &str) -> Result<bool, ()> {
+ 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();
}