chumsky
chumsky copied to clipboard
`Repeated` deleting custom error and returning generic `Unexpected` error instead
Consider the following code:
use std::fmt::{Debug, Display};
use chumsky::{prelude::*, util::Maybe};
#[derive(Debug, Clone, PartialEq, Eq)]
enum MyErr {
Unexpected {
expected: Vec<Option<char>>,
found: Option<char>,
span: SimpleSpan<usize>,
},
UnclosedComment {
start: SimpleSpan<usize>,
},
}
impl Display for MyErr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
<Self as Debug>::fmt(&self, f)
}
}
impl std::error::Error for MyErr {}
impl<'a> chumsky::error::Error<'a, &'a str> for MyErr {
fn expected_found<
E: IntoIterator<Item = Option<chumsky::util::MaybeRef<'a, <&'a str as Input<'a>>::Token>>>,
>(
expected: E,
found: Option<chumsky::util::MaybeRef<'a, <&'a str as Input<'a>>::Token>>,
span: <&'a str as Input<'a>>::Span,
) -> Self {
MyErr::Unexpected {
expected: expected
.into_iter()
.map(|m| m.map(Maybe::into_inner))
.collect(),
found: found.map(Maybe::into_inner),
span,
}
}
fn merge(self, other: Self) -> Self {
match (self, other) {
(MyErr::Unexpected { .. }, a) => a,
(a, MyErr::Unexpected { .. }) => a,
(a, _) => a,
}
}
}
fn comment<'a>() -> impl Parser<'a, &'a str, (), extra::Err<MyErr>> {
just("#")
.to_span()
.then(choice((just("#").to(Some(())), empty().to(None))))
.try_map(|(start, end), _| match end {
Some(()) => Ok(()),
None => Err(MyErr::UnclosedComment { start }),
})
}
#[test]
fn test_comment_ok() {
comment().parse("##").into_result().unwrap()
}
#[test]
fn test_comment_ok_repeated() {
let input = "##".repeat(3);
comment().repeated().parse(&input).into_result().unwrap();
}
#[test]
fn test_comment_unclosed() {
assert_eq!(
comment().parse("#").into_result().unwrap_err(),
vec![MyErr::UnclosedComment {
start: (0..1).into()
}]
)
}
#[test]
fn test_comment_unclosed_repeated() {
let input = "##".repeat(3) + "#";
assert_eq!(
comment()
.repeated()
.parse(&input)
.into_result()
.unwrap_err(),
vec![MyErr::UnclosedComment {
start: (6..7).into()
}]
);
}
All tests beside test_comment_unclosed_repeated
run successfully.
This is the output of the failing test:
thread 'test_comment_unclosed_repeated' panicked at 'assertion failed: `(left == right)`
left: `[Unexpected { expected: [], found: Some('#'), span: 6..7 }]`,
right: `[UnclosedComment { start: 6..7 }]`', src/lib.rs:86:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
As you can see, instead of the expected custom UnclosedComment
error, a generic Unexpected
error is returned instead.
I traced the issue to this line where my UnclosedComment
error get's deleted.