使用Rust macro_rules!实现方法时报错“no rules expected the token”的原因
Rust宏报错:
no rules expected this token 原因及解决 问题背景
本人此前使用C/C++,近期开始学习Rust。编写Scanner结构体(从stdio扫描数据并转换为指定类型)后,尝试通过macro_rules!编写宏来自动实现两个分别返回T和Vec<T>的辅助方法,但调用宏时出现错误:no rules expected this token。移除宏定义中的第三个参数及对应方法声明后,代码可正常运行,想了解错误的具体原因。
报错的宏代码
// 报错的宏定义 macro_rules! scanner_shortcut { ($scan_type:ident, $single_scan_ident:ident, &multi_scan_ident:ident) => { impl Scanner { fn $single_scan_ident(&mut self) -> $scan_type { self.next() } fn $multi_scan_ident(&mut self, n: usize) -> Vec<$scan_type> { (0..n).map(|_| self.next()).collect() } } }; } scanner_shortcut!(i32, scan_i32, scan_i32s); scanner_shortcut!(i64, scan_i64, scan_i64s);
正常运行的宏代码
// 正常运行的宏定义 macro_rules! scanner_shortcut { ($scan_type:ident, $single_scan_ident:ident) => { impl Scanner { fn $single_scan_ident(&mut self) -> $scan_type { self.next() } } }; } scanner_shortcut!(i32, scan_i32); scanner_shortcut!(i64, scan_i64);
错误原因
问题出在宏定义的第三个参数语法上:&multi_scan_ident:ident是错误写法。
在Rust的macro_rules!中,参数的标准格式是$参数名:指定符,你错误地在参数名前添加了&符号。这个&会被纳入宏的匹配规则,意味着调用宏时第三个参数前必须带有&,但你实际调用时传入的是scan_i32s这类不带&的标识符,宏找不到匹配的规则,因此抛出no rules expected this token错误。
修正方法
将宏定义里的&multi_scan_ident:ident修改为$multi_scan_ident:ident即可,修正后的宏代码如下:
macro_rules! scanner_shortcut { ($scan_type:ident, $single_scan_ident:ident, $multi_scan_ident:ident) => { impl Scanner { fn $single_scan_ident(&mut self) -> $scan_type { self.next() } fn $multi_scan_ident(&mut self, n: usize) -> Vec<$scan_type> { (0..n).map(|_| self.next()).collect() } } }; } scanner_shortcut!(i32, scan_i32, scan_i32s); scanner_shortcut!(i64, scan_i64, scan_i64s);
修改后宏可以正确匹配调用时传入的三个参数,生成对应的impl代码。
内容的提问来源于stack exchange,提问作者Jeonghyeon Kim
相关产品推荐
相关产品推荐

