繁体   English   中英

我可以在宏输入中指定运算符或其他语法文字吗?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM