use loess::{Error, ErrorPriority, Errors, Input, IntoTokens, PopFrom};
use proc_macro2::{TokenStream, TokenTree};
use quote::ToTokens;
use syn::{
Expr, Pat, Path, Stmt,
parse::{Parse, ParseStream, Parser},
};
fn error_reporter(errors: &mut Errors) -> impl '_ + FnOnce(syn::Error) {
move |error| {
errors.push(Error::new(
ErrorPriority::GRAMMAR,
error.to_string(),
[error.span()],
))
}
}
macro_rules! wrappers {
($(
$(#[$($attr:tt)*])*
$name:ident($wrapped:ty)$(: $(
// $(PeekFrom $(@ $PeekFrom:tt)?)?
$(PopFrom $(@ $PopFrom:tt)?)?
$(IntoTokens $(@ $IntoTokens:tt)?)?
),*$(,)?)?;
)*) => {$(
$(#[$($attr)*])*
#[derive(Clone)]
pub struct $name($wrapped);
$($(
// $(
// $(@ $PeekFrom)?
// impl PeekFrom for $name {
// fn peek_from(input: &Input) -> bool {
$(
$(@ $PopFrom)?
impl PopFrom for $name {
fn pop_from(input: &mut Input, errors: &mut Errors) -> Result<Self, ()> {
fn parse(input: ParseStream) -> syn::Result<($wrapped, TokenStream)> {
Ok((<$wrapped>::parse(input)?, TokenStream::parse(input)?))
}
let tokens: TokenStream = input.tokens.drain(..).collect();
let (parsed, rest) = parse.parse2(tokens).map_err(error_reporter(errors))?;
input.prepend(rest.into_iter().collect::<Vec<_>>());
Ok(Self(parsed))
}
}
)?
$(
$(@ $IntoTokens)?
impl IntoTokens for $name {
fn into_tokens(self, root: &TokenStream, tokens: &mut impl Extend<TokenTree>) {
self.0.into_token_stream().into_tokens(root, tokens);
}
}
)?
)*)?
)*};
}
wrappers! {
Expression(Expr): PopFrom, IntoTokens;
ExpressionExceptStructExpression(Expr): IntoTokens;
Pattern(Pat): IntoTokens;
SimplePath(Path): IntoTokens;
Statement(Stmt): PopFrom, IntoTokens;
}
impl PopFrom for ExpressionExceptStructExpression {
fn pop_from(input: &mut Input, errors: &mut Errors) -> Result<Self, ()> {
fn parse(
input: ParseStream,
) -> syn::Result<(ExpressionExceptStructExpression, TokenStream)> {
Ok((
ExpressionExceptStructExpression(Expr::parse_without_eager_brace(input)?),
TokenStream::parse(input)?,
))
}
let tokens = input.tokens.drain(..).collect::<TokenStream>().into();
let (this, rest) = parse.parse2(tokens).map_err(error_reporter(errors))?;
input.prepend(rest.into_iter().collect::<Vec<_>>());
Ok(this)
}
}
impl PopFrom for Pattern {
fn pop_from(input: &mut Input, errors: &mut Errors) -> Result<Self, ()> {
fn parse(input: ParseStream) -> syn::Result<(Pattern, TokenStream)> {
Ok((
Pattern(Pat::parse_multi_with_leading_vert(input)?),
TokenStream::parse(input)?,
))
}
let tokens = input.tokens.drain(..).collect::<TokenStream>().into();
let (this, rest) = parse.parse2(tokens).map_err(error_reporter(errors))?;
input.prepend(rest.into_iter().collect::<Vec<_>>());
Ok(this)
}
}
impl PopFrom for SimplePath {
fn pop_from(input: &mut Input, errors: &mut Errors) -> Result<Self, ()> {
fn parse(input: ParseStream) -> syn::Result<(SimplePath, TokenStream)> {
Ok((
SimplePath(Path::parse_mod_style(input)?),
TokenStream::parse(input)?,
))
}
let tokens = input.tokens.drain(..).collect::<TokenStream>().into();
let (this, rest) = parse.parse2(tokens).map_err(error_reporter(errors))?;
input.prepend(rest.into_iter().collect::<Vec<_>>());
Ok(this)
}
}