如何在nom中匹配CSV样式的引用字符串?

时间:2018-06-07 11:55:15

标签: csv rust nom

出于此问题的目的,CSV样式引用字符串是一个字符串,其中包含:

  1. 字符串的开头和结尾只有一个"
  2. 字符串中的两个双引号折叠为一个双引号。 "Alo""ha"Alo"ha
  3. “”本身就是一个空字符串。
  4. 无法解析错误输入,例如"A""" e"。这是A",其次是垃圾e"
  5. 我尝试了几件事,但都没有完全发挥作用。

    我得到的最接近的,感谢Mozilla IRC上#nom用户粉红色的一些帮助:

    use std::error as stderror; /* Avoids needing nightly to compile */
    
    named!(csv_style_string<&str, String>, map_res!(
       terminated!(tag!("\""), not!(peek!(char!('"')))),
       csv_string_to_string
    ));
    
    fn csv_string_to_string(s: &str) -> Result<String, Box<stderror::Error>> {
       Ok(s.to_string().replace("\"\"", "\""))
    }
    

    这不会正确捕获字符串的结尾。

    我还尝试将re_match!宏与r#""([^"]|"")*""#一起使用,但总会产生Err::Incomplete(1)

    我已经确定given CSV example for Nom 1.0对于引用的CSV字符串不起作用,因为我正在描述它,但我知道实现方式不同。

1 个答案:

答案 0 :(得分:2)

这是一种方法:

map!()

(我用完全名词写的,但像你这样的解决方案,基于外部函数而不是nom每个角色,也会起作用,并且可能更有效。)

这里的魔力,也可以解决你的正则表达式问题,就是使用CompleteStr。这基本上告诉nom在输入之后没有任何内容(否则,"假设您正在进行流式解析器,因此可能会有更多输入。)

这是必需的,因为我们需要知道如果nom"的最后一个字符,该怎么办。根据其后面的字符(另一个Incomplete,正常字符或EOF),我们必须做出不同的决定 - 因此nom结果,意味着nom不会有足够的投入来做出决定。告诉Incomplete EOF接下来会解决这个犹豫不决的问题。

进一步阅读nom作者博客上的csv_style_stringhttp://unhandledexpression.com/general/2018/05/14/nom-4-0-faster-safer-simpler-parsers.html#dealing-with-incomplete-usage

您可能会注意到,此解析器实际上并不拒绝无效输入,但会解析开头并返回其余内容。如果你在另一个解析器中使用这个解析器作为子解析器,后者会将余数提供给下一个subparser,这也会崩溃(因为它会期望一个逗号),导致整个解析器失败。

如果您不想这样,可以peek!(alt!(char!(',')|char!('\n")|eof!()))匹配Startup.cs