macro_rules! ast_struct {
(
$(#[$attr:meta])*
pub struct $name:ident #full $($rest:tt)*
) => {
#[cfg(feature = "full")]
$(#[$attr])*
#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
#[cfg_attr(feature = "clone-impls", derive(Clone))]
pub struct $name $($rest)*
#[cfg(not(feature = "full"))]
$(#[$attr])*
#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
#[cfg_attr(feature = "clone-impls", derive(Clone))]
pub struct $name {
_noconstruct: (),
}
};
(
$(#[$attr:meta])*
pub struct $name:ident $($rest:tt)*
) => {
$(#[$attr])*
#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
#[cfg_attr(feature = "clone-impls", derive(Clone))]
pub struct $name $($rest)*
};
}
macro_rules! ast_enum {
(
$(#[$enum_attr:meta])*
pub enum $name:ident { $($variants:tt)* }
) => (
$(#[$enum_attr])*
#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
#[cfg_attr(feature = "clone-impls", derive(Clone))]
pub enum $name {
$($variants)*
}
)
}
macro_rules! ast_enum_of_structs {
(
$(#[$enum_attr:meta])*
pub enum $name:ident {
$(
$(#[$variant_attr:meta])*
pub $variant:ident($member:ident $($rest:tt)*),
)*
}
$($remaining:tt)*
) => (
ast_enum! {
$(#[$enum_attr])*
pub enum $name {
$(
$(#[$variant_attr])*
$variant($member),
)*
}
}
$(
maybe_ast_struct! {
$(#[$variant_attr])*
pub struct $member $($rest)*
}
impl From<$member> for $name {
fn from(e: $member) -> $name {
$name::$variant(e)
}
}
)*
generate_to_tokens! {
$($remaining)*
enum $name { $($variant [$($rest)*],)* }
}
)
}
macro_rules! generate_to_tokens {
(do_not_generate_to_tokens $($foo:tt)*) => ();
(enum $name:ident { $($variant:ident [$($rest:tt)*],)* }) => (
#[cfg(feature = "printing")]
impl ::quote::ToTokens for $name {
fn to_tokens(&self, tokens: &mut ::quote::Tokens) {
match *self {
$(
$name::$variant(ref _e) =>
to_tokens_call!(_e, tokens, $($rest)*),
)*
}
}
}
);
}
#[cfg(feature = "full")]
macro_rules! to_tokens_call {
($e:ident, $tokens:ident, $($rest:tt)*) => {
$e.to_tokens($tokens)
};
}
#[cfg(not(feature = "full"))]
macro_rules! to_tokens_call {
($e:ident, $tokens:ident, #full $($rest:tt)*) => {
unreachable!()
};
($e:ident, $tokens:ident, $($rest:tt)*) => {
$e.to_tokens($tokens)
};
}
macro_rules! maybe_ast_struct {
(
$(#[$attr:meta])*
pub struct $name:ident
) => ();
($($rest:tt)*) => (ast_struct! { $($rest)* });
}