parsingrustparser-combinatorsnom

How to force nom to parse the whole input string?


I am working with nom version 6.1.2 and I am trying to parse Strings like A 2 1 2.

At the moment I would be happy to at least differentiate between input that fits the requirements and inputs which don't do that. (After that I would like to change the output to a tuple that has the "A" as first value and as second value a vector of the u16 numbers.)

The String always has to start with a capital A and after that there should be at least one space and after that one a number. Furthermore, there can be as much additional spaces and numbers as you want. It is just important to end with a number and not with a space. All numbers will be within the range of u16. I already wrote the following function:

extern crate nom;

use nom::sequence::{preceded, pair};
use nom::character::streaming::{char, space1};
use nom::combinator::recognize;
use nom::multi::many1;
use nom::character::complete::digit1;


pub fn parse_and(line: &str) -> IResult<&str, &str>{
    preceded(
        char('A'),
        recognize(
            many1(
                pair(
                    space1,
                    digit1
                )
            )
        )
    )(line)
}

Also I want to mention that there are answers for such a problem which use CompleteStr but that isn't an option anymore because it got removed some time ago.

People explained that the reason for my behavior is that nom doesn't know when the slice of a string ends and therefore I get parse_and: Err(Incomplete(Size(1))) as answer for the provided example as input.


Solution

  • It seems like that one part of the use declarations created that problem. In the documentation (somewhere in some paragraph way to low that I looked at it) it says: " Streaming / Complete Some of nom's modules have streaming or complete submodules. They hold different variants of the same combinators.

    A streaming parser assumes that we might not have all of the input data. This can happen with some network protocol or large file parsers, where the input buffer can be full and need to be resized or refilled.

    A complete parser assumes that we already have all of the input data. This will be the common case with small files that can be read entirely to memory. "

    Therefore, the solution to my problem is to swap use nom::character::complete::{char, space1}; instead of nom::character::streaming::{char, space1}; (3rd loc without counting empty lines). That worked for me :)