Skip to main content

cl_parser/parser/
error.rs

1use super::pat::Prec as PatPrec;
2use cl_lexer::LexError;
3use cl_structures::span::Span;
4use cl_token::TKind;
5use std::{error::Error, fmt::Display};
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8pub enum ParseError {
9    /// Reached the expected end of input.
10    EOF(Span),
11    /// Unexpectedly reached end of input.
12    UnexpectedEOF(Span),
13    /// Did not reach end of enput when expected.
14    ExpectedEOF(TKind, Span),
15    FromLexer(LexError),
16    Expected(TKind, TKind, Span),
17    NotLiteral(TKind, Span),
18    NotUse(TKind, Span),
19    NotPattern(TKind, PatPrec, Span),
20    NotBind(TKind, Span),
21    NotPrefix(TKind, Span),
22    NotInfix(TKind, Span),
23    NotPostfix(TKind, Span),
24}
25
26pub use ParseError::EOF;
27
28impl Error for ParseError {}
29impl Display for ParseError {
30    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31        match self {
32            Self::EOF(loc) => write!(f, "{loc}: Reached end of input."),
33            Self::UnexpectedEOF(loc) => write!(f, "{loc}: Unexpected end of input."),
34            Self::ExpectedEOF(tk, loc) => write!(f, "{loc}: Expected end of input, got {tk:?}."),
35            Self::FromLexer(e) => e.fmt(f),
36            Self::Expected(e, tk, loc) => write!(f, "{loc}: Expected {e:?}, got {tk:?}."),
37            Self::NotLiteral(tk, loc) => write!(f, "{loc}: {tk:?} is not valid in a literal."),
38            Self::NotUse(tk, loc) => write!(f, "{loc}: {tk:?} is no use!"),
39            Self::NotPattern(tk, prec, loc) => {
40                write!(f, "{loc}: {tk:?} is not valid in a {prec:?} pattern.")
41            }
42            Self::NotBind(bind, loc) => {
43                write!(f, "{loc}: {bind:?} is not valid in a bind expression.")
44            }
45            Self::NotPrefix(tk, loc) => write!(f, "{loc}: {tk:?} is not a prefix operator."),
46            Self::NotInfix(tk, loc) => write!(f, "{loc}: {tk:?} is not a infix operator."),
47            Self::NotPostfix(tk, loc) => write!(f, "{loc}: {tk:?} is not a postfix operator."),
48        }
49    }
50}
51
52pub type PResult<T> = Result<T, ParseError>;
53
54pub trait PResultExt<T> {
55    fn no_eof(self) -> PResult<T>;
56    fn allow_eof(self) -> PResult<Option<T>>;
57    fn is_eof(&self) -> bool;
58}
59
60impl<T> PResultExt<T> for PResult<T> {
61    fn no_eof(self) -> Self {
62        match self {
63            Err(ParseError::EOF(span)) => Err(ParseError::UnexpectedEOF(span)),
64            other => other,
65        }
66    }
67    fn allow_eof(self) -> PResult<Option<T>> {
68        match self {
69            Ok(t) => Ok(Some(t)),
70            Err(ParseError::EOF(_)) => Ok(None),
71            Err(e) => Err(e),
72        }
73    }
74    fn is_eof(&self) -> bool {
75        matches!(self, Err(ParseError::EOF(_)))
76    }
77}
78
79/// Opens a scope where [`ParseError::EOF`] is unexpected (See [`PResultExt::no_eof`])
80pub fn no_eof<T>(f: impl FnOnce() -> PResult<T>) -> PResult<T> {
81    f().no_eof()
82}