1use std::cmp::Ordering;
2use std::fmt;
3use std::fmt::Debug;
4use thiserror::*;
5
6#[derive(Debug, PartialEq, Eq, Clone, Error, Hash)]
7pub enum Expected {
8 EOI,
9 Char(char),
10 Nil,
11 CharIn(&'static str),
12 ObOn(&'static str, &'static str),
13 Str(&'static str),
14 OneOf(Vec<Expected>),
15 Except(Box<Expected>),
16}
17
18impl fmt::Display for Expected {
19 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
20 use Expected::*;
21 match self {
22 EOI => write!(f, "EOI"),
23 Char(c) => write!(f, "Char:\"{}\"", c),
24 Nil => write!(f, "Nil"),
25 CharIn(s) => write!(f, "Char In {:?}", s),
26 ObOn(p, o) => write!(f, "{} on parser {}", o, p),
27 Str(s) => write!(f, "{:?}", s),
28 OneOf(v) => {
29 write!(f, "one of:(")?;
30 for e in v {
31 write!(f, "{} ", e)?;
32 }
33 write!(f, ")")
34 }
35 Except(e) => write!(f, " Except : ({})", e),
36 }
37 }
38}
39
40impl Expected {
41 pub fn or(self, b: Self) -> Self {
42 match self {
43 Expected::OneOf(mut v) => {
44 v.push(b);
45 Expected::OneOf(v)
46 }
47 v => Expected::OneOf(vec![v, b]),
48 }
49 }
50 pub fn except(a: Self) -> Self {
51 Expected::Except(Box::new(a))
52 }
53
54 pub fn join(self, b: Self) -> Self {
55 match (self, b) {
56 (Expected::OneOf(mut ae), Expected::OneOf(be)) => {
57 ae.extend(be);
58 Expected::OneOf(ae)
59 }
60 (Expected::OneOf(mut ae), b) | (b, Expected::OneOf(mut ae)) => {
61 if b != Expected::Nil {
62 ae.push(b);
63 }
64 Expected::OneOf(ae)
65 }
66 (Expected::Nil, a) => a,
67 (a, Expected::Nil) => a,
68 (a, b) => Expected::OneOf(vec![a, b]),
69 }
70 }
71
72 pub fn first(a: Self, b: Self) -> Self {
73 match a == Expected::Nil {
74 true => b,
75 false => a,
76 }
77 }
78}
79
80#[derive(Clone, PartialEq, Eq, Error, Hash)]
81pub struct PErr<'a> {
82 pub exp: Expected,
83 pub found: &'a str,
84 pub index: Option<usize>,
85 pub line: usize,
86 pub col: usize,
87 pub is_brk: bool,
88 pub child: Option<Box<PErr<'a>>>,
89}
90
91fn compare_index(a: &Option<usize>, b: &Option<usize>) -> Ordering {
92 match (a, b) {
93 (Some(a), Some(b)) => a.cmp(b),
94 (Some(_), None) => Ordering::Less,
95 (None, Some(_)) => Ordering::Greater,
96 _ => Ordering::Equal,
97 }
98}
99
100fn join_children<'a>(a: Option<Box<PErr<'a>>>, b: Option<Box<PErr<'a>>>) -> Option<Box<PErr<'a>>> {
101 match (a, b) {
102 (Some(ac), Some(bc)) => Some(Box::new((*ac).join(*bc))),
103 (None, b) => b,
104 (a, None) => a,
105 }
106}
107
108pub fn n_chars(s: &str, n: usize) -> String {
109 s.chars().take(n).collect()
110}
111
112impl<'a> PErr<'a> {
113 pub fn longer(mut self, b: Self) -> Self {
114 match compare_index(&self.index, &b.index) {
115 Ordering::Greater => self,
116 Ordering::Less => b,
117 _ => {
118 self.child = join_children(self.child, b.child);
119 self.exp = self.exp.join(b.exp);
120 self
121 }
122 }
123 }
124
125 pub fn join(mut self, mut b: Self) -> Self {
126 match compare_index(&self.index, &b.index) {
127 Ordering::Greater => {
128 self.child = join_children(self.child, Some(Box::new(b)));
129 self
130 }
131 Ordering::Less => {
132 b.child = join_children(b.child, Some(Box::new(self)));
133 b
134 }
135 _ => {
136 self.child = join_children(self.child, b.child);
137 self.exp = self.exp.join(b.exp);
138 self
139 }
140 }
141 }
142
143 pub fn join_op(self, b: Option<Self>) -> Self {
144 match b {
145 Some(v) => self.join(v),
146 None => self,
147 }
148 }
149
150 pub fn strung(self) -> StrungError {
151 StrungError {
152 exp: self.exp,
153 found: n_chars(self.found, 10),
154 line: self.line,
155 col: self.col,
156 index: self.index,
157 is_brk: self.is_brk,
158 child: self.child.map(|v| Box::new((*v).strung())),
159 }
160 }
161
162 pub fn brk(mut self) -> Self {
176 self.is_brk = true;
177 self
178 }
179
180 pub fn set_brk(mut self, b: bool) -> Self {
181 self.is_brk = b;
182 self
183 }
184}
185impl<'a> fmt::Debug for PErr<'a> {
186 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
187 let i_str = match self.index {
188 Some(n) => n.to_string(),
189 None => "EOI".to_string(),
190 };
191 write!(
192 f,
193 "Expected '{}', Found '{}', at (i={},l={},c={})\n",
194 self.exp,
195 n_chars(&self.found, 10),
196 i_str,
197 self.line,
198 self.col
199 )?;
200 if let Some(ref c) = self.child {
201 write!(f, "\t{:?}", c)?
202 }
203 Ok(())
204 }
205}
206impl<'a> fmt::Display for PErr<'a> {
207 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
208 let i_str = match self.index {
209 Some(n) => n.to_string(),
210 None => "EOI".to_string(),
211 };
212 write!(
213 f,
214 "Expected '{}', Found '{}', at (i={},l={},c={})\n",
215 self.exp,
216 n_chars(&self.found, 10),
217 i_str,
218 self.line,
219 self.col
220 )?;
221 if let Some(ref c) = self.child {
222 write!(f, "\t{}", c)?
223 }
224 Ok(())
225 }
226}
227
228#[derive(Clone, Error, PartialEq, Eq, Hash)]
230pub struct StrungError {
231 pub exp: Expected,
232 pub found: String,
233 pub index: Option<usize>,
234 pub line: usize,
235 pub col: usize,
236 pub is_brk: bool,
237 pub child: Option<Box<StrungError>>,
238}
239
240impl fmt::Debug for StrungError {
241 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
242 let i_str = match self.index {
243 Some(n) => n.to_string(),
244 None => "EOI".to_string(),
245 };
246 write!(
247 f,
248 "Expected '{}', Found '{}', at (i={},l={},c={})\n",
249 self.exp, self.found, i_str, self.line, self.col
250 )
251 }
252}
253impl fmt::Display for StrungError {
254 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
255 let i_str = match self.index {
256 Some(n) => n.to_string(),
257 None => "EOI".to_string(),
258 };
259 write!(
260 f,
261 "Expected '{}', Found '{}', at (i={},l={},c={})\n",
262 self.exp, self.found, i_str, self.line, self.col
263 )?;
264 if let Some(ref c) = self.child {
265 write!(f, "\t{}", c)?
266 }
267 Ok(())
268 }
269}