如何使用宏生成可能包含或不包含关联值的枚举变量?

时间:2018-08-25 19:09:56

标签: enums rust rust-macros

我试图创建一个宏来定义一些代表汇编指令的枚举变量。

现在,我有以下工作正常。这几乎没有用,但是最终我将添加一些自动派生的方法,以便稍后使用:

macro_rules! define_instructions {
    ($($inames:tt),+ $(,)*) => {
        #[derive(Debug)]
        pub enum Instruction {
            $($inames),*
        }
    };
}

define_instructions! {
    PsqLux,
    PsqLx,
    Twi,
}

fn main() {}

问题在于,我要添加的大多数(但不是全部)变体需要具有关联的值:

define_instructions! {
    PsqLux(u32, u32, u32, u32, u32),
    PsqLx(u32, u32, u32, u32, u32),
    Twi(u32, u32, u32),
    SomethingWithoutAVariant,
}

我尝试使用它来允许变量具有关联的值(它实际上还不支持关联的值,这只是一个开始):

macro_rules! define_instructions {
    (@define) => {};

    (@define $iname:ident) => {
        $iname,
    };

    (@define $iname:ident $($inames:tt)*) => {
        $iname,
        define_instructions! { @define $($inames)* }
    };

    ($($inames:tt),+ $(,)*) => {
        #[derive(Debug)]
        pub enum Instruction {
            define_instructions! { @define $($inames)* }
        }
    };
}

define_instructions! {
    PsqLux,
    PsqLx,
    Twi,
}

该代码给了我这个错误:

error: expected one of `(`, `,`, `=`, `{`, or `}`, found `!`
  --> src/main.rs:17:32
   |
17 |               define_instructions! { @define $($inames)* }
   |                                  ^ expected one of `(`, `,`, `=`, `{`, or `}` here
...
22 | / define_instructions! {
23 | |     PsqLux,
24 | |     PsqLx,
25 | |     Twi,
26 | | }
   | |_- in this macro invocation

似乎我不能在enum定义中使用宏。假设是真的,我如何解决此问题并能够生成可能包含或可能不包含关联值的枚举变量?

注意:我确定我添加的规则有问题,但我至少希望能够解决这些问题,以便我能他们正在工作。

修改

mcarton explained另一种做我想做的事情的方法,目前很有用。

但是我仍然想知道如何在枚举定义中使用宏,因为将来我会喜欢这样编写宏:

define_instructions! {
    /// Name: Trap Word Immediate
    /// Simplified Mnemonics:
    /// twgti rA, value = twi 8, _rA, _value
    /// twllei rA, value = twi 6, _rA, _value
    twi TO, rA, SIMM;

    // and so on...  
}

// That macro would become

pub enum Instruction {
    /// Name: Trap Word Immediate
    /// Usage: twi TO, rA, SIMM
    /// Simplified Mnemonics:
    /// twi 8, rA, value = twgti rA, value
    /// twllei rA, value = twi 6, rA, value
    Twi(u32, u32, u32, u32, u32),
}

所以我有解决方法,但是我仍然很好奇是否可以在enum定义中使用宏。那有可能吗,如果没有,为什么不呢?

0 个答案:

没有答案