解析带有nom的整数总是导致不完整

时间:2018-07-10 03:54:45

标签: rust nom

我所尝试的一切都给了我Incomplete(Size(1))。我现在最好的猜测是:

named!(my_u64(&str) -> u64,
    map_res!(recognize!(nom::digit), u64::from_str)
);

测试:

#[cfg(test)]
mod test {
    #[test]
    fn my_u64() {
        assert_eq!(Ok(("", 0)), super::my_u64("0"));
    }
}

有时候在我的变体中(例如添加complete!),如果我在末尾添加一个字符,我就能够解析它。

我希望对此进行有效的分析(最终我希望这将使我能够为u64包装类型创建一个解析器),但我想从整体上了解一下如何自己正确地构建解析器。

2 个答案:

答案 0 :(得分:5)

Nom 4使部分数据的处理比以前的版本更加严格,以更好地支持流解析器和自定义输入类型。

有效地,如果解析器用完了输入并且不能说输入已用完是 meant ,它将始终返回Err::Incomplete。这可能还包含有关解析器期望输入多少确切信息(在您的情况下,至少要多1个字节)。

它使用AtEof特性来确定是否还有更多输入。对于false&str,这总是返回&[u8],因为它们不提供有关它们是否完整的信息!

诀窍是更改解析器的输入类型,以明确表明输入将始终是完整的-为此,Nom提供了CompleteStrCompleteByteSlice包装器,也可以实现您的自己的输入类型。

因此,为了使您的解析器按预期工作,它需要看起来像这样:

named!(my_u64(CompleteStr) -> u64,
    map_res!(recognize!(nom::digit), u64::from_str)
);

您的测试将如下所示:

#[cfg(test)]
mod test {
    #[test]
    fn my_u64() {
        assert_eq!(Ok((CompleteStr(""), 0)), super::my_u64(CompleteStr("0")));
    }
}

有关更多详细信息,请参见the announcement post for Nom 4

答案 1 :(得分:5)

nom 5.1.1开始,用于组合解析器的方法已从基于宏的功能变为基于函数的功能,在nom's author blog中进行了更广泛的讨论。

随着这一更改,随后又出现了另一个问题- complete 解析器现在位于不同的模块中,您需要明确选择所需的解析类型。通常,模块名称之间有明显的区别。

保留了旧的宏,但它们严格在流模式下工作。 CompleteStrCompleteByteSlice之类的类型不见了。

要编写代码以寻求新的方法 ,您可以这样做(例如,注意导入中的显式character::complete

由于花了我一些时间来理解它-解析器,例如map_res返回一个impl Fn(I) -> IResult<I, O2, E>,这就是为什么要附加一对括号的原因-称其为闭包。 < / p>

use std::str;
use nom::{
    IResult,
    character::complete::{
        digit1
    },
    combinator::{
        recognize,
        map_res
    }
};

fn my_u64(input : &str) -> IResult<&str, u64> {
    map_res(recognize(digit1), str::parse)(input)
}

#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn test_my_u64() {
        let input = "42";
        let num = my_u64(input);
        assert_eq!(Ok(("", 42u64)), num);
    }
}