tuck5 0.2.0

A pragmatic lexer/parser generator
Documentation
pub use crate::*;
pub use std::fmt::Write;
pub use std::ops::Range;

#[derive(Debug)]
pub struct Token<'a, T> {
    pub root: &'a str,
    pub t_type: TokenType<'a, T>,
    pub data: T,
}

#[derive(Debug)]
pub enum TokenType<'a, T> {
    Leaf(Range<usize>),
    Branch(Vec<Token<'a, T>>),
}

impl<'a, T> Token<'a, T> {
    pub fn token_vec_from_str(
        from: &'a str,
        data: impl Fn(&'a str, usize) -> T,
    ) -> Vec<Token<'a, T>> {
        (0..from.len())
            .map(|i| Token {
                t_type: TokenType::Leaf(i..i + 1),
                root: from,
                data: data(from, i),
            })
            .collect::<Vec<Token<T>>>()
    }

    pub fn content_range(&self) -> Range<usize> {
        match &self.t_type {
            TokenType::Leaf(r) => r.clone(),
            TokenType::Branch(children) => {
                children[0].content_range().start
                    ..children
                        .last()
                        .expect("Branch tokens should have children!")
                        .content_range()
                        .end
            }
        }
    }

    pub fn content(&self) -> &str {
        &self.root[self.content_range()]
    }

    pub fn graph(&self) -> String {
        let mut to_ret = String::new();
        self.graph_depth(0, &mut to_ret)
            .expect("Couldn't graph the token");
        to_ret
    }

    pub fn graph_vec(tox: &Vec<Token<T>>) -> String {
        tox.iter()
            .map(|i| i.graph())
            .fold(String::new(), |l, r| format!("{l}\n{r}"))
    }

    pub fn vec_content(tox: &Vec<Token<T>>) -> String {
        tox.iter()
            .map(|i| i.content())
            .fold(String::new(), |l, r| format!("{l}{r}"))
    }

    pub fn graph_depth(&self, depth: usize, buf: &mut String) -> Result<(), std::fmt::Error> {
        for _ in 0..depth {
            write!(buf, "\t")?;
        }
        match &self.t_type {
            TokenType::Branch(children) => {
                writeln!(buf, "{{")?;
                for child in children {
                    child.graph_depth(depth + 1, buf)?;
                }
                for _ in 0..depth {
                    write!(buf, "\t")?;
                }
                writeln!(buf, "}}")?;
            }
            TokenType::Leaf(_) => {
                writeln!(buf, "{}", self.content())?;
            }
        }

        Ok(())
    }

    pub fn children<'b>(&'b self) -> Option<&'b Vec<Self>> {
        match &self.t_type {
            TokenType::Branch(children) => Some(&children),
            _ => None,
        }
    }

    pub fn nth_child<'b>(&'b self, n: usize) -> Option<&'b Self> {
        self.children().map(|o| o.get(n)).flatten()
    }
}