1use std::ops::Range;
4
5#[derive(Clone, Debug, PartialEq)]
6pub enum ParserError<Msg> {
8 Range(Range<usize>),
10 Stack(Vec<ParserError<Msg>>),
12 Message(Msg, Box<ParserError<Msg>>),
14}
15
16impl<Msg> ParserError<Msg> {
17 #[inline]
18 pub fn with_message(self, tag: Msg) -> Self {
19 match self {
20 ParserError::Range(_) => ParserError::Message(tag, Box::new(self)),
21 ParserError::Stack(_) => ParserError::Message(tag, Box::new(self)),
22 _ => ParserError::Message(tag, Box::new(self)),
23 }
24 }
25}
26
27pub trait ParserErrorMethods {
29 fn bounds(&self) -> Range<usize>;
31}
32
33impl<Msg> ParserErrorMethods for ParserError<Msg> {
34 fn bounds(&self) -> Range<usize> {
35 match self {
36 ParserError::Range(bounds) => bounds.clone(),
37 ParserError::Stack(stack) => stack.bounds(),
38 ParserError::Message(_, stack) => stack.bounds(),
39 }
40 }
41}
42
43impl<Msg> ParserErrorMethods for Vec<ParserError<Msg>> {
44 fn bounds(&self) -> Range<usize> {
45 let mut start = std::usize::MAX;
46 let mut end = 0;
47
48 for error in self {
49 let bounds = error.bounds();
50
51 if start > bounds.start {
52 start = bounds.start;
53 }
54
55 if end < bounds.end {
56 end = bounds.end;
57 }
58 }
59
60 start..end
61 }
62}
63
64impl<Msg> ParserErrorMethods for Option<Vec<ParserError<Msg>>> {
65 fn bounds(&self) -> Range<usize> {
66 if let Some(stack) = self {
67 stack.bounds()
68 } else {
69 0..0
70 }
71 }
72}
73
74#[test]
75fn parser_error_with_message() {
76 assert_eq!(
77 ParserError::Range(0..9).with_message("An error message."),
78 ParserError::Message(
79 "An error message.".into(),
80 Box::new(ParserError::Range(0..9))
81 ),
82 );
83
84 assert_eq!(
85 ParserError::Message(
86 "An error message.".into(),
87 Box::new(ParserError::Range(0..9))
88 )
89 .with_message("Oh no!"),
90 ParserError::Message(
91 "Oh no!".into(),
92 Box::new(ParserError::Message(
93 "An error message.".into(),
94 Box::new(ParserError::Range(0..9))
95 ))
96 )
97 )
98}
99
100#[test]
101fn custom_error_message() {
102 #[derive(Clone, Debug, PartialEq)]
103 enum Message {
104 AnError,
105 }
106
107 assert_eq!(
108 ParserError::Range(0..9).with_message(Message::AnError),
109 ParserError::Message(Message::AnError, Box::new(ParserError::Range(0..9)))
110 )
111}