#parser #nom

nom-greedyerror

Custom error type to take a deepest error

7 unstable releases (3 breaking)

0.4.0 Aug 31, 2021
0.3.1 Nov 27, 2020
0.2.0 Apr 1, 2020
0.1.2 Oct 16, 2019

#20 in #nom

Download history 93/week @ 2021-07-01 125/week @ 2021-07-08 85/week @ 2021-07-15 96/week @ 2021-07-22 112/week @ 2021-07-29 160/week @ 2021-08-05 102/week @ 2021-08-12 136/week @ 2021-08-19 165/week @ 2021-08-26 49/week @ 2021-09-02 135/week @ 2021-09-09 83/week @ 2021-09-16 68/week @ 2021-09-23 82/week @ 2021-09-30 60/week @ 2021-10-07 101/week @ 2021-10-14

437 downloads per month
Used in 10 crates (4 directly)

MIT/Apache

16KB
322 lines

nom-greedyerror

Custom error type of nom to improve accuracy of error position.

Actions Status Crates.io Docs.rs

The default error types of nom ( (I, ErrorKind) and VerboseError ) take a last challenged error at alt combinator. Alternatively GreedyError of nom-greedyerror take a deepest error.

For example, the following parser accepts string like abc012abc or 012abc012.

alt((
    tuple((alpha1, digit1, alpha1)),
    tuple((digit1, alpha1, digit1)),
))(input)

If abc012::: is provided, we expect that the parse error happens at:

abc012:::
      ^

But VerboseError reports the parse error at:

abc012:::
^

This is because the last challenged parser is tuple((digit1, alpha1, digit1)) and it is failed. GreedyError reports the parse error at the expected position.

Requirement

nom must be 5.0.0 or later.

Usage

[dependencies]
nom-greedyerror = "0.4.0"

Example

use nom::branch::alt;
use nom::character::complete::{alpha1, digit1};
use nom::error::{ErrorKind, ParseError, VerboseError};
use nom::sequence::tuple;
use nom::Err::Error;
use nom::IResult;
use nom_greedyerror::{error_position, GreedyError, Position};
use nom_locate::LocatedSpan;

type Span<'a> = LocatedSpan<&'a str>;

fn parser<'a, E: ParseError<Span<'a>>>(
    input: Span<'a>,
) -> IResult<Span<'a>, (Span<'a>, Span<'a>, Span<'a>), E> {
    alt((
        tuple((alpha1, digit1, alpha1)),
        tuple((digit1, alpha1, digit1)),
    ))(input)
}

fn main() {
    // VerboseError failed at
    //   abc012:::
    //   ^
    let error = parser::<VerboseError<Span>>(Span::new("abc012:::"));
    dbg!(&error);
    match error {
        Err(Error(e)) => assert_eq!(e.errors.first().map(|x| x.0.position()), Some(0)),
        _ => (),
    };

    // GreedyError failed at
    //   abc012:::
    //         ^
    let error = parser::<GreedyError<Span, ErrorKind>>(Span::new("abc012:::"));
    dbg!(&error);
    match error {
        Err(Error(e)) => assert_eq!(error_position(&e), Some(6)),
        _ => (),
    };
}

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Dependencies

~1MB
~19K SLoC