parserc-derive 0.12.7

proc-macros for `parserc`
Documentation
use proc_macro::TokenStream;
use quote::quote;
use syn::{Error, LitInt, parse_macro_input};

pub fn derive_tuple_syntax(args: TokenStream) -> TokenStream {
    let len = parse_macro_input!(args as LitInt);

    let len = match len.base10_parse::<usize>() {
        Ok(num) => {
            if num < 3 {
                return Error::new(len.span(), "length argument must greater than 2.")
                    .into_compile_error()
                    .into();
            }

            num
        }
        Err(err) => return err.into_compile_error().into(),
    };

    let mut stmts = vec![];

    for i in 2..len {
        let mut types = vec![];

        let mut pos = vec![];

        for j in 0..i {
            types.push(
                format!("T{}", j)
                    .parse::<proc_macro2::TokenStream>()
                    .unwrap(),
            );

            pos.push(
                format!("self.{}", j)
                    .parse::<proc_macro2::TokenStream>()
                    .unwrap(),
            );
        }

        stmts.push(quote! {
            impl<I,#(#types),*> Syntax<I> for (#(#types),*)
            where
                I: Input,
                #(#types: Syntax<I>),*
            {
                #[inline]
                fn parse(input: &mut I) -> std::result::Result<Self, I::Error> {
                    #(
                        let #types = #types::parse(input)?;
                    )*

                    Ok((#(#types),*))
                }

                #[inline]
                fn to_span(&self) -> Span {
                    let mut lhs = Span::None;

                    #(
                        let lhs = lhs.union(&#pos.to_span());
                    )*

                    lhs
                }
            }
        });
    }

    quote! {
        #(#stmts)*
    }
    .into()
}