rust - 使用 nom 5.0 解析数字

标签 rust streaming nom

我正在尝试使用 Nom 5.0 解析一个大文件(数十 GB)流式传输。解析器的一部分尝试解析数字:

use nom::IResult;
use nom::character::streaming::{char, digit1};
// use nom::character::complete::{char, digit1};
use nom::combinator::{map, opt};
use nom::multi::many1;
use nom::sequence::{preceded, tuple};

pub fn number(input: &str) -> IResult<&str, &str> {
    map(
        tuple((
            opt(char('-')),
            many1(digit1),
            opt(preceded(char('.'), many1(digit1)))
        )),
        |_| "0"
    )(input)
}

(显然,它不应该为所有数字返回“0”;这只是为了使函数尽可能简单。)对于这个解析器,我写了一个测试:

#[test]
fn match_positive_integer() {
    let (_, res) = number("0").unwrap();
    assert_eq!("0", res);
}

此测试因 Incomplete(Size(1)) 而失败,因为“小数”opt() 想要读取数据,但它不存在。如果我切换到匹配器的 complete 版本(如注释掉的行),则测试通过。

我认为这实际上会在生产中起作用,因为当提示不完整时它会被提供额外的数据,但我仍然想创建单元测试。此外,如果一个数字恰好是文件中输入的最后一位,那么在生产中就会出现这个问题。我如何说服流式 Nom 解析器没有更多可用数据?

最佳答案

可以说测试的原始形式是正确的:解析器无法确定给定的输入是否为数字,因此解析结果实际上尚未确定。在生产中,尤其是像您一样读取大文件时,已读取但待解析字节的缓冲区可能恰好在可能 之间结束,除非它实际上不是。然后,解析器需要保留其当前状态并请求更多输入以便重试/继续。 Incomplete 不是最终错误,而是我什至不知道:这可能是一个错误,具体取决于下一个字节,这个问题目前还无法确定! .

您可以使用 complete-combinator 在你的顶级解析器上 所以当你实际上到达 EOF 时,你就错了。 不完整-results within 顶级解析器应该被处理,例如通过将读取缓冲区扩大一些余量并重试。

您可以将解析器包装在 complete() 中 - 当前单元测试的本地解析器并对其进行测试。一些符合的调子

#[test]
fn match_positive_integer() {
    let (_, res) = complete(number("0")).unwrap();
    assert_eq!("0", res);
}

关于rust - 使用 nom 5.0 解析数字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57914504/

相关文章:

macos - 错误 : linking with `cc` failed: exit code: 1

android - 流式传输 .m3u 音频

rust - 如何使用 nom 解析 Redis RESP 批量字符串?

json - 如何在 Express 4 中将 Promise 的 yield 结果作为流发送?

rust - 如何将 nom take_while 和 is_digit 用于 &str 输入

dependencies - Cargo 无法下载 nom v0.5.0

rust - 在 From 实现中 panic 是惯用的吗?

c# - 使用FFI将字符串从C#传递到Rust

rust - 如何通过在 Rust 中调用它们的方法来避免重复重新声明变量?

java - 在 HTTP Servlet 中正确地流式传输输入和输出