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/lib/eval/arith.rs | 5 +-- src/lib/tokenize.rs | 5 +-- src/main.rs | 92 +++++++++++++++++++++++++++++++++++---------------- 3 files changed, 69 insertions(+), 33 deletions(-) diff --git a/src/lib/eval/arith.rs b/src/lib/eval/arith.rs index fe3a06b..d7d53e0 100644 --- a/src/lib/eval/arith.rs +++ b/src/lib/eval/arith.rs @@ -1,10 +1,11 @@ use std::ops::{Add, Sub, Mul, Div}; use super::super::types::Type; +use super::super::types::FloatType; use super::super::types::Number; fn apply_arithmetic( func_i: fn(isize, isize) -> isize, - func_f: fn(f32, f32) -> f32, + func_f: fn(FloatType, FloatType) -> FloatType, operand_a: &Type, operand_b: &Type) -> Result { @@ -17,7 +18,7 @@ fn apply_arithmetic( (Type::Number(Number::Int(i)), Type::Number(Number::Float(f))) | (Type::Number(Number::Float(f)), Type::Number(Number::Int(i))) => { - Ok(Type::Number(Number::Float(func_f(*f, *i as f32)))) + Ok(Type::Number(Number::Float(func_f(*f, *i as FloatType)))) }, (Type::Number(Number::Int(a)), Type::Number(Number::Int(b))) => { diff --git a/src/lib/tokenize.rs b/src/lib/tokenize.rs index 0a50036..483536f 100644 --- a/src/lib/tokenize.rs +++ b/src/lib/tokenize.rs @@ -1,4 +1,5 @@ use super::types::Type; +use super::types::FloatType; use super::types::Number; use super::types::Op; use super::sexpr::SExpr; @@ -242,7 +243,7 @@ pub fn is_int(word: &str) -> MaybeToken { } pub fn is_float(word: &str) -> MaybeToken { - match word.parse::() { + match word.parse::() { Ok(x) => (Some(Ok(Token::Value(Type::Number(Number::Float(x))))), word.len()), _ => (None, 0) } @@ -268,7 +269,7 @@ pub fn descend(tokenstream: &mut TokenStream) -> Result { let token = match tokenstream.next() { Some(Ok(x)) => x, Some(Err(f)) => return Err(f), - None => panic!("Empty string".to_string()) + None => return Err("Unexpected end of expression".to_string()) }; match token { 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