xee_xpath_ast/
error.rs

1use chumsky::input::ValueInput;
2use chumsky::prelude::SimpleSpan as Span;
3use chumsky::util::MaybeRef;
4use xee_xpath_lexer::Token;
5
6use crate::ast;
7
8#[derive(Debug, Clone, PartialEq)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize))]
10pub enum ParserError {
11    ExpectedFound { span: Span },
12    UnknownPrefix { span: Span, prefix: String },
13    Reserved { span: Span, name: String },
14    ArityOverflow { span: Span },
15    UnknownType { span: Span, name: ast::Name },
16    IllegalFunctionInPattern { span: Span, name: ast::Name },
17}
18
19impl ParserError {
20    pub fn span(&self) -> Span {
21        match self {
22            Self::ExpectedFound { span, .. } => *span,
23            Self::UnknownPrefix { span, .. } => *span,
24            Self::Reserved { span, .. } => *span,
25            Self::ArityOverflow { span } => *span,
26            Self::UnknownType { span, .. } => *span,
27            Self::IllegalFunctionInPattern { span, .. } => *span,
28        }
29    }
30
31    pub fn adjust(mut self, start: usize) -> Self {
32        use ParserError::*;
33        let span = match &mut self {
34            ExpectedFound { span } => span,
35            UnknownPrefix { span, .. } => span,
36            Reserved { span, .. } => span,
37            ArityOverflow { span } => span,
38            UnknownType { span, .. } => span,
39            IllegalFunctionInPattern { span, .. } => span,
40        };
41        *span = Span::new(span.start + start, span.end + start);
42        self
43    }
44}
45
46impl<'a, I, L> chumsky::error::LabelError<'a, I, L> for ParserError
47where
48    I: ValueInput<'a, Token = Token<'a>, Span = Span>,
49{
50    // we don't do anything with expected and found, instead just retaining
51    // the span. This is because these contain tokens with a lifetime, and
52    // having a lifetime for the ParserError turns out open up a world of trouble
53    // as soon as we want to build on it in the XSLT parser. We also don't
54    // have a good way to turn a logos token into a human-readable string, so
55    // we couldn't really construct good error messages anyway.
56    fn expected_found<E: IntoIterator<Item = L>>(
57        _expected: E,
58        _found: Option<MaybeRef<'a, I::Token>>,
59        span: I::Span,
60    ) -> Self {
61        Self::ExpectedFound { span }
62    }
63}
64
65impl<'a, I> chumsky::error::Error<'a, I> for ParserError
66where
67    I: ValueInput<'a, Token = Token<'a>, Span = Span>,
68{
69    fn merge(self, other: Self) -> Self {
70        match (self, other) {
71            (
72                ParserError::ExpectedFound { span: span_a },
73                ParserError::ExpectedFound { span: _ },
74            ) => ParserError::ExpectedFound { span: span_a },
75            (ParserError::ExpectedFound { .. }, a) => a,
76            (a, ParserError::ExpectedFound { .. }) => a,
77            (a, _) => a,
78        }
79    }
80}