terbium_grammar/
error.rs

1use super::*;
2
3use std::fmt::{Display, Formatter, Result as FmtResult};
4use std::ops::Range;
5
6type Span = Range<usize>;
7
8#[derive(Debug, PartialEq, Hash)]
9pub enum TargetKind {
10    Char(char),
11    Token(Token),
12    Literal,
13    Identifier,
14    End,
15}
16
17impl From<char> for TargetKind {
18    fn from(c: char) -> Self {
19        Self::Char(c)
20    }
21}
22
23impl From<Token> for TargetKind {
24    fn from(t: Token) -> Self {
25        Self::Token(t)
26    }
27}
28
29impl Display for TargetKind {
30    fn fmt(&self, f: &mut Formatter) -> FmtResult {
31        match self {
32            TargetKind::Token(token) => write!(f, "{}", token),
33            TargetKind::Char(c) => write!(f, "{:?}", c),
34            TargetKind::Literal => write!(f, "literal"),
35            TargetKind::Identifier => write!(f, "identifier"),
36            TargetKind::End => write!(f, "end"),
37        }
38    }
39}
40
41#[derive(Debug, PartialEq)]
42pub enum ErrorKind {
43    UnexpectedEnd,
44    Unexpected(TargetKind),
45    Unclosed {
46        start: TargetKind,
47        span: Span,
48        before: Option<TargetKind>,
49    },
50}
51
52#[derive(Debug, PartialEq)]
53pub struct Error {
54    pub kind: ErrorKind,
55    pub span: Span,
56    pub expected: Vec<TargetKind>,
57    pub label: Option<&'static str>,
58}
59
60impl<T: Into<TargetKind>> chumsky::Error<T> for Error {
61    type Span = Span;
62    type Label = &'static str;
63
64    fn expected_input_found<Iter: IntoIterator<Item = Option<T>>>(
65        span: Self::Span,
66        expected: Iter,
67        found: Option<T>,
68    ) -> Self {
69        Self {
70            kind: found
71                .map(Into::into)
72                .map(ErrorKind::Unexpected)
73                .unwrap_or(ErrorKind::UnexpectedEnd),
74            span,
75            expected: expected
76                .into_iter()
77                .map(|x| x.map(Into::into).unwrap_or(TargetKind::End))
78                .collect::<Vec<TargetKind>>(),
79            label: None,
80        }
81    }
82
83    fn unclosed_delimiter(
84        span: Self::Span,
85        start: T,
86        before_span: Self::Span,
87        expected: T,
88        before: Option<T>,
89    ) -> Self {
90        Self {
91            kind: ErrorKind::Unclosed {
92                start: start.into(),
93                span: before_span,
94                before: before.map(Into::into),
95            },
96            span,
97            expected: std::iter::once(expected.into()).collect(),
98            label: None,
99        }
100    }
101
102    fn with_label(mut self, label: Self::Label) -> Self {
103        self.label.get_or_insert(label);
104        self
105    }
106
107    fn merge(self, other: Self) -> Self {
108        Self {
109            kind: self.kind,
110            span: self.span.start..other.span.end,
111            expected: self.expected,
112            label: self.label,
113        }
114    }
115}