kladd 0.1.0

A weirdly personal markup language
Documentation
use std::rc::Rc;

use crate::lexer::{Token, TokenKind};

#[derive(Debug, Default, Clone)]
pub struct TokenStream(pub Rc<Vec<Token>>);

impl TokenStream {
    pub fn new(ts: Vec<Token>) -> Self {
        TokenStream(Rc::new(ts))
    }

    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    pub fn len(&self) -> usize {
        self.0.len()
    }

    pub fn get(&self, idx: usize) -> Option<&Token> {
        self.0.get(idx)
    }

    pub fn iter(&self) -> TokenStreamIter<'_> {
        TokenStreamIter::new(self)
    }
}

impl FromIterator<Token> for TokenStream {
    fn from_iter<I: IntoIterator<Item = Token>>(iter: I) -> Self {
        TokenStream::new(iter.into_iter().collect::<Vec<Token>>())
    }
}

#[derive(Clone)]
pub struct TokenStreamIter<'a> {
    stream: &'a TokenStream,
    index: usize,
}

impl<'a> TokenStreamIter<'a> {
    pub fn new(stream: &'a TokenStream) -> Self {
        TokenStreamIter { stream, index: 0 }
    }

    pub fn peek(&self) -> Option<&'a Token> {
        self.stream.get(self.index)
    }
}

impl<'a> Iterator for TokenStreamIter<'a> {
    type Item = &'a Token;

    fn next(&mut self) -> Option<Self::Item> {
        self.stream.get(self.index).inspect(|_| {
            self.index += 1;
        })
    }
}

#[derive(Debug)]
pub struct TokenCursor {
    iter: TokenStream,
    idx: usize,
}

impl TokenCursor {
    pub fn new(input: Vec<Token>) -> Self {
        TokenCursor {
            iter: TokenStream::from_iter(input),
            idx: 0,
        }
    }

    pub fn peek(&self) -> Option<&Token> {
        self.iter.get(self.idx)
    }

    pub fn peek_kind(&self) -> Option<TokenKind> {
        self.iter.get(self.idx).map(|t| t.kind)
    }

    pub fn peek_nth(&self, n: usize) -> Option<&Token> {
        self.iter.get(self.idx + n)
    }

    pub fn _peek_nth_kind(&self, n: usize) -> Option<TokenKind> {
        self.iter.get(self.idx + n).map(|t| t.kind)
    }

    pub fn advance(&mut self) -> Token {
        debug_assert!(self.idx <= self.iter.len());
        let t = self.iter.0[self.idx].clone();
        self.idx += 1;
        t
    }

    pub fn iter(&self) -> TokenStreamIter<'_> {
        self.iter.iter()
    }

    pub fn is_at_end(&self) -> bool {
        self.iter.is_empty()
    }

    pub fn advance_if(&mut self, mut pred: impl FnMut(Option<&Token>) -> bool) -> Token {
        debug_assert!(pred(self.peek()));
        if pred(self.peek()) {
            self.advance()
        } else {
            panic!("invalid predicate")
        }
    }

    pub fn eat_while(&mut self, mut predicate: impl FnMut(Option<&Token>) -> bool) -> Vec<Token> {
        let mut res = Vec::new();

        while predicate(self.peek()) && !self.is_at_end() {
            res.push(self.advance());
        }

        res
    }
}