aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lisp/error.rs110
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)] 1use crate::lisp::lex::{Span, SpanDisplay};
2
3use std::fmt;
4
5#[derive(Debug, PartialEq, Clone)]
2pub enum LispError { 6pub enum LispError {
3 ParseError, 7 Parse(ParseError),
4 EvalError, 8 Eval(EvalError),
9}
10
11impl 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)]
21pub struct ParseError {
22 pub span: Span,
23 pub kind: ParseErrorKind,
24}
25
26impl 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)]
37pub 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
53impl 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
76impl From<ParseError> for LispError {
77 fn from(p: ParseError) -> Self {
78 LispError::Parse(p)
79 }
80}
81
82#[derive(Debug, PartialEq, Clone)]
83pub enum EvalError {
84 ArgumentCount(Option<u32>), // expected
85 BadForm,
86 UnboundVariable(String),
87 DivByZero,
88 TypeMismatch,
89}
90
91impl 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
105impl From<EvalError> for LispError {
106 fn from(e: EvalError) -> Self {
107 LispError::Eval(e)
108 }
5} 109}