#[cfg(doc)]
use crate::*;
#[cfg(doc)]
#[macro_export]
macro_rules! unsynn {
(enum $name:ident { $($variant:ident),* }) => {};
(struct $name:ident { $($member:ident: $parser:ty),* }) => {};
(struct $name:ident ( $($parser:ty),*);) => {};
(trait $name:ident;) => {};
(trait $name:ident{}) => {};
(impl { $($trait:ident $semicolon_or_block:tt)+ }) => {};
(impl $trait:ident for $type:ty {$body:tt}) => {};
(impl $trait:ident for $($type:ty),+;) => {};
(fn $function:ident($params:tt) {$body:tt}) => {};
(use $($path:path)+ $(as $alias:ident)?) => {};
(keyword $name:ident = keyword_or_group;) => {};
(keyword $name:ident != keyword_or_group;) => {};
(operator $name:ident = "punct";) => {};
(predicatetrait $name:ident $(: $super:ident $(+ $supers:ident)*)?;) => {};
(predicateflag $name:ident = Enable $(for $($trait:ident),+)?;) => {};
(predicateflag $name:ident = Disable $(for $($trait:ident),+)?;) => {};
(predicateflag $name:ident = TokensRemain $(for $($trait:ident),+)?;) => {};
(predicateflag $name:ident $(for $($trait:ident),+)?;) => {};
}
#[doc(hidden)]
#[cfg(not(doc))]
#[macro_export]
macro_rules! unsynn{
(
$(#[$attribute:meta])* $pub:vis enum $name:ident
<$lifetime:lifetime $(, $($param:tt),*)? $(,)?>
{
$($variants:tt)*
}
impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
$($cont:tt)*
) => {
$crate::unsynn!{
@enum_lifetime
$(#[$attribute])* $pub enum $name
<$lifetime $(, $($param),*)?>
{
$($variants)*
}
}
$crate::unsynn!{
@impl
for $name
{$({$(#[$tattr])* $trait $bracesemi})*}
}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis enum $name:ident
<$lifetime:lifetime $(, $($param:tt),*)? $(,)?>
{
$($variants:tt)*
}
$($cont:tt)*
) => {
$crate::unsynn!{
@enum_lifetime
$(#[$attribute])* $pub enum $name
<$lifetime $(, $($param),*)?>
{
$($variants)*
}
}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis enum $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?
{
$($variants:tt)*
}
impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
$($cont:tt)*
) => {
$crate::unsynn!{
@enum
$(#[$attribute])* $pub enum $name
$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
$($variants)*
}
}
$crate::unsynn!{
@impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
for $name
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{$({$(#[$tattr])* $trait $bracesemi})*}
}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis enum $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?
{
$($variants:tt)*
}
$($cont:tt)*
) => {
$crate::unsynn!{
@enum
$(#[$attribute])* $pub enum $name
$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
$($variants)*
}
}
$crate::unsynn!{$($cont)*}
};
(
@enum
$(#[$attribute:meta])* $pub:vis enum $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?
{
$($variants:tt)*
}
) => {
#[derive(Debug)]
$(#[$attribute])* $pub enum $name
$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
$($variants)*
}
impl$(<$($generic: $crate::Parser $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::Parser
for $name$(<$($generic),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
let mut err = $crate::Error::no_error();
$crate::unsynn!{@enum_parse_variant(tokens, err) $($variants)*}
Err(err)
}
}
impl$(<$($generic: $crate::ToTokens $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::ToTokens
for $name$(< $($generic),* >)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
$crate::unsynn!{@enum_to_tokens(self, tokens) {$($variants)*}}
}
}
};
(
@enum_lifetime
$(#[$attribute:meta])* $pub:vis enum $name:ident
<$lifetime:lifetime $(, $($param:tt),*)? $(,)?>
{
$($variants:tt)*
}
) => {
#[derive(Debug)]
$(#[$attribute])* $pub enum $name<$lifetime $(, $($param),*)?> {
$($variants)*
}
impl<$lifetime $(, $($param),*)?> $crate::Parser
for $name<$lifetime $(, $($param),*)?>
{
fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
let mut err = $crate::Error::no_error();
$crate::unsynn!{@enum_parse_variant(tokens, err) $($variants)*}
Err(err)
}
}
impl<$lifetime $(, $($param),*)?> $crate::ToTokens
for $name<$lifetime $(, $($param),*)?>
{
fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
$crate::unsynn!{@enum_to_tokens(self, tokens) {$($variants)*}}
}
}
};
(
$(#[$attribute:meta])* $pub:vis struct $name:ident;
$($cont:tt)*
) => {
compile_error!(concat!(
"Unit structs are not yet supported in unsynn! macro.\n",
"\n",
"Found: `", stringify!($pub struct $name;), "`\n",
"\n",
"Unit structs (like `struct Foo;`) are commonly used as marker types\n",
"in unsynn (e.g., Enable, Disable, EndOfStream). Support for defining\n",
"them inside unsynn! is planned but not yet implemented.\n",
"\n",
"Workarounds:\n",
" 1. Define marker types outside unsynn! and implement Parser/ToTokens manually\n",
" 2. Use empty tuple struct: `", stringify!($pub struct $name();), "`\n",
" (though this may also not be supported yet)\n",
"\n",
"See ROADMAP.md for planned features."
));
};
// Empty tuple struct - may want to make this an error too
(
$(#[$attribute:meta])* $pub:vis struct $name:ident();
$($cont:tt)*
) => {
compile_error!(concat!(
"Empty tuple structs are not supported in unsynn! macro.\n",
"\n",
"Found: `", stringify!($pub struct $name();), "`\n",
"\n",
"Empty tuple structs would parse and emit no tokens, which is typically\n",
"only useful for marker types. If you need a marker, define it outside\n",
"unsynn! as a unit struct with manual Parser/ToTokens implementation.\n",
"\n",
"If you need a struct that parses tokens, use tuple struct with fields:\n",
" `", stringify!($pub struct $name(Type);), "`\n",
"\n",
"See ROADMAP.md for discussion on marker type support."
));
};
(
$(#[$attribute:meta])* $pub:vis struct $name:ident
<$lifetime:lifetime, $tparam:ident $(,)?>
{
$($(#[$mattr:meta])* $mpub:vis $member:ident: $parser:ty),* $(,)?
}
impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
$($cont:tt)*
) => {
$crate::unsynn!{
@struct_lifetime_tparam
$(#[$attribute])* $pub struct $name
<$lifetime, $tparam>
{
$($(#[$mattr])* $mpub $member: $parser),*
}
}
$crate::unsynn!{
@impl
for $name
{$({$(#[$tattr])* $trait $bracesemi})*}
}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis struct $name:ident
<$lifetime:lifetime, $tparam:ident $(,)?>
{
$($(#[$mattr:meta])* $mpub:vis $member:ident: $parser:ty),* $(,)?
}
$($cont:tt)*
) => {
$crate::unsynn!{
@struct_lifetime_tparam
$(#[$attribute])* $pub struct $name
<$lifetime, $tparam>
{
$($(#[$mattr])* $mpub $member: $parser),*
}
}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis struct $name:ident
<$lifetime:lifetime $(, $($param:tt),*)? $(,)?>
{
$($(#[$mattr:meta])* $mpub:vis $member:ident: $parser:ty),* $(,)?
}
impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
$($cont:tt)*
) => {
$crate::unsynn!{
@struct_lifetime
$(#[$attribute])* $pub struct $name
<$lifetime $(, $($param),*)?>
{
$($(#[$mattr])* $mpub $member: $parser),*
}
}
$crate::unsynn!{
@impl
for $name
{$({$(#[$tattr])* $trait $bracesemi})*}
}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis struct $name:ident
<$lifetime:lifetime $(, $($param:tt),*)? $(,)?>
{
$($(#[$mattr:meta])* $mpub:vis $member:ident: $parser:ty),* $(,)?
}
$($cont:tt)*
) => {
$crate::unsynn!{
@struct_lifetime
$(#[$attribute])* $pub struct $name
<$lifetime $(, $($param),*)?>
{
$($(#[$mattr])* $mpub $member: $parser),*
}
}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis struct $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?
{
$($(#[$mattr:meta])* $mpub:vis $member:ident: $parser:ty),* $(,)?
}
impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
$($cont:tt)*
) => {
$crate::unsynn!{
@struct
$(#[$attribute])* $pub struct $name
$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
$($(#[$mattr])* $mpub $member: $parser),*
}
}
$crate::unsynn!{
@impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
for $name
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{$({$(#[$tattr])* $trait $bracesemi})*}
}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis struct $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?
{
$($(#[$mattr:meta])* $mpub:vis $member:ident: $parser:ty),* $(,)?
}
$($cont:tt)*
) => {
$crate::unsynn!{
@struct
$(#[$attribute])* $pub struct $name
$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
$($(#[$mattr])* $mpub $member: $parser),*
}
}
$crate::unsynn!{$($cont)*}
};
(
@struct
$(#[$attribute:meta])* $pub:vis struct $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?
{
$($(#[$mattr:meta])* $mpub:vis $member:ident: $parser:ty),* $(,)?
}
) => {
#[derive(Debug)]
$(#[$attribute])* $pub struct $name
$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
$(
$(#[$mattr])* $mpub $member : $parser
),*
}
impl$(<$($generic: $crate::Parser $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::Parser
for $name$(<$($generic),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
Ok(Self{$($member: <$parser as $crate::Parse>::parse(tokens)?),*})
}
}
impl$(<$($generic: $crate::ToTokens $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::ToTokens
for $name$(<$($generic),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
$(self.$member.to_tokens(tokens);)*
}
}
};
(
@struct_lifetime_tparam
$(#[$attribute:meta])* $pub:vis struct $name:ident
<$lifetime:lifetime, $tparam:ident>
{
$($(#[$mattr:meta])* $mpub:vis $member:ident: $parser:ty),* $(,)?
}
) => {
#[derive(Debug)]
$(#[$attribute])* $pub struct $name<$lifetime, $tparam> {
$(
$(#[$mattr])* $mpub $member : $parser
),*
}
impl<$lifetime, $tparam: $crate::Parser> $crate::Parser
for $name<$lifetime, $tparam>
{
fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
Ok(Self{$($member: <$parser as $crate::Parse>::parse(tokens)?),*})
}
}
impl<$lifetime, $tparam: $crate::ToTokens> $crate::ToTokens
for $name<$lifetime, $tparam>
{
fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
$(self.$member.to_tokens(tokens);)*
}
}
};
(
@struct_lifetime
$(#[$attribute:meta])* $pub:vis struct $name:ident
<$lifetime:lifetime $(, $($param:tt),*)?>
{
$($(#[$mattr:meta])* $mpub:vis $member:ident: $parser:ty),* $(,)?
}
) => {
#[derive(Debug)]
$(#[$attribute])* $pub struct $name<$lifetime $(, $($param),*)?> {
$(
$(#[$mattr])* $mpub $member : $parser
),*
}
impl<$lifetime $(, $($param),*)?> $crate::Parser
for $name<$lifetime $(, $($param),*)?>
{
fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
Ok(Self{$($member: <$parser as $crate::Parse>::parse(tokens)?),*})
}
}
impl<$lifetime $(, $($param),*)?> $crate::ToTokens
for $name<$lifetime $(, $($param),*)?>
{
fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
$(self.$member.to_tokens(tokens);)*
}
}
};
(
$(#[$attribute:meta])* $pub:vis struct $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
(
$(#[$mattr:meta])* $mpub:vis $field:ty
)
from $parse_type:ty:
parse_with |$pval:ident, $ptok:ident| $parse_body:block
to_tokens |$tval:ident, $ttok:ident| $tokens_body:block
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
$($cont:tt)*
) => {
$crate::unsynn!{
@tuplestruct_parse_with_as_to_tokens
$(#[$attribute])* $pub struct $name
$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
($(#[$mattr])* $mpub $field)
from $parse_type:
parse_with |$pval, $ptok| $parse_body
to_tokens |$tval, $ttok| $tokens_body
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis struct $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
(
$(#[$mattr:meta])* $mpub:vis $field:ty
)
from $parse_type:ty:
parse_with |$pval:ident, $ptok:ident| $closure_body:block
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
$($cont:tt)*
) => {
$crate::unsynn!{
@tuplestruct_parse_with_as
$(#[$attribute])* $pub struct $name
$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
($(#[$mattr])* $mpub $field)
from $parse_type:
parse_with |$pval, $ptok| $closure_body
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis struct $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
(
$($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
);
parse_with |$pval:ident, $ptok:ident| $parse_body:block
to_tokens |$tval:ident, $ttok:ident| $tokens_body:block
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
$($cont:tt)*
) => {
$crate::unsynn!{
@tuplestruct_parse_with_to_tokens
$(#[$attribute])* $pub struct $name
$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
(
$($(#[$mattr])* $mpub $parser),*
);
parse_with |$pval, $ptok| $parse_body
to_tokens |$tval, $ttok| $tokens_body
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis struct $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
(
$($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
);
parse_with |$pval:ident, $ptok:ident| $closure_body:block
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
$($cont:tt)*
) => {
$crate::unsynn!{
@tuplestruct_parse_with
$(#[$attribute])* $pub struct $name
$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
(
$($(#[$mattr])* $mpub $parser),*
);
parse_with |$pval, $ptok| $closure_body
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis struct $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
(
$($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
);
to_tokens |$tval:ident, $ttok:ident| $tokens_body:block
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
$($cont:tt)*
) => {
$crate::unsynn!{
@tuplestruct_to_tokens
$(#[$attribute])* $pub struct $name
$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
(
$($(#[$mattr])* $mpub $parser),*
);
to_tokens |$tval, $ttok| $tokens_body
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis struct $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
(
$($parser:ty),* $(,)?
)
from $parse_type:ty:
$($cont:tt)*
) => {
compile_error!("`from` requires `parse_with` clause. Use: `from Type: parse_with |value, tokens| { ... }`");
};
(
$(#[$attribute:meta])* $pub:vis struct $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
(
$field1:ty,
$field2:ty
$(, $rest_fields:ty)* $(,)?
)
from $parse_type:ty:
parse_with |$pval:ident, $ptok:ident| $closure_body:block
$($cont:tt)*
) => {
compile_error!("`from` only supported for single-field tuple structs. For multi-field structs, use `parse_with` without `from` for validation.");
};
(
$(#[$attribute:meta])* $pub:vis struct $name:ident
<$lifetime:lifetime $(, $($param:tt),*)? $(,)?>
(
$($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
);
impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
$($cont:tt)*
) => {
$crate::unsynn!{
@tuplestruct_lifetime
$(#[$attribute])* $pub struct $name
<$lifetime $(, $($param),*)?>
(
$($(#[$mattr])* $mpub $parser),*
);
}
$crate::unsynn!{
@impl
for $name
{$({$(#[$tattr])* $trait $bracesemi})*}
}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis struct $name:ident
<$lifetime:lifetime $(, $($param:tt),*)? $(,)?>
(
$($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
)
impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
$($cont:tt)*
) => {
$crate::unsynn!{
@tuplestruct_lifetime
$(#[$attribute])* $pub struct $name
<$lifetime $(, $($param),*)?>
(
$($(#[$mattr])* $mpub $parser),*
);
}
$crate::unsynn!{
@impl
for $name
{$({$(#[$tattr])* $trait $bracesemi})*}
}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis struct $name:ident
<$lifetime:lifetime $(, $($param:tt),*)? $(,)?>
(
$($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
);
$($cont:tt)*
) => {
$crate::unsynn!{
@tuplestruct_lifetime
$(#[$attribute])* $pub struct $name
<$lifetime $(, $($param),*)?>
(
$($(#[$mattr])* $mpub $parser),*
);
}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis struct $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
(
$($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
)
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
$($cont:tt)*
) => {
$crate::unsynn!{
@tuplestruct
$(#[$attribute])* $pub struct $name
$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
(
$($(#[$mattr])* $mpub $parser),*
)
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
}
$crate::unsynn!{
@impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
for $name
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{$({$(#[$tattr])* $trait $bracesemi})*}
}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis struct $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
(
$($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
)
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?
impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
$($cont:tt)*
) => {
$crate::unsynn!{
@tuplestruct
$(#[$attribute])* $pub struct $name
$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
(
$($(#[$mattr])* $mpub $parser),*
)
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
}
$crate::unsynn!{
@impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
for $name
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{$({$(#[$tattr])* $trait $bracesemi})*}
}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis struct $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
(
$($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
)
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
$($cont:tt)*
) => {
$crate::unsynn!{
@tuplestruct
$(#[$attribute])* $pub struct $name
$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
(
$($(#[$mattr])* $mpub $parser),*
)
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
}
$crate::unsynn!{$($cont)*}
};
(
@tuplestruct
$(#[$attribute:meta])* $pub:vis struct $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
(
$($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
)
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
) => {
#[derive(Debug)]
$(#[$attribute])* $pub struct $name
$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
($($(#[$mattr])* $mpub $parser),*)
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
impl$(<$($generic: $crate::Parser $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::Parser
for $name$(<$($generic),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
Ok(Self($(<$parser as $crate::Parse>::parse(tokens)?),*))
}
}
impl$(<$($generic: $crate::ToTokens $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::ToTokens
for $name$(<$($generic),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
unsynn! {@tuple_for_each item in self : Self($($parser),*) {
item.to_tokens(tokens);
}}
}
}
};
(
@tuplestruct_parse_with_as
$(#[$attribute:meta])* $pub:vis struct $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
($(#[$mattr:meta])* $mpub:vis $field:ty)
from $parse_type:ty:
parse_with |$pval:ident, $ptok:ident| $closure_body:block
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
) => {
#[derive(Debug)]
$(#[$attribute])* $pub struct $name
$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
($(#[$mattr])* $mpub $field)
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
impl$(<$($generic: $crate::Parser $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::Parser
for $name$(<$($generic),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
<$parse_type>::parse_with(tokens, |$pval, $ptok| $closure_body)
}
}
impl$(<$($generic: $crate::ToTokens $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::ToTokens
for $name$(<$($generic),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
self.0.to_tokens(tokens)
}
}
};
(
@tuplestruct_parse_with
$(#[$attribute:meta])* $pub:vis struct $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
(
$($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
);
parse_with |$pval:ident, $ptok:ident| $closure_body:block
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
) => {
#[derive(Debug)]
$(#[$attribute])* $pub struct $name
$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
($($(#[$mattr])* $mpub $parser),*)
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
impl$(<$($generic: $crate::Parser $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::Parser
for $name$(<$($generic),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
let parsed = Self($(<$parser as $crate::Parse>::parse(tokens)?),*);
(|$pval: Self, $ptok: &mut $crate::TokenIter| $closure_body)(parsed, tokens)
}
}
impl$(<$($generic: $crate::ToTokens $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::ToTokens
for $name$(<$($generic),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
unsynn! {@tuple_for_each item in self : Self($($parser),*) {
item.to_tokens(tokens);
}}
}
}
};
(
@tuplestruct_parse_with_as_to_tokens
$(#[$attribute:meta])* $pub:vis struct $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
($(#[$mattr:meta])* $mpub:vis $field:ty)
from $parse_type:ty:
parse_with |$pval:ident, $ptok:ident| $closure_body:block
to_tokens |$tval:ident, $ttok:ident| $tokens_body:block
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
) => {
#[derive(Debug)]
$(#[$attribute])* $pub struct $name
$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
($(#[$mattr])* $mpub $field)
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
impl$(<$($generic: $crate::Parser $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::Parser
for $name$(<$($generic),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
<$parse_type>::parse_with(tokens, |$pval, $ptok| $closure_body)
}
}
impl$(<$($generic),*>)? $crate::ToTokens
for $name$(<$($generic),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
(|$tval: &Self, $ttok: &mut $crate::TokenStream| $tokens_body)(self, tokens)
}
}
};
(
@tuplestruct_parse_with_to_tokens
$(#[$attribute:meta])* $pub:vis struct $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
(
$($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
);
parse_with |$pval:ident, $ptok:ident| $closure_body:block
to_tokens |$tval:ident, $ttok:ident| $tokens_body:block
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
) => {
#[derive(Debug)]
$(#[$attribute])* $pub struct $name
$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
($($(#[$mattr])* $mpub $parser),*)
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
impl$(<$($generic: $crate::Parser $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::Parser
for $name$(<$($generic),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
let parsed = Self($(<$parser as $crate::Parse>::parse(tokens)?),*);
(|$pval: Self, $ptok: &mut $crate::TokenIter| $closure_body)(parsed, tokens)
}
}
impl$(<$($generic),*>)? $crate::ToTokens
for $name$(<$($generic),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
(|$tval: &Self, $ttok: &mut $crate::TokenStream| $tokens_body)(self, tokens)
}
}
};
(
@tuplestruct_to_tokens
$(#[$attribute:meta])* $pub:vis struct $name:ident
$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
(
$($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
);
to_tokens |$tval:ident, $ttok:ident| $tokens_body:block
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
) => {
#[derive(Debug)]
$(#[$attribute])* $pub struct $name
$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
($($(#[$mattr])* $mpub $parser),*)
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
impl$(<$($generic: $crate::Parser $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::Parser
for $name$(<$($generic),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
Ok(Self($(<$parser as $crate::Parse>::parse(tokens)?),*))
}
}
impl$(<$($generic),*>)? $crate::ToTokens
for $name$(<$($generic),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{
fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
(|$tval: &Self, $ttok: &mut $crate::TokenStream| $tokens_body)(self, tokens)
}
}
};
(
@tuplestruct_lifetime
$(#[$attribute:meta])* $pub:vis struct $name:ident
<$lifetime:lifetime $(, $($param:tt),*)?>
(
$($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
);
) => {
#[derive(Debug)]
$(#[$attribute])* $pub struct $name<$lifetime $(, $($param),*)?>(
$($(#[$mattr])* $mpub $parser),*
);
impl<$lifetime $(, $($param),*)?> $crate::Parser
for $name<$lifetime $(, $($param),*)?>
{
fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
Ok(Self($(<$parser as $crate::Parse>::parse(tokens)?),*))
}
}
impl<$lifetime $(, $($param),*)?> $crate::ToTokens
for $name<$lifetime $(, $($param),*)?>
{
fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
unsynn! {@tuple_for_each item in self : Self($($parser),*) {
item.to_tokens(tokens);
}}
}
}
};
(
$(#[$attribute:meta])* $pub:vis type $name:ident
$(<$($generic:ident $(: $constraint:ident $(+ $constraints:ident)*)? $(= $default:ty)?),*$(,)?>)?
= $orig:path;
$($cont:tt)*
) => {
$(#[$attribute])* $pub type $name$(<$($generic$(: $constraint $(+ $constraints)*)? $(= $default)?),*>)? = $orig;
$crate::unsynn!{$($cont)*}
};
(
$(#[$attributeall:meta])*
$pub:vis trait {
$($(#[$attribute:meta])* $name:ident$(: $super:ident $(+ $supers:ident)*)?);+$(;)?
}
$($cont:tt)*
) => {
$crate::unsynn!{@expand_marker_trait($(#[$attributeall])*)
$({$(#[$attribute])* $pub $name$(: $super $(+ $supers)*)?})+
}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attributeall:meta])*
trait {
$($(#[$attribute:meta])* $pub:vis $name:ident$(: $super:ident $(+ $supers:ident)*)?);+$(;)?
}
$($cont:tt)*
) => {
$crate::unsynn!{@expand_marker_trait($(#[$attributeall])*)
$({$(#[$attribute])* $pub $name$(: $super $(+ $supers)*)?})+
}
$crate::unsynn!{$($cont)*}
};
(
@expand_marker_trait($(#[$attributeall:meta])*)
{$(#[$attribute:meta])* $pub:vis $name:ident$(: $super:ident $(+ $supers:ident)*)?}
$($cont:tt)*
) => {
$(#[$attributeall])* $(#[$attribute])* $pub trait $name$(: $super $(+ $supers)*)? {}
$crate::unsynn!{@expand_marker_trait($(#[$attributeall])*) $($cont)*}
};
(@expand_marker_trait($(#[$attributeall:meta])*)) => {};
(
$(#[$attribute:meta])* $pub:vis trait $name:ident$(: $super:ident $(+ $supers:ident)*)?;
$($cont:tt)*
) => {
$(#[$attribute])* $pub trait $name$(: $super $(+ $supers)*)? {}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis trait $name:ident$(: $super:ident $(+ $supers:ident)*)?
{$($body:tt)*}
$($cont:tt)*
) => {
$(#[$attribute])* $pub trait $name$(: $super $(+ $supers)*)? {$($body)*}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])*
impl$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)?),*$(,)?>)?
$type:ident$(<$($genparam:ident),*>)?
{$($body:tt)*}
$($cont:tt)*
) => {
$(#[$attribute])*
impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
$type$(<$($genparam),*>)?
{$($body)*}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])*
impl$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)?),*$(,)?>)?
$trait:ident$(<$($traitgenparam:ident),*$(,)?>)?
for $type:ty {$($body:tt)*}
$($cont:tt)*
) => {
$(#[$attribute])*
impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
$trait$(<$($traitgenparam),*$(,)?>)?
for $type {$($body)*}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])*
impl$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)?),*$(,)?>)?
$trait:ident$(<$($traitgenparam:ident),*$(,)?>)?
for $($type:ty),+;
$($cont:tt)*
) => {
$crate::unsynn!{
@impl_markers(
$(#[$attribute])*
impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
$trait$(<$($traitgenparam),*$(,)?>)?
)
$($type),+,
}
$crate::unsynn!{$($cont)*}
};
(
@impl_markers(
$(#[$attribute:meta])*
impl$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)?),*$(,)?>)?
$trait:ident$(<$($traitgenparam:ident),*$(,)?>)?
)
$type:ty,
$($cont:tt)*
) => {
$(#[$attribute])*
impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
$trait$(<$($traitgenparam),*$(,)?>)?
for $type{}
$crate::unsynn!{
@impl_markers(
$(#[$attribute])*
impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
$trait$(<$($traitgenparam),*$(,)?>)?
)
$($cont)*
}
};
(@impl_markers($($_:tt)*)) => {};
(
$(#[$attribute:meta])* $pub:vis fn $name:ident$(<$($generic:tt),*>)?($($param:tt)*) $(-> $ret:ty)? {$($body:tt)*}
$($cont:tt)*
) => {
$(#[$attribute])* $pub fn $name$(<$($generic),*>)?($($param)*) $(-> $ret)? {$($body)*}
$crate::unsynn!{$($cont)*}
};
(use ::$($path:ident)::+$(::{$($inside:tt)+})?; $($cont:tt)*) => {
use ::$($path)::+$(::{$($inside)+})?;
$crate::unsynn!{$($cont)*}
};
(use $($path:ident)::+$(::{$($inside:tt)+})?; $($cont:tt)*) => {
use $($path)::+$(::{$($inside)+})?;
$crate::unsynn!{$($cont)*}
};
(use ::$($path:ident)::+ as $alias:ident; $($cont:tt)*) => {
use $($path)::+ as $alias;
$crate::unsynn!{$($cont)*}
};
(use ::$($path:ident)::+ as $alias:ident; $($cont:tt)*) => {
use $($path)::+ as $alias;
$crate::unsynn!{$($cont)*}
};
(macro_rules! $name:ident {$($rules:tt)*} $($cont:tt)*) => {
macro_rules! $name {$($rules)*}
$crate::unsynn!{$($cont)*}
};
($macro:ident! {$($args:tt)*} $($cont:tt)*) => {
$macro! {$($args)*}
$crate::unsynn!{$($cont)*}
};
($macro:ident! ($($args:tt)*); $($cont:tt)*) => {
$macro! ($($args)*);
$crate::unsynn!{$($cont)*}
};
($macro:ident! [$($args:tt)*]; $($cont:tt)*) => {
$macro! [$($args)*];
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis keyword $name:ident = $str:literal;
impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
$($cont:tt)*
) => {
$crate::keyword!{$(#[$attribute])* $pub $name = $str}
$crate::unsynn!{
@impl
for $name
{$({$(#[$tattr])* $trait $bracesemi})*}
}
$crate::unsynn!{$($cont)*}
};
($(#[$attribute:meta])* $pub:vis keyword $name:ident = $str:literal; $($cont:tt)*) => {
$crate::keyword!{$(#[$attribute])* $pub $name = $str}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis keyword $name:ident != $str:literal;
impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
$($cont:tt)*
) => {
$crate::keyword!{$(#[$attribute])* $pub $name != $str}
$crate::unsynn!{
@impl
for $name
{$({$(#[$tattr])* $trait $bracesemi})*}
}
$crate::unsynn!{$($cont)*}
};
($(#[$attribute:meta])* $pub:vis keyword $name:ident != $str:literal; $($cont:tt)*) => {
$crate::keyword!{$(#[$attribute])* $pub $name != $str}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis keyword $name:ident = $group:path;
impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
$($cont:tt)*
) => {
$crate::keyword!{$(#[$attribute])* $pub $name = $group}
$crate::unsynn!{
@impl
for $name
{$({$(#[$tattr])* $trait $bracesemi})*}
}
$crate::unsynn!{$($cont)*}
};
($(#[$attribute:meta])* $pub:vis keyword $name:ident = $group:path; $($cont:tt)*) => {
$crate::keyword!{$(#[$attribute])* $pub $name = $group}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis keyword $name:ident != $group:path;
impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
$($cont:tt)*
) => {
$crate::keyword!{$(#[$attribute])* $pub $name != $group}
$crate::unsynn!{
@impl
for $name
{$({$(#[$tattr])* $trait $bracesemi})*}
}
$crate::unsynn!{$($cont)*}
};
($(#[$attribute:meta])* $pub:vis keyword $name:ident != $group:path; $($cont:tt)*) => {
$crate::keyword!{$(#[$attribute])* $pub $name != $group}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis keyword $name:ident = [$($keywords:tt),+ $(,)?];
impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
$($cont:tt)*
) => {
$crate::keyword!{$(#[$attribute])* $pub $name = [$($keywords),+]}
$crate::unsynn!{
@impl
for $name
{$({$(#[$tattr])* $trait $bracesemi})*}
}
$crate::unsynn!{$($cont)*}
};
($(#[$attribute:meta])* $pub:vis keyword $name:ident = [$($keywords:tt),+ $(,)?]; $($cont:tt)*) => {
$crate::keyword!{$(#[$attribute])* $pub $name = [$($keywords),+]}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis keyword $name:ident != [$($keywords:tt),+ $(,)?];
impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
$($cont:tt)*
) => {
$crate::keyword!{$(#[$attribute])* $pub $name != [$($keywords),+]}
$crate::unsynn!{
@impl
for $name
{$({$(#[$tattr])* $trait $bracesemi})*}
}
$crate::unsynn!{$($cont)*}
};
($(#[$attribute:meta])* $pub:vis keyword $name:ident != [$($keywords:tt),+ $(,)?]; $($cont:tt)*) => {
$crate::keyword!{$(#[$attribute])* $pub $name != [$($keywords),+]}
$crate::unsynn!{$($cont)*}
};
(
$(#[$attribute:meta])* $pub:vis operator $name:ident = $str:literal;
impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
$($cont:tt)*
) => {
$crate::operator!{$(#[$attribute])* $pub $name = $str}
$crate::unsynn!{
@impl
for $name
{$({$(#[$tattr])* $trait $bracesemi})*}
}
$crate::unsynn!{$($cont)*}
};
($(#[$attribute:meta])* $pub:vis operator $name:ident = $str:literal; $($cont:tt)*) => {
$crate::operator!{$(#[$attribute])* $pub $name = $str}
$crate::unsynn!{$($cont)*}
};
($(#[$attribute:meta])* $pub:vis predicatetrait $name:ident $(: $super:ident $(+ $supers:ident)*)? ; $($cont:tt)*) => {
$(#[$attribute])* $pub trait $name$(: $super $(+ $supers)*)? : $crate::PredicateOp {}
impl $name for $crate::Enable {}
impl $name for $crate::Disable {}
impl $name for $crate::TokensRemain {}
impl<A: $name, B: $name, C: $name, D: $name> $name for $crate::AllOf<A, B, C, D> {}
impl<A: $name, B: $name, C: $name, D: $name> $name for $crate::AnyOf<A, B, C, D> {}
impl<A: $name, B: $name, C: $name, D: $name> $name for $crate::OneOf<A, B, C, D> {}
impl<T: $name> $name for $crate::Not<T> {}
$crate::unsynn!{$($cont)*}
};
($(#[$attribute:meta])* $pub:vis predicateflag $name:ident = Enable $(for $($trait:ident),+ $(,)?)? ; $($cont:tt)*) => {
$(#[$attribute])*
#[derive(Debug, Clone, Default)]
$pub struct $name($crate::Enable);
impl $crate::Parser for $name {
#[inline]
fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
$crate::Enable::parse(tokens).map($name)
}
}
impl $crate::ToTokens for $name {
#[inline]
fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
self.0.to_tokens(tokens);
}
}
impl $crate::PredicateOp for $name {}
$($(impl $trait for $name {})*)?
$crate::unsynn!{$($cont)*}
};
($(#[$attribute:meta])* $pub:vis predicateflag $name:ident = Disable $(for $($trait:ident),+ $(,)?)? ; $($cont:tt)*) => {
$(#[$attribute])*
#[derive(Debug, Clone)]
$pub struct $name($crate::Disable);
impl $crate::Parser for $name {
#[inline]
fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
$crate::Disable::parse(tokens).map($name)
}
}
impl $crate::ToTokens for $name {
#[inline]
fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
self.0.to_tokens(tokens);
}
}
impl $crate::PredicateOp for $name {}
$($(impl $trait for $name {})*)?
$crate::unsynn!{$($cont)*}
};
($(#[$attribute:meta])* $pub:vis predicateflag $name:ident = TokensRemain $(for $($trait:ident),+ $(,)?)? ; $($cont:tt)*) => {
$(#[$attribute])*
#[derive(Debug, Clone, Default)]
$pub struct $name($crate::TokensRemain);
impl $crate::Parser for $name {
#[inline]
fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
$crate::TokensRemain::parse(tokens).map($name)
}
}
impl $crate::ToTokens for $name {
#[inline]
fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
self.0.to_tokens(tokens);
}
}
impl $crate::PredicateOp for $name {}
$($(impl $trait for $name {})*)?
$crate::unsynn!{$($cont)*}
};
($(#[$attribute:meta])* $pub:vis predicateflag $name:ident $(for $($trait:ident),+ $(,)?)? ; $($cont:tt)*) => {
$(#[$attribute])*
#[derive(Debug, Clone, Default)]
$pub struct $name($crate::Enable);
impl $crate::Parser for $name {
#[inline]
fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
$crate::Enable::parse(tokens).map($name)
}
}
impl $crate::ToTokens for $name {
#[inline]
fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
self.0.to_tokens(tokens);
}
}
impl $crate::PredicateOp for $name {}
$($(impl $trait for $name {})*)?
$crate::unsynn!{$($cont)*}
};
() => {};
(
@impl$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)?),*>)?
for $name:ident
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?
{{$(#[$tattr:meta])* $trait:ident ;} $($cont:tt)*}
) => {
$(#[$tattr])*
impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $trait
for $name$(<$($generic),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{}
$crate::unsynn!{
@impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
for $name
{$($cont)*}
}
};
(
@impl$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)?),*>)?
for $name:ident
$(where
$($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?
{{$(#[$tattr:meta])* $trait:ident {$($body:tt)*}} $($cont:tt)*}
) => {
$(#[$tattr])*
impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $trait
for $name$(<$($generic),*>)?
$(where
$($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
{$($body)*}
$crate::unsynn!{
@impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
for $name
{$($cont)*}
}
};
(
@impl$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)?),*>)?
for $name:ident {}
) => {};
(
@enum_to_tokens($self:ident, $tokens:ident)
{
$(#[$_attrs:meta])* $variant:ident($($tuple:tt)*) $(,$($cont:tt)*)?
}
) => {
if matches!($self, Self::$variant(..)) {
unsynn! {@tuple_for_each item in $self : Self::$variant($($tuple)*) {
item.to_tokens($tokens);
}}
return
}
$crate::unsynn!{@enum_to_tokens($self, $tokens) {$($($cont)*)?}}
};
(
@enum_to_tokens($self:ident, $tokens:ident)
{
$(#[$_attrs:meta])* $variant:ident {
$($(#[$_mattrs:meta])* $member:ident: $_type:ty),* $(,)?
}
$(,$($cont:tt)*)?
}
) => {
if matches!($self, Self::$variant{..}) {
$(
let Self::$variant{$member: member, ..} = $self else {unreachable!()};
member.to_tokens($tokens);
)*
return
}
$crate::unsynn!{@enum_to_tokens($self, $tokens) {$($($cont)*)?}}
};
(
@enum_to_tokens($self:ident, $tokens:ident)
{
$(#[$_attrs:meta])* $variant:ident
$(,$($cont:tt)*)?
}
) => {
if matches!($self, Self::$variant) {
return
}
$crate::unsynn!{@enum_to_tokens($self, $tokens) {$($($cont)*)?}}
};
(@enum_to_tokens($self:ident, $tokens:ident) {}) => {};
(
@enum_write($self:ident, $f:ident)
{
$(#[$_attrs:meta])* $variant:ident($($tuple:tt)*) $(,$($cont:tt)*)?
}
) => {
if matches!($self, Self::$variant(..)) {
unsynn! {@tuple_for_each item in $self : Self::$variant($($tuple)*) {
write!($f, "{} " , &item)?;
}}
}
$crate::unsynn!{@enum_write($self, $f) {$($($cont)*)?}}
};
(@enum_write($self:ident, $f:ident) {
$(#[$_attrs:meta])* $variant:ident {
$($(#[$_mattrs:meta])* $member:ident: $_type:ty),* $(,)?
} $(,$($cont:tt)*)?} ) => {
if matches!($self, Self::$variant{..}) {
$(
let Self::$variant{$member: that, ..} = $self else {unreachable!()};
write!($f, "{} ", that)?;
)*
}
$crate::unsynn!{@enum_write($self, $f) {$($($cont)*)?}}
};
(
@enum_write($self:ident, $f:ident)
{
$(#[$_attrs:meta])* $variant:ident $(,$($cont:tt)*)?
}
) => {
if matches!($self, Self::$variant) {
}
$crate::unsynn!{@enum_write($self, $f) {$($($cont)*)?}}
};
(@enum_write($self:ident, $f:ident) {}) => {};
(
@enum_parse_variant($tokens:ident, $err:ident)
$(#[$_attrs:meta])* $variant:ident($($tuple:tt)*)
$(, $($cont:tt)*)?
) => {
if let Ok(parsed) = (|| -> $crate::Result<_> {
$err.upgrade($crate::unsynn!{@enum_parse_tuple($tokens) $variant($($tuple)*)})
})() {
return Ok(parsed);
}
$crate::unsynn!{@enum_parse_variant($tokens, $err) $($($cont)*)?}
};
(
@enum_parse_variant($tokens:ident, $err:ident)
$(#[$_attrs:meta])*
$variant:ident{$($members:tt)*}
$(, $($cont:tt)*)?
) => {
if let Ok(parsed) = (|| -> $crate::Result<_> {
$err.upgrade($crate::unsynn!{@enum_parse_struct($tokens) $variant{$($members)*}})
})() {
return Ok(parsed);
}
$crate::unsynn!{@enum_parse_variant($tokens, $err) $($($cont)*)?}
};
(
@enum_parse_variant($tokens:ident, $err:ident)
$(#[$_attrs:meta])* $variant:ident
$(, $($cont:tt)*)?
) => {
$crate::unsynn!{@enum_parse_variant($tokens, $err) $($($cont)*)?}
};
(@enum_parse_variant($tokens:ident, $err:ident)) => {};
(
@enum_parse_tuple($tokens:ident)
$variant:ident($($(#[$_attrs:meta])* $parser:ty),* $(,)?)
) => {
$crate::Transaction::transaction($tokens,
|tokens| Ok(Self::$variant($(<$parser as $crate::Parse>::parse(tokens)?,)*))
)
};
(
@enum_parse_struct($tokens:ident)
$variant:ident{$($(#[$_attrs:meta])* $name:ident : $parser:ty),* $(,)?}
) => {
$crate::Transaction::transaction($tokens,
|tokens| Ok(Self::$variant{$($name : <$parser as $crate::Parse>::parse(tokens)?,)*})
)
};
(
@tuple_for_each
$i:ident in $this:ident :
$($variant:ident)::*($($tuple:tt)*)
{
$($code:tt)*
}
) => {
{
$crate::unsynn!{@tuple_for_each $i in $this : $($variant)::*[$($tuple)*] { $($code)* }}
}
};
(
@tuple_for_each
$i:ident in $this:ident :
$($variant:ident)::*[
$(#[$_attrs:meta])* $_pub:vis $element:ty
$(,$($rest:tt)*)?
]{
$($code:tt)*
}
) => {
$crate::unsynn!{@tuple_for_each $i in $this : $($variant)::*[$($($rest)*)?] { $($code)* }}
#[allow(irrefutable_let_patterns)]
let $crate::unsynn!{@tuple_nth $i $($variant)::*[$($($rest)*)?]} = $this else {unreachable!()};
$($code)*
};
(@tuple_for_each $i:ident in $_this:ident : $($variant:ident)::*[] { $($code:tt)* }) => {};
(@tuple_nth $i:ident $($variant:ident)::*[$($(#[$_attrs:meta])* $_pub:vis $_element:ty),* $(,)?]) => {
$($variant)::*(
$($crate::unsynn!(@_ $_element),)*
$i,
..
)
};
(@_ $_tt:tt) => {_};
($unexpected:tt $($rest:tt)*) => {
compile_error!(concat!(
"Unexpected token in unsynn! macro: '",
stringify!($unexpected),
"'\n\nExpected one of:\n",
" - struct definition: struct Name { field: Type }\n",
" - tuple struct: struct Name(Type);\n",
" - enum: enum Name { Variant }\n",
" - trait: trait Name;\n",
" - impl block: impl Type { ... } or impl Trait for Type { ... }\n",
" - function: fn name(params) { body }\n",
" - type alias: type Name = Path;\n",
" - use statement: use path;\n",
" - macro_rules! definition\n",
" - keyword/operator definition\n\n",
"Check for:\n",
" - Missing semicolons\n",
" - Mismatched braces\n",
" - Invalid syntax in struct/enum definitions"
));
};
}
#[cfg(doc)]
#[macro_export]
macro_rules! keyword {
($name:ident = $str:literal; ...) => {};
($name:ident = $group:path; ...) => {};
($name:ident = [$($keywords:tt),+]; ...) => {};
($name:ident != $str:literal; ...) => {};
($name:ident != $group:path; ...) => {};
($name:ident != [$($keywords:tt),+]; ...) => {};
}
#[doc(hidden)]
#[cfg(not(doc))]
#[macro_export]
macro_rules! keyword{
($(#[$attribute:meta])* $pub:vis $name:ident = $str:literal $(;$($cont:tt)*)?) => {
$crate::keyword!{
@{} $(#[$attribute])* $pub $name [$str]
}
$crate::keyword!{
@default $name $str
}
$crate::keyword!{$($($cont)*)?}
};
($(#[$attribute:meta])* $pub:vis $name:ident != $str:literal $(;$($cont:tt)*)?) => {
$crate::keyword!{
@{!} $(#[$attribute])* $pub $name [$str]
}
$crate::keyword!{$($($cont)*)?}
};
($(#[$attribute:meta])* $pub:vis $name:ident = $group:path $(;$($cont:tt)*)?) => {
$crate::keyword!{
@{} $(#[$attribute])* $pub $name [$group]
}
$crate::keyword!{$($($cont)*)?}
};
($(#[$attribute:meta])* $pub:vis $name:ident != $group:path $(;$($cont:tt)*)?) => {
$crate::keyword!{
@{!} $(#[$attribute])* $pub $name [$group]
}
$crate::keyword!{$($($cont)*)?}
};
(
$(#[$attribute:meta])*
$pub:vis $name:ident = [$($keywords:tt),+ $(,)?]
$(;$($cont:tt)*)?
) => {
$crate::keyword!{
@{} $(#[$attribute])* $pub $name [$($keywords),+]
}
$crate::keyword!{$($($cont)*)?}
};
(
$(#[$attribute:meta])*
$pub:vis $name:ident != [$($keywords:tt),+ $(,)?]
$(;$($cont:tt)*)?
) => {
$crate::keyword!{
@{!} $(#[$attribute])* $pub $name [$($keywords),+]
}
$crate::keyword!{$($($cont)*)?}
};
(
@{$($not:tt)?} $(#[$attribute:meta])*
$pub:vis $name:ident [$($keywords:tt),+]
$(;$($cont:tt)*)?
) => {
$(#[$attribute])*
#[doc = concat!(
$crate::docgen!{@keyword_header $($not)?},
$($crate::docgen!{@keyword_doc $keywords}),+
)]
#[derive(Debug, Clone, PartialEq, Eq)]
$pub struct $name($crate::CachedIdent);
impl $crate::Parser for $name {
fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
use $crate::{Parse, RefineErr};
let at = tokens.clone().next();
$crate::CachedIdent::parse_with(tokens, |ident, tokens| {
if $($not)? Self::matches(ident.as_str()) {
Ok($name(ident))
} else {
$crate::Error::other::<$name>(
at,
tokens,
format!(
"keyword for {:?} expected, got {:?} at {:?}",
stringify!($name),
ident.as_str(),
ident.span().start()
),
)
}
}).refine_err::<Self>()
}
}
impl $crate::ToTokens for $name {
fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
self.0.to_tokens(tokens);
}
}
impl AsRef<str> for $name {
fn as_ref(&self) -> &str {
self.0.as_str()
}
}
impl AsRef<$crate::Ident> for $name {
fn as_ref(&self) -> &$crate::Ident {
&*self.0
}
}
impl $name {
#[allow(dead_code)]
pub fn as_str(&self) -> &str {
self.0.as_str()
}
#[doc(hidden)]
#[inline]
pub const fn keywords() -> &'static $crate::KeywordGroup {
static KEYWORDS: $crate::KeywordGroup = $crate::keyword! {@group $($keywords),+};
&KEYWORDS
}
fn matches(this: &str) -> bool {
static MATCHFN: std::sync::LazyLock<Box<dyn Fn(&str) -> bool + Send + Sync>> =
std::sync::LazyLock::new(|| $crate::create_matchfn($name::keywords()));
MATCHFN(this)
}
}
$crate::keyword!{$($($cont)*)?}
};
() => {};
(@default $name:ident $str:literal) => {
impl Default for $name {
fn default() -> Self {
use $crate::{ToTokens, Parse};
Self($crate::CachedIdent::parse(&mut $str.to_token_iter()).unwrap())
}
}
};
(@group $($entry:tt),+) => {
$crate::KeywordGroup::List(
&[$(&$crate::keyword!{@entry $entry}),+]
)
};
(@entry $kw:literal) => {
$crate::KeywordGroup::Keyword($kw)
};
(@entry $sub:path) => {
*<$sub>::keywords()
};
}
#[macro_export]
macro_rules! operator{
($($(#[$attribute:meta])* $pub:vis $name:ident = $op:literal);*$(;)?) => {
$(
$crate::operator!(@operator $(#[$attribute])* $pub $name = $op);
)*
};
(@operator $(#[$attribute:meta])* $pub:vis $name:ident = $op:literal) => {
$(#[$attribute])*
#[doc = $crate::docgen!{@operator_doc $op}]
$pub type $name = $crate::Operator<
{
assert!(
$op.len() >= 1 && $op.len() <= 4,
"Operators must be 1-4 ASCII punctuation characters"
);
let c0 = $crate::operator!(@char_at 0 $op);
assert!(c0.is_ascii_punctuation(), "Operator must be ASCII punctuation");
c0
},
{
let c1 = $crate::operator!(@char_at 1 $op);
assert!(c1 == '\0' || c1.is_ascii_punctuation(), "Operator must be ASCII punctuation");
c1
},
{
let c2 = $crate::operator!(@char_at 2 $op);
assert!(c2 == '\0' || c2.is_ascii_punctuation(), "Operator must be ASCII punctuation");
c2
},
{
let c3 = $crate::operator!(@char_at 3 $op);
assert!(c3 == '\0' || c3.is_ascii_punctuation(), "Operator must be ASCII punctuation");
c3
},
>;
};
(@char_at $at:literal $op:literal) => {
const {
concat!($op, "\0\0\0").as_bytes()[$at] as char
}
}
}
#[cfg(not(feature = "docgen"))]
#[doc(hidden)]
#[macro_export]
macro_rules! docgen {
($($_:tt)*) => {
""
};
}
#[cfg(feature = "docgen")]
#[doc(hidden)]
#[macro_export]
macro_rules! docgen {
(@keyword_header) => {
"Matches: "
};
(@keyword_header !) => {
"Matches any `Ident` but: "
};
(@keyword_doc $kw:literal) => {
concat!("`", $kw, "`, ")
};
(@keyword_doc $sub:path) => {
concat!("[`", stringify!($sub), "`], ")
};
(@operator_doc $op:literal) => {
concat!("`", $op, "`")
};
}
#[macro_export]
macro_rules! quote {
($($tokens:tt)*) => {
{
let mut tokenstream = $crate::TokenStream::new();
$crate::quote_intern!{tokenstream $($tokens)*};
tokenstream
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! quote_intern {
($tokenstream:ident #$var:ident $($rest:tt)*) => {
$var.to_tokens(&mut $tokenstream);
$crate::quote_intern!{$tokenstream $($rest)*}
};
($tokenstream:ident #{$($code:tt)*} $($rest:tt)*) => {
{$($code)*}.into_iter().for_each(|i| i.to_tokens(&mut $tokenstream));
$crate::quote_intern!{$tokenstream $($rest)*}
};
($tokenstream:ident #($($reserved:tt)*) $($rest:tt)*) => {
compile_error!("#(...) reserved for future")
};
($tokenstream:ident ( $($nested:tt)* ) $($rest:tt)*) => {
$tokenstream.extend(
Some(
$crate::TokenTree::Group(
$crate::Group::new($crate::Delimiter::Parenthesis, $crate::quote!{$($nested)*})
)
).into_iter()
);
$crate::quote_intern!{$tokenstream $($rest)*}
};
($tokenstream:ident { $($nested:tt)* } $($rest:tt)*) => {
$tokenstream.extend(
Some(
$crate::TokenTree::Group(
$crate::Group::new($crate::Delimiter::Brace, $crate::quote!{$($nested)*})
)
).into_iter()
);
$crate::quote_intern!{$tokenstream $($rest)*}
};
($tokenstream:ident [ $($nested:tt)* ] $($rest:tt)*) => {
$tokenstream.extend(
Some(
$crate::TokenTree::Group(
$crate::Group::new($crate::Delimiter::Bracket, $crate::quote!{$($nested)*})
)
).into_iter()
);
$crate::quote_intern!{$tokenstream $($rest)*}
};
($tokenstream:ident $token:tt $($rest:tt)*) => {
let t: $crate::TokenStream = std::str::FromStr::from_str(stringify!($token)).unwrap();
$tokenstream.extend(Some(t).into_iter());
$crate::quote_intern!{$tokenstream $($rest)*}
};
($tokenstream:ident) => {};
}