在宏中重复一组标记

repeat a group of tokens in a macro

我正在尝试创建一个基于宏的有限状态机,但我在弄清楚如何让我的重复模式捕获多行标记时遇到了问题。我试过移动重复块并更改行之间的分隔符,但这似乎并没有让我更接近。我找不到在单个重复模式中使用多个标记的示例,所以我猜我违反了某种我找不到的规则...

macro_rules! build_machine {
    ($($state_a:tt : $activity:tt -> $state_b:tt),* $(,)*) => {
        #[derive(Debug)]
        enum State { $( $state_a, $state_b )* }

        #[derive(Debug)]
        enum Activity { $( $activity )* }
    }
}

build_machine!(
    Locked : TurnKey -> Unlocked,
    //Stopped : Push -> Moving,
);

fn main() {
    println!(
        "{:?} + {:?} -> {:?}",
        State::Locked,
        Activity::TurnKey,
        State::Unlocked,
    );
    // println!(
    //     "{:?} + {:?} -> {:?}",
    //     State::Stopped,
    //     Activity::Push,
    //     State::Moving,
    // );
}

它像这样按预期工作,但是在注释行中添加会出现奇怪的错误,抱怨缺少逗号 at the comma:

error: expected one of `(`, `,`, `=`, `{`, or `}`, found `Stopped`
  --> src/main.rs:13:5
   |
12 |     Locked : TurnKey -> Unlocked,
   |                                 -
   |                                 |
   |                                 expected one of `(`, `,`, `=`, `{`, or `}`
   |                                 help: missing `,`
13 |     Stopped : Push -> Moving,
   |     ^^^^^^^ unexpected token

我是宏的新手,但我认为使用 macro_rules 比使用 proc_macro 更合适。但是,如果不是这样,我也可以切换。

您在生成的代码中缺少逗号:

#[derive(Debug)]
enum State { $( $state_a, $state_b, )* }
//                                ^ this

#[derive(Debug)]
enum Activity { $( $activity, )* }
//                          ^ and this

如果没有这些,如果外部宏重复不止一次,您的宏将生成无效代码。

Playground