this doesn't work but I wanna switch computers

parse-tree
Jordan Orelli 2 years ago
parent 869cc68abd
commit 7abb60a3bc

@ -19,7 +19,7 @@ use anyhow::Result;
fn main() -> Result<()> {
let mut shell = Shell::new()?;
let log_path = shell.expand_path("~/wash.log");
let log_path = shell.expand_path("~/clyde.log");
match Log::file(log_path) {
Ok(f) => {
let target = Box::leak(Box::new(f));
@ -63,7 +63,7 @@ fn main() -> Result<()> {
info!("◇ {}", s);
let tree = parse::parse(&s)?;
debug!(" {:?}", tree);
shell.exec(tree)?;
shell.exec(tree.into())?;
// Some commands don't leave the terminal in a clean state, so we use reset
// to ensure that our input and output modes are what we expect them to be.
shell.reset()?;

@ -1,4 +1,8 @@
use log::debug;
use std::{
cell::RefCell,
rc::Rc,
};
use thiserror::Error;
#[derive(Debug, Error)]
@ -104,42 +108,178 @@ impl<'text> Lexer<'text> {
}
}
struct Parser {
state: Node,
// struct Parser {
// state: Tree,
// }
//
// impl Parser {
// fn new() -> Self {
// Self {
// state: Tree::new(),
// }
// }
//
// fn parse(mut self, tokens: Vec<Token>) -> Result<Node, Error> {
// Ok(Node::empty())
// // for token in tokens {
// // self.take(token);
// // }
// // let t = self.state.replace(Node::empty());
// // Ok(t.root())
// }
// }
#[derive(Debug, PartialEq, Clone)]
pub enum Element {
Empty,
Command(String),
Literal(String),
}
impl Parser {
fn new() -> Self {
#[derive(Debug)]
pub struct Node {
pub elem: Element,
pub parent: Option<Rc<RefCell<Node>>>,
pub children: Vec<Rc<RefCell<Node>>>,
}
impl Node {
pub fn new(elem: Element) -> Self {
Self {
state: Node::Empty,
elem,
parent: None,
children: Vec::new(),
}
}
fn parse(mut self, tokens: Vec<Token>) -> Result<Node, Error> {
for token in tokens {
match (self.state, token) {
(Node::Empty, Token::Ident(name)) => {
self.state = Node::Command{name, args: vec!()};
},
(Node::Command{name, mut args}, Token::Ident(s)) => {
args.push(s);
self.state = Node::Command{name, args};
},
_ => return Err(Error::UnexpectedToken),
pub fn empty() -> Self {
Self::new(Element::Empty)
}
pub fn child_of(parent: Rc<RefCell<Self>>, elem: Element) -> Self {
Self {
elem,
parent: Some(parent),
children: Vec::new(),
}
Ok(self.state)
}
pub fn visit(self) -> Tree {
self.into()
}
}
#[derive(Debug)]
pub enum Node {
Empty,
Command {
name: String,
args: Vec<String>,
},
pub struct Tree {
target: Rc<RefCell<Node>>,
}
impl Tree {
fn new() -> Self {
Node::empty().into()
}
/// Adds an element as a node as a child of the current node, then descends the tree to select
/// that child node. This is similar to how pushing a value changes the top element of a stack.
fn push(self, elem: Element) -> Self {
if self.is_empty() {
self.target.replace(Node::new(elem));
self
} else {
let child = Node::child_of(Rc::clone(&self.target), elem);
Tree{target: Rc::new(RefCell::new(child))}
}
}
/// Adds a child node with a given element value to the currently selected node without chaning
/// our selection.
fn append(self, elem: Element) -> Self {
if self.is_empty() {
self.target.replace(Node::new(elem));
} else {
let node = Node::child_of(Rc::clone(&self.target), elem);
let child = Rc::new(RefCell::new(node));
self.target.borrow_mut().children.push(child);
}
self
}
/// Tells us whether or not the currently selected node is an empty node
fn is_empty(&self) -> bool {
self.target.borrow().elem == Element::Empty
}
fn parent(&self) -> Option<Self> {
self.target.borrow().parent.as_ref().map(|parent| Self {
target: Rc::clone(parent),
})
}
fn is_root(&self) -> bool {
self.parent().is_none()
}
pub fn root(self) -> Self {
match self.parent() {
Some(parent) => parent.root(),
None => self,
}
}
fn peek(&self) -> Element {
self.target.borrow().elem.clone()
}
fn into_node(self) -> Node {
self.into()
}
fn children(&self) -> ChildIter {
ChildIter {
target: Rc::clone(&self.target),
idx: 0,
last: None,
}
}
}
pub struct ChildIter<'n> {
/// pointer to the node in the tree whose children we are looking at.
target: Rc<RefCell<Node>>,
idx: usize,
last: Option<&'n Node>,
}
impl <'n> Iterator for ChildIter<'n> {
type Item = &'n Node;
fn next(&mut self) -> Option<Self::Item> {
if self.idx >= self.target.borrow().children.len() {
None
} else {
let child = Rc::clone(&self.target.borrow().children[self.idx]);
self.idx += 1;
self.last = Some(&child.as_ref().borrow());
None
//Some(&child.as_ref().borrow())
//Some(&*child.borrow())
}
}
}
impl From<Tree> for Node {
fn from(value: Tree) -> Self {
value.target.replace(Node::empty())
}
}
impl From<Node> for Tree {
fn from(value: Node) -> Self {
Self {
target: Rc::new(RefCell::new(value)),
}
}
}
// I don't know how to write a parser lol
@ -167,11 +307,20 @@ pub enum Node {
// ]
// }
pub fn parse<S: AsRef<str>>(text: S) -> Result<Node, Error> {
let tokens = lex(text)?;
let parser = Parser::new();
debug!(" {:?}", tokens);
parser.parse(tokens)
pub fn parse<S: AsRef<str>>(text: S) -> Result<Tree, Error> {
let mut tree = Tree::new();
for token in lex(text)? {
match (tree.peek(), token) {
(Element::Empty, Token::Ident(cmd)) => {
tree = tree.push(Element::Command(cmd));
}
(Element::Command(_), Token::Ident(arg)) => {
tree = tree.append(Element::Literal(arg));
}
_ => todo!(),
}
}
Ok(tree.root())
}
#[cfg(test)]
@ -241,4 +390,68 @@ mod tests {
"one |two"
ident("one") Pipe ident("two");
}
#[test]
fn empty_tree() {
let root = Tree::new().root();
assert!(root.is_root());
assert_eq!(root.peek(), Element::Empty);
assert_eq!(root.children().count(), 0);
}
#[test]
fn tree_root() {
let root = Tree::new()
.push(Element::Command(String::from("ls")))
.root();
assert!(root.is_root());
assert_eq!(root.children().count(), 0);
assert_eq!(root.into_node().elem, Element::Command(String::from("ls")));
}
#[test]
fn tree_push() {
let tree = Tree::new()
.push(Element::Command(String::from("ls")));
assert_eq!(tree.peek(), Element::Command(String::from("ls")));
let tree = Tree::new()
.push(Element::Command(String::from("ls")))
.append(Element::Command(String::from("one")));
assert_eq!(tree.peek(), Element::Command(String::from("ls")));
}
#[test]
fn test_parse() {
let res = parse("ls one two");
assert!(res.is_ok());
let tree = res.unwrap();
assert_eq!(tree.peek(), Element::Command(String::from("ls")));
assert_eq!(tree.children().count(), 2);
let args = tree.children();
// assert_eq!(args.next().unwrap(), Element::Literal(String::from("one")));
}
/*
#[test]
fn tree_command() {
/*
Command(ls)
Literal(.)
*/
let root = Tree::new()
.push(Element::Command(String::from("ls")))
.push(Element::Literal(String::from(".")))
.root();
assert!(root.is_root());
assert_eq!(root.children().count(), 1);
// assert_eq!(root.elem, Element::Command(String::from("ls")));
// assert_eq!(root.children.len(), 1);
// assert_eq!(root.children[0].borrow(), Element::Literal(String::from(".")));
}
*/
}

@ -9,6 +9,7 @@ use crate::{
};
use std::path::{Path, PathBuf};
use std::rc::Rc;
use anyhow::Result;
use dirs;
@ -97,16 +98,17 @@ impl Shell {
}
}
pub fn exec(&mut self, mut node: Node) -> Result<bool> {
loop {
match node {
Node::Empty => break,
Node::Command{name, args} => {
self.eval(name, args.iter().map(|s| s.as_str()).collect())?;
node = Node::Empty;
},
}
}
pub fn exec(&mut self, root: Node) -> Result<bool> {
// match &tree.elem {
// Node::Command(name) => {
// let args: Vec<&str> = tree.children.iter().map(|t| match &t.elem {
// Node::Literal(arg) => arg.as_str(),
// _ => todo!(),
// }).collect();
// self.eval(name.to_string(), args)?;
// },
// _ => todo!(),
// }
Ok(true)
}

Loading…
Cancel
Save