impl Trait
shouldn't harm compiletimes much on its own
R: Read
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()
})
}
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?
from_str(count_min_max::<String, _, _>(min, max, digit()))
parse::<i32>
is acceptable
and_then
like from_str
does and substitute your own message https://github.com/Marwes/combine/blob/a358c88933bb58c4df0d9a0212b4a33d2b24be7b/src/parser/combinator.rs#L1165-L1169
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.
captures
I get some incredible error spam that's hard to sort through.
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)
}
}
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]))
}
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...
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
self.1
ThenPartial
rather than Then
?
self.1
calls?