prop_tune_macro 0.2.0

The procedural macro crate for proc_tune
Documentation
use std::ops::{Deref, DerefMut};

use proc_macro::{TokenStream, TokenTree};
use prop_tune_core::operators::Proposition;
use prop_tune_core::stream::{self, Bracket, Operator, Token};

#[derive(Debug, Clone)]
pub struct PropStream(stream::TokenStream);

impl PropStream {
    pub fn new(stream: impl Into<stream::TokenStream>) -> Self {
        PropStream(stream.into())
    }
}

impl AsMut<Vec<Token>> for PropStream {
    fn as_mut(&mut self) -> &mut Vec<Token> {
        self.0.as_mut()
    }
}

impl Deref for PropStream {
    type Target = stream::TokenStream;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl DerefMut for PropStream {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

impl Into<stream::TokenStream> for PropStream {
    fn into(self) -> stream::TokenStream {
        self.0
    }
}

impl TryInto<Proposition> for PropStream {
    type Error = <stream::TokenStream as TryInto<Proposition>>::Error;
    fn try_into(self) -> Result<Proposition, Self::Error> {
        self.0.try_into()
    }
}

impl TryInto<PropStream> for TokenStream {
    type Error = String;
    fn try_into(self) -> Result<PropStream, Self::Error> {
        let tok: Vec<TokenTree> = self.into_iter().collect();
        let mut out = PropStream(stream::TokenStream(vec![]));

        let mut i = 0;
        while i < tok.len() {
            match &tok[i] {
                TokenTree::Punct(ident) => match ident.to_string().as_str() {
                    "&" => match &tok[i + 1] {
                        TokenTree::Punct(ident2) => match ident2.to_string().as_str() {
                            "&" => {
                                out.push(Token::Operator(Operator::And));
                                i += 2
                            }
                            _ => return Err("&* is not a valid operator".to_string()),
                        },
                        _ => return Err("Invalid operator".to_string()),
                    },
                    "|" => match &tok[i + 1] {
                        TokenTree::Punct(ident2) => match ident2.to_string().as_str() {
                            "|" => {
                                out.push(Token::Operator(Operator::Or));
                                i += 2
                            }
                            _ => return Err("|* is not a valid operator".to_string()),
                        },
                        _ => return Err("Invalid operator".to_string()),
                    },
                    "!" => {
                        out.push(Token::Operator(Operator::Not));
                        i += 1
                    }
                    _ => return Err("Invalid punctuation".to_string()),
                },
                TokenTree::Ident(ident) => {
                    out.push(Token::Predicate(ident.to_string()));
                    i += 1;
                }
                TokenTree::Group(inner_tok) => {
                    let mut inner_out: PropStream = match inner_tok.stream().try_into() {
                        Ok(inner_out) => inner_out,
                        Err(err) => return Err(err),
                    };
                    out.push(Token::Bracket(Bracket::Open));
                    out.append(inner_out.as_mut());
                    out.push(Token::Bracket(Bracket::Close));
                    i += 1;
                }

                TokenTree::Literal(_) => return Err("No implimentation for literals!".to_string()),
            }
        }
        Ok(out)
    }
}