-
-
Notifications
You must be signed in to change notification settings - Fork 155
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
nested_in()
+ repeated()
produce incorrect error spans.
#577
Comments
Yes, you could use That aside, it's not clear to me why |
You'd think I'd be able to something like the following for the parser. let parser = numbers
.separated_by(blank_line)
.allow_trailing()
.collect::<Vec<_>>(); However this assertion will fail. let result = parser.parse("1\n2\n\n3\n4\n\n").into_result();
assert_eq!(result, Ok(vec![vec!["1", "2"], vec!["3", "4"]])); // fails with left: Err([found end of input at 5..6 expected something else]) I think it's because the trailing member of the numbers parser consumes the last let numbers = text::int(10)
.separated_by(text::newline())
.at_least(1)
.collect::<Vec<_>>(); However the following test case would fail let result = parser.parse("1\n2\n\n3\n4\n").into_result();
assert_eq!(result, Ok(vec![vec!["1", "2"], vec!["3", "4"]])); // fails with left: Err([found end of input at 9..9 expected ''0'', ''\r'', or ''\n'']) This would imply I need to add I originally attempted to write this parser a year ago on version
Thanks I'll take a look at this. My initial attempt stalled out after converting the input to a spanned input. (Which doesn't feel the best) let input = "1\n2\n\n3\n4\n\n";
let spanned = input
.chars()
.enumerate()
.map(|(i, c)| (c, SimpleSpan::new(i, i + 1)))
.collect::<Vec<_>>()
.spanned(SimpleSpan::new(input.len(), input.len())); All my parsers are defined currently with input as It's not immediately clear to me the next step from there. |
Correct me if I am wrong, but wouldn't it be possible to deny allowing trailing, and then allow the last one to have trailing newlines? Something like: let blank_line = text::newline::<&str, extra::Err<Rich<'_, char>>>()
.repeated()
.exactly(2)
.ignored();
let numbers = text::int::<_, _, extra::Err<Rich<'_, _>>>(10)
.separated_by(text::newline())
.at_least(1)
.collect::<Vec<_>>();
let parser = numbers
.separated_by(blank_line)
.collect::<Vec<_>>()
.then_ignore(text::newline().repeated());
let result = parser.parse("1\n2\n\n3\n4\n\n").into_result();
assert_eq!(result, Ok(vec![vec!["1", "2"], vec!["3", "4"]]));
let result: Result<Vec<Vec<&str>>, Vec<Rich<'_, char>>> =
parser.parse("1\na\n\n3\n4\n\n").into_result();
assert_eq!(
result.map_err(|e: Vec<_>| *e.first().unwrap().span()),
Err(SimpleSpan::new(2usize, 3))
);
let result = parser.parse("1\n2\n\n3\n4\n").into_result();
assert_eq!(result, Ok(vec![vec!["1", "2"], vec!["3", "4"]])); |
This works and passes all my tests. Thanks! @zesterer I still think the default nested_in error span behavior is a bit surprising and does not seem consistent with the other combinators. At the very least I think this should be called out in the docs, though I think ideally the combinator would internally track the proper spans. I'll leave it to you if you want to close this issue or not. |
I'm not sure how that could work in the general case. Chumsky doesn't intuitively 'understand' spans, they're entirely determined by the input you're parsing. |
Using
1.0.0.alpha6
using a combination ofnested_in
+repeated()
if there is a parse error in the inner parser, the error is reported with a span relative to the start of the chunk that the outer parser parsed rather than the start of the entire input. (This makes sense from the inner parser's perspective as it does not know about the other input). Though my expectation would be for the combinator to reframe error spans to be consistent with the outer span context.Example:
Alternatively is there a nice way for me to manually map the span to the correct outer context?
The text was updated successfully, but these errors were encountered: