我正在写一个解析器:
match ch {
// ...
'b' => {
token.push('\b');
continue;
},
'f' => {
token.push('\f');
continue;
},
'n' => {
token.push('\n');
continue;
},
'r' => {
token.push('\r');
continue;
},
't' => {
token.push('\t');
continue;
},
// ...
},
有很多重复的代码,所以我正在考虑采用更优雅的方式。我认为这样的事情是可能的:
macro_rules! escaped_match {
($char:expr) => (
'$char' => {
token.push('\$char')
continue;
}
)
}
但我的希望消失了:
error: character literal may only contain one codepoint: '$
--> src/main.rs:3:9
|
3 | '$char' => {
| ^^
是否有更美妙的方法,无论是使用宏,编译器插件,黑客还是黑魔法?
答案 0 :(得分:4)
Rust宏不是C宏 - 您无法创建无效令牌,并希望它们在将来的某个时间有效。同样地,它们不是连接字符串的奇特方式,后来被解释为代码。
查看代码,似乎主要重复在push
和continue
。我可能会使用普通函数和模式匹配来干掉特定代码:
fn escape_char(c: char) -> Option<char> {
Some(match c {
// 'b' => '\b',
// 'f' => '\f',
'n' => '\n',
'r' => '\r',
't' => '\t',
_ => return None,
})
}
fn main() {
// ...
if let Some(escape) = escape_char('b') {
token.push(escape);
continue;
}
// ...
}
现在,映射被限制为单个x => '\y'
行。
请注意,\b
和\f
在Rust中无法识别转义码;不确定你要为那些人做些什么。