'How to parse a function with a declarative macro?

I need a declarative macro to parse a function.

I wrote one:

macro_rules! parse_fn
{

  () => {};

  (
    $( #[ $Meta : meta ] )*
    $( pub )?
    fn $Name : ident
    $( $Rest : tt )*
  )
  =>
  {
    $crate::parse_fn!
    {
      as DEFINE_FN
      as META $( #[ $Meta ] )*
      as VIS $( pub )?
      as NAME $Name
      as INPUT ()
      as OUTPUT
      as BLOCK {}
      as REST
        $( #[ $Meta ] )*
        $( pub )? fn $Name
        $( $Rest )*
    }
  };

  (
    as DEFINE_FN
    as META $( #[ $Meta : meta ] )*
    as VIS $( pub )*
    as NAME $Name : ident
    as INPUT $Input : tt
    as OUTPUT $( -> $Output : ty )?
    as BLOCK $Block : block
    as REST
      $Item : item
      $( $Rest : tt )*
  )
  =>
  {
    macro_rules! $Name
    {
      () =>
      {
        $Item
      };
    }
    $crate::parse_fn!
    {
      $( $Rest )*
    }
  };

}

But the problem of my solution is that it does not let pass visibility directive $( pub )?.

It gives

error: attempted to repeat an expression containing no syntax variables matched as repeating at this depth

There is workaround of duplicating of

  (
    $( #[ $Meta : meta ] )*
    pub
    fn $Name : ident
    $( $Rest : tt )*
  ) =>
...
  (
    $( #[ $Meta : meta ] )*
    fn $Name : ident
    $( $Rest : tt )*
  ) =>
...

But that solution is not good enough because visibility prefix is not only optional part, permutation of all combinations is too tedious.

Why am I getting the exception? Better solution to parse a function?

Playground



Solution 1:[1]

Use the :vis metaspecifier:

vis: a possibly empty Visibility qualifier

You got lucky: in other cases you would have to use a TT muncher for alternation.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Chayim Friedman