rust 声明性宏合并trait和结构体

bttbmeg0  于 2023-03-30  发布在  其他
关注(0)|答案(1)|浏览(165)

我想把一个宏称为这样的东西:

my_macro! {
  some_ident {
    fn any_number() -> char { 'a' }
    fn of_them() -> char { 'a' }
  }
  other1 {}
  other2 {}
}

我希望它合并内部块中的所有函数与宏产生的一个或多个函数。类似于以下内容:

macro_rules! my_macro {
  { $a:ident $b:tt $($c:ident $d:tt)+ } => {
    pub struct $a {}
    impl $a {
      fn something_new() { }
      $b
    }
  }
}

上面的代码不起作用,non-item in item list编译错误,因为在那个位置,它需要一个函数定义列表,但是$b是一个以{开始的单个块。使用$b:block给出了同样的错误。
有没有什么方法可以剥离块或其他东西,并获得内部的列表,所以我可以这样做?
我可以试试这样的:

macro_rules! my_macro {
  { $a:ident { $($b:tt)* } $($c:ident $($d:tt)*)+ } => {
    pub struct $a {}
    impl $a {
      fn something_new() { }
      $($b)*
    }
  }
}

但是这会产生一个multiple parsing options错误(显然 * 是贪婪的)。它不能决定提取另一个tt或匹配}并在$c:ident上移动。
我猜我可以做一些类型的$($v:vis fn $i:ident(...) $b:block)*拼出所有函数的整个匹配,但真的有必要吗?

xzlaal3s

xzlaal3s1#

正如Chayim Friedman所指出的,由于过度简化了我的实际代码,我在问题中的代码中犯了一些重大错误。
我误解了第二种方法中的错误。它最终出现在比赛的下半场$d附近。它周围缺少{...}
对于第一种方法,答案在错误消息中。当我看到non-item in item list时,我只是认为这意味着我在那里放了一些不是列表的东西,它需要一个列表。但它意味着item,就像在item语法片段中一样。
下面的工作。它也可以使用tt而不是item,但我认为item更准确。

macro_rules! my_macro {
  { $a:ident { $($b:item)* } $($c:ident { $($d:item)* })+ } => {
    pub struct $a {}
    impl $a {
      fn something_new() { }
      $($b)*
    }
  }
}

my_macro! {
  some_ident {
    fn any_number() -> char { 'a' }
    fn of_them() -> char { 'a' }
  }
  other1 {
    fn any_number();
  }
  other2 {}
}

相关问题