diff --git a/src/parse.rs b/src/parse.rs index ead60bb..737deea 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -1,10 +1,4 @@ -use log::debug; -use std::{ - fmt, - ops::Deref, - cell::RefCell, - rc::Rc, -}; +use std::{cell::RefCell, fmt, rc::Rc}; use thiserror::Error; #[derive(Debug, Error)] @@ -17,6 +11,7 @@ pub enum Error { #[derive(Debug, PartialEq)] pub enum Token { Ident(String), + Glob(String), Pipe, } @@ -28,6 +23,7 @@ fn lex>(text: S) -> Result, Error> { struct Lexer<'text> { chars: std::str::Chars<'text>, peeked: Option, + kept: Vec, } impl<'text> Lexer<'text> { @@ -35,6 +31,7 @@ impl<'text> Lexer<'text> { Self { chars: text.chars(), peeked: None, + kept: Vec::new(), } } @@ -48,6 +45,9 @@ impl<'text> Lexer<'text> { tokens.push(Token::Pipe); self.skip(); } + Some('*') => { + tokens.push(self.glob()); + } Some(_) => { tokens.push(self.ident()); } @@ -92,50 +92,66 @@ impl<'text> Lexer<'text> { } } + fn keep(&mut self) { + match self.peeked { + Some(c) => { + self.kept.push(c); + self.peeked = None; + } + None => match self.chars.next() { + Some(c) => self.kept.push(c), + None => todo!(), + }, + } + } + fn ident(&mut self) -> Token { - let mut kept: Vec = vec![]; loop { match self.peek() { None => break, + Some('*') => { + self.keep(); + self.glob(); + }, Some(c) => { if c.is_whitespace() { break; } - kept.push(c); - self.skip(); + self.keep(); } } } - Token::Ident(kept.iter().collect()) + Token::Ident(self.pop()) + } + + fn glob(&mut self) -> Token { + loop { + match self.peek() { + None => break, + Some(c) => { + if c.is_whitespace() { + break; + } + self.keep(); + } + } + } + Token::Glob(self.pop()) } -} -// struct Parser { -// state: Tree, -// } -// -// impl Parser { -// fn new() -> Self { -// Self { -// state: Tree::new(), -// } -// } -// -// fn parse(mut self, tokens: Vec) -> Result { -// Ok(Node::empty()) -// // for token in tokens { -// // self.take(token); -// // } -// // let t = self.state.replace(Node::empty()); -// // Ok(t.root()) -// } -// } + fn pop(&mut self) -> String { + let s: String = self.kept.iter().collect(); + self.kept.clear(); + s + } +} #[derive(PartialEq, Clone)] pub enum Element { Empty, Command(String), Literal(String), + Glob(String), } impl fmt::Debug for Element { @@ -144,6 +160,7 @@ impl fmt::Debug for Element { Element::Empty => write!(f, "()"), Element::Command(cmd) => write!(f, "cmd<{}>", cmd), Element::Literal(lit) => write!(f, "lit<{}>", lit), + Element::Glob(glob) => write!(f, "glob<{}>", glob), } } } @@ -211,7 +228,9 @@ impl Tree { self } else { let child = Node::child_of(Rc::clone(&self.target), elem); - Tree{target: Rc::new(RefCell::new(child))} + Tree { + target: Rc::new(RefCell::new(child)), + } } } @@ -287,7 +306,7 @@ impl Iterator for ChildIter { } else { let child = Rc::clone(&self.parent.borrow().children[self.idx]); self.idx += 1; - Some(Tree{target: child}) + Some(Tree { target: child }) } } } @@ -306,31 +325,6 @@ impl From for Tree { } } -// I don't know how to write a parser lol - -// ls -// Command{name: "ls"} - -// echo one two three -// Command{name: "echo", args: [Lit("one"), Lit("two"), Lit("three")]} - -// echo *.rs -// Command{name: "echo", args: [Glob("*.rs")]} -// Command{name: "echo", args: [Path("main.rs"), Path("parse.rs"), ...]} - -// cat main.rs | wc -l -// Pipe{ -// src: Command{name: "cat", args: [Lit("main.rs")]} -// dest: Command{name: "wc", args: [Lit("-l")]} -// } - -// echo one ; echo two -// Sequence{ -// children: [ -// Command{Name: -// ] -// } - pub fn parse>(text: S) -> Result { let mut tree = Tree::new(); for token in lex(text)? { @@ -435,8 +429,7 @@ mod tests { #[test] fn tree_push() { - let tree = Tree::new() - .push(Element::Command(String::from("ls"))); + let tree = Tree::new().push(Element::Command(String::from("ls"))); assert_eq!(tree.peek(), Element::Command(String::from("ls"))); let tree = Tree::new() @@ -455,9 +448,18 @@ mod tests { assert_eq!(tree.children().count(), 3); let mut args = tree.children(); - assert_eq!(args.next().unwrap().peek(), Element::Literal(String::from("one"))); - assert_eq!(args.next().unwrap().peek(), Element::Literal(String::from("two"))); - assert_eq!(args.next().unwrap().peek(), Element::Literal(String::from("three"))); + assert_eq!( + args.next().unwrap().peek(), + Element::Literal(String::from("one")) + ); + assert_eq!( + args.next().unwrap().peek(), + Element::Literal(String::from("two")) + ); + assert_eq!( + args.next().unwrap().peek(), + Element::Literal(String::from("three")) + ); assert!(args.next().is_none()); } } diff --git a/src/shell.rs b/src/shell.rs index 9a0edb8..29b9cb0 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -4,12 +4,10 @@ use crate::{ line::Line, log::*, output, - // parse::parse, parse::{Element, Node}, }; use std::path::{Path, PathBuf}; -use std::rc::Rc; use anyhow::Result; use dirs; @@ -116,6 +114,7 @@ impl Shell { ) } Element::Literal(_) => todo!(), + Element::Glob(_) => todo!(), } }