Skip to main content

gobble/
err.rs

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 wrap(mut self, ne: Self) -> Self {
163        match self.child {
164            Some(c) => self.child = Some(Box::new(c.wrap(ne))),
165            None => self.child = Some(Box::new(ne)),
166        }
167        self
168    }*/
169
170    /*pub fn new_exp(mut self, nexp: Expected) -> ParseError {
171        self.exp = nexp;
172        self
173    }*/
174
175    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//The StrungError has the String it was parsed from attached to it.
229#[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}