有没有更美妙的方法将字符文字转换为相应的转义字符?

时间:2016-10-14 22:36:09

标签: rust

我正在写一个解析器:

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' => {
  |         ^^

是否有更美妙的方法,无论是使用宏,编译器插件,黑客还是黑魔法?

1 个答案:

答案 0 :(得分:4)

Rust宏不是C宏 - 您无法创建无效令牌,并希望它们在将来的某个时间有效。同样地,它们不是连接字符串的奇特方式,后来被解释为代码。

查看代码,似乎主要重复在pushcontinue。我可能会使用普通函数和模式匹配来干掉特定代码:

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中无法识别转义码;不确定你要为那些人做些什么。