Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Markus Westerlind
@Marwes
I use it https://github.com/Marwes/combine-jpegif you want to see it in use
william light
@wrl
@Marwes so, I'm trying to parse a source file via Read. I would like to avoid reading the entire file into a string before parsing it, for a few reasons. IndexPositioner is not very useful here – it would be very excellent to have SourcePositioner implemented for u8. Would you accept a PR to that effect?
william light
@wrl
maybe the issue here is that there seems to be an assumption that Read streams always want to parse over u8
Markus Westerlind
@Marwes
Implementing Positioner<u8> should be possible, then you can construct the stream with https://docs.rs/combine/4.0.0-beta.1/combine/stream/position/struct.Stream.html#method.with_positioner
william light
@wrl
@Marwes yep! took a little extra work to get it working with ReadStream but nothing huge: wrl/combine@ca605d4
Markus Westerlind
@Marwes
The P parameter seems redundat but otherwise that looks good if you want to send a PR
william light
@wrl
@Marwes needs to be generic over Position unfortunately. was usize before and SourcePosition didn't like that.
Joe Grund
@jgrund
What’s the best way to debug a parser? Specifically, I want to figure out where an UnexpectedError is being pushed into the list of errors
Markus Westerlind
@Marwes
Using a verbose error type for debugging (even if you don't use one in prod) helps https://docs.rs/combine/4.0.0-beta.1/combine/
Otherwise, minimizing test input, testing only the part of the parser that fails works
Joe Grund
@jgrund
When you say verbose error, is that the easy Error?
Markus Westerlind
@Marwes
Yeah
That ensures you get position information and information about all attempted parsers at the failure
Cheaper error types may omit some of that information
william light
@wrl
@Marwes hey, hoping you can help with this. I want to write a macro (or similar) which works like choice!(), but which lets me inspect the result of the previous parser. basically, something like .then(|x| match x { a => parser_for_a(), b => parser_for_b(), ... })
however, I'm having a lot of difficulty getting the types to match up
the sub-parsers are all defined in functions which return impl Parser, but since they're different opaque types, rustc doesn't like it at all
is there a way to make this work without having a huge enum with the separate types?
Markus Westerlind
@Marwes
No, you either need an enum or you need to box the parsers. But if you use the 4.x beta there is the dispatch! parser which does exactly this https://docs.rs/combine/4.0.0-beta.1/src/combine/parser/choice.rs.html#800-816
Seems I forgot to add a doc comment to it however
If you don't need to pass any arguments to the parsers in the alternatives there is also the option of wrapping them with https://docs.rs/combine/4.0.0-beta.1/combine/parser/combinator/fn.opaque.html
That unifies their types to FnOpaque
william light
@wrl
Yeah, I'm on 4.x beta. Both dispatch! and opaque! look like they might work for me – I'll give them a shot and report back.
william light
@wrl
@Marwes dispatch! worked with a slight modification to add match guards. I've submitted a PR.
william light
@wrl
so, I have ended up with a lot of small parser functions returning impl Trait and which are generic over Input. my compile times have absolutely skyrocketed and i'm looking for a way to bring them down. i've isolated all of my parser logic into a separate crate, but that doesn't seem to help – the outer crate compile times are still brutal.
is there any way around this?
this is in debug mode, too – not release
Markus Westerlind
@Marwes
I would guess that it is because the parsers are generic by the input type maybe?
If it is, then rust is still force to monomorphize in the callsite of the outer crate which is likely most of the work
Using impl Trait shouldn't harm compiletimes much on its own
william light
@wrl
@Marwes yeah, that's what I'm thinking too. even though the function that I've exported from the inner crate isn't generic, I'm guessing it's just monomorphizing in the outer crate.
is there some way to, uh... fix this? or speed it up at all?
Markus Westerlind
@Marwes
Add a function to the inner crate which specializes and the call that
william light
@wrl
ah, I bet it know what it is
the inner function is generic over R: Read
Markus Westerlind
@Marwes
Running compilation with RUSTFLAGS=-Z time-passes could be helpful to get some insight
Only works on nightly however
william light
@wrl
I'll give that a shot
John Sullivan
@itsjohncs
I'm trying to produce a nice parser error in the event of an integer overflow while parsing, and I'm not really getting anywhere.
fn n_digits<Input>(min: usize, max: usize) -> impl Parser<Input, Output = i32>
where
    Input: Stream<Token = char>,
    // Necessary due to rust-lang/rust#24159
    Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
    count_min_max(min, max, digit()).map(|s: String| {
        s.parse::<i32>().unwrap()
    })
}
I would like to not panic in the event that s.parse fails, but despite diving into a few codebases that use combine and trying many things, I'm not getting anywhere. Can anyone help me out?
Markus Westerlind
@Marwes
https://docs.rs/combine/4.0.1/combine/fn.from_str.html
from_str(count_min_max::<String, _, _>(min, max, digit()))
Easiest way, as long as the error message from parse::<i32> is acceptable
Otherwise you can use and_then like from_str does and substitute your own message https://github.com/Marwes/combine/blob/a358c88933bb58c4df0d9a0212b4a33d2b24be7b/src/parser/combinator.rs#L1165-L1169
John Sullivan
@itsjohncs
Lovely, thank you

I did stumble onto StreamErrorFor::<Input>::other eventually yesterday, and ended up with

fn n_digits<Input>(min: usize, max: usize) -> impl Parser<Input, Output = i32>
where
    Input: Stream<Token = char>,
    // Necessary due to rust-lang/rust#24159
    Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
    count_min_max(min, max, digit()).and_then(|s: String| {
        s.parse().map_err(StreamErrorFor::<Input>::other)
    })
}

Which was acceptable. I'll try out from_str tonight though and compare the error messages that they generate, looks like they may arrive at different errors, though I'm not sure how they'll differ.

John Sullivan
@itsjohncs
I've been trying to get captures working, but I can't find an example of its use anywhere. Even using GitHub's search all public repos feature.
It works in a toy example with types inferred, but if I try to make a function using captures I get some incredible error spam that's hard to sort through.
In particular, this works fine:
fn main() {
    let mut p = 
        captures(Regex::new(r"<((?:\\\\|\\>|[^>\n])*)>").unwrap())
            .map(|captures: Vec<&str>| String::from(captures[1]));
    let input = "<hello>";
    let result = p.easy_parse(input);
    match result {
        Ok((value, _remaining_input)) => println!("{:?}", value),
        Err(err) => println!("{}", err)
    }
}