|
|
|
@ -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(".")));
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|