使用nom解析整数会导致不完整

spe*_*ase 3 rust nom

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

named!(my_u64(&str) -> u64,
    map_res!(recognize!(nom::digit), u64::from_str)
);
Run Code Online (Sandbox Code Playgroud)

测试:

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

有时在我的变体(例如添加complete!)中,如果我在最后添加一个字符,我已经能够解析它.

我想得到一个工作解析(最终我希望这将允许我为u64包装类型创建一个解析器)但更大的图片我想了解如何正确地自己构建一个解析器.

Gra*_*Cat 8

至于nom 5.1.1组合解析器的方法从基于宏更改为基于函数,在nom 的作者博客中进行了更广泛的讨论。

随着这一变化,另一个随之而来的变化 -完整的解析器现在驻留在不同的模块中,你需要明确地选择你需要的解析类型。大多数情况下,模块名称有明显的区别。

旧的宏被保留,但它们在流模式下严格工作。像CompleteStrCompleteByteSlice已经消失的类型。

要编写您要求使用新方式的代码,例如像这样(注意character::complete导入中的显式

因为我花了一些时间来掌握它 - 解析器例如map_res返回 aimpl Fn(I) -> IResult<I, O2, E>这就是为什么有额外的一对括号 - 来调用该闭包。

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);
    }
}
Run Code Online (Sandbox Code Playgroud)


Joe*_*lay 5

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

实际上,如果解析器用完输入,它不能告诉大家,它意味着已经用完输入,它会始终返回Err::Incomplete.这可能还包含有关解析器预期输入的确切数据的信息(在您的情况下,至少还有1个字节).

它确定是否可能使用AtEof特征进一步输入.这总是返回false&str&[u8],因为它们不提供有关它们是否是完整的还是不任何信息!

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

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

named!(my_u64(CompleteStr) -> u64,
    map_res!(recognize!(nom::digit), u64::from_str)
);
Run Code Online (Sandbox Code Playgroud)

你的测试看起来像这样:

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

有关详细信息,请参阅Nom 4的公告帖子.