Created
October 19, 2018 20:41
-
-
Save jonesnl/16fac3b532e3b083b72bec1212c61f7c to your computer and use it in GitHub Desktop.
Parser for block 2 of shell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::io::{self, Write}; | |
use std::process::Command; | |
trait Statement { | |
fn run(&self) -> bool; | |
} | |
struct AndStatement { | |
left: Box<Statement>, | |
right: Box<Statement>, | |
} | |
impl Statement for AndStatement { | |
fn run(&self) -> bool { | |
if self.left.run() { | |
self.right.run() | |
} else { | |
false | |
} | |
} | |
} | |
struct OrStatement { | |
left: Box<Statement>, | |
right: Box<Statement>, | |
} | |
impl Statement for OrStatement { | |
fn run(&self) -> bool { | |
if self.left.run() { | |
true | |
} else { | |
self.right.run() | |
} | |
} | |
} | |
struct SemicolonStatement { | |
stmts: Vec<Box<Statement>>, | |
} | |
impl Statement for SemicolonStatement { | |
fn run(&self) -> bool { | |
let mut ret_val = false; | |
for s in &self.stmts { | |
ret_val = s.run(); | |
} | |
ret_val | |
} | |
} | |
struct StrStatement{ | |
string: String, | |
} | |
impl Statement for StrStatement { | |
fn run(&self) -> bool { | |
let mut split_cmd = self.string.split_whitespace(); | |
let cmd_name = split_cmd.next().unwrap(); | |
let args = split_cmd.collect::<Vec<&str>>(); | |
// execute the cmd in a seperate process | |
// show output | |
match Command::new(cmd_name).args(&args).output() { | |
Ok(output) => { | |
print!("{}", String::from_utf8_lossy(&output.stdout)); | |
io::stdout().flush().expect("Failed to flush"); | |
output.status.success() | |
}, | |
Err(msg) => { | |
println!("Error! {}", msg); | |
false | |
} | |
} | |
} | |
} | |
fn parse_statement(string: &str) -> Box<Statement> { | |
if string.find(';').is_some() { | |
let semi_statements = string.split(';').map(|s| parse_statement(s)).collect::<Vec<Box<Statement>>>(); | |
let semi_stmt = Box::new(SemicolonStatement{stmts: semi_statements}); | |
return semi_stmt; | |
} | |
if string.find("&&").is_some() { | |
let mut and_iter = string.splitn(2, "&&"); | |
let left = parse_statement(and_iter.next().unwrap()); | |
let right = parse_statement(and_iter.next().unwrap()); | |
return Box::new(AndStatement{left, right}); | |
} | |
if string.find("||").is_some() { | |
let mut and_iter = string.splitn(2, "||"); | |
let left = parse_statement(and_iter.next().unwrap()); | |
let right = parse_statement(and_iter.next().unwrap()); | |
return Box::new(OrStatement{left, right}); | |
} | |
return Box::new(StrStatement{string: string.to_string()}); | |
} | |
fn main() -> io::Result<()> { | |
loop { | |
// read line from stdin | |
print!("nsh$ "); | |
io::stdout().flush().expect("Failed to flush"); | |
let mut input = String::new(); | |
io::stdin().read_line(&mut input).expect("Error reading from input"); | |
parse_statement(&input).run(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment