diff options
Diffstat (limited to 'src/lisp')
-rw-r--r-- | src/lisp/error.rs | 110 |
1 files changed, 107 insertions, 3 deletions
diff --git a/src/lisp/error.rs b/src/lisp/error.rs index 99dec3b..4f90d14 100644 --- a/src/lisp/error.rs +++ b/src/lisp/error.rs | |||
@@ -1,5 +1,109 @@ | |||
1 | #[derive(Debug, PartialEq, Copy, Clone)] | 1 | use crate::lisp::lex::{Span, SpanDisplay}; |
2 | |||
3 | use std::fmt; | ||
4 | |||
5 | #[derive(Debug, PartialEq, Clone)] | ||
2 | pub enum LispError { | 6 | pub enum LispError { |
3 | ParseError, | 7 | Parse(ParseError), |
4 | EvalError, | 8 | Eval(EvalError), |
9 | } | ||
10 | |||
11 | impl fmt::Display for LispError { | ||
12 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
13 | match self { | ||
14 | Self::Parse(p) => write!(f, "parse error: {}", p.kind), | ||
15 | Self::Eval(e) => write!(f, "eval error: {}", e), | ||
16 | } | ||
17 | } | ||
18 | } | ||
19 | |||
20 | #[derive(Debug, PartialEq, Clone)] | ||
21 | pub struct ParseError { | ||
22 | pub span: Span, | ||
23 | pub kind: ParseErrorKind, | ||
24 | } | ||
25 | |||
26 | impl ParseError { | ||
27 | pub fn new(span: Span, kind: ParseErrorKind) -> Self { | ||
28 | Self { span, kind } | ||
29 | } | ||
30 | pub fn fmt(&self, f: &mut fmt::Formatter<'_>, text: &str) -> fmt::Result { | ||
31 | let SpanDisplay { line, col, .. } = SpanDisplay::highlight_span(self.span, text); | ||
32 | write!(f, "line {}, col {}: {}", line, col, self.kind) | ||
33 | } | ||
34 | } | ||
35 | |||
36 | #[derive(Debug, PartialEq, Clone)] | ||
37 | pub enum ParseErrorKind { | ||
38 | InvalidLiteral, | ||
39 | InvalidToken, | ||
40 | InvalidChar(char), | ||
41 | LiteralParseError, | ||
42 | MissingCloseParen, | ||
43 | UnbalancedComma, | ||
44 | UnexpectedEof, | ||
45 | UnexpectedToken { | ||
46 | expected: &'static str, | ||
47 | found: &'static str, | ||
48 | }, | ||
49 | UnmatchedParen, | ||
50 | UnterminatedString, | ||
51 | } | ||
52 | |||
53 | impl fmt::Display for ParseErrorKind { | ||
54 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
55 | match self { | ||
56 | ParseErrorKind::InvalidChar(ch) => write!(f, "invalid character {}", ch), | ||
57 | ParseErrorKind::InvalidToken => write!(f, "invalid token"), | ||
58 | ParseErrorKind::UnexpectedEof => write!(f, "unexpected end of file"), | ||
59 | ParseErrorKind::InvalidLiteral => write!(f, "invalid literal"), | ||
60 | ParseErrorKind::UnmatchedParen => write!(f, "unmatched `)`"), | ||
61 | ParseErrorKind::UnbalancedComma => write!(f, "unbalanced comma"), | ||
62 | ParseErrorKind::UnexpectedToken { expected, found } => { | ||
63 | write!( | ||
64 | f, | ||
65 | "unexpected token, got `{}`, expected `{}`", | ||
66 | found, expected | ||
67 | ) | ||
68 | } | ||
69 | ParseErrorKind::LiteralParseError => write!(f, "error parsing literal"), | ||
70 | ParseErrorKind::MissingCloseParen => write!(f, "missing `)`"), | ||
71 | ParseErrorKind::UnterminatedString => write!(f, "unterminated string literal"), | ||
72 | } | ||
73 | } | ||
74 | } | ||
75 | |||
76 | impl From<ParseError> for LispError { | ||
77 | fn from(p: ParseError) -> Self { | ||
78 | LispError::Parse(p) | ||
79 | } | ||
80 | } | ||
81 | |||
82 | #[derive(Debug, PartialEq, Clone)] | ||
83 | pub enum EvalError { | ||
84 | ArgumentCount(Option<u32>), // expected | ||
85 | BadForm, | ||
86 | UnboundVariable(String), | ||
87 | DivByZero, | ||
88 | TypeMismatch, | ||
89 | } | ||
90 | |||
91 | impl fmt::Display for EvalError { | ||
92 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
93 | match self { | ||
94 | Self::ArgumentCount(i) => { | ||
95 | write!(f, "invalid number of arguments, expected atleast {:?}", i) | ||
96 | } | ||
97 | Self::BadForm => write!(f, "bad expression form"), | ||
98 | Self::UnboundVariable(s) => write!(f, "unbound variable {}", s), | ||
99 | Self::TypeMismatch => write!(f, "mismatched types"), | ||
100 | Self::DivByZero => write!(f, "attempt to divide by zero"), | ||
101 | } | ||
102 | } | ||
103 | } | ||
104 | |||
105 | impl From<EvalError> for LispError { | ||
106 | fn from(e: EvalError) -> Self { | ||
107 | LispError::Eval(e) | ||
108 | } | ||
5 | } | 109 | } |