oxidate 0.1.0

Turns strings into a Rust AST
Documentation
use derive_new::new;
use peekmore::{PeekMore, PeekMoreIterator};
use proc_macro2::{self};

use crate::lex::{Lexed, Punctuation, Word};

#[derive(Debug, Default, new)]
pub struct Tokens {
    inner: proc_macro2::TokenStream,
}

impl Tokens {
    pub fn empty() -> Tokens {
        Default::default()
    }

    pub fn parse(self) -> ParseBuffer {
        ParseBuffer {
            inner: self.inner.into_iter().peekmore(),
        }
    }
}

impl From<proc_macro2::TokenStream> for Tokens {
    fn from(stream: proc_macro2::TokenStream) -> Self {
        Tokens::new(stream)
    }
}

impl From<proc_macro::TokenStream> for Tokens {
    fn from(stream: proc_macro::TokenStream) -> Self {
        Tokens::new(stream.into())
    }
}

impl Into<proc_macro2::TokenStream> for Tokens {
    fn into(self) -> proc_macro2::TokenStream {
        self.inner
    }
}

impl Into<proc_macro::TokenStream> for Tokens {
    fn into(self) -> proc_macro::TokenStream {
        let inner: proc_macro2::TokenStream = self.inner.into();
        inner.into()
    }
}

#[derive(Debug)]
pub struct ParseBuffer {
    inner: PeekMoreIterator<proc_macro2::token_stream::IntoIter>,
}

impl Default for ParseBuffer {
    fn default() -> Self {
        Self::new(proc_macro2::TokenStream::default())
    }
}

#[derive(Debug, Clone)]
pub enum PeekedToken<'a> {
    EOF,
    Lexed(Lexed<'a>),
}

impl<'a> PeekedToken<'a> {
    pub fn as_punctuation(&self, char: &str) -> Option<&Punctuation> {
        match self {
            PeekedToken::Lexed(lexed) => lexed.as_punctuation(char),
            _ => None,
        }
    }

    pub fn as_word(&self, word: &str) -> Option<&Word> {
        match self {
            PeekedToken::Lexed(lexed) => lexed.as_word(word),
            _ => None,
        }
    }
}

impl ParseBuffer {
    pub fn new(stream: impl Into<proc_macro2::TokenStream>) -> ParseBuffer {
        ParseBuffer {
            inner: stream.into().into_iter().peekmore(),
        }
    }

    pub fn peek(&mut self) -> PeekedToken {
        match self.inner.peek() {
            Some(token) => {
                let token: Lexed = token.into();
                PeekedToken::Lexed(token)
            }
            None => PeekedToken::EOF,
        }
    }
}