2021-07-13 13:54:27 -05:00
|
|
|
use std::{fmt::Display, io, ops::Range};
|
2021-04-18 15:33:55 -05:00
|
|
|
|
2021-06-06 17:09:45 -05:00
|
|
|
use crate::{brian::InterpretError, lexer::Token};
|
2021-06-02 15:29:31 -05:00
|
|
|
|
2021-06-18 16:05:50 -05:00
|
|
|
#[derive(Debug)]
|
2021-04-18 15:33:55 -05:00
|
|
|
pub struct Error {
|
|
|
|
pub kind: ErrorKind,
|
2021-06-06 16:13:48 -05:00
|
|
|
pub span: Range<usize>,
|
2021-04-18 15:33:55 -05:00
|
|
|
}
|
|
|
|
|
2021-06-18 16:05:50 -05:00
|
|
|
#[derive(Debug)]
|
2021-04-18 15:33:55 -05:00
|
|
|
pub enum ErrorKind {
|
2021-04-26 03:44:42 -05:00
|
|
|
SyntaxError(String),
|
2021-06-06 17:09:45 -05:00
|
|
|
UnexpectedEof,
|
|
|
|
UnexpectedToken(Token),
|
2021-04-27 04:09:19 -05:00
|
|
|
InvalidIdentifier,
|
2021-05-20 18:18:01 -05:00
|
|
|
UnknownVariable(String),
|
|
|
|
MeloVariable(String),
|
|
|
|
TypeError(String),
|
2021-05-25 21:22:38 -05:00
|
|
|
TopLevelBreak,
|
2021-06-02 15:29:31 -05:00
|
|
|
BfInterpretError(InterpretError),
|
2021-06-12 22:07:58 -05:00
|
|
|
MismatchedArgumentError,
|
2021-06-06 17:09:45 -05:00
|
|
|
MissingLhs,
|
2021-06-18 16:05:50 -05:00
|
|
|
IOError(io::Error),
|
2021-06-06 17:09:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Error {
|
|
|
|
pub fn new(kind: ErrorKind, span: Range<usize>) -> Self {
|
|
|
|
Self { kind, span }
|
|
|
|
}
|
|
|
|
|
2021-06-07 20:03:26 -05:00
|
|
|
/// Create an UnexpectedEof error, where the EOF occurs at the
|
|
|
|
/// given index in the file.
|
|
|
|
pub fn unexpected_eof(index: usize) -> Self {
|
|
|
|
Self::new(ErrorKind::UnexpectedEof, index..index)
|
2021-06-06 17:09:45 -05:00
|
|
|
}
|
2021-04-27 06:48:56 -05:00
|
|
|
}
|
2021-06-18 16:05:50 -05:00
|
|
|
|
2021-07-13 13:54:27 -05:00
|
|
|
impl Display for Error {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
write!(
|
|
|
|
f,
|
|
|
|
"Error at range {}-{}: {}",
|
|
|
|
self.span.start, self.span.end, self.kind
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl std::error::Error for Error {}
|
|
|
|
|
|
|
|
impl Display for ErrorKind {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
match self {
|
|
|
|
ErrorKind::SyntaxError(desc) => write!(f, "syntax error: {}", desc),
|
|
|
|
ErrorKind::UnexpectedEof => write!(f, "unexpected end of file"),
|
|
|
|
ErrorKind::UnexpectedToken(token) => write!(f, "unexpected token {:?}", token),
|
|
|
|
ErrorKind::InvalidIdentifier => write!(f, "invalid identifier"),
|
|
|
|
ErrorKind::UnknownVariable(name) => write!(f, "unknown identifier \"{}\"", name),
|
|
|
|
ErrorKind::MeloVariable(name) => write!(f, "banned variable \"{}\"", name),
|
|
|
|
ErrorKind::TypeError(desc) => write!(f, "type error: {}", desc),
|
|
|
|
ErrorKind::TopLevelBreak => write!(f, "can only `break` out of a loop"),
|
|
|
|
ErrorKind::BfInterpretError(err) => write!(f, "brainfuck error: {}", err),
|
|
|
|
// TODO: give concrete numbers here.
|
|
|
|
ErrorKind::MismatchedArgumentError => write!(f, "wrong number of function arguments"),
|
|
|
|
ErrorKind::MissingLhs => write!(f, "missing expression before binary operation"),
|
|
|
|
ErrorKind::IOError(err) => write!(f, "I/O error: {}", err),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-18 16:05:50 -05:00
|
|
|
impl From<io::Error> for Error {
|
|
|
|
fn from(e: io::Error) -> Self {
|
|
|
|
Self {
|
|
|
|
kind: ErrorKind::IOError(e),
|
|
|
|
span: 0..0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|