'Using recursive declarative macros to create enums

Is it possible to write a declarative macro in Rust that takes a tree like structure of blocks and creates a combined assortment of enums? I'm trying to determine if this is only possible with procedural macros, or if I can get away with using TT munchers. Recursion isn't the only challenge, as I would also need to combine the identifiers used to label each block, like Exposure and Mode becoming ExposureMode, which I can't seem to find a means of achieving.

For example, given a statement like:

enum_tree! {
  Exposure {
    Mode {
      FullAuto,
      Manual,
      ShutterPriority,
      IrisPriority,
      GainPriority,
    },
    Iris {
      Reset,
      Up,
      Down,
      Direct(u8),
    },
  },
  Focus {
    In,
    Out,
    Stop,
  }
}

would yield a result like:

enum ExposureMode {
    FullAuto,
    Manual,
    ShutterPriority,
    IrisPriority,
    GainPriority,
}
enum ExposureIris {
    Reset,
    Up,
    Down,
    Direct(u8),
}
enum Focus {
    In,
    Out,
    Stop,
}


Solution 1:[1]

If I remember correctly, tt-munchers are turing-complete and thus almost equivalent to proc macros. Even if they are not in general, this problem is solvable with them.

The only thing they cannot do is to manipulate atoms... Like concatenating identifiers. There is the concat_ident!() macro for that, but as explained in its documentation:

Also, as a general rule, macros are only allowed in item, statement or expression position. That means while you may use this macro for referring to existing variables, functions or modules etc, you cannot define a new one with it.

So it is not applicable in this case. However, that doesn't mean you cannot use a macro_rules, because people have already wrote crates with proc macros that can concatenate identifiers. A popular example is paste.

However, if the macro is complex, you may find it much easier to understand and write as a proc macro.

See also Is it possible to declare variables procedurally using Rust macros?.

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