winnow-rs / winnow

Making parsing a breeze
https://docs.rs/winnow
Other
525 stars 40 forks source link

Winnow and nom produce differing outcomes when running identical code when use take_until #489

Closed baoyachi closed 7 months ago

baoyachi commented 7 months ago

Please complete the following tasks

rust version

rustc 1.74.0 (79e9716c9 2023-11-13)

winnow version

0.6.2

Minimal reproducible code

use winnow::error::ErrMode::Backtrack;

fn main() {
    test_winnow();
    test_nom();
}

fn test_winnow() {
    use winnow::ascii::multispace0;
    use winnow::error::ContextError;
    use winnow::token::{literal, take_until};
    use winnow::Parser;

    let result = (
        multispace0::<&str, ContextError>,
        literal("}"),
+        take_until(0.., ""),
        literal(""),
    ).parse_peek("}");
+    assert_eq!(result, Err(Backtrack(ContextError::new())))
}

fn test_nom() {
    use nom::bytes::complete::{tag, take_until};
    use nom::character::complete::multispace0;
    use nom::error::VerboseError;
    use nom::sequence::tuple;

    let result = tuple((
        multispace0::<&str, VerboseError<_>>,
        tag("}"),
+        take_until(""),
        tag(""),
    ))("}");
+    assert_eq!(result, Ok(("", ("", "}", "",""))));
}
[dependencies]
nom = "7.1.3"
winnow = {version = "0.6",features = ["debug"]}

Steps to reproduce the bug with the above code

cargo run

Actual Behaviour

In the example provided above: winnow and nom have the same code logic, but they yield inconsistent results upon execution. Currently, I have ported the internal code from nom to winnow; however, despite maintaining the same logic, winnow throws errors during execution while nom successfully completes.

Expected Behaviour

Anticipating consistency in the logic between the two.

Additional Context

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=2a9b80d71c7077990cb025305b290fcb

epage commented 7 months ago

Looks like we have inconsistent behavior between simd feature being on and off.

I am curious why you have have take_until("") and literal("")

baoyachi commented 7 months ago

@epage Thanks for your quick fix.