Add statement continuation in REPL in CLI
Typing ``` var foo = [ ``` into the REPL now causes it to prompt you to complete the statement rather than just printing an "unexpected EOF" error.
This commit is contained in:
parent
6f8a49b711
commit
6eb97c6032
|
@ -1,12 +1,12 @@
|
||||||
#![forbid(unsafe_code, clippy::unwrap_used)]
|
#![forbid(unsafe_code, clippy::unwrap_used)]
|
||||||
|
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
|
pub mod error;
|
||||||
pub mod interpret;
|
pub mod interpret;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
|
|
||||||
mod base_55;
|
mod base_55;
|
||||||
mod brian;
|
mod brian;
|
||||||
mod consts;
|
mod consts;
|
||||||
mod error;
|
|
||||||
mod lexer;
|
mod lexer;
|
||||||
mod variables;
|
mod variables;
|
||||||
|
|
|
@ -6,39 +6,44 @@ use ablescript::parser::Parser;
|
||||||
pub fn repl(ast_print: bool) {
|
pub fn repl(ast_print: bool) {
|
||||||
let mut rl = Editor::<()>::new();
|
let mut rl = Editor::<()>::new();
|
||||||
let mut env = ExecEnv::new();
|
let mut env = ExecEnv::new();
|
||||||
|
|
||||||
|
// If this is `Some`, the user has previously entered an
|
||||||
|
// incomplete statement and is now completing it; otherwise, the
|
||||||
|
// user is entering a completely new statement.
|
||||||
|
let mut partial: Option<String> = None;
|
||||||
loop {
|
loop {
|
||||||
let readline = rl.readline(":: ");
|
match rl.readline(if partial.is_some() { ">> " } else { ":: " }) {
|
||||||
match readline {
|
Ok(readline) => {
|
||||||
Ok(line) => {
|
let readline = readline.trim_end();
|
||||||
// NOTE(Alex): `readline()` leaves a newline at the
|
let partial_data = match partial {
|
||||||
// end of the string if stdin is connected to a file
|
Some(line) => line + &readline,
|
||||||
// or unsupported terminal; this can interfere with
|
None => readline.to_owned(),
|
||||||
// error printing.
|
};
|
||||||
rl.add_history_entry(&line);
|
|
||||||
let line = line.trim_end();
|
|
||||||
|
|
||||||
if line == "exit" {
|
partial = match Parser::new(&partial_data).init().and_then(|ast| {
|
||||||
println!("bye");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut parser = Parser::new(line);
|
|
||||||
let value = parser.init().and_then(|ast| {
|
|
||||||
if ast_print {
|
if ast_print {
|
||||||
println!("{:#?}", &ast);
|
println!("{:#?}", &ast);
|
||||||
}
|
}
|
||||||
env.eval_stmts(&ast)
|
env.eval_stmts(&ast)
|
||||||
});
|
}) {
|
||||||
|
Ok(_) => None,
|
||||||
if let Err(e) = value {
|
Err(ablescript::error::Error {
|
||||||
println!("{}", e);
|
// Treat "Unexpected EOF" errors as "we need
|
||||||
println!(" | {}", line);
|
// more data".
|
||||||
println!(
|
kind: ablescript::error::ErrorKind::UnexpectedEof,
|
||||||
" {}{}",
|
..
|
||||||
" ".repeat(e.span.start),
|
}) => Some(partial_data),
|
||||||
"^".repeat((e.span.end - e.span.start).max(1))
|
Err(e) => {
|
||||||
);
|
println!("{}", e);
|
||||||
}
|
println!(" | {}", partial_data);
|
||||||
|
println!(
|
||||||
|
" {}{}",
|
||||||
|
" ".repeat(e.span.start),
|
||||||
|
"^".repeat((e.span.end - e.span.start).max(1))
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
Err(rustyline::error::ReadlineError::Eof) => {
|
Err(rustyline::error::ReadlineError::Eof) => {
|
||||||
println!("bye");
|
println!("bye");
|
||||||
|
|
Loading…
Reference in a new issue