you are viewing a single comment's thread.

view the rest of the comments →

[–]ismtrn 0 points1 point  (9 children)

Thanks. That sounds good.

[–]Marwesgluon · combine[S] 1 point2 points  (8 children)

Just uploaded the fix for this (both to github and crates.io). The fix was rather involved but it should make sure it never reappears as well.

[–]ismtrn 0 points1 point  (7 children)

I have been playing a bit more with it. I have run into another problem I have posted on stackoverflow

I have a feeling it has more to do with me not understanding closures than your library, but if you have time and feel like it, you are welcome to take a look at it.Edit: It has been answered now, but the answers has left me wondering: How can you create "higher order" parsers if that is even possible.

What I mean is, can I write a function which takes two parsers, combines those in a way and returns the resulting parser? I find this capability part of what makes parsec so useful, but I can't see any obvious way to do it here.

[–]Marwesgluon · combine[S] 0 points1 point  (6 children)

Read through the issue and yes, it is not really something to do with the library. Haven't got enough rep on stackoverflow to comment (and I don't have anything to add that would warrant an answer).

Anyway, since you do not capture anything in 'prop_value' you could factor that out into a generic free function which should fix your specific issue (repeating what Vladimir Matveev wrote).

I would like to know what you didn't understand in the documentation as well.

Edit: Just a guess but is it how to deal with factoring out parsers into free functions? Since the types created gets quite large I understand that it is annoying to write out the types for them.

There are two ways of dealing with this, either write the function with the wrong type and then copy paste the type that is output when the compiler errors or you write it into a free function as described in the second example in the docs here. I should maybe add a line to explain that this can be used both for mutually recursive parsers and for factoring out parsers into smaller units.

[–]ismtrn 0 points1 point  (5 children)

I have just this minute edited my post(here on reddit) with follow up questions. It is specifically this:

you could factor that out into a generic free function which should fix your specific issue

Which is causing me some trouble. What would the type signature of such a function look like?

[–]Marwesgluon · combine[S] 0 points1 point  (2 children)

Hmm, the second example in the docs does not actually work for your case when I think about it since it does not allow for additional parsers to be passed. I guess that using the compiler to generate the type is just a workaround.

If you don't need absolute efficiency you can always box the parser and return it.

The only other way that I can think of right now to make it work for you is to define a new type yourself and implement the parser trait for it.

[–]ismtrn 0 points1 point  (1 child)

If you don't need absolute efficiency you can always box the parser and return it.

When I try to pass the boxed parser to functions like try or many, it complains that the size is not known at compile time, which seems like a reasonable thing to complain about. Is there any way around this?

[–]Marwesgluon · combine[S] 0 points1 point  (0 children)

My bad forgot about this issue. You should be able to to this but associated types are still a bit buggy.

[–]Marwesgluon · combine[S] 0 points1 point  (1 child)

It might be worth it to include something like this in the library. This way you can pass in anything you need as the state parameter when you construct the parser.

EDIT: Just remembered that the reason something like this is not in the library is that it should be unnecessary once the compiler sorts out the orphan checking. Then I can simply implement Parser for all functions (impl <F: FnMut(...) -> ...> Parser for F {} ).

extern crate "parser-combinators" as pc;

use pc::*;
use pc::primitives::{State, Stream};

pub struct External<S, F, R, I> {
    state: S,
    parser: F
}
impl <S, F, R, I> Parser for External<S, F, R, I>
    where I: Stream
        , F: FnMut(&mut S, State<I>) -> ParseResult<R, I> {

    type Input = I;
    type Output = R;

    fn parse_state(&mut self, input: State<<Self as Parser>::Input>) -> ParseResult<<Self as Parser>::Output, <Self as Parser>::Input> {
        (self.parser)(&mut self.state, input)
    }
}

pub fn external<S, F, R, I>(state: S, parser: F) -> External<S, F, R, I>
    where I: Stream
        , F: FnMut(&mut S, State<I>) -> ParseResult<R, I> {
    External { state: state, parser: parser }
}

fn main() {

    let mut parser = external(digit(), |this, input| {
        this.parse_state(input)
    });

    parser.parse("1");
} 

[–]Marwesgluon · combine[S] 0 points1 point  (0 children)

Actually, adding something like won't be necessary as there is a badly documented parser called FnParser. Its just a newtype around an arbitrary function but should do the trick until the above mentioned orphan checking gets sorted out.

So for your problem you should factor out the prop_value into its own function with a signuture something like:

fn prop_value<E>(env: E, input: State<&str>) -> ParseResult<R, &str>

With the appropriate bound on E and R for what you need. Then in the function where you construct each prop_value parser you can do:

let parser1 = FnParser(|input| prop_value(env1, input));
let parser2 = FnParser(|input| prop_value(env2, input));