use error::Error; use std::io; use std::io::prelude::*; #[macro_use] extern crate lalrpop_util; lalrpop_mod!(pub commandline); pub mod error; pub mod path; pub type Result = std::result::Result; pub enum Input { String(String), End, } fn main() -> Result<()> { std::process::exit(match repl() { Ok(()) => 0, Err(ref e) => { eprintln!("{}", e); 1 } }) } fn repl() -> Result<()> { println!("Hello, terminal!"); loop { prompt()?; let input = read()?; match input { Input::String(string) => execute(&string)?, Input::End => break, } } Ok(()) } fn prompt() -> Result<()> { print!("$ "); io::stdout().flush()?; Ok(()) } fn read() -> Result { let mut input = String::new(); let n_bytes = io::stdin().read_line(&mut input)?; if n_bytes == 0 { Ok(Input::End) } else { Ok(Input::String(input)) } } fn execute(input: &str) -> Result<()> { let invocation = commandline::InvocationParser::new().parse(input)?; println!("{}", input); match invocation.as_slice() { ["paths", path_list, ..] => { println!("{:?}", path_list); match path::parser::PathListParser::new().parse(path_list) { Ok(parsed_paths) => { println!("paths '{:?}'", parsed_paths); }, Err(_) => { match path::parser::PathListAllowingEmptyPathsParser::new() .parse(path_list) { Ok(parsed) => { println!("path list has empty component"); println!("{:?}", parsed); }, Err(error) => { println!("path list is okay, does not have empty component"); println!("{:?}", error); }, } }, } }, _ => { println!("invocation '{:?}'", invocation); } } Ok(()) }