-
-
Notifications
You must be signed in to change notification settings - Fork 156
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Custom error isn't respected in some cases #530
Comments
I believe in this case the solution is to use fn year_parser<'a>() -> impl Parser<'a, &'a str, i32, MyExtra> {
let digit = any::<&str, MyExtra>().filter(|c: &char| c.is_ascii_digit());
let digits = digit.repeated().at_least(1).collect::<String>();
digits.validate(|digits, _, emitter| {
dbg!(&digits);
dbg!(if digits.len() <= 4 {
2000
} else {
emitter.emit(MyError::Custom);
// Some sentinel value because you know it was a date, just not a valid one.
// The custom error will be produced and will be found in the `ParseResult`
-1
})
})
} You get the expected output (and all tests now pass): error: [Custom]
In the docs for Validate an output, producing non-terminal errors if it does not fulfil certain criteria. The errors will not immediately halt parsing on this path, but instead it will continue, potentially emitting one or more other errors, only failing after the pattern has otherwise successfully, or emitted another terminal error. This function also permits mapping the output to a value of another type, similar to Parser::map. If you wish parsing of this pattern to halt when an error is generated instead of continuing, consider using Parser::try_map instead. |
Thank you! I will give that a shot. I had encountered Your explanation:
is helpful. I think some improvements in the docs might be helpful, but I need to digest this a bit more first. |
@faassen I realize now that my explanation wasn't totally correct. I personally haven't used |
I'm still confused why I must be wrong about there being no other branch - there is a valid branch with just 4 digits, but the rest of the pattern can't be parsed. It's just that it doesn't even seem to enter that branch, as I only see one output of |
I am quite confused about the original issue. Maybe I've missed something (I'm currently viewing this on mobile while on a train) but to me the original code should be producing |
To confirm, as @Zij-IT suggested, using Could there be a shortcut API for emit that looks more like try_validate(sentinel, |s, _| {
// this returns a result
s.parse()
}) and this gets turned into: validate(|s, _, emitter| {
match s.parse() {
Ok(parsed) => parsed,
Err(err) => {
emitter.emit(err);
sentinel
}
}
}) This way |
I've implemented a custom error class, with a
Custom
error type on it. I want to return this custom error usingtry_map
and then see it at the end of the failed parse. It works, but not always. When it doesn't work,ExpectedFound
is produced instead (i.e. a non-custom error).combined_year_custom_error
fails, the rest doesn't. Thedbg!
inyear_parser
behaves intriguingly: while the custom error is indeed returned fromtry_map
, it's replaced by anExpectedFound
by the time themap_err
immediately followingyear_parser
is invoked. If I useyear_parser
by myself theCustom
error is emitted by bothdbg!
.I tried to replicate the behavior in a simplified with using
combined_true_false_parser
but this does exhibit the expected behavior.As a usability note: it was surprising to me that I needed to implement
merge
. Without it,year_custom_error
also fails.merge
doesn't get invoked forcombined_year_custom_error
, however.This is with the latest git version of chumsky.
It may be related to #483 in some way, as this talks about the use of
repeated
as well as triggering some kind of error erasure.The text was updated successfully, but these errors were encountered: