use std::fmt;
use crate::datum::{Delim, Prefix};
use crate::span::Span;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum ErrorKind {
#[non_exhaustive]
UnexpectedDelimiter {
found: Delim,
},
#[non_exhaustive]
MismatchedDelimiter {
expected: Delim,
found: Delim,
},
#[non_exhaustive]
UnclosedList {
open: Delim,
},
#[non_exhaustive]
MalformedToken {
text: Box<str>,
},
#[non_exhaustive]
DanglingPrefix {
prefix: Prefix,
},
DanglingTag,
DanglingLabel,
DanglingDot,
ItemAfterDottedTail,
DepthLimitExceeded,
}
impl fmt::Display for ErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ErrorKind::UnexpectedDelimiter { found } => {
write!(f, "unexpected closing delimiter `{}`", close_glyph(*found))
}
ErrorKind::MismatchedDelimiter { expected, found } => write!(
f,
"mismatched closing delimiter: expected `{}`, found `{}`",
close_glyph(*expected),
close_glyph(*found)
),
ErrorKind::UnclosedList { open } => {
write!(f, "unclosed list opened with `{}`", open_glyph(*open))
}
ErrorKind::MalformedToken { text } => write!(f, "malformed token `{text}`"),
ErrorKind::DanglingPrefix { prefix } => {
write!(f, "{prefix:?} prefix with no following datum")
}
ErrorKind::DanglingTag => write!(f, "tagged literal with no following datum"),
ErrorKind::DanglingLabel => write!(f, "datum label with no following datum"),
ErrorKind::DanglingDot => write!(f, "dotted list with no tail datum"),
ErrorKind::ItemAfterDottedTail => {
write!(f, "item after dotted tail")
}
ErrorKind::DepthLimitExceeded => {
write!(f, "nesting too deep; stopped descending")
}
}
}
}
fn open_glyph(delim: Delim) -> &'static str {
match delim {
Delim::Round => "(",
Delim::Square => "[",
Delim::Curly => "{",
Delim::Set => "#{",
}
}
fn close_glyph(delim: Delim) -> &'static str {
match delim {
Delim::Round => ")",
Delim::Square => "]",
Delim::Curly | Delim::Set => "}",
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ParseError {
pub span: Span,
pub line: u32,
pub kind: ErrorKind,
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "line {}: {}", self.line, self.kind)
}
}
impl std::error::Error for ParseError {}