use proc_macro2::Ident;
use syn::{
Error as SynError, Token,
parse::{Parse, ParseStream},
punctuated::Punctuated,
};
macro_rules! parse {
($pattern:path, $expr:expr) => {{
let span = $expr.span();
if let $pattern(value) = $expr {
Ok(value)
} else {
Err(::syn::Error::new(span, "expected $pattern here"))
}
}};
}
macro_rules! declare_cat_type {
($name:ident < $($T:ident),+ >) => {
pub struct $name<$($T),+>($(pub $T),+);
impl<$($T),+> $name<$($T),+> {
#[allow(non_snake_case)]
pub fn into_tuple(self) -> ($($T),+) {
let Self($($T),+) = self;
($($T),+)
}
}
impl<$($T: Parse),+> Parse for $name<$($T),+> {
fn parse(parse_stream: ParseStream) -> Result<Self, SynError> {
Ok(Self(
$(parse_stream.parse::<$T>()?),+
))
}
}
};
}
declare_cat_type!(Cat3<X, Y, Z>);
declare_cat_type!(Cat6<U, V, W, X, Y, Z>);
pub type Colon = Token![:];
pub type Equals = Token![=];
pub type Assignment<L, R> = Cat3<L, Equals, R>;
pub type IdentAssignment<T> = Assignment<Ident, T>;
pub type Comma = Token![,];
pub type CommaPunctuated<T> = Punctuated<T, Comma>;
pub(crate) use parse;