生成宏的Rust宏

huangapple go评论76阅读模式
英文:

Rust macro to generate a macro

问题

I'm writing some macros that are all really similar (MWE the actual ones are much larger):

macro_rules! var1 {
  () => {some_func(some_enum::Var1, vec![])};
  ($($e:expr),*) => {some_func(some_enum::Var1, vec![$($s),*])};
}
macro_rules! var2 {
  () => {some_func(some_enum::Var2, vec![])};
  ($($e:expr),*) => {some_func(some_enum::Var2, vec![$($s),*])};
}

I instead decided to try different brackets

macro_rules! var {
  () => {some_func(some_enum::Var1, vec![])};
  ($($e:expr),*) => {some_func(some_enum::Var1, vec![$($s),*])};
  [] => {some_func(some_enum::Var2, vec![])};
  [$($e:expr),*] => {some_func(some_enum::Var2, vec![$($s),*])};
}

which didn't work. This would have been my preferred method to do this so if you know how to do this that's be greatly appreciated.

I instead tried to use a macro to generate the other macros:

macro_rules! generator {
  ($t:ident, $s:expr) => {
    macro_rules! $t {
      () => {some_func($s:expr, vec![])};
      ($($e:expr),*) => {some_func($s:expr, vec![$($s),*])};
    }
  };
}
generator!(var1, some_enum::Var1);
generator!(var2, some_enum::Var2);

This gives me the error "attempted to repeat an expression containing no syntax variables matched as repeating at this depth" and I don't know what it means.

英文:

I'm writing some macros that are all really similar (MWE the actual ones are much larger):

macro_rules! var1 {
  () => {some_func(some_enum::Var1, vec![])};
  ($($e:expr),*) => {some_func(some_enum::Var1, vec![$($s),*])};
}
macro_rules! var2 {
  () => {some_func(some_enum::Var2, vec![])};
  ($($e:expr),*) => {some_func(some_enum::Var2, vec![$($s),*])};
}

I instead decided to try different brackets

macro_rules! var {
  () => {some_func(some_enum::Var1, vec![])};
  ($($e:expr),*) => {some_func(some_enum::Var1, vec![$($s),*])};
  [] => {some_func(some_enum::Var2, vec![])};
  [$($e:expr),*] => {some_func(some_enum::Var2, vec![$($s),*])};
}

which didn't work. This would have been my preferred method to do this so if you know how to do this that's be greatly appreciated.

I instead tried to use a macro to generate the other macros:

macro_rules! generator {
  ($t:ident, $s:expr) => {
    macro_rules! $t {
      () => {some_func($s:expr, vec![])};
      ($($e:expr),*) => {some_func($s:expr, vec![$($s),*])};
    }
  };
}
generator!(var1, some_enum::Var1);
generator!(var2, some_enum::Var2);

This gives me the error "attempted to repeat an expression containing no syntax variables matched as repeating at this depth" andx I don't know what it means.

答案1

得分: 0

The error you're getting means that you use the repeat syntax $(),* without a syntax variable in it, which you see when you look at the full error message:

错误消息的意思是,您在重复语法中使用了$(),*,但没有包含语法变量,这是从完整的错误消息中可以看到的:

error: attempted to repeat an expression containing no syntax variables matched as repeating at this depth
  --> src/main.rs:10:9
   |
10 |       ($($e:expr),*) => {some_func($s:expr, vec![$($e),*])};
   |         ^^^^^^^^^

The problem is you try to use the special syntax to define syntax variables inside of a macro where it has some different special meaning.

问题是,您尝试在宏中使用特殊语法来定义语法变量,而这在宏中具有不同的特殊含义。

You can get around it by simply escaping the $ that you do not wish to expand on the first macro invocation:

您可以通过在第一个宏调用中简单地转义您不希望展开的$来解决这个问题:

macro_rules! generator {
  ($t:ident, $s:expr) => {
    macro_rules! $t {
      () => {some_func($s, vec![])};
      ($$($$e:expr),*) => {some_func($s, vec![$$($$e),*])};
    }
  }
}

But macro_metavar_expr isn't stable yet so you have to add #![feature(macro_metavar_expr)] at the top of your crate and compile with a nightly compiler.

macro_metavar_expr目前还不稳定,因此您需要在您的crate顶部添加#![feature(macro_metavar_expr)],并使用夜间编译器进行编译。

Note: added ; after the macro branches and fixed some other syntax errors in there as well.

注意:在宏分支后面添加了;,还修复了其中的一些其他语法错误。

英文:

The error you're getting means that you use the repeat syntax $(),* without a syntax variable in it, which you see when you look at the full error message:

error: attempted to repeat an expression containing no syntax variables matched as repeating at this depth
  --> src/main.rs:10:9
   |
10 |       ($($e:expr),*) => {some_func($s:expr, vec![$($e),*])};
   |         ^^^^^^^^^

The problem is you try to use the special syntax to define syntax variables inside of a macro where it has some different special meaning.
You can get around it by simply escaping the $ that you do not wish to expand on the first macro invocation:

macro_rules! generator {
  ($t:ident, $s:expr) => {
    macro_rules! $t {
      () => {some_func($s, vec![])};
      ($$($$e:expr),*) => {some_func($s, vec![$$($$e),*])};
    }
  }
}

But macro_metavar_expr isn't stable yet so you have to add #![feature(macro_metavar_expr)] at the top of your crate and compile with a nightly compiler.

Note: added ; after the macro branches and fixed some other syntax errors in there as well.

huangapple
  • 本文由 发表于 2023年3月7日 02:05:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/75654323.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定