unsynn/
macros.rs

1//! This module contains the big macros and helper functions to define and parse custom types.
2//!
3//! **Note**: When the `proc_macro2` feature is disabled, format macros (`format_ident!`,
4//! `format_literal!`, `format_literal_string!`) are not available.
5
6#[cfg(doc)]
7use crate::*;
8
9/// This macro supports the definition of enums, tuple structs and normal structs and
10/// generates [`Parser`] and [`ToTokens`] implementations for them. It will derive `Debug`.
11/// Generics/Lifetimes are not supported on the primary type.  Note: eventually a derive macro
12/// for `Parser` and `ToTokens` will become supported by a 'unsynn-derive' crate to give finer
13/// control over the expansion. `#[derive(Copy, Clone)]` have to be manually defined. Keyword
14/// and operator definitions can also be defined, they delegate to the `keyword!` and
15/// `operator!` macro described below. All entities can be prefixed by `pub` to make them
16/// public. Type aliases, function definitions, macros and use statements are passed through. This
17/// makes thing easier readable when you define larger unsynn macro blocks.
18///
19/// The macro definition above is simplified for readability `struct`, `enum` and `type`
20/// definitions can include most of the things normal rust definitions can do. This also
21/// includes definitions of members of structs and enums:
22///
23/// * Any number of attributes (`#[...]`), including documentation comments. Note that the
24///   unsynn macros have limited support for automatically generation documentation. This
25///   auto-generated documentation is appended after the user supplied docs.
26/// * structs, enums, types and members can exported with the usual `pub` declarations.
27/// * struct, enum, and type definitions support generics and lifetime parameters. These can include
28///   trait bounds (simple identifiers, qualified paths like `std::fmt::Debug`, and lifetime bounds
29///   like `'static`) and defaults. Multiple bounds can be combined with `+`. Trait bounds can be
30///   defined with where-clauses as well. Lifetime parameters (e.g., `<'a>`, `<'a, T>`) are fully
31///   supported for structs. Enums and tuple structs support lifetime parameters except when combined
32///   with inline `impl` blocks. HRTB (Higher-Ranked Trait Bounds) are not yet supported.
33///   See the [COOKBOOK](https://docs.rs/unsynn/latest/unsynn/#generic-types-with-trait-bounds)
34///   for examples.
35///
36/// Common for enum and struct variants is that entries are tried in order. Disjunctive for
37/// enums and conjunctive in structures. This makes the order important, e.g. for enums, in
38/// case some entries are subsets of others.
39///
40/// Enum variants without any data will never be parsed and will not generate any tokens. For
41/// *parsing* a enum that is optional one can add a variant like `None(Nothing)` at the end
42/// (at the end is important, because Nothing always matches).
43///
44/// The `unsynn!{}` macro is still a declarative macro and is somewhat limited in what it can
45/// do. We extend it as needed and provide some convenient rust syntax extensions, but some
46/// standard rust syntax is just hard to impossible to support.
47///
48///
49/// ## Example
50///
51/// ```
52/// # use unsynn::*;
53/// // Define some types
54/// unsynn!{
55///     keyword MyKeyword = "keyword";
56///     // all items can be declared pub/pub(..) etc
57///     pub(crate) operator MyOperator = "+++";
58///
59///     enum MyEnum {
60///         /// Entries can have attributes/doc comments
61///         Ident(Ident),
62/// #       TupleWithDocs(
63/// #           /// fooo
64/// #           Ident,
65/// #           /// bar
66/// #           Optional<Ident>
67/// #       ),
68///         Braced(BraceGroup),
69///         Text(LiteralString),
70///         Number(LiteralInteger),
71/// #       TrailingComma(LiteralInteger, Ident,),
72///         Struct{
73///             keyword: MyKeyword,
74///             id: Ident,
75///         },
76///         // finally if nothing of the above matched, this will match.
77///         None(Nothing),
78///         // won't be parsed/matched at all
79///         Empty,
80///     }
81///
82///     // With generics - qualified paths work, no need to import
83///     struct MyStruct<T: std::fmt::Debug = i32> {
84///         text: LiteralString,
85///         number: T,
86///     }
87///
88///     // Multiple bounds with lifetime bound
89///     struct GenericContainer<T: Clone + std::fmt::Display + 'static> {
90///         value: T,
91///     }
92///
93///     struct MyTupleStruct(Ident, LiteralString);
94///
95///     // Lifetime parameters are also supported:
96///     //struct WithLifetime<'a> { /* ... */ }
97///     //struct MixedParams<'a, T> { /* ... */ }
98///
99///     // type definitions are pass-through.
100///     pub type Alias = MyStruct<LiteralInteger>;
101///
102///     // functions are pass though too
103///     fn testfn() -> bool { true }
104/// }
105///
106/// // Create an iterator over the things we want to parse
107/// let mut token_iter = r#"
108///     // some enum variants
109///     ident { within brace } "literal string" 1234 ()
110///     // MyStruct fields
111///     "literal string" 1234
112///     // MyTupleStruct fields
113///     ident "literal string"
114///     // MyKeyword and MyOperator
115///     keyword +++
116/// "#.to_token_iter();
117///
118/// // Use the defined types
119/// let MyEnum::Ident(myenum_ident) = MyEnum::parse(&mut token_iter).unwrap() else { panic!()};
120/// # assert_tokens_eq!(myenum_ident, "ident");
121/// let MyEnum::Braced(myenum_braced) = MyEnum::parse(&mut token_iter).unwrap() else { panic!()};
122/// # assert_tokens_eq!(myenum_braced, "{within brace}");
123/// let MyEnum::Text(myenum_text) = MyEnum::parse(&mut token_iter).unwrap() else { panic!()};
124/// # assert_tokens_eq!(myenum_text, "\"literal string\"");
125/// let MyEnum::Number(myenum_number) = MyEnum::parse(&mut token_iter).unwrap() else { panic!()};
126/// # assert_tokens_eq!(myenum_number, "1234");
127/// // the () will not be consumed by the MyEnum but match None(Nothing)
128/// let myenum_nothing = MyEnum::parse(&mut token_iter).unwrap();
129/// # assert_tokens_eq!(myenum_nothing, "");
130/// // consume the ()
131/// <ParenthesisGroup>::parse(&mut token_iter).unwrap();
132///
133/// let my_struct =  Alias::parse(&mut token_iter).unwrap();
134/// let my_tuple_struct =  MyTupleStruct::parse(&mut token_iter).unwrap();
135/// let my_keyword =  MyKeyword::parse(&mut token_iter).unwrap();
136/// let my_operator =  MyOperator::parse(&mut token_iter).unwrap();
137/// # assert!(testfn());
138/// ```
139///
140///
141/// # Traits within the `unsynn!` macro ***(EXPERIMENTAL)***
142///
143/// The `unsynn!` macro has limited but ergonomic support for defining and implementing
144/// traits. The main purpose for this is to be able to define simple markers and accessors
145/// this helps with compile-time validation of grammars.
146///
147/// Trait definitions are passed though. There are simplifications that they are allowed to
148/// end with a `;` instead a `{}`. This signifies simple marker traits that have no
149/// methods. The form `trait {Name; ...}` is supported to define a set of simple markers
150/// in one go. This syntax not support traits with methods.
151///
152/// Trait implementations are either passed through or are a `impl {}` block directly
153/// following an ADT definition. In the later case most boilerplate is left out and will be
154/// auto generated by the macro.
155///
156/// ## Generic Types and Trait Bounds
157///
158/// Generic type parameters and lifetime parameters are fully supported:
159/// - **Lifetime parameters**: `<'a>`, `<'a, 'b>`, or mixed `<'a, T>`
160/// - **Simple trait names**: `T: Clone`
161/// - **Qualified paths**: `T: std::fmt::Debug` (no need to import the trait)
162/// - **Lifetime bounds**: `T: 'static` (can appear anywhere in the bound list)
163/// - **Multiple bounds**: `T: Clone + std::fmt::Debug + 'static` (any combination)
164/// - **Where clauses**: Support the same bound syntax as inline bounds
165///
166/// **Examples**:
167/// ```ignore
168/// struct WithLifetime<'a> { /* ... */ }
169/// struct MultipleLifetimes<'a, 'b> { /* ... */ }
170/// struct MixedParams<'a, T: Clone> { /* ... */ }
171/// ```
172///
173/// **Limitations**:
174/// - Generic type arguments in bounds (e.g., `T: Trait<U>`) are not supported
175/// - HRTB (Higher-Ranked Trait Bounds like `for<'a>`) are not yet supported
176/// - Lifetime parameters on tuple structs and enums with inline `impl` blocks are not supported
177///   (use separate `impl` blocks outside the macro instead)
178///
179/// See the [COOKBOOK](https://docs.rs/unsynn/latest/unsynn/#generic-types-with-trait-bounds)
180/// for detailed examples and patterns.
181///
182/// Trait support is very basic and experimental, it is unspecified what features are supported.
183/// Try it out, we promise not to break working things (if possible). For trait definitions that
184/// are not supported within the unsynn macro it is still possible and advised to define them
185/// outside of the macro block.
186///
187///
188/// ## Example
189///
190/// ```
191/// # use unsynn::*;
192/// unsynn!{
193///     // Marker traits can be defined in a block
194///     // with attributes and visibility at the whole block
195///     #[doc = "This is a marker trait"] // applies to each item
196///     pub trait {
197///         TestMarker;
198///         TestMarker2;
199///     }
200///     // or per item
201///     trait {
202///         pub MarkerPub;
203///         MarkerPrivate;
204///     }
205///
206///     // ending with a semicolon, supertraits are supported
207///     trait TestMarker3: TestMarker + TestMarker2;
208///     // or a brace
209///     trait TestMarker4 {}
210///
211///     // Normal rust syntax for accessor methods
212///     trait SimpleAccessor { fn get(&self) -> bool;}
213///
214///     // simplified trait impl block following the struct definition
215///     pub struct SimpleStruct{
216///         flag: bool
217///     } impl {
218///         #[doc = "impl attributes go here"]
219///         TestMarker;
220///         TestMarker2 {}
221///         SimpleAccessor {fn get(&self) -> bool {self.flag}}
222///     }
223///
224///     // Marker traits or traits that have blanket implementations can
225///     // be implemented by a comma separated list
226///     impl TestMarker for i32, u32, i64, u64;
227///
228///     // normal rust syntax, passthough trait impl
229///     impl SimpleAccessor for bool {fn get(&self) -> bool {*self}}
230/// }
231///
232/// // implementing traits outside of the macro works as usual
233/// impl TestMarker4 for SimpleStruct {}
234/// ```
235///
236///
237/// # Extended Syntax Forms
238///
239/// The `unsynn!` macro extends standard Rust syntax with these conveniences:
240///
241/// ## Semicolon Terminators
242///
243/// Traits and tuple structs can end with `;` instead of `{}`:
244/// ```rust
245/// # use unsynn::*;
246/// unsynn! {
247///     trait MyMarker;  // Instead of: trait MyMarker {}
248///     struct MyTuple(Ident);  // Semicolon instead of no punctuation
249/// }
250/// ```
251///
252/// ## Trait Blocks
253///
254/// Define multiple marker traits at once using `trait { Name1; Name2; }`:
255/// ```rust
256/// # use unsynn::*;
257/// unsynn! {
258///     trait {
259///         MarkerA;
260///         MarkerB;
261///         MarkerC;
262///     }
263/// }
264/// ```
265///
266/// ## Inline Impl Blocks
267///
268/// Apply traits directly after struct/enum definitions with `impl { Trait; }`:
269/// ```rust
270/// # use unsynn::*;
271/// unsynn! {
272/// #   trait { Marker; }
273///     // Semicolon is optional before impl
274///     struct MyStruct(Ident) impl { Marker; }
275///     // Or with semicolon (both work)
276///     struct OtherStruct(Ident); impl { Marker; }
277/// }
278/// ```
279///
280/// ## Multi-Type Impl
281///
282/// Implement traits for multiple types with `impl Trait for Type1, Type2, Type3;`:
283/// ```rust
284/// # use unsynn::*;
285/// unsynn! {
286///     trait MyTrait;
287///     impl MyTrait for Ident, LiteralInteger, TokenTree;
288/// }
289/// ```
290///
291/// ## Custom Parsing with `parse_with`
292///
293/// Transform or validate parsed values using closure syntax. See [`Parse::parse_with()`] for the
294/// underlying method this uses.
295///
296/// **Validation** (without `from`): Verify parsed value meets requirements
297/// ```rust
298/// # use unsynn::*;
299/// unsynn! {
300///     // Only accept positive integers
301///     struct PositiveInt(LiteralInteger);
302///     parse_with |this, tokens| {
303///         if this.0.value() > 0 {
304///             Ok(this)
305///         } else {
306///             Error::other(None, tokens, "must be positive".into())
307///         }
308///     };
309/// }
310/// ```
311///
312/// **Transformation** (with `from Type:`): Parse as one type, transform to another
313/// ```rust
314/// # use unsynn::*;
315/// unsynn! {
316///     // Parse integer as bool (0 = false, non-zero = true)
317///     struct BoolInt(bool) from LiteralInteger:
318///     parse_with |value, _tokens| {
319///         Ok(Self(value.value() != 0))
320///     };
321/// }
322/// ```
323///
324/// The closure receives:
325/// - `value` - The parsed value (type after `from`, or `Self` without `from`)
326/// - `tokens` - Reference to [`TokenIter`] for error reporting
327///
328/// Returns: `Result<Self>` where errors use [`Error`] type
329///
330/// ## Custom Token Emission with `to_tokens`
331///
332/// Customize how types are emitted back to tokens. See [`ToTokens::to_tokens()`] for the trait
333/// method this implements.
334///
335/// ```rust
336/// # use unsynn::*;
337/// unsynn! {
338///     // Emit booleans as custom keywords
339///     struct BoolKeyword(bool);
340///     to_tokens |s, tokens| {
341///         if s.0 {
342///             Ident::new("TRUE", Span::call_site()).to_tokens(tokens);
343///         } else {
344///             Ident::new("FALSE", Span::call_site()).to_tokens(tokens);
345///         }
346///     };
347/// }
348/// ```
349///
350/// The closure receives:
351/// - `self` - Reference to the value being emitted
352/// - `tokens` - Mutable reference to [`TokenStream`] to append to
353///
354/// ## Combining `parse_with` and `to_tokens`
355///
356/// Both clauses are independent and can be used together:
357/// ```rust
358/// # use unsynn::*;
359/// unsynn! {
360///     // Parse int as bool, emit bool as int
361///     struct BoolInt(bool) from LiteralInteger:
362///     parse_with |value, _tokens| { Ok(Self(value.value() != 0)) }
363///     to_tokens |s, tokens| {
364///         Literal::u64_unsuffixed(if s.0 {1} else {0}).to_tokens(tokens);
365///     };
366/// }
367/// ```
368///
369/// **Clause Order**: For tuple structs: `struct Name(Fields) [from Type:] [parse_with ...] [to_tokens ...] [impl {...}];`
370///
371/// The `parse_with` and `to_tokens` clauses are independent and optional. The `from` clause requires `parse_with`. Impl blocks always come last.
372///
373/// See the [COOKBOOK](crate#custom-parsing-and-totokens-with-unsynn) for more examples and patterns.
374///
375///
376/// ## Keywords and Operators
377///
378/// Define custom keywords and operators within the macro. See also the standalone [`keyword!`]
379/// and [`operator!`] macros.
380///
381/// **Keywords**: Match specific identifier strings
382/// ```rust
383/// # use unsynn::*;
384/// unsynn! {
385///     keyword If = "if";
386///     keyword While = "while";
387///     keyword Function = "fn";
388/// }
389/// ```
390///
391/// **Operators**: Match specific punctuation sequences
392/// ```rust
393/// # use unsynn::*;
394/// unsynn! {
395///     operator Plus = "+";
396///     operator Arrow = "->";
397///     operator DoubleColon = "::";
398/// }
399/// ```
400///
401/// See [`operator::names`](crate::operator::names) for a comprehensive list of predefined operators.
402///
403/// # Parse Predicates
404///
405/// Parse predicates provide zero-cost compile-time control over parser behavior using type-level
406/// constraints. The `unsynn!` macro supports two special forms for defining predicates:
407///
408/// - **`predicatetrait`**: Defines custom context traits that extend [`PredicateOp`], automatically
409///   implementing them for universal predicates ([`Enable`], [`Disable`], [`TokensRemain`]) and
410///   logical operators ([`AllOf`], [`AnyOf`], [`OneOf`], [`Not`]).
411///
412/// - **`predicateflag`**: Creates zero-sized newtype wrappers around base predicates that implement
413///   custom traits, enabling type-safe context validation at compile time.
414///
415/// **Example**:
416/// ```
417/// # use unsynn::*;
418/// unsynn! {
419///     // Define context traits
420///     predicatetrait ExpressionContext;
421///     predicatetrait StatementContext;
422///     
423///     // Create context-specific predicates
424///     predicateflag InExpression = Enable for ExpressionContext;
425///     predicateflag InStatement = Disable for ExpressionContext;
426///     
427///     // Use predicates as type constraints
428///     pub struct StructLiteral<P: ExpressionContext = InExpression> {
429///         _guard: P,  // Zero-sized, no runtime cost
430///         name: Ident,
431///     }
432/// }
433/// ```
434///
435/// See the [COOKBOOK Parse Predicates section](https://docs.rs/unsynn/latest/unsynn/#parse-predicates)
436/// and the [`predicates`] module for detailed examples and API reference.
437#[cfg(doc)]
438#[macro_export]
439macro_rules! unsynn {
440    (enum $name:ident { $($variant:ident),* }) => {};
441    (struct $name:ident { $($member:ident: $parser:ty),* }) => {};
442    (struct $name:ident ( $($parser:ty),*);) => {};
443    (trait $name:ident;) => {};
444    (trait $name:ident{}) => {};
445    (impl { $($trait:ident $semicolon_or_block:tt)+ }) => {};
446    (impl $trait:ident for $type:ty {$body:tt}) => {};
447    (impl $trait:ident for $($type:ty),+;) => {};
448    (fn $function:ident($params:tt) {$body:tt}) => {};
449    (use $($path:path)+ $(as $alias:ident)?) => {};
450    (keyword $name:ident = keyword_or_group;) => {};
451    (keyword $name:ident != keyword_or_group;) => {};
452    (operator $name:ident = "punct";) => {};
453    (predicatetrait $name:ident $(: $super:ident $(+ $supers:ident)*)?;) => {};
454    (predicateflag $name:ident = Enable $(for $($trait:ident),+)?;) => {};
455    (predicateflag $name:ident = Disable $(for $($trait:ident),+)?;) => {};
456    (predicateflag $name:ident = TokensRemain $(for $($trait:ident),+)?;) => {};
457    (predicateflag $name:ident $(for $($trait:ident),+)?;) => {};
458}
459
460#[doc(hidden)]
461#[cfg(not(doc))]
462#[macro_export]
463macro_rules! unsynn{
464    // Lifetime parameter patterns for enums - MUST come before generic patterns
465    (
466        $(#[$attribute:meta])* $pub:vis enum $name:ident
467        <$lifetime:lifetime $(, $($param:tt),*)? $(,)?>
468        {
469            $($variants:tt)*
470        }
471        impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
472        $($cont:tt)*
473    ) => {
474        $crate::unsynn!{
475            @enum_lifetime
476            $(#[$attribute])* $pub enum $name
477            <$lifetime $(, $($param),*)?>
478            {
479                $($variants)*
480            }
481        }
482        $crate::unsynn!{
483            @impl
484            for $name
485            {$({$(#[$tattr])* $trait $bracesemi})*}
486        }
487        $crate::unsynn!{$($cont)*}
488    };
489    (
490        $(#[$attribute:meta])* $pub:vis enum $name:ident
491        <$lifetime:lifetime $(, $($param:tt),*)? $(,)?>
492        {
493            $($variants:tt)*
494        }
495        $($cont:tt)*
496    ) => {
497        $crate::unsynn!{
498            @enum_lifetime
499            $(#[$attribute])* $pub enum $name
500            <$lifetime $(, $($param),*)?>
501            {
502                $($variants)*
503            }
504        }
505        $crate::unsynn!{$($cont)*}
506    };
507
508    // enums
509    (
510        $(#[$attribute:meta])* $pub:vis enum $name:ident
511        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
512        $(where
513            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?
514        {
515            $($variants:tt)*
516        }
517        // PLANNED: impl$(<extragenerics: bounds>)* Trait$(<extra>)
518        impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
519        $($cont:tt)*
520    ) => {
521        $crate::unsynn!{
522            @enum
523            $(#[$attribute])* $pub enum $name
524            $(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
525            $(where
526                $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
527            {
528                $($variants)*
529            }
530        }
531        $crate::unsynn!{
532            @impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
533            for $name
534            $(where
535                $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
536            {$({$(#[$tattr])* $trait $bracesemi})*}
537        }
538        // next item
539        $crate::unsynn!{$($cont)*}
540    };
541    (
542        $(#[$attribute:meta])* $pub:vis enum $name:ident
543        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
544        $(where
545            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?
546        {
547            $($variants:tt)*
548        }
549        $($cont:tt)*
550    ) => {
551        $crate::unsynn!{
552            @enum
553            $(#[$attribute])* $pub enum $name
554            $(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
555            $(where
556                $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
557            {
558                $($variants)*
559            }
560        }
561        // next item
562        $crate::unsynn!{$($cont)*}
563    };
564    (
565        @enum
566        $(#[$attribute:meta])* $pub:vis enum $name:ident
567        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
568        $(where
569            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?
570        {
571            $($variants:tt)*
572        }
573    ) => {
574        // The actual enum definition is written as given
575        #[derive(Debug)]
576        $(#[$attribute])* $pub enum $name
577        $(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
578        $(where
579            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
580        {
581            $($variants)*
582        }
583
584        impl$(<$($generic: $crate::Parser $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::Parser
585        for $name$(<$($generic),*>)?
586        $(where
587            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
588        {
589            fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
590                let mut err = $crate::Error::no_error();
591                // try to parse each variant
592                $crate::unsynn!{@enum_parse_variant(tokens, err) $($variants)*}
593                // nothing matched, error out
594                Err(err)
595            }
596        }
597
598        impl$(<$($generic: $crate::ToTokens $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::ToTokens
599        for $name$(< $($generic),* >)?
600        $(where
601            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
602        {
603            fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
604                $crate::unsynn!{@enum_to_tokens(self, tokens) {$($variants)*}}
605            }
606        }
607    };
608
609    // @enum_lifetime helper for enums with lifetime parameters
610    (
611        @enum_lifetime
612        $(#[$attribute:meta])* $pub:vis enum $name:ident
613        <$lifetime:lifetime $(, $($param:tt),*)? $(,)?>
614        {
615            $($variants:tt)*
616        }
617    ) => {
618        // The actual enum definition is written as given
619        #[derive(Debug)]
620        $(#[$attribute])* $pub enum $name<$lifetime $(, $($param),*)?> {
621            $($variants)*
622        }
623
624        impl<$lifetime $(, $($param),*)?> $crate::Parser
625        for $name<$lifetime $(, $($param),*)?>
626        {
627            fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
628                let mut err = $crate::Error::no_error();
629                // try to parse each variant
630                $crate::unsynn!{@enum_parse_variant(tokens, err) $($variants)*}
631                // nothing matched, error out
632                Err(err)
633            }
634        }
635
636        impl<$lifetime $(, $($param),*)?> $crate::ToTokens
637        for $name<$lifetime $(, $($param),*)?>
638        {
639            fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
640                $crate::unsynn!{@enum_to_tokens(self, tokens) {$($variants)*}}
641            }
642        }
643    };
644
645    // ERROR PATTERNS - Catch unsupported constructs and provide helpful messages
646
647    // Unit struct - not yet supported
648    (
649        $(#[$attribute:meta])* $pub:vis struct $name:ident;
650        $($cont:tt)*
651    ) => {
652        compile_error!(concat!(
653            "Unit structs are not yet supported in unsynn! macro.\n",
654            "\n",
655            "Found: `", stringify!($pub struct $name;), "`\n",
656            "\n",
657            "Unit structs (like `struct Foo;`) are commonly used as marker types\n",
658            "in unsynn (e.g., Enable, Disable, EndOfStream). Support for defining\n",
659            "them inside unsynn! is planned but not yet implemented.\n",
660            "\n",
661            "Workarounds:\n",
662            "  1. Define marker types outside unsynn! and implement Parser/ToTokens manually\n",
663            "  2. Use empty tuple struct: `", stringify!($pub struct $name();), "`\n",
664            "     (though this may also not be supported yet)\n",
665            "\n",
666            "See ROADMAP.md for planned features."
667        ));
668    };
669
670    // Empty tuple struct - may want to make this an error too
671    (
672        $(#[$attribute:meta])* $pub:vis struct $name:ident();
673        $($cont:tt)*
674    ) => {
675        compile_error!(concat!(
676            "Empty tuple structs are not supported in unsynn! macro.\n",
677            "\n",
678            "Found: `", stringify!($pub struct $name();), "`\n",
679            "\n",
680            "Empty tuple structs would parse and emit no tokens, which is typically\n",
681            "only useful for marker types. If you need a marker, define it outside\n",
682            "unsynn! as a unit struct with manual Parser/ToTokens implementation.\n",
683            "\n",
684            "If you need a struct that parses tokens, use tuple struct with fields:\n",
685            "  `", stringify!($pub struct $name(Type);), "`\n",
686            "\n",
687            "See ROADMAP.md for discussion on marker type support."
688        ));
689    };
690
691    // normal structs - lifetime parameter patterns FIRST
692    // Pattern 1: Lifetime + one type param with no bounds: <'a, T>
693    (
694        $(#[$attribute:meta])* $pub:vis struct $name:ident
695        <$lifetime:lifetime, $tparam:ident $(,)?>
696        {
697            $($(#[$mattr:meta])* $mpub:vis $member:ident: $parser:ty),* $(,)?
698        }
699        impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
700        $($cont:tt)*
701    ) => {
702        $crate::unsynn!{
703            @struct_lifetime_tparam
704            $(#[$attribute])* $pub struct $name
705            <$lifetime, $tparam>
706            {
707                $($(#[$mattr])* $mpub $member: $parser),*
708            }
709        }
710        $crate::unsynn!{
711            @impl
712            for $name
713            {$({$(#[$tattr])* $trait $bracesemi})*}
714        }
715        $crate::unsynn!{$($cont)*}
716    };
717    (
718        $(#[$attribute:meta])* $pub:vis struct $name:ident
719        <$lifetime:lifetime, $tparam:ident $(,)?>
720        {
721            $($(#[$mattr:meta])* $mpub:vis $member:ident: $parser:ty),* $(,)?
722        }
723        $($cont:tt)*
724    ) => {
725        $crate::unsynn!{
726            @struct_lifetime_tparam
727            $(#[$attribute])* $pub struct $name
728            <$lifetime, $tparam>
729            {
730                $($(#[$mattr])* $mpub $member: $parser),*
731            }
732        }
733        $crate::unsynn!{$($cont)*}
734    };
735
736    // Pattern 2: Lifetime only: <'a> or <'a, 'b>
737    (
738        $(#[$attribute:meta])* $pub:vis struct $name:ident
739        <$lifetime:lifetime $(, $($param:tt),*)? $(,)?>
740        {
741            $($(#[$mattr:meta])* $mpub:vis $member:ident: $parser:ty),* $(,)?
742        }
743        impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
744        $($cont:tt)*
745    ) => {
746        $crate::unsynn!{
747            @struct_lifetime
748            $(#[$attribute])* $pub struct $name
749            <$lifetime $(, $($param),*)?>
750            {
751                $($(#[$mattr])* $mpub $member: $parser),*
752            }
753        }
754        $crate::unsynn!{
755            @impl
756            for $name
757            {$({$(#[$tattr])* $trait $bracesemi})*}
758        }
759        $crate::unsynn!{$($cont)*}
760    };
761    (
762        $(#[$attribute:meta])* $pub:vis struct $name:ident
763        <$lifetime:lifetime $(, $($param:tt),*)? $(,)?>
764        {
765            $($(#[$mattr:meta])* $mpub:vis $member:ident: $parser:ty),* $(,)?
766        }
767        $($cont:tt)*
768    ) => {
769        $crate::unsynn!{
770            @struct_lifetime
771            $(#[$attribute])* $pub struct $name
772            <$lifetime $(, $($param),*)?>
773            {
774                $($(#[$mattr])* $mpub $member: $parser),*
775            }
776        }
777        $crate::unsynn!{$($cont)*}
778    };
779
780    // normal structs with generics
781    (
782        $(#[$attribute:meta])* $pub:vis struct $name:ident
783        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
784        $(where
785            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?
786        {
787            $($(#[$mattr:meta])* $mpub:vis $member:ident: $parser:ty),* $(,)?
788        }
789        // PLANNED: impl$(<extragenerics: bounds>)* Trait$(<extra>)
790        impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
791        $($cont:tt)*
792    ) => {
793        $crate::unsynn!{
794            @struct
795            $(#[$attribute])* $pub struct $name
796            $(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
797            $(where
798                $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
799            {
800                $($(#[$mattr])* $mpub $member: $parser),*
801            }
802        }
803        $crate::unsynn!{
804            @impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
805            for $name
806            $(where
807                $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
808            {$({$(#[$tattr])* $trait $bracesemi})*}
809        }
810        // next item
811        $crate::unsynn!{$($cont)*}
812    };
813    (
814        $(#[$attribute:meta])* $pub:vis struct $name:ident
815        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
816        $(where
817            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?
818        {
819            $($(#[$mattr:meta])* $mpub:vis $member:ident: $parser:ty),* $(,)?
820        }
821        $($cont:tt)*
822    ) => {
823        $crate::unsynn!{
824            @struct
825            $(#[$attribute])* $pub struct $name
826            $(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
827            $(where
828                $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
829            {
830                $($(#[$mattr])* $mpub $member: $parser),*
831            }
832        }
833        // next item
834        $crate::unsynn!{$($cont)*}
835    };
836
837    (
838        @struct
839        $(#[$attribute:meta])* $pub:vis struct $name:ident
840        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
841        $(where
842            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?
843        {
844            $($(#[$mattr:meta])* $mpub:vis $member:ident: $parser:ty),* $(,)?
845        }
846    ) => {
847        #[derive(Debug)]
848        $(#[$attribute])* $pub struct $name
849        $(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
850        $(where
851            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
852        {
853            $(
854                $(#[$mattr])* $mpub $member : $parser
855            ),*
856        }
857
858        impl$(<$($generic: $crate::Parser $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::Parser
859        for $name$(<$($generic),*>)?
860        $(where
861            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
862        {
863            fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
864                Ok(Self{$($member: <$parser as $crate::Parse>::parse(tokens)?),*})
865            }
866        }
867
868        impl$(<$($generic: $crate::ToTokens $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::ToTokens
869        for $name$(<$($generic),*>)?
870        $(where
871            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
872        {
873            fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
874                $(self.$member.to_tokens(tokens);)*
875            }
876        }
877    };
878
879    // @struct_lifetime_tparam - struct with <'a, T>
880    (
881        @struct_lifetime_tparam
882        $(#[$attribute:meta])* $pub:vis struct $name:ident
883        <$lifetime:lifetime, $tparam:ident>
884        {
885            $($(#[$mattr:meta])* $mpub:vis $member:ident: $parser:ty),* $(,)?
886        }
887    ) => {
888        #[derive(Debug)]
889        $(#[$attribute])* $pub struct $name<$lifetime, $tparam> {
890            $(
891                $(#[$mattr])* $mpub $member : $parser
892            ),*
893        }
894
895        impl<$lifetime, $tparam: $crate::Parser> $crate::Parser
896        for $name<$lifetime, $tparam>
897        {
898            fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
899                Ok(Self{$($member: <$parser as $crate::Parse>::parse(tokens)?),*})
900            }
901        }
902
903        impl<$lifetime, $tparam: $crate::ToTokens> $crate::ToTokens
904        for $name<$lifetime, $tparam>
905        {
906            fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
907                $(self.$member.to_tokens(tokens);)*
908            }
909        }
910    };
911
912    // @struct_lifetime - struct with just lifetimes
913    (
914        @struct_lifetime
915        $(#[$attribute:meta])* $pub:vis struct $name:ident
916        <$lifetime:lifetime $(, $($param:tt),*)?>
917        {
918            $($(#[$mattr:meta])* $mpub:vis $member:ident: $parser:ty),* $(,)?
919        }
920    ) => {
921        #[derive(Debug)]
922        $(#[$attribute])* $pub struct $name<$lifetime $(, $($param),*)?> {
923            $(
924                $(#[$mattr])* $mpub $member : $parser
925            ),*
926        }
927
928        impl<$lifetime $(, $($param),*)?> $crate::Parser
929        for $name<$lifetime $(, $($param),*)?>
930        {
931            fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
932                Ok(Self{$($member: <$parser as $crate::Parse>::parse(tokens)?),*})
933            }
934        }
935
936        impl<$lifetime $(, $($param),*)?> $crate::ToTokens
937        for $name<$lifetime $(, $($param),*)?>
938        {
939            fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
940                $(self.$member.to_tokens(tokens);)*
941            }
942        }
943    };
944
945    // tuple structs with parse_with and/or to_tokens - MUST COME BEFORE regular tuple struct patterns
946
947    // Single-field with `from <type>: parse_with; to_tokens`
948    (
949        $(#[$attribute:meta])* $pub:vis struct $name:ident
950        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
951        (
952            $(#[$mattr:meta])* $mpub:vis $field:ty
953        )
954        from $parse_type:ty:
955        parse_with |$pval:ident, $ptok:ident| $parse_body:block
956        to_tokens |$tval:ident, $ttok:ident| $tokens_body:block
957        $(where
958            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
959        $($cont:tt)*
960    ) => {
961        $crate::unsynn!{
962            @tuplestruct_parse_with_as_to_tokens
963            $(#[$attribute])* $pub struct $name
964            $(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
965            ($(#[$mattr])* $mpub $field)
966            from $parse_type:
967            parse_with |$pval, $ptok| $parse_body
968            to_tokens |$tval, $ttok| $tokens_body
969            $(where
970                $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
971        }
972        $crate::unsynn!{$($cont)*}
973    };
974
975    // Single-field with `from <type>: parse_with` (no to_tokens - uses default)
976    (
977        $(#[$attribute:meta])* $pub:vis struct $name:ident
978        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
979        (
980            $(#[$mattr:meta])* $mpub:vis $field:ty
981        )
982        from $parse_type:ty:
983        parse_with |$pval:ident, $ptok:ident| $closure_body:block
984        $(where
985            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
986        $($cont:tt)*
987    ) => {
988        $crate::unsynn!{
989            @tuplestruct_parse_with_as
990            $(#[$attribute])* $pub struct $name
991            $(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
992            ($(#[$mattr])* $mpub $field)
993            from $parse_type:
994            parse_with |$pval, $ptok| $closure_body
995            $(where
996                $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
997        }
998        $crate::unsynn!{$($cont)*}
999    };
1000
1001    // Tuple struct with `parse_with; to_tokens` (validation + custom tokens)
1002    (
1003        $(#[$attribute:meta])* $pub:vis struct $name:ident
1004        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
1005        (
1006            $($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
1007        );
1008        parse_with |$pval:ident, $ptok:ident| $parse_body:block
1009        to_tokens |$tval:ident, $ttok:ident| $tokens_body:block
1010        $(where
1011            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
1012        $($cont:tt)*
1013    ) => {
1014        $crate::unsynn!{
1015            @tuplestruct_parse_with_to_tokens
1016            $(#[$attribute])* $pub struct $name
1017            $(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
1018            (
1019                $($(#[$mattr])* $mpub $parser),*
1020            );
1021            parse_with |$pval, $ptok| $parse_body
1022            to_tokens |$tval, $ttok| $tokens_body
1023            $(where
1024                $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
1025        }
1026        $crate::unsynn!{$($cont)*}
1027    };
1028
1029    // Tuple struct with `parse_with` only (validation, default tokens)
1030    (
1031        $(#[$attribute:meta])* $pub:vis struct $name:ident
1032        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
1033        (
1034            $($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
1035        );
1036        parse_with |$pval:ident, $ptok:ident| $closure_body:block
1037        $(where
1038            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
1039        $($cont:tt)*
1040    ) => {
1041        $crate::unsynn!{
1042            @tuplestruct_parse_with
1043            $(#[$attribute])* $pub struct $name
1044            $(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
1045            (
1046                $($(#[$mattr])* $mpub $parser),*
1047            );
1048            parse_with |$pval, $ptok| $closure_body
1049            $(where
1050                $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
1051        }
1052        $crate::unsynn!{$($cont)*}
1053    };
1054
1055    // Tuple struct with `to_tokens` only (default parsing, custom tokens)
1056    (
1057        $(#[$attribute:meta])* $pub:vis struct $name:ident
1058        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
1059        (
1060            $($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
1061        );
1062        to_tokens |$tval:ident, $ttok:ident| $tokens_body:block
1063        $(where
1064            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
1065        $($cont:tt)*
1066    ) => {
1067        $crate::unsynn!{
1068            @tuplestruct_to_tokens
1069            $(#[$attribute])* $pub struct $name
1070            $(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
1071            (
1072                $($(#[$mattr])* $mpub $parser),*
1073            );
1074            to_tokens |$tval, $ttok| $tokens_body
1075            $(where
1076                $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
1077        }
1078        $crate::unsynn!{$($cont)*}
1079    };
1080
1081    // Error: `from` without `parse_with`
1082    (
1083        $(#[$attribute:meta])* $pub:vis struct $name:ident
1084        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
1085        (
1086            $($parser:ty),* $(,)?
1087        )
1088        from $parse_type:ty:
1089        $($cont:tt)*
1090    ) => {
1091        compile_error!("`from` requires `parse_with` clause. Use: `from Type: parse_with |value, tokens| { ... }`");
1092    };
1093
1094    // TODO: review, is this restriction necessary?
1095    // Error: `from` with multiple fields
1096    (
1097        $(#[$attribute:meta])* $pub:vis struct $name:ident
1098        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
1099        (
1100            $field1:ty,
1101            $field2:ty
1102            $(, $rest_fields:ty)* $(,)?
1103        )
1104        from $parse_type:ty:
1105        parse_with |$pval:ident, $ptok:ident| $closure_body:block
1106        $($cont:tt)*
1107    ) => {
1108        compile_error!("`from` only supported for single-field tuple structs. For multi-field structs, use `parse_with` without `from` for validation.");
1109    };
1110
1111    // tuple structs - lifetime parameter patterns FIRST
1112    // w/ impl - WITH semicolon
1113    (
1114        $(#[$attribute:meta])* $pub:vis struct $name:ident
1115        <$lifetime:lifetime $(, $($param:tt),*)? $(,)?>
1116        (
1117            $($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
1118        );
1119        impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
1120        $($cont:tt)*
1121    ) => {
1122        $crate::unsynn!{
1123            @tuplestruct_lifetime
1124            $(#[$attribute])* $pub struct $name
1125            <$lifetime $(, $($param),*)?>
1126            (
1127                $($(#[$mattr])* $mpub $parser),*
1128            );
1129        }
1130        $crate::unsynn!{
1131            @impl
1132            for $name
1133            {$({$(#[$tattr])* $trait $bracesemi})*}
1134        }
1135        $crate::unsynn!{$($cont)*}
1136    };
1137    // w/ impl - WITHOUT semicolon (optional)
1138    (
1139        $(#[$attribute:meta])* $pub:vis struct $name:ident
1140        <$lifetime:lifetime $(, $($param:tt),*)? $(,)?>
1141        (
1142            $($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
1143        )
1144        impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
1145        $($cont:tt)*
1146    ) => {
1147        $crate::unsynn!{
1148            @tuplestruct_lifetime
1149            $(#[$attribute])* $pub struct $name
1150            <$lifetime $(, $($param),*)?>
1151            (
1152                $($(#[$mattr])* $mpub $parser),*
1153            );
1154        }
1155        $crate::unsynn!{
1156            @impl
1157            for $name
1158            {$({$(#[$tattr])* $trait $bracesemi})*}
1159        }
1160        $crate::unsynn!{$($cont)*}
1161    };
1162    (
1163        $(#[$attribute:meta])* $pub:vis struct $name:ident
1164        <$lifetime:lifetime $(, $($param:tt),*)? $(,)?>
1165        (
1166            $($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
1167        );
1168        $($cont:tt)*
1169    ) => {
1170        $crate::unsynn!{
1171            @tuplestruct_lifetime
1172            $(#[$attribute])* $pub struct $name
1173            <$lifetime $(, $($param),*)?>
1174            (
1175                $($(#[$mattr])* $mpub $parser),*
1176            );
1177        }
1178        $crate::unsynn!{$($cont)*}
1179    };
1180
1181    // tuple structs with generics
1182    // w/ traits - WITH semicolon
1183    (
1184        $(#[$attribute:meta])* $pub:vis struct $name:ident
1185        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
1186        (
1187            $($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
1188        )
1189        $(where
1190            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
1191        // PLANNED: impl$(<extragenerics: bounds>)* Trait$(<extra>)
1192        impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
1193        $($cont:tt)*
1194    ) => {
1195        $crate::unsynn!{
1196            @tuplestruct
1197            $(#[$attribute])* $pub struct $name
1198            $(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
1199            (
1200                $($(#[$mattr])* $mpub $parser),*
1201            )
1202            $(where
1203                $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
1204        }
1205        $crate::unsynn!{
1206            @impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
1207            for $name
1208            $(where
1209                $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
1210            {$({$(#[$tattr])* $trait $bracesemi})*}
1211        }
1212        $crate::unsynn!{$($cont)*}
1213    };
1214    // w/ traits - WITHOUT semicolon (optional semicolon)
1215    (
1216        $(#[$attribute:meta])* $pub:vis struct $name:ident
1217        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
1218        (
1219            $($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
1220        )
1221        $(where
1222            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?
1223        // PLANNED: impl$(<extragenerics: bounds>)* Trait$(<extra>)
1224        impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
1225        $($cont:tt)*
1226    ) => {
1227        $crate::unsynn!{
1228            @tuplestruct
1229            $(#[$attribute])* $pub struct $name
1230            $(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
1231            (
1232                $($(#[$mattr])* $mpub $parser),*
1233            )
1234            $(where
1235                $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
1236        }
1237        $crate::unsynn!{
1238            @impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
1239            for $name
1240            $(where
1241                $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
1242            {$({$(#[$tattr])* $trait $bracesemi})*}
1243        }
1244        $crate::unsynn!{$($cont)*}
1245    };
1246    // w/o traits
1247    (
1248        $(#[$attribute:meta])* $pub:vis struct $name:ident
1249        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
1250        (
1251            $($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
1252        )
1253        $(where
1254            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
1255        $($cont:tt)*
1256    ) => {
1257        $crate::unsynn!{
1258            @tuplestruct
1259            $(#[$attribute])* $pub struct $name
1260            $(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
1261            (
1262                $($(#[$mattr])* $mpub $parser),*
1263            )
1264            $(where
1265                $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
1266        }
1267        $crate::unsynn!{$($cont)*}
1268    };
1269    (
1270        @tuplestruct
1271        $(#[$attribute:meta])* $pub:vis struct $name:ident
1272        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
1273        (
1274            $($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
1275        )
1276        $(where
1277            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
1278    ) => {
1279        #[derive(Debug)]
1280        $(#[$attribute])* $pub struct $name
1281        $(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
1282        ($($(#[$mattr])* $mpub $parser),*)
1283        $(where
1284            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
1285
1286        impl$(<$($generic: $crate::Parser $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::Parser
1287        for $name$(<$($generic),*>)?
1288        $(where
1289            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
1290        {
1291            fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
1292                Ok(Self($(<$parser as $crate::Parse>::parse(tokens)?),*))
1293            }
1294        }
1295
1296        impl$(<$($generic: $crate::ToTokens $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::ToTokens
1297        for $name$(<$($generic),*>)?
1298        $(where
1299            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
1300        {
1301            fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
1302                unsynn! {@tuple_for_each item in self : Self($($parser),*) {
1303                    item.to_tokens(tokens);
1304                }}
1305            }
1306        }
1307    };
1308
1309    // @tuplestruct_parse_with_as - single-field tuple struct with transformation
1310    (
1311        @tuplestruct_parse_with_as
1312        $(#[$attribute:meta])* $pub:vis struct $name:ident
1313        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
1314        ($(#[$mattr:meta])* $mpub:vis $field:ty)
1315        from $parse_type:ty:
1316        parse_with |$pval:ident, $ptok:ident| $closure_body:block
1317        $(where
1318            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
1319    ) => {
1320        #[derive(Debug)]
1321        $(#[$attribute])* $pub struct $name
1322        $(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
1323        ($(#[$mattr])* $mpub $field)
1324        $(where
1325            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
1326
1327        impl$(<$($generic: $crate::Parser $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::Parser
1328        for $name$(<$($generic),*>)?
1329        $(where
1330            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
1331        {
1332            fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
1333                <$parse_type>::parse_with(tokens, |$pval, $ptok| $closure_body)
1334            }
1335        }
1336
1337        impl$(<$($generic: $crate::ToTokens $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::ToTokens
1338        for $name$(<$($generic),*>)?
1339        $(where
1340            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
1341        {
1342            fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
1343                self.0.to_tokens(tokens)
1344            }
1345        }
1346    };
1347
1348    // @tuplestruct_parse_with - tuple struct with validation (any number of fields)
1349    (
1350        @tuplestruct_parse_with
1351        $(#[$attribute:meta])* $pub:vis struct $name:ident
1352        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
1353        (
1354            $($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
1355        );
1356        parse_with |$pval:ident, $ptok:ident| $closure_body:block
1357        $(where
1358            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
1359    ) => {
1360        #[derive(Debug)]
1361        $(#[$attribute])* $pub struct $name
1362        $(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
1363        ($($(#[$mattr])* $mpub $parser),*)
1364        $(where
1365            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
1366
1367        impl$(<$($generic: $crate::Parser $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::Parser
1368        for $name$(<$($generic),*>)?
1369        $(where
1370            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
1371        {
1372            fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
1373                // Parse normally first
1374                let parsed = Self($(<$parser as $crate::Parse>::parse(tokens)?),*);
1375                // Then validate
1376                (|$pval: Self, $ptok: &mut $crate::TokenIter| $closure_body)(parsed, tokens)
1377            }
1378        }
1379
1380        impl$(<$($generic: $crate::ToTokens $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::ToTokens
1381        for $name$(<$($generic),*>)?
1382        $(where
1383            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
1384        {
1385            fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
1386                unsynn! {@tuple_for_each item in self : Self($($parser),*) {
1387                    item.to_tokens(tokens);
1388                }}
1389            }
1390        }
1391    };
1392
1393    // @tuplestruct_parse_with_as_to_tokens - single-field with transformation + custom tokens
1394    (
1395        @tuplestruct_parse_with_as_to_tokens
1396        $(#[$attribute:meta])* $pub:vis struct $name:ident
1397        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
1398        ($(#[$mattr:meta])* $mpub:vis $field:ty)
1399        from $parse_type:ty:
1400        parse_with |$pval:ident, $ptok:ident| $closure_body:block
1401        to_tokens |$tval:ident, $ttok:ident| $tokens_body:block
1402        $(where
1403            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
1404    ) => {
1405        #[derive(Debug)]
1406        $(#[$attribute])* $pub struct $name
1407        $(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
1408        ($(#[$mattr])* $mpub $field)
1409        $(where
1410            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
1411
1412        impl$(<$($generic: $crate::Parser $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::Parser
1413        for $name$(<$($generic),*>)?
1414        $(where
1415            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
1416        {
1417            fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
1418                <$parse_type>::parse_with(tokens, |$pval, $ptok| $closure_body)
1419            }
1420        }
1421
1422        impl$(<$($generic),*>)? $crate::ToTokens
1423        for $name$(<$($generic),*>)?
1424        $(where
1425            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
1426        {
1427            fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
1428                (|$tval: &Self, $ttok: &mut $crate::TokenStream| $tokens_body)(self, tokens)
1429            }
1430        }
1431    };
1432
1433    // @tuplestruct_parse_with_to_tokens - validation + custom tokens (any number of fields)
1434    (
1435        @tuplestruct_parse_with_to_tokens
1436        $(#[$attribute:meta])* $pub:vis struct $name:ident
1437        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
1438        (
1439            $($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
1440        );
1441        parse_with |$pval:ident, $ptok:ident| $closure_body:block
1442        to_tokens |$tval:ident, $ttok:ident| $tokens_body:block
1443        $(where
1444            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
1445    ) => {
1446        #[derive(Debug)]
1447        $(#[$attribute])* $pub struct $name
1448        $(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
1449        ($($(#[$mattr])* $mpub $parser),*)
1450        $(where
1451            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
1452
1453        impl$(<$($generic: $crate::Parser $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::Parser
1454        for $name$(<$($generic),*>)?
1455        $(where
1456            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
1457        {
1458            fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
1459                // Parse normally first
1460                let parsed = Self($(<$parser as $crate::Parse>::parse(tokens)?),*);
1461                // Then validate
1462                (|$pval: Self, $ptok: &mut $crate::TokenIter| $closure_body)(parsed, tokens)
1463            }
1464        }
1465
1466        impl$(<$($generic),*>)? $crate::ToTokens
1467        for $name$(<$($generic),*>)?
1468        $(where
1469            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
1470        {
1471            fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
1472                (|$tval: &Self, $ttok: &mut $crate::TokenStream| $tokens_body)(self, tokens)
1473            }
1474        }
1475    };
1476
1477    // @tuplestruct_to_tokens - default parsing + custom tokens (any number of fields)
1478    (
1479        @tuplestruct_to_tokens
1480        $(#[$attribute:meta])* $pub:vis struct $name:ident
1481        $(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)? $(= $default:ty)?),*$(,)?>)?
1482        (
1483            $($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
1484        );
1485        to_tokens |$tval:ident, $ttok:ident| $tokens_body:block
1486        $(where
1487            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?;
1488    ) => {
1489        #[derive(Debug)]
1490        $(#[$attribute])* $pub struct $name
1491        $(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)? $(= $default)?),*>)?
1492        ($($(#[$mattr])* $mpub $parser),*)
1493        $(where
1494            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?;
1495
1496        impl$(<$($generic: $crate::Parser $(+ $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $crate::Parser
1497        for $name$(<$($generic),*>)?
1498        $(where
1499            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
1500        {
1501            fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
1502                Ok(Self($(<$parser as $crate::Parse>::parse(tokens)?),*))
1503            }
1504        }
1505
1506        impl$(<$($generic),*>)? $crate::ToTokens
1507        for $name$(<$($generic),*>)?
1508        $(where
1509            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
1510        {
1511            fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
1512                (|$tval: &Self, $ttok: &mut $crate::TokenStream| $tokens_body)(self, tokens)
1513            }
1514        }
1515    };
1516
1517    // @tuplestruct_lifetime - tuple struct with lifetime parameters
1518    (
1519        @tuplestruct_lifetime
1520        $(#[$attribute:meta])* $pub:vis struct $name:ident
1521        <$lifetime:lifetime $(, $($param:tt),*)?>
1522        (
1523            $($(#[$mattr:meta])* $mpub:vis $parser:ty),* $(,)?
1524        );
1525    ) => {
1526        #[derive(Debug)]
1527        $(#[$attribute])* $pub struct $name<$lifetime $(, $($param),*)?>(
1528            $($(#[$mattr])* $mpub $parser),*
1529        );
1530
1531        impl<$lifetime $(, $($param),*)?> $crate::Parser
1532        for $name<$lifetime $(, $($param),*)?>
1533        {
1534            fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
1535                Ok(Self($(<$parser as $crate::Parse>::parse(tokens)?),*))
1536            }
1537        }
1538
1539        impl<$lifetime $(, $($param),*)?> $crate::ToTokens
1540        for $name<$lifetime $(, $($param),*)?>
1541        {
1542            fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
1543                unsynn! {@tuple_for_each item in self : Self($($parser),*) {
1544                    item.to_tokens(tokens);
1545                }}
1546            }
1547        }
1548    };
1549
1550    // type passthough
1551    (
1552        $(#[$attribute:meta])* $pub:vis type $name:ident
1553        $(<$($generic:ident $(: $constraint:ident $(+ $constraints:ident)*)? $(= $default:ty)?),*$(,)?>)?
1554        = $orig:path;
1555        $($cont:tt)*
1556    ) => {
1557        $(#[$attribute])* $pub type $name$(<$($generic$(: $constraint $(+ $constraints)*)? $(= $default)?),*>)? = $orig;
1558        // next item
1559        $crate::unsynn!{$($cont)*}
1560    };
1561
1562    // TODO: generics
1563
1564    // marker trait blocks
1565    (
1566        $(#[$attributeall:meta])*
1567        $pub:vis trait {
1568            $($(#[$attribute:meta])* $name:ident$(: $super:ident $(+ $supers:ident)*)?);+$(;)?
1569        }
1570        $($cont:tt)*
1571    ) => {
1572        $crate::unsynn!{@expand_marker_trait($(#[$attributeall])*)
1573            $({$(#[$attribute])* $pub $name$(: $super $(+ $supers)*)?})+
1574        }
1575        // next item
1576        $crate::unsynn!{$($cont)*}
1577    };
1578    (
1579        $(#[$attributeall:meta])*
1580        trait {
1581            $($(#[$attribute:meta])* $pub:vis $name:ident$(: $super:ident $(+ $supers:ident)*)?);+$(;)?
1582        }
1583        $($cont:tt)*
1584    ) => {
1585        $crate::unsynn!{@expand_marker_trait($(#[$attributeall])*)
1586            $({$(#[$attribute])* $pub $name$(: $super $(+ $supers)*)?})+
1587        }
1588        // next item
1589        $crate::unsynn!{$($cont)*}
1590    };
1591    (
1592        @expand_marker_trait($(#[$attributeall:meta])*)
1593        {$(#[$attribute:meta])* $pub:vis $name:ident$(: $super:ident $(+ $supers:ident)*)?}
1594        // next item
1595        $($cont:tt)*
1596    ) => {
1597        $(#[$attributeall])* $(#[$attribute])* $pub trait $name$(: $super $(+ $supers)*)? {}
1598        $crate::unsynn!{@expand_marker_trait($(#[$attributeall])*) $($cont)*}
1599    };
1600    (@expand_marker_trait($(#[$attributeall:meta])*)) => {};
1601
1602    // marker trait definitions with ; at the end
1603    (
1604        $(#[$attribute:meta])* $pub:vis trait $name:ident$(: $super:ident $(+ $supers:ident)*)?;
1605        $($cont:tt)*
1606    ) => {
1607        $(#[$attribute])* $pub trait $name$(: $super $(+ $supers)*)? {}
1608        // next item
1609        $crate::unsynn!{$($cont)*}
1610    };
1611    // trait definition passthrough
1612    (
1613        $(#[$attribute:meta])* $pub:vis trait $name:ident$(: $super:ident $(+ $supers:ident)*)?
1614        {$($body:tt)*}
1615        $($cont:tt)*
1616    ) => {
1617        $(#[$attribute])* $pub trait $name$(: $super $(+ $supers)*)? {$($body)*}
1618        // next item
1619        $crate::unsynn!{$($cont)*}
1620    };
1621
1622    // impl passthrough for inherent implementations (without 'for' keyword)
1623    (
1624        $(#[$attribute:meta])*
1625        impl$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)?),*$(,)?>)?
1626        $type:ident$(<$($genparam:ident),*>)?
1627        {$($body:tt)*}
1628        $($cont:tt)*
1629    ) => {
1630        $(#[$attribute])*
1631        impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
1632        $type$(<$($genparam),*>)?
1633        {$($body)*}
1634        // next item
1635        $crate::unsynn!{$($cont)*}
1636    };
1637
1638    // impl passthrough (trait impl with 'for')
1639    (
1640        $(#[$attribute:meta])*
1641        impl$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)?),*$(,)?>)?
1642        $trait:ident$(<$($traitgenparam:ident),*$(,)?>)?
1643        for $type:ty {$($body:tt)*}
1644        $($cont:tt)*
1645    ) => {
1646        $(#[$attribute])*
1647        impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
1648        $trait$(<$($traitgenparam),*$(,)?>)?
1649        for $type {$($body)*}
1650        // next item
1651        $crate::unsynn!{$($cont)*}
1652    };
1653    (
1654        $(#[$attribute:meta])*
1655        impl$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)?),*$(,)?>)?
1656        $trait:ident$(<$($traitgenparam:ident),*$(,)?>)?
1657        for $($type:ty),+;
1658        $($cont:tt)*
1659    ) => {
1660        $crate::unsynn!{
1661            @impl_markers(
1662                $(#[$attribute])*
1663                impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
1664                $trait$(<$($traitgenparam),*$(,)?>)?
1665            )
1666            $($type),+,
1667        }
1668        // next item
1669        $crate::unsynn!{$($cont)*}
1670    };
1671
1672    // impl Marker for Many, Types, At, Once;
1673    (
1674        @impl_markers(
1675            $(#[$attribute:meta])*
1676            impl$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)?),*$(,)?>)?
1677            $trait:ident$(<$($traitgenparam:ident),*$(,)?>)?
1678        )
1679        $type:ty,
1680        $($cont:tt)*
1681    ) => {
1682        $(#[$attribute])*
1683        impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
1684        $trait$(<$($traitgenparam),*$(,)?>)?
1685        for $type{}
1686
1687        $crate::unsynn!{
1688            @impl_markers(
1689                $(#[$attribute])*
1690                impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
1691                $trait$(<$($traitgenparam),*$(,)?>)?
1692            )
1693            $($cont)*
1694        }
1695    };
1696    (@impl_markers($($_:tt)*)) => {};
1697
1698    // fn passthrough - with optional generics
1699    (
1700        $(#[$attribute:meta])* $pub:vis fn $name:ident$(<$($generic:tt),*>)?($($param:tt)*) $(-> $ret:ty)? {$($body:tt)*}
1701        $($cont:tt)*
1702    ) => {
1703        $(#[$attribute])* $pub fn $name$(<$($generic),*>)?($($param)*) $(-> $ret)? {$($body)*}
1704        $crate::unsynn!{$($cont)*}
1705    };
1706
1707    // use passthrough
1708    (use ::$($path:ident)::+$(::{$($inside:tt)+})?; $($cont:tt)*) => {
1709        use ::$($path)::+$(::{$($inside)+})?;
1710        $crate::unsynn!{$($cont)*}
1711    };
1712    (use $($path:ident)::+$(::{$($inside:tt)+})?; $($cont:tt)*) => {
1713        use $($path)::+$(::{$($inside)+})?;
1714        $crate::unsynn!{$($cont)*}
1715    };
1716    (use ::$($path:ident)::+ as $alias:ident; $($cont:tt)*) => {
1717        use $($path)::+ as $alias;
1718        $crate::unsynn!{$($cont)*}
1719    };
1720    (use ::$($path:ident)::+ as $alias:ident; $($cont:tt)*) => {
1721        use $($path)::+ as $alias;
1722        $crate::unsynn!{$($cont)*}
1723    };
1724
1725    // macro_rules! passthrough
1726    (macro_rules! $name:ident {$($rules:tt)*} $($cont:tt)*) => {
1727        macro_rules! $name {$($rules)*}
1728        $crate::unsynn!{$($cont)*}
1729    };
1730
1731    // macro passthrough
1732    ($macro:ident! {$($args:tt)*} $($cont:tt)*) => {
1733        $macro! {$($args)*}
1734        $crate::unsynn!{$($cont)*}
1735    };
1736    ($macro:ident! ($($args:tt)*); $($cont:tt)*) => {
1737        $macro! ($($args)*);
1738        $crate::unsynn!{$($cont)*}
1739    };
1740    ($macro:ident! [$($args:tt)*]; $($cont:tt)*) => {
1741        $macro! [$($args)*];
1742        $crate::unsynn!{$($cont)*}
1743    };
1744
1745    // keyword delegation
1746    (
1747        $(#[$attribute:meta])* $pub:vis keyword $name:ident = $str:literal;
1748        impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
1749        $($cont:tt)*
1750    ) => {
1751        $crate::keyword!{$(#[$attribute])* $pub $name = $str}
1752        $crate::unsynn!{
1753            @impl
1754            for $name
1755            {$({$(#[$tattr])* $trait $bracesemi})*}
1756        }
1757        $crate::unsynn!{$($cont)*}
1758    };
1759    ($(#[$attribute:meta])* $pub:vis keyword $name:ident = $str:literal; $($cont:tt)*) => {
1760        $crate::keyword!{$(#[$attribute])* $pub $name = $str}
1761        $crate::unsynn!{$($cont)*}
1762    };
1763    (
1764        $(#[$attribute:meta])* $pub:vis keyword $name:ident != $str:literal;
1765        impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
1766        $($cont:tt)*
1767    ) => {
1768        $crate::keyword!{$(#[$attribute])* $pub $name != $str}
1769        $crate::unsynn!{
1770            @impl
1771            for $name
1772            {$({$(#[$tattr])* $trait $bracesemi})*}
1773        }
1774        $crate::unsynn!{$($cont)*}
1775    };
1776    ($(#[$attribute:meta])* $pub:vis keyword $name:ident != $str:literal; $($cont:tt)*) => {
1777        $crate::keyword!{$(#[$attribute])* $pub $name != $str}
1778        $crate::unsynn!{$($cont)*}
1779    };
1780    (
1781        $(#[$attribute:meta])* $pub:vis keyword $name:ident = $group:path;
1782        impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
1783        $($cont:tt)*
1784    ) => {
1785        $crate::keyword!{$(#[$attribute])* $pub $name = $group}
1786        $crate::unsynn!{
1787            @impl
1788            for $name
1789            {$({$(#[$tattr])* $trait $bracesemi})*}
1790        }
1791        $crate::unsynn!{$($cont)*}
1792    };
1793    ($(#[$attribute:meta])* $pub:vis keyword $name:ident = $group:path; $($cont:tt)*) => {
1794        $crate::keyword!{$(#[$attribute])* $pub $name = $group}
1795        $crate::unsynn!{$($cont)*}
1796    };
1797    (
1798        $(#[$attribute:meta])* $pub:vis keyword $name:ident != $group:path;
1799        impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
1800        $($cont:tt)*
1801    ) => {
1802        $crate::keyword!{$(#[$attribute])* $pub $name != $group}
1803        $crate::unsynn!{
1804            @impl
1805            for $name
1806            {$({$(#[$tattr])* $trait $bracesemi})*}
1807        }
1808        $crate::unsynn!{$($cont)*}
1809    };
1810    ($(#[$attribute:meta])* $pub:vis keyword $name:ident != $group:path; $($cont:tt)*) => {
1811        $crate::keyword!{$(#[$attribute])* $pub $name != $group}
1812        $crate::unsynn!{$($cont)*}
1813    };
1814    (
1815        $(#[$attribute:meta])* $pub:vis keyword $name:ident = [$($keywords:tt),+ $(,)?];
1816        impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
1817        $($cont:tt)*
1818    ) => {
1819        $crate::keyword!{$(#[$attribute])* $pub $name = [$($keywords),+]}
1820        $crate::unsynn!{
1821            @impl
1822            for $name
1823            {$({$(#[$tattr])* $trait $bracesemi})*}
1824        }
1825        $crate::unsynn!{$($cont)*}
1826    };
1827    ($(#[$attribute:meta])* $pub:vis keyword $name:ident = [$($keywords:tt),+ $(,)?]; $($cont:tt)*) => {
1828        $crate::keyword!{$(#[$attribute])* $pub $name = [$($keywords),+]}
1829        $crate::unsynn!{$($cont)*}
1830    };
1831    (
1832        $(#[$attribute:meta])* $pub:vis keyword $name:ident != [$($keywords:tt),+ $(,)?];
1833        impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
1834        $($cont:tt)*
1835    ) => {
1836        $crate::keyword!{$(#[$attribute])* $pub $name != [$($keywords),+]}
1837        $crate::unsynn!{
1838            @impl
1839            for $name
1840            {$({$(#[$tattr])* $trait $bracesemi})*}
1841        }
1842        $crate::unsynn!{$($cont)*}
1843    };
1844    ($(#[$attribute:meta])* $pub:vis keyword $name:ident != [$($keywords:tt),+ $(,)?]; $($cont:tt)*) => {
1845        $crate::keyword!{$(#[$attribute])* $pub $name != [$($keywords),+]}
1846        $crate::unsynn!{$($cont)*}
1847    };
1848
1849    // operator delegation
1850    (
1851        $(#[$attribute:meta])* $pub:vis operator $name:ident = $str:literal;
1852        impl {$($(#[$tattr:meta])* $trait:ident $bracesemi:tt)*}
1853        $($cont:tt)*
1854    ) => {
1855        $crate::operator!{$(#[$attribute])* $pub $name = $str}
1856        $crate::unsynn!{
1857            @impl
1858            for $name
1859            {$({$(#[$tattr])* $trait $bracesemi})*}
1860        }
1861        $crate::unsynn!{$($cont)*}
1862    };
1863    ($(#[$attribute:meta])* $pub:vis operator $name:ident = $str:literal; $($cont:tt)*) => {
1864        $crate::operator!{$(#[$attribute])* $pub $name = $str}
1865        $crate::unsynn!{$($cont)*}
1866    };
1867
1868    // predicatetrait - creates a context trait and implements it for universal predicates
1869    ($(#[$attribute:meta])* $pub:vis predicatetrait $name:ident $(: $super:ident $(+ $supers:ident)*)? ; $($cont:tt)*) => {
1870        // Define the trait
1871        $(#[$attribute])* $pub trait $name$(: $super $(+ $supers)*)? : $crate::PredicateOp {}
1872
1873        // Implement for universal predicates
1874        impl $name for $crate::Enable {}
1875        impl $name for $crate::Disable {}
1876        impl $name for $crate::TokensRemain {}
1877
1878        // Implement for logic operators when all operands implement the trait
1879        impl<A: $name, B: $name, C: $name, D: $name> $name for $crate::AllOf<A, B, C, D> {}
1880        impl<A: $name, B: $name, C: $name, D: $name> $name for $crate::AnyOf<A, B, C, D> {}
1881        impl<A: $name, B: $name, C: $name, D: $name> $name for $crate::OneOf<A, B, C, D> {}
1882        impl<T: $name> $name for $crate::Not<T> {}
1883
1884        $crate::unsynn!{$($cont)*}
1885    };
1886
1887    // predicateflag - creates newtype wrappers with optional trait implementations
1888    ($(#[$attribute:meta])* $pub:vis predicateflag $name:ident = Enable $(for $($trait:ident),+ $(,)?)? ; $($cont:tt)*) => {
1889        $(#[$attribute])*
1890        #[derive(Debug, Clone, Default)]
1891        $pub struct $name($crate::Enable);
1892
1893        impl $crate::Parser for $name {
1894            #[inline]
1895            fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
1896                $crate::Enable::parse(tokens).map($name)
1897            }
1898        }
1899
1900        impl $crate::ToTokens for $name {
1901            #[inline]
1902            fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
1903                self.0.to_tokens(tokens);
1904            }
1905        }
1906
1907        impl $crate::PredicateOp for $name {}
1908
1909        $($(impl $trait for $name {})*)?
1910
1911        $crate::unsynn!{$($cont)*}
1912    };
1913    ($(#[$attribute:meta])* $pub:vis predicateflag $name:ident = Disable $(for $($trait:ident),+ $(,)?)? ; $($cont:tt)*) => {
1914        $(#[$attribute])*
1915        #[derive(Debug, Clone)]
1916        $pub struct $name($crate::Disable);
1917
1918        impl $crate::Parser for $name {
1919            #[inline]
1920            fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
1921                $crate::Disable::parse(tokens).map($name)
1922            }
1923        }
1924
1925        impl $crate::ToTokens for $name {
1926            #[inline]
1927            fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
1928                self.0.to_tokens(tokens);
1929            }
1930        }
1931
1932        impl $crate::PredicateOp for $name {}
1933
1934        $($(impl $trait for $name {})*)?
1935
1936        $crate::unsynn!{$($cont)*}
1937    };
1938    ($(#[$attribute:meta])* $pub:vis predicateflag $name:ident = TokensRemain $(for $($trait:ident),+ $(,)?)? ; $($cont:tt)*) => {
1939        $(#[$attribute])*
1940        #[derive(Debug, Clone, Default)]
1941        $pub struct $name($crate::TokensRemain);
1942
1943        impl $crate::Parser for $name {
1944            #[inline]
1945            fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
1946                $crate::TokensRemain::parse(tokens).map($name)
1947            }
1948        }
1949
1950        impl $crate::ToTokens for $name {
1951            #[inline]
1952            fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
1953                self.0.to_tokens(tokens);
1954            }
1955        }
1956
1957        impl $crate::PredicateOp for $name {}
1958
1959        $($(impl $trait for $name {})*)?
1960
1961        $crate::unsynn!{$($cont)*}
1962    };
1963
1964    // predicateflag without value defaults to Enable
1965    ($(#[$attribute:meta])* $pub:vis predicateflag $name:ident $(for $($trait:ident),+ $(,)?)? ; $($cont:tt)*) => {
1966        $(#[$attribute])*
1967        #[derive(Debug, Clone, Default)]
1968        $pub struct $name($crate::Enable);
1969
1970        impl $crate::Parser for $name {
1971            #[inline]
1972            fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
1973                $crate::Enable::parse(tokens).map($name)
1974            }
1975        }
1976
1977        impl $crate::ToTokens for $name {
1978            #[inline]
1979            fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
1980                self.0.to_tokens(tokens);
1981            }
1982        }
1983
1984        impl $crate::PredicateOp for $name {}
1985
1986        $($(impl $trait for $name {})*)?
1987
1988        $crate::unsynn!{$($cont)*}
1989    };
1990
1991    // terminate recursion
1992    () => {};
1993
1994    // @impl muncher
1995    (
1996        @impl$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)?),*>)?
1997        for $name:ident
1998        $(where
1999            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?
2000        {{$(#[$tattr:meta])* $trait:ident ;} $($cont:tt)*}
2001    ) => {
2002        $(#[$tattr])*
2003        impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $trait
2004        for $name$(<$($generic),*>)?
2005        $(where
2006            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
2007        {}
2008        $crate::unsynn!{
2009            @impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
2010            for $name
2011            {$($cont)*}
2012        }
2013    };
2014    (
2015        @impl$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)?),*>)?
2016        for $name:ident
2017        $(where
2018            $($where:ident: $wfirst:tt $(:: $wrest:ident)* $(+ $wmore:tt $(:: $wmrest:ident)*)*),*$(,)?)?
2019        {{$(#[$tattr:meta])* $trait:ident {$($body:tt)*}} $($cont:tt)*}
2020    ) => {
2021        $(#[$tattr])*
2022        impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)? $trait
2023        for $name$(<$($generic),*>)?
2024        $(where
2025            $($where: $wfirst $(:: $wrest)* $(+ $wmore $(:: $wmrest)*)*),*)?
2026        {$($body)*}
2027        $crate::unsynn!{
2028            @impl$(<$($generic$(: $first $(:: $rest)* $(+ $more $(:: $mrest)*)*)?),*>)?
2029            for $name
2030            {$($cont)*}
2031        }
2032    };
2033    (
2034        @impl$(<$($generic:ident$(: $first:tt $(:: $rest:ident)* $(+ $more:tt $(:: $mrest:ident)*)*)?),*>)?
2035        for $name:ident {}
2036    ) => {};
2037
2038    // to_tokens for enum tuple variant
2039    (
2040        @enum_to_tokens($self:ident, $tokens:ident)
2041        {
2042            $(#[$_attrs:meta])* $variant:ident($($tuple:tt)*) $(,$($cont:tt)*)?
2043        }
2044    ) => {
2045        if matches!($self, Self::$variant(..)) {
2046            unsynn! {@tuple_for_each item in $self : Self::$variant($($tuple)*) {
2047                item.to_tokens($tokens);
2048            }}
2049            return
2050        }
2051        $crate::unsynn!{@enum_to_tokens($self, $tokens) {$($($cont)*)?}}
2052    };
2053
2054    // to_tokens for enum struct variant
2055    (
2056        @enum_to_tokens($self:ident, $tokens:ident)
2057        {
2058            $(#[$_attrs:meta])* $variant:ident {
2059                $($(#[$_mattrs:meta])* $member:ident: $_type:ty),* $(,)?
2060            }
2061            $(,$($cont:tt)*)?
2062        }
2063    ) => {
2064            if matches!($self, Self::$variant{..}) {
2065                $(
2066                    let Self::$variant{$member: member, ..} = $self else {unreachable!()};
2067                    member.to_tokens($tokens);
2068                )*
2069                return
2070            }
2071            $crate::unsynn!{@enum_to_tokens($self, $tokens) {$($($cont)*)?}}
2072    };
2073
2074    // to_tokens for empty variant does nothing
2075    (
2076        @enum_to_tokens($self:ident, $tokens:ident)
2077        {
2078            $(#[$_attrs:meta])* $variant:ident
2079            $(,$($cont:tt)*)?
2080        }
2081    ) => {
2082        if matches!($self, Self::$variant) {
2083            return
2084        }
2085        $crate::unsynn!{@enum_to_tokens($self, $tokens) {$($($cont)*)?}}
2086    };
2087
2088    // end recursion
2089    (@enum_to_tokens($self:ident, $tokens:ident) {}) => {};
2090
2091    // write for enum tuple variant
2092    (
2093        @enum_write($self:ident, $f:ident)
2094        {
2095            $(#[$_attrs:meta])* $variant:ident($($tuple:tt)*) $(,$($cont:tt)*)?
2096        }
2097    ) => {
2098        if matches!($self, Self::$variant(..)) {
2099            unsynn! {@tuple_for_each item in $self : Self::$variant($($tuple)*) {
2100                write!($f, "{} " , &item)?;
2101            }}
2102        }
2103        $crate::unsynn!{@enum_write($self, $f) {$($($cont)*)?}}
2104    };
2105
2106    // to_tokens for enum struct variant
2107    (@enum_write($self:ident, $f:ident) {
2108        $(#[$_attrs:meta])* $variant:ident {
2109            $($(#[$_mattrs:meta])* $member:ident: $_type:ty),* $(,)?
2110        } $(,$($cont:tt)*)?} ) => {
2111            if matches!($self, Self::$variant{..}) {
2112                $(
2113                    let Self::$variant{$member: that, ..} = $self else {unreachable!()};
2114                    write!($f, "{} ", that)?;
2115                )*
2116            }
2117            $crate::unsynn!{@enum_write($self, $f) {$($($cont)*)?}}
2118    };
2119
2120    // write for empty variant does nothing
2121    (
2122        @enum_write($self:ident, $f:ident)
2123        {
2124            $(#[$_attrs:meta])* $variant:ident $(,$($cont:tt)*)?
2125        }
2126    ) => {
2127        if matches!($self, Self::$variant) {
2128        }
2129        $crate::unsynn!{@enum_write($self, $f) {$($($cont)*)?}}
2130    };
2131
2132    // end recursion
2133    (@enum_write($self:ident, $f:ident) {}) => {};
2134
2135    // Tuple enum variant
2136    (
2137        @enum_parse_variant($tokens:ident, $err:ident)
2138        $(#[$_attrs:meta])* $variant:ident($($tuple:tt)*)
2139        $(, $($cont:tt)*)?
2140    ) => {
2141        if let Ok(parsed) = (|| -> $crate::Result<_> {
2142            $err.upgrade($crate::unsynn!{@enum_parse_tuple($tokens) $variant($($tuple)*)})
2143        })() {
2144            return Ok(parsed);
2145        }
2146        $crate::unsynn!{@enum_parse_variant($tokens, $err) $($($cont)*)?}
2147    };
2148
2149    // Struct enum variant
2150    (
2151        @enum_parse_variant($tokens:ident, $err:ident)
2152        $(#[$_attrs:meta])*
2153        $variant:ident{$($members:tt)*}
2154        $(, $($cont:tt)*)?
2155    ) => {
2156        if let Ok(parsed) = (|| -> $crate::Result<_> {
2157            $err.upgrade($crate::unsynn!{@enum_parse_struct($tokens) $variant{$($members)*}})
2158        })() {
2159            return Ok(parsed);
2160        }
2161        $crate::unsynn!{@enum_parse_variant($tokens, $err) $($($cont)*)?}
2162    };
2163
2164    // Empty enum variant
2165    (
2166        @enum_parse_variant($tokens:ident, $err:ident)
2167        $(#[$_attrs:meta])* $variant:ident
2168        $(, $($cont:tt)*)?
2169    ) => {
2170        /* NOP */
2171        $crate::unsynn!{@enum_parse_variant($tokens, $err) $($($cont)*)?}
2172    };
2173
2174    // end recursion
2175    (@enum_parse_variant($tokens:ident, $err:ident)) => {};
2176
2177    // Parse a tuple variant
2178    (
2179        @enum_parse_tuple($tokens:ident)
2180        $variant:ident($($(#[$_attrs:meta])* $parser:ty),* $(,)?)
2181    ) => {
2182        $crate::Transaction::transaction($tokens,
2183            |tokens| Ok(Self::$variant($(<$parser as $crate::Parse>::parse(tokens)?,)*))
2184        )
2185    };
2186
2187    // Parse a struct variant
2188    (
2189        @enum_parse_struct($tokens:ident)
2190        $variant:ident{$($(#[$_attrs:meta])* $name:ident : $parser:ty),* $(,)?}
2191    ) => {
2192        $crate::Transaction::transaction($tokens,
2193            |tokens| Ok(Self::$variant{$($name : <$parser as $crate::Parse>::parse(tokens)?,)*})
2194        )
2195    };
2196
2197    // iterate over $variant:($tuple) in $this and apply some $code for each $i
2198    (
2199        @tuple_for_each
2200        $i:ident in $this:ident :
2201        $($variant:ident)::*($($tuple:tt)*)
2202        {
2203            $($code:tt)*
2204        }
2205    ) => {
2206        {
2207            $crate::unsynn!{@tuple_for_each $i in $this : $($variant)::*[$($tuple)*] { $($code)* }}
2208        }
2209    };
2210
2211    (
2212        @tuple_for_each
2213        $i:ident in $this:ident :
2214        $($variant:ident)::*[
2215            $(#[$_attrs:meta])* $_pub:vis $element:ty
2216            $(,$($rest:tt)*)?
2217        ]{
2218            $($code:tt)*
2219        }
2220    ) => {
2221        $crate::unsynn!{@tuple_for_each $i in $this : $($variant)::*[$($($rest)*)?] { $($code)* }}
2222        #[allow(irrefutable_let_patterns)]
2223        let $crate::unsynn!{@tuple_nth $i $($variant)::*[$($($rest)*)?]} = $this else {unreachable!()};
2224            $($code)*
2225        };
2226    (@tuple_for_each $i:ident in $_this:ident : $($variant:ident)::*[] { $($code:tt)* }) => {};
2227
2228    // replaces each prefix item with a underscore, followed by $i and .. finally
2229    (@tuple_nth $i:ident $($variant:ident)::*[$($(#[$_attrs:meta])* $_pub:vis $_element:ty),* $(,)?]) => {
2230        $($variant)::*(
2231            $($crate::unsynn!(@_ $_element),)*
2232            $i,
2233            ..
2234        )
2235    };
2236
2237    // replaces a single token with a underscore
2238    (@_ $_tt:tt) => {_};
2239
2240    // Error handler: catch malformed input that doesn't match any pattern
2241    // This must come AFTER all valid patterns (including internal @ patterns) but BEFORE the final termination
2242    ($unexpected:tt $($rest:tt)*) => {
2243        compile_error!(concat!(
2244            "Unexpected token in unsynn! macro: '",
2245            stringify!($unexpected),
2246            "'\n\nExpected one of:\n",
2247            "  - struct definition: struct Name { field: Type }\n",
2248            "  - tuple struct: struct Name(Type);\n",
2249            "  - enum: enum Name { Variant }\n",
2250            "  - trait: trait Name;\n",
2251            "  - impl block: impl Type { ... } or impl Trait for Type { ... }\n",
2252            "  - function: fn name(params) { body }\n",
2253            "  - type alias: type Name = Path;\n",
2254            "  - use statement: use path;\n",
2255            "  - macro_rules! definition\n",
2256            "  - keyword/operator definition\n\n",
2257            "Check for:\n",
2258            "  - Missing semicolons\n",
2259            "  - Mismatched braces\n",
2260            "  - Invalid syntax in struct/enum definitions"
2261        ));
2262    };
2263}
2264
2265/// Define types matching keywords.
2266///
2267///  * Any number of attributes (`#[...]`), including documentation comments. Keyword
2268///    documentation is automatically extended by a small auto generated doc comment listing
2269///    what a keyword definition will match.
2270/// * A optional `pub` declaration.
2271/// * `Name` is the name for the struct to be generated.
2272/// * `"identifier"` is the case sensitive keyword.
2273/// * `group` can be a non empty bracketed list of `"identifier"` or any an other keyword
2274///   definition.
2275/// * By using `=` the keyword must match the given definition while `!=` negates the output
2276///   and matches any identifier that is not in the definition.
2277///
2278/// `Name::parse()` will then only match the defined identifier.  It will implement `Debug`
2279/// and `Clone` for keywords. Additionally `AsRef<str>` is implemented for each Keyword
2280/// to access the identifier string from rust code.
2281///
2282/// The [`unsynn!`] macro supports defining keywords by using `keyword Name = "ident";`, the
2283/// `pub` specification has to come before `keyword` then. See the
2284/// [unsynn! keyword documentation](crate::unsynn#keywords-and-operators) for details.
2285///
2286/// In case a invalid keyword is defined (not an identifier) the compilation will panic. But
2287/// because the actual matching function is optimized and lazy evaluated this will only happen
2288/// on the first use of the invalid keyword definition.
2289///
2290/// Keywords implement `AsRef<str>`, `AsRef<Ident>` and `Keyword::as_str(&self) -> &str`. For
2291/// Keywords that are defined with a single literal string (`keyword!{ Foo = "foo"}`) the
2292/// `Default` trait is implemented. Thus they can be created and inserted statically.
2293///
2294///
2295/// # Example
2296///
2297/// ```
2298/// # use unsynn::*;
2299/// keyword!{
2300///     /// Optional documentation for `If`
2301///     pub If = "if";
2302///     pub Else = "else";
2303///     // keywords can be grouped from existing keywords
2304///     IfElse = [If, Else,];
2305///     // or contain identifiers in double quotes
2306///     IfElseThen = [IfElse, "then"];
2307///     // matching can be negated with `!=`
2308///     NotIfElseThen != [IfElse, "then"];
2309/// }
2310///
2311/// let mut tokens = "if".to_token_iter();
2312/// let if_kw = If::parse(&mut tokens).unwrap();
2313/// assert_eq!(if_kw.as_str(), "if");
2314/// # let mut tokens = "else if then something".to_token_iter();
2315/// # let else_kw = Else::parse(&mut tokens).unwrap();
2316/// # assert_eq!(else_kw.as_str(), "else");
2317/// # let ifelse_kw = IfElse::parse(&mut tokens).unwrap();
2318/// # assert_eq!(ifelse_kw.as_str(), "if");
2319/// # let ifelsethen_kw = IfElseThen::parse(&mut tokens).unwrap();
2320/// # assert_eq!(ifelsethen_kw.as_str(), "then");
2321/// # let notifelsethen_kw = NotIfElseThen::parse(&mut tokens).unwrap();
2322/// # assert_eq!(notifelsethen_kw.as_str(), "something");
2323/// ```
2324#[cfg(doc)]
2325#[macro_export]
2326macro_rules! keyword {
2327    ($name:ident = $str:literal; ...) => {};
2328    ($name:ident = $group:path; ...) => {};
2329    ($name:ident = [$($keywords:tt),+]; ...) => {};
2330    ($name:ident != $str:literal; ...) => {};
2331    ($name:ident != $group:path; ...) => {};
2332    ($name:ident != [$($keywords:tt),+]; ...) => {};
2333}
2334
2335#[doc(hidden)]
2336#[cfg(not(doc))]
2337#[macro_export]
2338macro_rules! keyword{
2339    ($(#[$attribute:meta])* $pub:vis $name:ident = $str:literal $(;$($cont:tt)*)?) => {
2340        $crate::keyword!{
2341            @{} $(#[$attribute])* $pub $name [$str]
2342        }
2343        // implement `Default` for single token keywords
2344        $crate::keyword!{
2345            @default $name $str
2346        }
2347        $crate::keyword!{$($($cont)*)?}
2348    };
2349    ($(#[$attribute:meta])* $pub:vis $name:ident != $str:literal $(;$($cont:tt)*)?) => {
2350        $crate::keyword!{
2351            @{!} $(#[$attribute])* $pub $name [$str]
2352        }
2353        $crate::keyword!{$($($cont)*)?}
2354    };
2355    ($(#[$attribute:meta])* $pub:vis $name:ident = $group:path $(;$($cont:tt)*)?) => {
2356        $crate::keyword!{
2357            @{} $(#[$attribute])* $pub $name [$group]
2358        }
2359        $crate::keyword!{$($($cont)*)?}
2360    };
2361    ($(#[$attribute:meta])* $pub:vis $name:ident != $group:path $(;$($cont:tt)*)?) => {
2362        $crate::keyword!{
2363            @{!} $(#[$attribute])* $pub $name [$group]
2364        }
2365        $crate::keyword!{$($($cont)*)?}
2366    };
2367    (
2368        $(#[$attribute:meta])*
2369        $pub:vis $name:ident = [$($keywords:tt),+ $(,)?]
2370        $(;$($cont:tt)*)?
2371    ) => {
2372        $crate::keyword!{
2373            @{} $(#[$attribute])* $pub $name [$($keywords),+]
2374        }
2375        $crate::keyword!{$($($cont)*)?}
2376    };
2377    (
2378        $(#[$attribute:meta])*
2379        $pub:vis $name:ident != [$($keywords:tt),+ $(,)?]
2380        $(;$($cont:tt)*)?
2381    ) => {
2382        $crate::keyword!{
2383            @{!} $(#[$attribute])* $pub $name [$($keywords),+]
2384        }
2385        $crate::keyword!{$($($cont)*)?}
2386    };
2387    (
2388        @{$($not:tt)?} $(#[$attribute:meta])*
2389        $pub:vis $name:ident [$($keywords:tt),+]
2390        $(;$($cont:tt)*)?
2391    ) => {
2392        $(#[$attribute])*
2393        // TODO $crate::docgen!{keyword {$($not)?} {$keywords}},
2394        #[doc = concat!(
2395             $crate::docgen!{@keyword_header $($not)?},
2396             $($crate::docgen!{@keyword_doc $keywords}),+
2397        )]
2398        #[derive(Debug, Clone, PartialEq, Eq)]
2399        $pub struct $name($crate::CachedIdent);
2400
2401        impl $crate::Parser for $name {
2402            fn parser(tokens: &mut $crate::TokenIter) -> $crate::Result<Self> {
2403                use $crate::{Parse, RefineErr};
2404                let at = tokens.clone().next();
2405                $crate::CachedIdent::parse_with(tokens, |ident, tokens| {
2406                    if $($not)? Self::matches(ident.as_str()) {
2407                        Ok($name(ident))
2408                    } else {
2409                        $crate::Error::other::<$name>(
2410                            at,
2411                            tokens,
2412                            format!(
2413                                "keyword for {:?} expected, got {:?} at {:?}",
2414                                stringify!($name),
2415                                ident.as_str(),
2416                                ident.span().start()
2417                            ),
2418                        )
2419                    }
2420                }).refine_err::<Self>()
2421            }
2422        }
2423
2424        impl $crate::ToTokens for $name {
2425            fn to_tokens(&self, tokens: &mut $crate::TokenStream) {
2426                self.0.to_tokens(tokens);
2427            }
2428        }
2429
2430        impl AsRef<str> for $name {
2431            fn as_ref(&self) -> &str {
2432                self.0.as_str()
2433            }
2434        }
2435
2436        impl AsRef<$crate::Ident> for $name {
2437            fn as_ref(&self) -> &$crate::Ident {
2438                &*self.0
2439            }
2440        }
2441
2442        impl $name {
2443            /// get the underlying `&str` from a keyword
2444            #[allow(dead_code)]
2445            pub fn as_str(&self) -> &str {
2446                self.0.as_str()
2447            }
2448
2449            #[doc(hidden)]
2450            #[inline]
2451            pub const fn keywords() -> &'static $crate::KeywordGroup {
2452                static KEYWORDS: $crate::KeywordGroup = $crate::keyword! {@group $($keywords),+};
2453                &KEYWORDS
2454            }
2455
2456            fn matches(this: &str) -> bool {
2457                static MATCHFN: std::sync::LazyLock<Box<dyn Fn(&str) -> bool + Send + Sync>> =
2458                    std::sync::LazyLock::new(|| $crate::create_matchfn($name::keywords()));
2459                MATCHFN(this)
2460            }
2461        }
2462
2463        $crate::keyword!{$($($cont)*)?}
2464    };
2465    () => {};
2466
2467    (@default $name:ident $str:literal) => {
2468        impl Default for $name {
2469            fn default() -> Self {
2470                use $crate::{ToTokens, Parse};
2471                Self($crate::CachedIdent::parse(&mut $str.to_token_iter()).unwrap())
2472            }
2473        }
2474    };
2475
2476    // keyword group creation
2477    (@group $($entry:tt),+) => {
2478        $crate::KeywordGroup::List(
2479            &[$(&$crate::keyword!{@entry $entry}),+]
2480        )
2481    };
2482    (@entry $kw:literal) => {
2483        $crate::KeywordGroup::Keyword($kw)
2484    };
2485    (@entry $sub:path) => {
2486        *<$sub>::keywords()
2487    };
2488}
2489
2490/// Define types matching operators (punctuation sequences).
2491///
2492/// `operator!{ pub Op = "punct"; ...}`
2493///
2494/// * A optional `pub` defines the operators public, default is private
2495/// * `Op` is the name for the struct to be generated
2496/// * `"punct"` is up to 4 ASCII punctuation characters
2497///
2498/// `Op::parse()` will match the defined operator. It will implement `Debug` and `Clone`
2499/// for operators.
2500///
2501/// The [`unsynn!`] macro supports defining operators by using `operator Op = "chars";`, the
2502/// `pub` specification has to come before `operator` then. See the
2503/// [unsynn! operator documentation](crate::unsynn#keywords-and-operators) for details.
2504///
2505/// For predefined operators, see [`operator::names`](crate::operator::names) which includes
2506/// common operators like `Plus`, `Minus`, `Star`, `Arrow`, etc.
2507///
2508/// # Example
2509///
2510/// ```
2511/// # use unsynn::*;
2512/// operator!{
2513///     /// Optional documentation for `<~~`
2514///     WLArrow = "<~~";
2515///     WRArrow = "~~>";
2516/// }
2517///
2518/// let mut tokens = "<~~~~> ~~><~~".to_token_iter();
2519/// let wl = WLArrow::parse(&mut tokens).unwrap();
2520/// assert_tokens_eq!(wl, str "<~~");
2521/// let wr = WRArrow::parse(&mut tokens).unwrap();
2522/// assert_tokens_eq!(wr, str "~~>");
2523/// # let wr = WRArrow::parse(&mut tokens).unwrap();
2524/// # assert_tokens_eq!(wr, "~~>");
2525/// # let wl = WLArrow::parse(&mut tokens).unwrap();
2526/// # assert_tokens_eq!(wl, "<~~");
2527/// ```
2528#[macro_export]
2529macro_rules! operator{
2530    // match a list of operator! defs
2531    ($($(#[$attribute:meta])* $pub:vis $name:ident = $op:literal);*$(;)?) => {
2532        $(
2533            $crate::operator!(@operator $(#[$attribute])* $pub $name = $op);
2534        )*
2535    };
2536
2537    // match a single operator! defs with len 1-4
2538    (@operator $(#[$attribute:meta])* $pub:vis $name:ident = $op:literal) => {
2539        $(#[$attribute])*
2540        // TODO $crate::docgen!{operator $op},
2541        #[doc = $crate::docgen!{@operator_doc $op}]
2542        $pub type $name = $crate::Operator<
2543        {
2544                assert!(
2545                    $op.len() >= 1 && $op.len() <= 4,
2546                    "Operators must be 1-4 ASCII punctuation characters"
2547                );
2548                let c0 = $crate::operator!(@char_at 0 $op);
2549                assert!(c0.is_ascii_punctuation(), "Operator must be ASCII punctuation");
2550                c0
2551        },
2552        {
2553                let c1 = $crate::operator!(@char_at 1 $op);
2554                assert!(c1 == '\0' || c1.is_ascii_punctuation(), "Operator must be ASCII punctuation");
2555                c1
2556        },
2557        {
2558                let c2 = $crate::operator!(@char_at 2 $op);
2559                assert!(c2 == '\0' || c2.is_ascii_punctuation(), "Operator must be ASCII punctuation");
2560                c2
2561        },
2562        {
2563                let c3 = $crate::operator!(@char_at 3 $op);
2564                assert!(c3 == '\0' || c3.is_ascii_punctuation(), "Operator must be ASCII punctuation");
2565                c3
2566        },
2567        >;
2568    };
2569
2570    // get a single ascii character from a literal string
2571    (@char_at $at:literal $op:literal) => {
2572       const {
2573           concat!($op, "\0\0\0").as_bytes()[$at] as char
2574       }
2575    }
2576}
2577
2578// The documentation generator
2579#[cfg(not(feature = "docgen"))]
2580#[doc(hidden)]
2581#[macro_export]
2582macro_rules! docgen {
2583    // just dispose anything
2584    ($($_:tt)*) => {
2585        ""
2586    };
2587}
2588
2589#[cfg(feature = "docgen")]
2590#[doc(hidden)]
2591#[macro_export]
2592macro_rules! docgen {
2593    (@keyword_header) => {
2594        "Matches: "
2595    };
2596    (@keyword_header !) => {
2597        "Matches any `Ident` but: "
2598    };
2599    (@keyword_doc $kw:literal) => {
2600        concat!("`", $kw, "`, ")
2601    };
2602    (@keyword_doc $sub:path) => {
2603        concat!("[`", stringify!($sub), "`], ")
2604    };
2605    (@operator_doc $op:literal) => {
2606        concat!("`", $op, "`")
2607    };
2608}
2609
2610/// unsynn provides its own `quote!{}` macro that translates tokens into a `TokenStream` while
2611/// interpolating variables prefixed with a `Pound` sign (#). This is similar to what the quote macro from
2612/// the quote crate does but not as powerful. There is no `#(...)` repetition (yet).
2613///
2614/// Instead we provide `#{...}` blocks which must return a `IntoIterator` whose items
2615/// implement `ToTokens`. When blocks returns a single value just wrap this in `Some()`
2616/// because `Option` implements the necessary `IntoIterator`.
2617///
2618///
2619/// # Example
2620///
2621/// ```
2622/// # use unsynn::*;
2623/// let ast = <Cons<ConstInteger<1>, Plus, ConstInteger<2>>>::default();
2624/// let quoted = quote! { let a = #ast;};
2625/// assert_tokens_eq!(quoted, "let a = 1+2;");
2626///
2627/// // or using #{...} blocks
2628/// let quoted = quote! {
2629///     let a = #{Some(<Cons<ConstInteger<1>, Plus, ConstInteger<2>>>::default())};
2630/// };
2631/// assert_tokens_eq!(quoted, "let a = 1+2;");
2632/// ```
2633#[macro_export]
2634macro_rules! quote {
2635    ($($tokens:tt)*) => {
2636        {
2637            let mut tokenstream = $crate::TokenStream::new();
2638            $crate::quote_intern!{tokenstream $($tokens)*};
2639            tokenstream
2640        }
2641    };
2642}
2643
2644#[doc(hidden)]
2645#[macro_export]
2646macro_rules! quote_intern {
2647    ($tokenstream:ident #$var:ident $($rest:tt)*) => {
2648        $var.to_tokens(&mut $tokenstream);
2649        $crate::quote_intern!{$tokenstream $($rest)*}
2650    };
2651    ($tokenstream:ident #{$($code:tt)*} $($rest:tt)*) => {
2652        {$($code)*}.into_iter().for_each(|i| i.to_tokens(&mut $tokenstream));
2653        $crate::quote_intern!{$tokenstream $($rest)*}
2654    };
2655    // hash followed by parenthesis is reserved
2656    ($tokenstream:ident #($($reserved:tt)*) $($rest:tt)*) => {
2657        compile_error!("#(...) reserved for future")
2658    };
2659    ($tokenstream:ident ( $($nested:tt)* ) $($rest:tt)*) => {
2660        $tokenstream.extend(
2661            Some(
2662                $crate::TokenTree::Group(
2663                    $crate::Group::new($crate::Delimiter::Parenthesis, $crate::quote!{$($nested)*})
2664                )
2665            ).into_iter()
2666        );
2667        $crate::quote_intern!{$tokenstream $($rest)*}
2668    };
2669    ($tokenstream:ident { $($nested:tt)* } $($rest:tt)*) => {
2670        $tokenstream.extend(
2671            Some(
2672                $crate::TokenTree::Group(
2673                    $crate::Group::new($crate::Delimiter::Brace, $crate::quote!{$($nested)*})
2674                )
2675            ).into_iter()
2676        );
2677        $crate::quote_intern!{$tokenstream $($rest)*}
2678    };
2679    ($tokenstream:ident [ $($nested:tt)* ] $($rest:tt)*) => {
2680        $tokenstream.extend(
2681            Some(
2682                $crate::TokenTree::Group(
2683                    $crate::Group::new($crate::Delimiter::Bracket, $crate::quote!{$($nested)*})
2684                )
2685            ).into_iter()
2686        );
2687        $crate::quote_intern!{$tokenstream $($rest)*}
2688    };
2689
2690    ($tokenstream:ident $token:tt $($rest:tt)*) => {
2691        let t: $crate::TokenStream = std::str::FromStr::from_str(stringify!($token)).unwrap();
2692        $tokenstream.extend(Some(t).into_iter());
2693        $crate::quote_intern!{$tokenstream $($rest)*}
2694    };
2695
2696    ($tokenstream:ident) => {};
2697}