[英]Can I specify an operator or other syntactic literal within a macro input?
First, I know this is not a good use of macros but I'm learning what I can do.首先,我知道这不是很好地使用宏,但我正在学习我能做什么。
I have a struct Rational
:我有一个结构
Rational
:
pub struct Rational{
pub n: i128,
pub d : i128
}
I have a macro that builds these:我有一个构建这些的宏:
macro_rules! rat{
($n : expr, $d : expr) => {
Rational{n : $n,d: $d}
}
}
The syntax for calling that macro looks like: rat,(1, 3)
.调用该宏的语法如下所示:
rat,(1, 3)
。 I would like it to visually show a fractional format, so you would call it like rat!(1 / 3)
instead, and the macro would parse that expression to yield the same result.我希望它直观地显示小数格式,因此您可以像
rat!(1 / 3)
那样称呼它,宏将解析该表达式以产生相同的结果。 (Note that if it first evaluates 1/3
, even as a float type, it will not exactly correspond as 1/3
does not correspond exactly to any float.) (请注意,如果它首先评估
1/3
,即使是浮点类型,它也不会完全对应,因为1/3
不完全对应于任何浮点数。)
I'm hoping there's some syntax like:我希望有一些语法,例如:
macro_rules! rat{
($n : expr `/` $d : expr) => {
Rational{n : $n,d: $d}
}
}
where I can specify syntax to be used in the call.我可以在其中指定要在调用中使用的语法。 (That attempt does not compile, of course.)
(当然,这种尝试不会编译。)
Again, obviously this is silly and an X/Y problem and all that.同样,显然这是一个愚蠢的 X/Y 问题等等。 For context, I'm considering building an equation wrangling system, and at some point I'd like to be able to parse things from a math-y syntax, which might actually justify the use of macros.
对于上下文,我正在考虑构建一个方程式争论系统,并且在某些时候我希望能够从 math-y 语法中解析事物,这实际上可能证明使用宏是合理的。 This is just a baby step.
这只是一小步。
Does such a thing exist using declarative macros?使用声明性宏是否存在这样的事情? If not, is it possible with procedural macros?
如果没有,是否可以使用程序宏? Finally, I know that in Scala macros there would be no way to make that work for literal values, because the expression
1/3
would be resolved so early in the compilation process the AST would be gone by the time even macros are called.最后,我知道在 Scala 宏中,没有办法使它对文字值起作用,因为表达式
1/3
会在编译过程的早期被解析,甚至在调用宏时 AST 也会消失。 Is that also the case in Rust? Rust也是这样吗?
Yes, you can use the /
token directly in the rule:是的,您可以直接在规则中使用
/
令牌:
#[derive(Debug)]
struct Rational{
n: i128,
d: i128
}
macro_rules! rat {
($n:literal / $d:literal) => {
Rational { n: $n, d: $d }
};
}
fn main() {
println!("rat!(1 / 3) = {:?}", rat!(1 / 3));
}
rat!(1 / 3) = Rational { n: 1, d: 3 }
However, notice I have changed the arguments from expr
to literal
.但是,请注意我已将 arguments 从
expr
更改为literal
。 Your question seems to imply this is fine for your use-case, but I bring it up because at least the first parameter $n
cannot be an expr
.你的问题似乎暗示这对你的用例来说很好,但我提出它是因为至少第一个参数
$n
不能是expr
。 It would cause a parsing ambiguity because /
is a valid continuation of an expression and Rust simply doesn't allow /
as a separator after a expr
.这会导致解析歧义,因为
/
是表达式的有效延续,而 Rust 根本不允许/
作为expr
之后的分隔符。 And this goes for all operators;这适用于所有运营商; from the follow-set ambiguity restrictions , only
=>
, ,
, or ;
从follow-set ambiguity restrictions , only
=>
, ,
, or ;
may follow an expr
.可以跟随一个
expr
。
If you do want to allow any expr
, a common trick is to require parenthesis:如果你确实想允许任何
expr
,一个常见的技巧是需要括号:
macro_rules! rat {
($n:literal / $d:expr) => {
Rational { n: $n, d: $d }
};
(($n:expr) / $d:expr) => {
Rational { n: $n, d: $d }
};
}
fn main() {
println!("rat!(1 / 3) = {:?}", rat!(1 / 3));
println!("rat!((1 + 2) / 3) = {:?}", rat!((1 + 2) / 3));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.