kparse/
parser_error.rs

1//!
2//! Error type, nom::error::Error replacement.
3//!
4//! It's main content is an error code and a span.
5//! Additionally
6//! * nom error codes
7//! * extra codes indicating expected input
8//! * extra codes for suggestions
9//! * cause
10//! * other user data.
11//!
12
13use crate::debug::error::debug_parse_error;
14use crate::debug::{restrict, DebugWidth};
15use crate::prelude::SpanFragment;
16use crate::{Code, ErrOrNomErr, KParseError};
17use nom::error::ErrorKind;
18use nom::{InputIter, InputLength, InputTake};
19use std::any::Any;
20#[cfg(debug_assertions)]
21use std::backtrace::Backtrace;
22use std::error::Error;
23use std::fmt;
24use std::fmt::{Debug, Display};
25
26/// Parser error.
27pub struct ParserError<C, I> {
28    /// Error code
29    pub code: C,
30    /// Error span
31    pub span: I,
32    /// Extra information
33    pub hints: Vec<Hints<C, I>>,
34    #[cfg(debug_assertions)]
35    pub backtrace: Backtrace,
36}
37
38/// Extra information added to a ParserError.
39pub enum Hints<C, I> {
40    /// Expected outcome of the parser.
41    Expect(SpanAndCode<C, I>),
42    /// Suggestions from the parser.
43    Suggest(SpanAndCode<C, I>),
44    /// External cause for the error.
45    Cause(Box<dyn Error>),
46    /// Extra user context.
47    UserData(Box<dyn Any>),
48}
49
50impl<C, I> ErrOrNomErr for ParserError<C, I>
51where
52    C: Code,
53    I: Clone + Debug + SpanFragment,
54    I: InputTake + InputLength + InputIter,
55{
56    type WrappedError = ParserError<C, I>;
57
58    fn wrap(self) -> nom::Err<Self::WrappedError> {
59        nom::Err::Error(self)
60    }
61}
62
63impl<C, I> ErrOrNomErr for nom::Err<ParserError<C, I>>
64where
65    C: Code,
66    I: Clone + Debug + SpanFragment,
67    I: InputTake + InputLength + InputIter,
68{
69    type WrappedError = ParserError<C, I>;
70
71    fn wrap(self) -> nom::Err<Self::WrappedError> {
72        self
73    }
74}
75
76impl<C, I> KParseError<C, I> for ParserError<C, I>
77where
78    C: Code,
79    I: Clone + Debug + SpanFragment,
80    I: InputTake + InputLength + InputIter,
81{
82    type WrappedError = ParserError<C, I>;
83
84    fn from(code: C, span: I) -> Self {
85        ParserError::new(code, span)
86    }
87
88    fn with_code(self, code: C) -> Self {
89        ParserError::with_code(self, code)
90    }
91
92    fn code(&self) -> Option<C> {
93        Some(self.code)
94    }
95
96    fn span(&self) -> Option<I> {
97        Some(self.span.clone())
98    }
99
100    fn err(&self) -> Option<&Self::WrappedError> {
101        Some(self)
102    }
103
104    fn parts(&self) -> Option<(C, I, &Self::WrappedError)> {
105        Some((self.code, self.span.clone(), self))
106    }
107}
108
109impl<C, I> KParseError<C, I> for nom::Err<ParserError<C, I>>
110where
111    C: Code,
112    I: Clone + Debug + SpanFragment,
113    I: InputTake + InputLength + InputIter,
114{
115    type WrappedError = ParserError<C, I>;
116
117    fn from(code: C, span: I) -> Self {
118        nom::Err::Error(KParseError::from(code, span))
119    }
120
121    fn with_code(self, code: C) -> Self {
122        match self {
123            nom::Err::Incomplete(_) => self,
124            nom::Err::Error(e) => nom::Err::Error(e.with_code(code)),
125            nom::Err::Failure(e) => nom::Err::Failure(e.with_code(code)),
126        }
127    }
128
129    fn code(&self) -> Option<C> {
130        match self {
131            nom::Err::Incomplete(_) => None,
132            nom::Err::Error(e) => Some(e.code),
133            nom::Err::Failure(e) => Some(e.code),
134        }
135    }
136
137    fn span(&self) -> Option<I> {
138        match self {
139            nom::Err::Incomplete(_) => None,
140            nom::Err::Error(e) => Some(e.span.clone()),
141            nom::Err::Failure(e) => Some(e.span.clone()),
142        }
143    }
144
145    fn err(&self) -> Option<&Self::WrappedError> {
146        match self {
147            nom::Err::Incomplete(_) => None,
148            nom::Err::Error(e) => Some(e),
149            nom::Err::Failure(e) => Some(e),
150        }
151    }
152
153    fn parts(&self) -> Option<(C, I, &Self::WrappedError)> {
154        match self {
155            nom::Err::Incomplete(_) => None,
156            nom::Err::Error(e) => Some((e.code, e.span.clone(), e)),
157            nom::Err::Failure(e) => Some((e.code, e.span.clone(), e)),
158        }
159    }
160}
161
162impl<C, I, O> KParseError<C, I> for Result<(I, O), nom::Err<ParserError<C, I>>>
163where
164    C: Code,
165    I: Clone + Debug + SpanFragment,
166    I: InputTake + InputLength + InputIter,
167{
168    type WrappedError = ParserError<C, I>;
169
170    fn from(code: C, span: I) -> Self {
171        Err(nom::Err::Error(KParseError::from(code, span)))
172    }
173
174    fn with_code(self, code: C) -> Self {
175        match self {
176            Ok((rest, token)) => Ok((rest, token)),
177            Err(nom::Err::Error(e)) => Err(nom::Err::Error(e.with_code(code))),
178            Err(nom::Err::Failure(e)) => Err(nom::Err::Error(e.with_code(code))),
179            Err(nom::Err::Incomplete(e)) => Err(nom::Err::Incomplete(e)),
180        }
181    }
182
183    fn code(&self) -> Option<C> {
184        match self {
185            Ok(_) => None,
186            Err(nom::Err::Error(e)) => Some(e.code),
187            Err(nom::Err::Failure(e)) => Some(e.code),
188            Err(nom::Err::Incomplete(_)) => None,
189        }
190    }
191
192    fn span(&self) -> Option<I> {
193        match self {
194            Ok(_) => None,
195            Err(nom::Err::Error(e)) => Some(e.span.clone()),
196            Err(nom::Err::Failure(e)) => Some(e.span.clone()),
197            Err(nom::Err::Incomplete(_)) => None,
198        }
199    }
200
201    fn err(&self) -> Option<&Self::WrappedError> {
202        match self {
203            Ok(_) => None,
204            Err(nom::Err::Error(e)) => Some(e),
205            Err(nom::Err::Failure(e)) => Some(e),
206            Err(nom::Err::Incomplete(_)) => None,
207        }
208    }
209
210    fn parts(&self) -> Option<(C, I, &Self::WrappedError)> {
211        match self {
212            Ok(_) => None,
213            Err(nom::Err::Error(e)) => Some((e.code, e.span.clone(), e)),
214            Err(nom::Err::Failure(e)) => Some((e.code, e.span.clone(), e)),
215            Err(nom::Err::Incomplete(_)) => None,
216        }
217    }
218}
219
220/// Combines two ParserErrors.
221pub trait AppendParserError<Rhs = Self> {
222    /// Result of the append. Usually (), but for nom::Err::Incomplete the error is not
223    /// appended but passed through.
224    type Output;
225    /// Appends
226    fn append(&mut self, err: Rhs) -> Self::Output;
227}
228
229impl<C, I> AppendParserError<ParserError<C, I>> for ParserError<C, I>
230where
231    C: Code,
232    I: Clone,
233{
234    type Output = ();
235
236    fn append(&mut self, err: ParserError<C, I>) {
237        self.append_err(err);
238    }
239}
240
241impl<C, I> AppendParserError<ParserError<C, I>> for Option<ParserError<C, I>>
242where
243    C: Code,
244    I: Clone,
245{
246    type Output = ();
247
248    fn append(&mut self, err: ParserError<C, I>) {
249        match self {
250            None => *self = Some(err),
251            Some(self_err) => self_err.append_err(err),
252        }
253    }
254}
255
256impl<C, I> AppendParserError<nom::Err<ParserError<C, I>>> for Option<ParserError<C, I>>
257where
258    C: Code,
259    I: Clone,
260{
261    type Output = Result<(), nom::Err<ParserError<C, I>>>;
262
263    fn append(
264        &mut self,
265        err: nom::Err<ParserError<C, I>>,
266    ) -> Result<(), nom::Err<ParserError<C, I>>> {
267        match self {
268            None => match err {
269                nom::Err::Incomplete(e) => return Err(nom::Err::Incomplete(e)),
270                nom::Err::Error(e) => *self = Some(e),
271                nom::Err::Failure(e) => *self = Some(e),
272            },
273            Some(self_err) => match err {
274                nom::Err::Incomplete(e) => return Err(nom::Err::Incomplete(e)),
275                nom::Err::Error(e) => self_err.append_err(e),
276                nom::Err::Failure(e) => self_err.append_err(e),
277            },
278        };
279        Ok(())
280    }
281}
282
283impl<C, I> AppendParserError<ParserError<C, I>> for nom::Err<ParserError<C, I>>
284where
285    C: Code,
286    I: Clone,
287{
288    type Output = Result<(), nom::Err<ParserError<C, I>>>;
289
290    fn append(&mut self, err: ParserError<C, I>) -> Self::Output {
291        match self {
292            nom::Err::Incomplete(e) => return Err(nom::Err::Incomplete(*e)),
293            nom::Err::Error(e) => e.append_err(err),
294            nom::Err::Failure(e) => e.append_err(err),
295        }
296        Ok(())
297    }
298}
299
300impl<C, I> AppendParserError<nom::Err<ParserError<C, I>>> for ParserError<C, I>
301where
302    C: Code,
303    I: Clone,
304{
305    type Output = Result<(), nom::Err<ParserError<C, I>>>;
306
307    fn append(&mut self, err: nom::Err<ParserError<C, I>>) -> Self::Output {
308        match err {
309            nom::Err::Incomplete(e) => return Err(nom::Err::Incomplete(e)),
310            nom::Err::Error(e) => self.append_err(e),
311            nom::Err::Failure(e) => self.append_err(e),
312        }
313        Ok(())
314    }
315}
316
317impl<C, I> AppendParserError<nom::Err<ParserError<C, I>>> for nom::Err<ParserError<C, I>>
318where
319    C: Code,
320    I: Clone,
321{
322    type Output = Result<(), nom::Err<ParserError<C, I>>>;
323
324    fn append(&mut self, err: nom::Err<ParserError<C, I>>) -> Self::Output {
325        match self {
326            nom::Err::Incomplete(e) => return Err(nom::Err::Incomplete(*e)),
327            nom::Err::Error(e) | nom::Err::Failure(e) => match err {
328                nom::Err::Incomplete(_) => return Err(err),
329                nom::Err::Error(e2) | nom::Err::Failure(e2) => e.append_err(e2),
330            },
331        }
332        Ok(())
333    }
334}
335
336impl<C, I> nom::error::ParseError<I> for ParserError<C, I>
337where
338    C: Code,
339    I: Clone,
340{
341    fn from_error_kind(input: I, _kind: ErrorKind) -> Self {
342        ParserError {
343            code: C::NOM_ERROR,
344            span: input,
345            hints: Default::default(),
346            #[cfg(debug_assertions)]
347            backtrace: Backtrace::capture(),
348        }
349    }
350
351    fn append(_input: I, _kind: ErrorKind, other: Self) -> Self {
352        other
353    }
354
355    fn from_char(input: I, _ch: char) -> Self {
356        ParserError {
357            code: C::NOM_ERROR,
358            span: input,
359            hints: Default::default(),
360            #[cfg(debug_assertions)]
361            backtrace: Backtrace::capture(),
362        }
363    }
364
365    /// Combines two parser errors.
366    fn or(mut self, other: Self) -> Self {
367        self.append_err(other);
368        self
369    }
370}
371
372impl<C, I> Display for ParserError<C, I>
373where
374    C: Code,
375    I: Clone + Debug + SpanFragment,
376    I: InputTake + InputLength + InputIter,
377{
378    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
379        write!(f, "{}", self.code)?;
380
381        if self.iter_expected().next().is_some() {
382            write!(f, " expected ")?;
383        }
384        for (i, exp) in self.iter_expected().enumerate() {
385            if i > 0 {
386                write!(f, " ")?;
387            }
388            write!(f, "{}", exp.code)?;
389        }
390
391        if self.iter_suggested().next().is_some() {
392            write!(f, " suggested ")?;
393        }
394        for (i, sug) in self.iter_suggested().enumerate() {
395            if i > 0 {
396                write!(f, " ")?;
397            }
398            write!(f, "{}", sug.code)?;
399        }
400
401        if let Some(cause) = self.cause() {
402            write!(f, " cause {:0?}, ", cause)?;
403        }
404
405        // no suggest
406        write!(
407            f,
408            " for span {:?}",
409            restrict(DebugWidth::Short, self.span.clone()).fragment()
410        )?;
411        Ok(())
412    }
413}
414
415impl<C, I> Debug for ParserError<C, I>
416where
417    C: Code,
418    I: Clone + Debug + SpanFragment,
419    I: InputTake + InputLength + InputIter,
420{
421    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
422        debug_parse_error(f, self)
423    }
424}
425
426impl<C, I> Debug for Hints<C, I>
427where
428    C: Code,
429    I: Clone + Debug + SpanFragment,
430    I: InputTake + InputLength + InputIter,
431{
432    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
433        match self {
434            Hints::Expect(v) => write!(f, "Expect {:?} ", v),
435            Hints::Suggest(v) => write!(f, "Suggest {:?} ", v),
436            Hints::Cause(v) => write!(f, "Cause {:?}", v),
437            Hints::UserData(v) => write!(f, "UserData {:?}", v),
438        }
439    }
440}
441
442impl<C, I> Error for ParserError<C, I>
443where
444    C: Code,
445    I: Clone + Debug + SpanFragment,
446    I: InputTake + InputLength + InputIter,
447{
448    fn source(&self) -> Option<&(dyn ::std::error::Error + 'static)> {
449        self.hints
450            .iter()
451            .find(|v| matches!(v, Hints::Cause(_)))
452            .and_then(|v| {
453                if let Hints::Cause(e) = v {
454                    Some(e.as_ref())
455                } else {
456                    None
457                }
458            })
459    }
460}
461
462/// Contains a error code and the span.
463#[derive(Clone, Copy)]
464pub struct SpanAndCode<C, I> {
465    /// Error code
466    pub code: C,
467    /// Span
468    pub span: I,
469}
470
471impl<C, I> Debug for SpanAndCode<C, I>
472where
473    C: Code,
474    I: Clone + Debug + SpanFragment,
475    I: InputTake + InputLength + InputIter,
476{
477    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
478        let w = f.width().into();
479        write!(
480            f,
481            "{:?}:{:?}",
482            self.code,
483            restrict(w, self.span.clone()).fragment()
484        )?;
485        Ok(())
486    }
487}
488
489impl<C, I> ParserError<C, I>
490where
491    C: Code,
492    I: Clone,
493{
494    /// New error.
495    pub fn new(code: C, span: I) -> Self {
496        Self {
497            code,
498            span,
499            hints: Vec::new(),
500            #[cfg(debug_assertions)]
501            backtrace: Backtrace::capture(),
502        }
503    }
504
505    /// With a cause.
506    pub fn with_cause<E>(mut self, err: E) -> Self
507    where
508        E: Error + 'static,
509    {
510        self.hints.push(Hints::Cause(Box::new(err)));
511        self
512    }
513
514    /// With user data.
515    pub fn with_user_data<Y>(mut self, user_data: Y) -> Self
516    where
517        Y: 'static,
518    {
519        self.hints.push(Hints::UserData(Box::new(user_data)));
520        self
521    }
522
523    /// Finds the first (single) cause.
524    pub fn cause(&self) -> Option<&dyn Error> {
525        self.hints
526            .iter()
527            .find(|v| matches!(v, Hints::Cause(_)))
528            .and_then(|v| match v {
529                Hints::Cause(e) => Some(e.as_ref()),
530                _ => None,
531            })
532    }
533
534    /// Finds the first (single) user data.
535    pub fn user_data<Y: 'static>(&self) -> Option<&Y> {
536        self.hints
537            .iter()
538            .find(|v| matches!(v, Hints::UserData(_)))
539            .and_then(|v| match v {
540                Hints::UserData(e) => e.downcast_ref::<Y>(),
541                _ => None,
542            })
543    }
544
545    /// Convert to a nom::Err::Error.
546    pub fn error(self) -> nom::Err<Self> {
547        nom::Err::Error(self)
548    }
549
550    /// Convert to a nom::Err::Failure.
551    pub fn failure(self) -> nom::Err<Self> {
552        nom::Err::Failure(self)
553    }
554
555    /// Adds information from the other parser error to this on.
556    ///
557    /// Adds the others code and span as expect values.
558    /// Adds all the others expect values.
559    pub fn append_err(&mut self, other: ParserError<C, I>) {
560        if other.code != C::NOM_ERROR {
561            self.expect(other.code, other.span);
562        }
563        for hint in other.hints {
564            self.hints.push(hint);
565        }
566    }
567
568    /// Convert to a new error code.
569    /// If the old one differs, it is added to the expect list.
570    pub fn with_code(mut self, code: C) -> Self {
571        if self.code != code && self.code != C::NOM_ERROR {
572            self.hints.push(Hints::Expect(SpanAndCode {
573                code: self.code,
574                span: self.span.clone(),
575            }));
576        }
577        self.code = code;
578        self
579    }
580
581    /// Was this one of the expected errors.
582    /// The main error code is one of the tested values.
583    pub fn is_expected(&self, code: C) -> bool {
584        if self.code == code {
585            return true;
586        }
587        for exp in &self.hints {
588            if let Hints::Expect(v) = exp {
589                if v.code == code {
590                    return true;
591                }
592            }
593        }
594        false
595    }
596
597    /// Add an expected code.
598    pub fn expect(&mut self, code: C, span: I) {
599        self.hints.push(Hints::Expect(SpanAndCode { code, span }))
600    }
601
602    /// Adds some expected codes.
603    pub fn append_expected(&mut self, exp_iter: impl Iterator<Item = SpanAndCode<C, I>>) {
604        for exp in exp_iter {
605            self.hints.push(Hints::Expect(exp));
606        }
607    }
608
609    /// Returns the expected codes.
610    ///
611    /// # Beware
612    ///
613    /// The main error code is not included here.
614    pub fn iter_expected(&self) -> impl Iterator<Item = SpanAndCode<C, I>> + '_ {
615        self.hints.iter().rev().filter_map(|v| match v {
616            Hints::Expect(v) => Some(v.clone()),
617            _ => None,
618        })
619    }
620
621    /// Add an suggested code.
622    pub fn suggest(&mut self, code: C, span: I) {
623        self.hints.push(Hints::Suggest(SpanAndCode { code, span }))
624    }
625
626    /// Was this one of the expected errors.
627    /// The main error code is one of the tested values.
628    pub fn is_suggested(&self, code: C) -> bool {
629        for exp in &self.hints {
630            if let Hints::Suggest(v) = exp {
631                if v.code == code {
632                    return true;
633                }
634            }
635        }
636        false
637    }
638
639    /// Adds some suggested codes.
640    pub fn append_suggested(&mut self, sug_iter: impl Iterator<Item = SpanAndCode<C, I>>) {
641        for exp in sug_iter {
642            self.hints.push(Hints::Suggest(exp));
643        }
644    }
645
646    /// Returns the suggested codes.
647    pub fn iter_suggested(&self) -> impl Iterator<Item = SpanAndCode<C, I>> + '_ {
648        self.hints.iter().rev().filter_map(|v| match v {
649            Hints::Suggest(v) => Some(v.clone()),
650            _ => None,
651        })
652    }
653}