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}