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
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 :)
william light
@wrl
I'll save that for the PR comments if necessary :)
alright cool, thanks for the help. I'll give this a shot later today.
william light
@wrl
:D
Matthias Petri
@mpetri
Hello, I was browsing examples/docs for a while and I was wondering how I would combine choice() with requiring certain choices in arbitrary order to be present after parsing? example: http header where certain header values need to be present but can be in arbitrary order
Markus Westerlind
@Marwes
That seems like a separate concern from parsing
You could validate that the headers are in the correct order after parsing
william light
@wrl
.flat_map() after the choice, in my opinion
return an Error if something's required isn't present
awygle
@awygle
hi all. i'm struggling with zero-copy parsing, and i'm not really making any headway. how can i write a parser function which can take an &str, outputs an &str, doesn't do extra copies, and restricts the input type as little as possible? you can find here my flailing attempt (see the symbol function): https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=ecd82417fdf8a3aaeed27e9151ef1152 help is appreciated! thanks
i think if i wanted to return String i could use map on the output of many1 but since i want to borrow i don't know what to do
Markus Westerlind
@Marwes
You need to specify the Range type in Stream

    where Input: RangeStream<Token = char, Range = &'a str>,
Should do it
awygle
@awygle
@Marwes so i tried that but the 'a doesn't come from anywhere. i added it as a parameter to the function but then many1 can't figure out what its output type should be. maybe i need a map call after all?
awygle
@awygle
oh i needed to skip_many1 instead of many1.
still not sure why though
Markus Westerlind
@Marwes
many expectes a collection type to collect into whereas skip_many1 just outputs ()