1use std::{error::Error, fmt};
2
3use crate::{parser::Parser, token::Tokenizer, Span};
4
5#[derive(Clone, Debug)]
6pub struct ParseErrors<P, T, Idx> {
7 pub errors: Vec<ParseError<P, T, Idx>>,
8}
9
10impl<P, T, Idx> Error for ParseErrors<P, T, Idx> where Self: fmt::Debug + fmt::Display {}
11
12pub type ParseErrorsFor<P, T> = ParseErrors<
13 <P as Parser<<T as Tokenizer>::Token>>::Error,
14 <T as Tokenizer>::Error,
15 <T as Tokenizer>::Position,
16>;
17
18impl<P: fmt::Display, T: fmt::Display, Idx: fmt::Display> fmt::Display for ParseErrors<P, T, Idx> {
19 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
20 if self.errors.len() == 1 {
21 f.write_str("Encountered 1 error:\n")?;
22 } else {
23 writeln!(f, "Encountered {} errors:", self.errors.len())?;
24 }
25 for error in &self.errors {
26 writeln!(f, "{error}")?;
27 }
28 Ok(())
29 }
30}
31
32impl<P, T, Idx> From<Vec<ParseError<P, T, Idx>>> for ParseErrors<P, T, Idx> {
33 fn from(errors: Vec<ParseError<P, T, Idx>>) -> Self {
34 ParseErrors { errors }
35 }
36}
37
38#[derive(Clone, Copy, Debug)]
39pub struct ParseError<P, T, Idx> {
40 pub span: Span<Idx>,
41 pub kind: ParseErrorKind<P, T, Idx>,
42}
43
44impl<P, T, Idx> Error for ParseError<P, T, Idx> where Self: fmt::Debug + fmt::Display {}
45
46impl<P, T, Idx> fmt::Display for ParseError<P, T, Idx>
47where
48 Span<Idx>: fmt::Display,
49 ParseErrorKind<P, T, Idx>: fmt::Display,
50{
51 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
52 write!(f, "Parse error at {}: {}", self.span, self.kind)
53 }
54}
55
56#[derive(Clone, Copy, Debug, Eq, PartialEq)]
57pub enum ParseErrorKind<P, T, Idx> {
58 EndOfInput { expected: &'static str },
59 UnexpectedToken { expected: &'static str },
60 MismatchedDelimiter { opening: Span<Idx> },
61 UnmatchedRightDelimiter,
62 UnmatchedLeftDelimiter,
63 Parser(P),
64 Tokenizer(T),
65}
66
67impl<P, T, Idx> fmt::Display for ParseErrorKind<P, T, Idx>
68where
69 P: fmt::Display,
70 T: fmt::Display,
71 Idx: fmt::Display,
72{
73 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74 match self {
75 Self::EndOfInput { expected } => {
76 write!(f, "Unexpected end of input (expected {expected})")
77 }
78 Self::UnexpectedToken { expected } => {
79 write!(f, "Unexpected token (expected {expected})")
80 }
81 Self::MismatchedDelimiter { opening } => {
82 write!(f, "Mismatched closing delimiter (opening {opening})")
83 }
84 Self::UnmatchedRightDelimiter => f.write_str("Unmatched closing delimiter"),
85 Self::UnmatchedLeftDelimiter => f.write_str("Unmatched opening delimiter"),
86 Self::Parser(err) => fmt::Display::fmt(err, f),
87 Self::Tokenizer(err) => fmt::Display::fmt(err, f),
88 }
89 }
90}
91
92impl<P, T, Idx> ParseErrorKind<P, T, Idx> {
93 #[cfg(test)]
94 pub(crate) fn map_tokenizer_error<U>(
95 self,
96 f: impl FnOnce(T) -> U,
97 ) -> ParseErrorKind<P, U, Idx> {
98 match self {
99 Self::EndOfInput { expected } => ParseErrorKind::EndOfInput { expected },
100 Self::UnexpectedToken { expected } => ParseErrorKind::UnexpectedToken { expected },
101 Self::MismatchedDelimiter { opening } => {
102 ParseErrorKind::MismatchedDelimiter { opening }
103 }
104 Self::UnmatchedRightDelimiter => ParseErrorKind::UnmatchedRightDelimiter,
105 Self::UnmatchedLeftDelimiter => ParseErrorKind::UnmatchedLeftDelimiter,
106 Self::Parser(e) => ParseErrorKind::Parser(e),
107 Self::Tokenizer(e) => ParseErrorKind::Tokenizer(f(e)),
108 }
109 }
110}