Macros 为什么我不能匹配结构';在Rust宏中使用“block”匹配器的用户的身体?

Macros 为什么我不能匹配结构';在Rust宏中使用“block”匹配器的用户的身体?,macros,rust,Macros,Rust,我正在尝试匹配Rust宏中的结构。我得把钥匙拔出来 struct稍微分离一下以获得其名称。我想那街区 matcher会这么做的。考虑一下,例如: macro_rules! multi { (struct $name:ident $block:block) => { enum George {$name} } } multi!{ struct Fred { a:String } } 扩展到 enum George { Fre

我正在尝试匹配Rust宏中的
结构。我得把钥匙拔出来
struct
稍微分离一下以获得其名称。我想那街区 matcher会这么做的。考虑一下,例如:

macro_rules! multi {
    (struct $name:ident $block:block) => {
        enum George {$name}
    }
}

multi!{
    struct Fred {
        a:String
    }
}
扩展到

enum George { Fred, }
这差不多是对的

但是,如果我将其转换回
结构
,它将失败

macro_rules! multi {
    (struct $name:ident $block:block) => {
        struct $name $block
    }
}
这就产生了这个错误

错误:应为“where`、`{`、`(`)或`;`在结构名称之后,找到了`{a:String}`
-->src/main.rs:64:22
|
64 |结构$name$块
|^^^^^结构名称后应为where`、`{`、`(`)或`;`
看起来,
{a:String}
被视为单个标记,而不是
而不是被重新解析;但这是其中应该包含的内容。

$:block
匹配器用于块表达式,即一组大括号,其中包含零个或多个Rust语句和项以及可选的尾部返回值。例如,以下是块:

{
    let x = 1;
}
锈迹斑斑的花括号示例如下:

  • 职能机构
  • if
    else
    条款
  • for
    while
    loop
    循环的循环体
结构字段周围的大括号不是块,因为它们不应该包含零个或多个Rust语句和项目,后面跟着可选的尾部返回值。相反,它们应该包含结构字段的名称和类型

在宏中,可以使用模式
{$($tt:tt)*}
匹配任意一组花括号,这意味着“包含任意数量标记的花括号”


一旦您使用特定的匹配器(例如,
)匹配了某个对象,它将永远不会被重新解析为其他内容。
block
与block语句匹配,没有其他内容,特别是,
struct
主体不是block语句。。是的,你说得对,tt完成了我几乎放弃的在
宏规则中匹配Rust结构的工作。
。我认为这比它值得的麻烦多了。有很多情况下,有效的Rust语法实际上是不可能匹配的。@PeterHall我需要实现50个结构,所有结构都非常相似。宏是唯一的方法。@PhilLord还有其他方法。1-你可以发明自己的语法,更容易匹配,并生成结构。2-使用过程宏。
{
    #[derive(Default)]
    struct S;
    S::default()
}
macro_rules! multi {
    (struct $name:ident { $($tt:tt)* }) => {
        struct $name { $($tt)* }
    };
}

multi! {
    struct Fred {
        a: String,
    }
}