我正在尝试使用nom5.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()想要读取数据,但它并不存在。如果我切换到matchers的complete版本(如注释行),测试就会通过。
我认为这实际上会在生产中起作用,因为当抱怨不完整时,它会被输入额外的数据,但是我仍然希望创建单元测试。此外,如果某个数字恰好是文件中的最后一个输入,则该问题将发生在生产过程中。我如何使流no解析器相信没有更多的数据可用?
发布于 2019-09-16 18:38:55
可以说,测试的原始形式是正确的:解析器无法确定给定的输入是否为数字,因此解析结果实际上尚未确定。在生产中,特别是在像您这样读取大型文件时,已经读取但将被解析的字节的缓冲区可能在数字之间结束,除非它实际上不是。然后,解析器需要保留其当前状态,并请求更多的输入,以便可以重试/继续。不要把Incomplete看作是一个最终的错误,而是把它看作是I don't even know: This could be an error depending on the next byte, this problem is undecidable as of yet!。
您可以在顶级解析器上使用-combinator,因此当您实际到达EOF时,就会出现错误。应该处理顶级解析器中的Incomplete-results,例如,通过对读取缓冲区进行扩展并重新尝试。
您可以将解析器封装在本地到当前单元的complete()-parser中,并对其进行测试。某物的曲调
#[test]
fn match_positive_integer() {
let (_, res) = complete(number("0")).unwrap();
assert_eq!("0", res);
}https://stackoverflow.com/questions/57914504
复制相似问题