jsonpath_plus/ast/
error.rs

1use super::Span;
2
3use std::collections::BTreeSet;
4
5/// The cause of a parse failure
6#[derive(Debug, PartialEq)]
7pub enum FailReason<I> {
8    /// An unexpected token at a span
9    Unexpected(Span),
10    /// An unclosed delimiter was encountered
11    Unclosed {
12        /// The span of the found token
13        found_span: Span,
14        /// The span of the unclosed starting token
15        unclosed_span: Span,
16        /// The expected ending delimiter
17        delimiter: I,
18    },
19    /// A custom message and span
20    Custom(Span, String),
21    /// Multiple reasons merged together
22    MultiReason(Vec<FailReason<I>>),
23}
24
25impl<I> FailReason<I> {
26    fn into_vec(self) -> Vec<FailReason<I>> {
27        match self {
28            FailReason::MultiReason(v) => v,
29            _ => vec![self],
30        }
31    }
32}
33
34/// A single parse failure error
35#[derive(Debug)]
36pub struct ParseFail<I: Ord, L> {
37    reason: FailReason<I>,
38    expected: BTreeSet<Option<I>>,
39    found: Option<I>,
40    label: Option<L>,
41}
42
43impl<I: Ord, L> ParseFail<I, L> {
44    /// Create a custom parse failure
45    pub(crate) fn custom(span: Span, message: &str) -> ParseFail<I, L> {
46        ParseFail {
47            reason: FailReason::Custom(span, message.to_string()),
48            expected: BTreeSet::new(),
49            found: None,
50            label: None,
51        }
52    }
53
54    /// Get the reason of this parse failure
55    pub fn reason(&self) -> &FailReason<I> {
56        &self.reason
57    }
58}
59
60impl<I: Ord, L> chumsky::Error<I> for ParseFail<I, L> {
61    type Span = Span;
62    type Label = L;
63
64    fn expected_input_found<Iter: IntoIterator<Item = Option<I>>>(
65        span: Self::Span,
66        expected: Iter,
67        found: Option<I>,
68    ) -> Self {
69        ParseFail {
70            reason: FailReason::Unexpected(span),
71            expected: expected.into_iter().collect(),
72            found,
73            label: None,
74        }
75    }
76
77    fn unclosed_delimiter(
78        unclosed_span: Self::Span,
79        unclosed: I,
80        span: Self::Span,
81        expected: I,
82        found: Option<I>,
83    ) -> Self {
84        ParseFail {
85            reason: FailReason::Unclosed {
86                delimiter: unclosed,
87                found_span: span,
88                unclosed_span,
89            },
90            expected: BTreeSet::from([Some(expected)]),
91            found,
92            label: None,
93        }
94    }
95
96    fn with_label(mut self, label: Self::Label) -> Self {
97        self.label = Some(label);
98        self
99    }
100
101    fn merge(self, other: Self) -> Self {
102        let mut reason = self.reason.into_vec();
103        reason.extend(other.reason.into_vec());
104        reason.dedup();
105        let reason = if reason.len() == 1 {
106            reason.remove(0)
107        } else {
108            FailReason::MultiReason(reason)
109        };
110
111        let mut expected = self.expected;
112        expected.extend(other.expected);
113
114        ParseFail {
115            reason,
116            expected,
117            found: self.found.or(other.found),
118            label: self.label.or(other.label),
119        }
120    }
121}