Helper function to convert Rich errors to our Error type
(
span: Span,
reason: &chumsky::error::RichReason<T>,
token_to_string: impl Fn(&T) -> String,
is_whitespace_token: impl Fn(&T) -> bool,
)
| 8 | |
| 9 | // Helper function to convert Rich errors to our Error type |
| 10 | fn rich_error_to_error<T>( |
| 11 | span: Span, |
| 12 | reason: &chumsky::error::RichReason<T>, |
| 13 | token_to_string: impl Fn(&T) -> String, |
| 14 | is_whitespace_token: impl Fn(&T) -> bool, |
| 15 | ) -> Error |
| 16 | where |
| 17 | T: std::fmt::Debug, |
| 18 | { |
| 19 | use chumsky::error::RichReason; |
| 20 | |
| 21 | let error = match reason { |
| 22 | RichReason::ExpectedFound { expected, found } => { |
| 23 | use chumsky::error::RichPattern; |
| 24 | let expected_strs: Vec<String> = expected |
| 25 | .iter() |
| 26 | .filter(|p| { |
| 27 | // Filter out whitespace tokens unless that's all we're expecting |
| 28 | let is_whitespace = match p { |
| 29 | RichPattern::EndOfInput => true, |
| 30 | RichPattern::Token(t) => is_whitespace_token(t), |
| 31 | _ => false, |
| 32 | }; |
| 33 | !is_whitespace |
| 34 | || expected.iter().all(|p| match p { |
| 35 | RichPattern::EndOfInput => true, |
| 36 | RichPattern::Token(t) => is_whitespace_token(t), |
| 37 | _ => false, |
| 38 | }) |
| 39 | }) |
| 40 | .map(|p| match p { |
| 41 | RichPattern::Token(t) => token_to_string(t), |
| 42 | RichPattern::EndOfInput => "end of input".to_string(), |
| 43 | _ => format!("{:?}", p), |
| 44 | }) |
| 45 | .collect(); |
| 46 | |
| 47 | let found_str = match found { |
| 48 | Some(t) => token_to_string(t), |
| 49 | None => "end of input".to_string(), |
| 50 | }; |
| 51 | |
| 52 | if expected_strs.is_empty() || expected_strs.len() > 10 { |
| 53 | Error::new_simple(format!("unexpected {found_str}")) |
| 54 | } else { |
| 55 | let mut expected_strs = expected_strs; |
| 56 | expected_strs.sort(); |
| 57 | |
| 58 | let expected_str = match expected_strs.len() { |
| 59 | 1 => expected_strs[0].clone(), |
| 60 | 2 => expected_strs.join(" or "), |
| 61 | _ => { |
| 62 | let last = expected_strs.pop().unwrap(); |
| 63 | format!("one of {} or {last}", expected_strs.join(", ")) |
| 64 | } |
| 65 | }; |
| 66 | |
| 67 | match found { |