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/// All the ways a [Parser](crate::parser::Parser) can fail
8#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9pub enum ParseError {
10    /// Reached the expected end of input.
11    EOF(Span),
12    /// *Unexpectedly* reached end of input.
13    UnexpectedEOF(Span),
14    /// Did not reach end of enput when expected.
15    ExpectedEOF(TKind, Span),
16    /// The [`Lexer`](cl_lexer::Lexer) didn't like that.
17    FromLexer(LexError),
18    /// Expected [`TKind`] `0`, got [`TKind`] `1` at [`struct@Span`]
19    Expected(TKind, TKind, Span),
20    /// Tried to parse a literal, but got [`TKind`] instead, at [`struct@Span`]
21    NotLiteral(TKind, Span),
22    /// Tried to parse a use item, but got [`TKind`] instead, at [`struct@Span`]
23    NotUse(TKind, Span),
24    /// Tried to parse a pattern, but got [`TKind`] at [`PatPrec`] instead, at [`struct@Span`]
25    NotPattern(TKind, PatPrec, Span),
26    /// Tried to parse a bind item, but got [`TKind`] instead, at [`struct@Span`]
27    NotBind(TKind, Span),
28    /// Tried to parse a prefix expression, but got [`TKind`] instead, at [`struct@Span`]
29    NotPrefix(TKind, Span),
30    /// Tried to parse an infix expression, but got [`TKind`] instead, at [`struct@Span`]
31    NotInfix(TKind, Span),
32    /// Tried to parse a postfix expression, but got [`TKind`] instead, at [`struct@Span`]
33    NotPostfix(TKind, Span),
34}
35
36pub use ParseError::EOF;
37
38impl Error for ParseError {}
39impl Display for ParseError {
40    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41        match self {
42            Self::EOF(loc) => write!(f, "{loc}: Reached end of input."),
43            Self::UnexpectedEOF(loc) => write!(f, "{loc}: Unexpected end of input."),
44            Self::ExpectedEOF(tk, loc) => write!(f, "{loc}: Expected end of input, got {tk:?}."),
45            Self::FromLexer(e) => e.fmt(f),
46            Self::Expected(e, tk, loc) => write!(f, "{loc}: Expected {e:?}, got {tk:?}."),
47            Self::NotLiteral(tk, loc) => write!(f, "{loc}: {tk:?} is not valid in a literal."),
48            Self::NotUse(tk, loc) => write!(f, "{loc}: {tk:?} is no use!"),
49            Self::NotPattern(tk, prec, loc) => {
50                write!(f, "{loc}: {tk:?} is not valid in a {prec:?} pattern.")
51            }
52            Self::NotBind(bind, loc) => {
53                write!(f, "{loc}: {bind:?} is not valid in a bind expression.")
54            }
55            Self::NotPrefix(tk, loc) => write!(f, "{loc}: {tk:?} is not a prefix operator."),
56            Self::NotInfix(tk, loc) => write!(f, "{loc}: {tk:?} is not a infix operator."),
57            Self::NotPostfix(tk, loc) => write!(f, "{loc}: {tk:?} is not a postfix operator."),
58        }
59    }
60}
61
62pub type PResult<T> = Result<T, ParseError>;
63
64pub trait PResultExt<T> {
65    /// Turns [`ParseError::EOF`] into [`ParseError::UnexpectedEOF`]
66    fn no_eof(self) -> PResult<T>;
67    /// Maps [`ParseError::EOF`] to [`None`], [`Ok`] to [`Some`]
68    fn allow_eof(self) -> PResult<Option<T>>;
69    /// Returns whether this is [Err] containing [ParseError::EOF]
70    fn is_eof(&self) -> bool;
71}
72
73impl<T> PResultExt<T> for PResult<T> {
74    fn no_eof(self) -> Self {
75        match self {
76            Err(ParseError::EOF(span)) => Err(ParseError::UnexpectedEOF(span)),
77            other => other,
78        }
79    }
80    fn allow_eof(self) -> PResult<Option<T>> {
81        match self {
82            Ok(t) => Ok(Some(t)),
83            Err(ParseError::EOF(_)) => Ok(None),
84            Err(e) => Err(e),
85        }
86    }
87    fn is_eof(&self) -> bool {
88        matches!(self, Err(ParseError::EOF(_)))
89    }
90}
91
92/// Opens a scope where [`ParseError::EOF`] is unexpected (See [`PResultExt::no_eof`])
93pub fn no_eof<T>(f: impl FnOnce() -> PResult<T>) -> PResult<T> {
94    f().no_eof()
95}