0

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

Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
Kos
  • 1,547
  • 14
  • 23
  • Don't edit a SO question to include a new question. Ask a new question instead. I rolled back your edit. As for your question, it's impossible to parse generics syntax without TT munching, don't bother. – Chayim Friedman May 13 '22 at 04:37

1 Answers1

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.

Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77