Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
william light
@wrl
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)
    }
}
But this gives me a great deal of errors:
fn custom_status<Input>() -> impl Parser<Input, Output = String>
where
    Input: Stream<Token = char>,
    // Necessary due to rust-lang/rust#24159
    Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
    captures(Regex::new("<(\\\\|\\>|[^>\n])>").unwrap()).map(|captures: Vec<&str>| String::from(captures[1]))
}
John Sullivan
@itsjohncs

Goddam, I am not nearly familiar enough with Rust to be doing this, but I did figure out how to make my function compile:

/**
 * Parses a status.
 */
fn custom_status<'a, Input: 'a>() -> impl Parser<Input, Output = String> + 'a
where
    Input: Stream<Token = char>,
    Input: RangeStreamOnce<Range = &'a str>,
    // Necessary due to rust-lang/rust#24159
    Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
    captures(Regex::new(r"<((?:\\\\|\\>|[^>\n])*)>").unwrap()).map(|captures: Vec<&str>| String::from(captures[1]))
}

I am dubious that this is the easiest way though...

william light
@wrl

i have been increasingly writing parsers that have chains of the form

.then(|val| {
    value(val)
        .and(.........

and I figure that there could be a combinator here that passes in the output of the previous parser as an immutable ref for dispatching but then just forwards that value through without consuming it

Markus Westerlind
@Marwes
I suppose that could be added
william light
@wrl
I'd be happy to add it and submit a PR, but I'm not all that familiar with the innards of Then or ThenPartial
Markus Westerlind
@Marwes
You should be able to to copy the existing parser and tweak it a bit
william light
@wrl
if you'd be willing to provide a bit of guidance about what'd have to change, I'd appreciate the insight
yeah
Markus Westerlind
@Marwes
I think you can change the Output type to a tuple of the output and make the function take a ref, then fix the compile errors
william light
@wrl
so probably Output = (P::Output, N::Output);
Markus Westerlind
@Marwes
Yep
william light
@wrl
and then change the parse_committed_mode() call? or
Markus Westerlind
@Marwes
You should just need to change what is returned from fn parse_mode_impl in Then(Ref)
And the argument to self.1
william light
@wrl
aha okay
@Marwes ah, do you think I should change ThenPartial rather than Then?
Markus Westerlind
@Marwes
If Then is enough for you then it is enough to just add an alternative implementation in ThenRef
william light
@wrl
yeah Then will be fine
Markus Westerlind
@Marwes
For completion ThenPartial(Ref) could be added (and and_then, etc)
So that may be overkill :)
:+1:
these are the relevant self.1 calls?
Markus Westerlind
@Marwes
Yep
(It should probably be a named field instead of a tuple)
If it compiles I'd expect it to be fine :)