J-F-Liu / pom

PEG parser combinators using operator overloading without macros.
MIT License
496 stars 30 forks source link

list() behaviour #4

Closed jeanm closed 7 years ago

jeanm commented 7 years ago

I am not sure if this is intended behaviour, but I find the way the list combinator works to be a bit counter-intuitive . It seems that, if it successfully matches a separator but ten fails to match the next element, it backtracks all the way to the beginning of the list, and the whole combinator fails. I would expect it to backtrack to the last successfully matched element.

Here is an example to illustrate what I mean:

extern crate pom;

use pom::{Parser, DataInput};
use pom::parser::*;

fn spaces() -> Parser<u8, ()> {
    one_of(b" ").repeat(1..).discard()
}

fn works() -> Parser<u8, Vec<u8>> {
    list(one_of(b"abc"), spaces() * seq(b"and") - spaces()) 
}

fn doesnt() -> Parser<u8, (Vec<u8>, Vec<u8>)> {
    list(one_of(b"abc"), spaces() * seq(b"and") - spaces()) + seq(b" and ")
}

fn main() {
    let mut one = DataInput::new(b"a and b and c");
    println!("{:?}", works().parse(&mut one));

    let mut two = DataInput::new(b"a and b and c and ");
    println!("{:?}", doesnt().parse(&mut two));
}

The first parser succeeds and consumes all output, but the second fails with:

Err(Mismatch { message: "expect item after separator, found: Incomplete", position: 0 })

I would expect both of them to succeed.

J-F-Liu commented 7 years ago

Yes, backtrack to the last successfully matched element is more practical, I'll fix this.