枚举解析

  1. macro_rules! parse_unitary_variants {
  2. (@as_expr $e:expr) => {$e};
  3. (@as_item $($i:item)+) => {$($i)+};
  4. // Exit rules.
  5. (
  6. @collect_unitary_variants ($callback:ident ( $($args:tt)* )),
  7. ($(,)*) -> ($($var_names:ident,)*)
  8. ) => {
  9. parse_unitary_variants! {
  10. @as_expr
  11. $callback!{ $($args)* ($($var_names),*) }
  12. }
  13. };
  14. (
  15. @collect_unitary_variants ($callback:ident { $($args:tt)* }),
  16. ($(,)*) -> ($($var_names:ident,)*)
  17. ) => {
  18. parse_unitary_variants! {
  19. @as_item
  20. $callback!{ $($args)* ($($var_names),*) }
  21. }
  22. };
  23. // Consume an attribute.
  24. (
  25. @collect_unitary_variants $fixed:tt,
  26. (#[$_attr:meta] $($tail:tt)*) -> ($($var_names:tt)*)
  27. ) => {
  28. parse_unitary_variants! {
  29. @collect_unitary_variants $fixed,
  30. ($($tail)*) -> ($($var_names)*)
  31. }
  32. };
  33. // Handle a variant, optionally with an with initialiser.
  34. (
  35. @collect_unitary_variants $fixed:tt,
  36. ($var:ident $(= $_val:expr)*, $($tail:tt)*) -> ($($var_names:tt)*)
  37. ) => {
  38. parse_unitary_variants! {
  39. @collect_unitary_variants $fixed,
  40. ($($tail)*) -> ($($var_names)* $var,)
  41. }
  42. };
  43. // Abort on variant with a payload.
  44. (
  45. @collect_unitary_variants $fixed:tt,
  46. ($var:ident $_struct:tt, $($tail:tt)*) -> ($($var_names:tt)*)
  47. ) => {
  48. const _error: () = "cannot parse unitary variants from enum with non-unitary variants";
  49. };
  50. // Entry rule.
  51. (enum $name:ident {$($body:tt)*} => $callback:ident $arg:tt) => {
  52. parse_unitary_variants! {
  53. @collect_unitary_variants
  54. ($callback $arg), ($($body)*,) -> ()
  55. }
  56. };
  57. }
  58. #
  59. # fn main() {
  60. # assert_eq!(
  61. # parse_unitary_variants!(
  62. # enum Dummy { A, B, C }
  63. # => stringify(variants:)
  64. # ),
  65. # "variants : ( A , B , C )"
  66. # );
  67. # }

此宏展示了如何使用标记树撕咬机下推累积来解析类C枚举的变量。完成后的parse_unitary_variants!宏将调用一个回调宏,为后者提供枚举中的所有选择(以及任何附加参数)。

经过改造后,此宏将也能用于解析struct的域,或为枚举变量计算标签值,甚至是将任意一个枚举中的所有变量名称都提取出来。