From 37c9534e98c5f0fb639400309ae0b4300205ed2a Mon Sep 17 00:00:00 2001 From: Akshay Date: Thu, 25 Mar 2021 13:05:54 +0530 Subject: ad display impls for parse and eval errors --- src/lisp/error.rs | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 107 insertions(+), 3 deletions(-) (limited to 'src') 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 @@ -#[derive(Debug, PartialEq, Copy, Clone)] +use crate::lisp::lex::{Span, SpanDisplay}; + +use std::fmt; + +#[derive(Debug, PartialEq, Clone)] pub enum LispError { - ParseError, - EvalError, + Parse(ParseError), + Eval(EvalError), +} + +impl fmt::Display for LispError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Parse(p) => write!(f, "parse error: {}", p.kind), + Self::Eval(e) => write!(f, "eval error: {}", e), + } + } +} + +#[derive(Debug, PartialEq, Clone)] +pub struct ParseError { + pub span: Span, + pub kind: ParseErrorKind, +} + +impl ParseError { + pub fn new(span: Span, kind: ParseErrorKind) -> Self { + Self { span, kind } + } + pub fn fmt(&self, f: &mut fmt::Formatter<'_>, text: &str) -> fmt::Result { + let SpanDisplay { line, col, .. } = SpanDisplay::highlight_span(self.span, text); + write!(f, "line {}, col {}: {}", line, col, self.kind) + } +} + +#[derive(Debug, PartialEq, Clone)] +pub enum ParseErrorKind { + InvalidLiteral, + InvalidToken, + InvalidChar(char), + LiteralParseError, + MissingCloseParen, + UnbalancedComma, + UnexpectedEof, + UnexpectedToken { + expected: &'static str, + found: &'static str, + }, + UnmatchedParen, + UnterminatedString, +} + +impl fmt::Display for ParseErrorKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ParseErrorKind::InvalidChar(ch) => write!(f, "invalid character {}", ch), + ParseErrorKind::InvalidToken => write!(f, "invalid token"), + ParseErrorKind::UnexpectedEof => write!(f, "unexpected end of file"), + ParseErrorKind::InvalidLiteral => write!(f, "invalid literal"), + ParseErrorKind::UnmatchedParen => write!(f, "unmatched `)`"), + ParseErrorKind::UnbalancedComma => write!(f, "unbalanced comma"), + ParseErrorKind::UnexpectedToken { expected, found } => { + write!( + f, + "unexpected token, got `{}`, expected `{}`", + found, expected + ) + } + ParseErrorKind::LiteralParseError => write!(f, "error parsing literal"), + ParseErrorKind::MissingCloseParen => write!(f, "missing `)`"), + ParseErrorKind::UnterminatedString => write!(f, "unterminated string literal"), + } + } +} + +impl From for LispError { + fn from(p: ParseError) -> Self { + LispError::Parse(p) + } +} + +#[derive(Debug, PartialEq, Clone)] +pub enum EvalError { + ArgumentCount(Option), // expected + BadForm, + UnboundVariable(String), + DivByZero, + TypeMismatch, +} + +impl fmt::Display for EvalError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::ArgumentCount(i) => { + write!(f, "invalid number of arguments, expected atleast {:?}", i) + } + Self::BadForm => write!(f, "bad expression form"), + Self::UnboundVariable(s) => write!(f, "unbound variable {}", s), + Self::TypeMismatch => write!(f, "mismatched types"), + Self::DivByZero => write!(f, "attempt to divide by zero"), + } + } +} + +impl From for LispError { + fn from(e: EvalError) -> Self { + LispError::Eval(e) + } } -- cgit v1.2.3