gettin somewhere
parent
56bfdcc9fc
commit
7004de4e82
@ -0,0 +1,202 @@
|
|||||||
|
use crate::{
|
||||||
|
error::{ExecError, ParseError},
|
||||||
|
lex::{Lexer, Token},
|
||||||
|
parse2,
|
||||||
|
};
|
||||||
|
use std::{collections::HashSet, process};
|
||||||
|
|
||||||
|
struct State {}
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Eval {
|
||||||
|
fn eval(&self, ctx: &mut State) -> Result<Value, ExecError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Element {
|
||||||
|
Block(Block),
|
||||||
|
Command(Command),
|
||||||
|
Literal(Value),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eval for Element {
|
||||||
|
fn eval(&self, ctx: &mut State) -> Result<Value, ExecError> {
|
||||||
|
use Element::*;
|
||||||
|
match self {
|
||||||
|
Block(block) => block.eval(ctx),
|
||||||
|
Command(cmd) => cmd.eval(ctx),
|
||||||
|
Literal(v) => v.eval(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
enum Value {
|
||||||
|
None,
|
||||||
|
Text(String),
|
||||||
|
ExitStatus(process::ExitStatus),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eval for Value {
|
||||||
|
fn eval(&self, ctx: &mut State) -> Result<Value, ExecError> {
|
||||||
|
Ok(self.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Value {
|
||||||
|
pub fn try_to_string(self) -> Result<String, ExecError> {
|
||||||
|
match self {
|
||||||
|
Value::None => Err(ExecError::type_error("expected text value, saw None value")),
|
||||||
|
Value::Text(v) => Ok(v),
|
||||||
|
Value::ExitStatus(_) => Err(ExecError::type_error(
|
||||||
|
"expected text value, saw ExitStatus value",
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Block {
|
||||||
|
commands: Vec<Command>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Block {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Block {
|
||||||
|
commands: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eval for Block {
|
||||||
|
fn eval(&self, ctx: &mut State) -> Result<Value, ExecError> {
|
||||||
|
let mut v = Value::None;
|
||||||
|
for cmd in self.commands.iter() {
|
||||||
|
v = cmd.eval(ctx)?;
|
||||||
|
}
|
||||||
|
Ok(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Command {
|
||||||
|
name: Box<Element>,
|
||||||
|
args: Vec<Element>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eval for Command {
|
||||||
|
fn eval(&self, ctx: &mut State) -> Result<Value, ExecError> {
|
||||||
|
let name = self.name.eval(ctx)?.try_to_string()?;
|
||||||
|
let mut proc = process::Command::new(name);
|
||||||
|
|
||||||
|
if self.args.len() > 0 {
|
||||||
|
let args = self
|
||||||
|
.args
|
||||||
|
.iter()
|
||||||
|
.map(|elem| elem.eval(ctx)?.try_to_string())
|
||||||
|
.collect::<Result<Vec<String>, ExecError>>()?;
|
||||||
|
proc.args(args);
|
||||||
|
}
|
||||||
|
let mut child = proc.spawn().map_err(|e| ExecError::ProcessSpawnError(e))?;
|
||||||
|
let status = child.wait().map_err(|e| ExecError::ProcessWaitError(e))?;
|
||||||
|
return Ok(Value::ExitStatus(status));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ????? waht am i doing now
|
||||||
|
struct TreeBuilder {
|
||||||
|
visited: HashSet<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TreeBuilder {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
visited: HashSet::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn descend(&mut self, source: &mut parse2::Cursor) -> Result<Element, ParseError> {
|
||||||
|
let e = match source.value() {
|
||||||
|
parse2::Value::Start => {
|
||||||
|
println!("start node");
|
||||||
|
let mut root = Block::new();
|
||||||
|
let children = source.iter_children();
|
||||||
|
for mut child in children {
|
||||||
|
println!("child");
|
||||||
|
let e = self.descend(&mut child)?;
|
||||||
|
match e {
|
||||||
|
Element::Command(cmd) => root.commands.push(cmd),
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Element::Block(root)
|
||||||
|
}
|
||||||
|
parse2::Value::Statement => {
|
||||||
|
println!("statement node");
|
||||||
|
let mut children = source.iter_children();
|
||||||
|
let mut first = children.next().unwrap();
|
||||||
|
let name = self.descend(&mut first)?;
|
||||||
|
let mut cmd = Command {
|
||||||
|
name: Box::new(name),
|
||||||
|
args: Vec::new(),
|
||||||
|
};
|
||||||
|
for mut child in children {
|
||||||
|
let e = self.descend(&mut child)?;
|
||||||
|
cmd.args.push(e);
|
||||||
|
}
|
||||||
|
Element::Command(cmd)
|
||||||
|
}
|
||||||
|
parse2::Value::Terminal(Token::Word(word)) => {
|
||||||
|
println!("terminal word node");
|
||||||
|
Element::Literal(Value::Text(word.to_string()))
|
||||||
|
}
|
||||||
|
parse2::Value::Terminal(Token::Glob(_)) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
println!("visited: {:?}", source.target.id);
|
||||||
|
self.visited.insert(source.target.id);
|
||||||
|
Ok(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build(mut source: parse2::Cursor) -> Result<Element, ParseError> {
|
||||||
|
source.up_to_root();
|
||||||
|
let mut builder = TreeBuilder::new();
|
||||||
|
builder.descend(&mut source)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn x(source: &str) -> Result<Element, ParseError> {
|
||||||
|
let tokens = Lexer::new(source);
|
||||||
|
let parser = parse2::Parser::new(tokens);
|
||||||
|
let mut parse_tree = parser.parse()?;
|
||||||
|
println!("parse tree: {parse_tree:?}");
|
||||||
|
let mut builder = TreeBuilder::new();
|
||||||
|
builder.descend(&mut parse_tree)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use crate::lex::lex;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hi() -> Result<(), ParseError> {
|
||||||
|
let e = x("ls one two three ; ls four")?;
|
||||||
|
print!("{:?}", e);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
> ls
|
||||||
|
command
|
||||||
|
name: ls
|
||||||
|
|
||||||
|
*/
|
Loading…
Reference in New Issue