[英]Can I specify an operator or other syntactic literal within a macro input?
首先,我知道这不是很好地使用宏,但我正在学习我能做什么。
我有一个结构Rational
:
pub struct Rational{
pub n: i128,
pub d : i128
}
我有一个构建这些的宏:
macro_rules! rat{
($n : expr, $d : expr) => {
Rational{n : $n,d: $d}
}
}
调用该宏的语法如下所示: rat,(1, 3)
。 我希望它直观地显示小数格式,因此您可以像rat!(1 / 3)
那样称呼它,宏将解析该表达式以产生相同的结果。 (请注意,如果它首先评估1/3
,即使是浮点类型,它也不会完全对应,因为1/3
不完全对应于任何浮点数。)
我希望有一些语法,例如:
macro_rules! rat{
($n : expr `/` $d : expr) => {
Rational{n : $n,d: $d}
}
}
我可以在其中指定要在调用中使用的语法。 (当然,这种尝试不会编译。)
同样,显然这是一个愚蠢的 X/Y 问题等等。 对于上下文,我正在考虑构建一个方程式争论系统,并且在某些时候我希望能够从 math-y 语法中解析事物,这实际上可能证明使用宏是合理的。 这只是一小步。
使用声明性宏是否存在这样的事情? 如果没有,是否可以使用程序宏? 最后,我知道在 Scala 宏中,没有办法使它对文字值起作用,因为表达式1/3
会在编译过程的早期被解析,甚至在调用宏时 AST 也会消失。 Rust也是这样吗?
是的,您可以直接在规则中使用/
令牌:
#[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 }
但是,请注意我已将 arguments 从expr
更改为literal
。 你的问题似乎暗示这对你的用例来说很好,但我提出它是因为至少第一个参数$n
不能是expr
。 这会导致解析歧义,因为/
是表达式的有效延续,而 Rust 根本不允许/
作为expr
之后的分隔符。 这适用于所有运营商; 从follow-set ambiguity restrictions , only =>
, ,
, or ;
可以跟随一个expr
。
如果你确实想允许任何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.