1use crate::{Parse, RuleResult};
4use std::fmt::{self, Debug, Display};
5
6#[cfg(feature = "std")]
7use std::collections::BTreeSet;
8
9#[cfg(not(feature = "std"))]
10use {alloc::collections::BTreeSet, alloc::vec::Vec};
11
12#[derive(PartialEq, Eq, Debug, Clone)]
14pub struct ExpectedSet {
15 expected: BTreeSet<&'static str>,
16}
17
18impl ExpectedSet {
19 pub fn tokens<'a>(&'a self) -> impl Iterator<Item = &'static str> + 'a {
21 self.expected.iter().map(|x| *x)
22 }
23}
24
25impl Display for ExpectedSet {
26 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
27 if self.expected.is_empty() {
28 write!(fmt, "<unreported>")?;
29 } else if self.expected.len() == 1 {
30 write!(fmt, "{}", self.expected.iter().next().unwrap())?;
31 } else {
32 let mut errors = self.tokens().collect::<Vec<_>>();
33 errors.sort();
34 let mut iter = errors.into_iter();
35
36 write!(fmt, "one of {}", iter.next().unwrap())?;
37 for elem in iter {
38 write!(fmt, ", {}", elem)?;
39 }
40 }
41
42 Ok(())
43 }
44}
45
46#[derive(PartialEq, Eq, Debug, Clone)]
48pub struct ParseError<L> {
49 pub location: L,
51
52 pub expected: ExpectedSet,
54}
55
56impl<L: Display> Display for ParseError<L> {
57 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
58 write!(
59 fmt,
60 "error at {}: expected {}",
61 self.location, self.expected
62 )
63 }
64}
65
66#[cfg(any(feature = "std", feature = "unstable"))]
67impl<L: Display + Debug> ::std::error::Error for ParseError<L> {
68 fn description(&self) -> &str {
69 "parse error"
70 }
71}
72
73#[doc(hidden)]
74pub struct ErrorState {
75 pub max_err_pos: usize,
77
78 pub suppress_fail: usize,
81
82 pub reparsing_on_error: bool,
85
86 pub expected: ExpectedSet,
88}
89
90impl ErrorState {
91 pub fn new(initial_pos: usize) -> Self {
92 ErrorState {
93 max_err_pos: initial_pos,
94 suppress_fail: 0,
95 reparsing_on_error: false,
96 expected: ExpectedSet {
97 expected: BTreeSet::new(),
98 },
99 }
100 }
101
102 pub fn reparse_for_error(&mut self) {
104 self.suppress_fail = 0;
105 self.reparsing_on_error = true;
106 }
107
108 #[inline(never)]
109 pub fn mark_failure_slow_path(&mut self, pos: usize, expected: &'static str) {
110 if pos == self.max_err_pos {
111 self.expected.expected.insert(expected);
112 }
113 }
114
115 #[inline(always)]
117 pub fn mark_failure(&mut self, pos: usize, expected: &'static str) -> RuleResult<()> {
118 if self.suppress_fail == 0 {
119 if self.reparsing_on_error {
120 self.mark_failure_slow_path(pos, expected);
121 } else if pos > self.max_err_pos {
122 self.max_err_pos = pos;
123 }
124 }
125 RuleResult::Failed
126 }
127
128 pub fn into_parse_error<I: Parse + ?Sized>(self, input: &I) -> ParseError<I::PositionRepr> {
129 ParseError {
130 location: Parse::position_repr(input, self.max_err_pos.into()),
131 expected: self.expected,
132 }
133 }
134}