asajeffrey / parsell

Parsell: an LL(1) parser combinator library for Rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

p.and_then(q) should Cow p's output

asajeffrey opened this issue · comments

The type for and_then should be that it Cow's p's output. For instance:

   let p = character(char::is_alphabetic).plus().buffer();
   let q = character(char::is_numeric).star().buffer();
   p.and_then(q).parse("abc1").unContinue().parse("23!")

should return (Owned(String::from("abc")),Owned(String::from("123"))). At the moment. "abc" is borrowed rather than owned, which is producing lifetime issues.

After a bit of bouncing around on the #rust irc, a possible solution is https://play.rust-lang.org/?gist=bcdf295150adc2a59519, which saves/restores transient data to persistent data. Internally, AndThenStatefulParser could store T::Persistent, which in the case of Cow<'a,str> would be String.

OK, got a test which fails:

fn test_different_lifetimes2() {
    use std::borrow::Cow;
    use std::borrow::Cow::{Owned, Borrowed};
    fn ignore() {}
    fn go<'a, 'b, P>(fst: &'a str, snd: &'b str, parser: P)
        where P: Copy + for<'c> Committed<&'c str, Output = (Cow<'c,str>, Cow<'c,str>)>
    {
        match parser.init().parse(fst) {
            Continue("", parsing) => match parsing.parse(snd) {
                Done("!", (Owned(fst), Owned(snd))) => {
                    assert_eq!(fst, "abc");
                    assert_eq!(snd, "123");
                },
                oops => panic!("Shouldn't happen 2 {:?}", oops),
            },
            Done("!", (Borrowed(fst), Borrowed(snd))) => {
                assert_eq!(fst, "abc");
                assert_eq!(snd, "123");
            },
            oops => panic!("Shouldn't happen 1 {:?}", oops),
        }
    }
    let parser = character(char::is_alphabetic).star(ignore).buffer()
        .and_then(character(char::is_numeric).star(ignore).buffer());
    go("abc123!", "!", parser);
    go("abc1", "23!", parser);
    go("ab", "c123!", parser);
}

In fact I'm a bit surprised this even type-checks.

Checked in the test, it's test_different_lifetimes2.

Fixed in v0.4.0.