#[derive(Debug, Clone)]
pub struct KabelError {
pub kind: ErrorKind,
pub message: String,
pub hint: Option<String>,
pub line: usize,
pub column: usize,
pub code: String,
}
impl KabelError {
pub fn new(kind: ErrorKind, message: String, hint: Option<String>, line: usize, column: usize, code: String) -> Self {
Self {
kind,
message,
hint,
line,
column,
code,
}
}
}
impl std::fmt::Display for KabelError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let caret_space: String = vec![' '; self.column].iter().collect();
f.write_str(&format!(
"Error {:0>4}: {1} at line {2}, column {3}\n\
{4}\n\
{5}^",
self.kind.clone() as usize,
self.message,
self.line + 1,
self.column + 1,
self.code,
caret_space
))?;
if let Some(ref hint) = self.hint {
f.write_str(&format!("\n{0}{1}", caret_space, hint))?;
}
Ok(())
}
}
impl std::error::Error for KabelError {}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ErrorKind {
UnexpectedEof,
UnexpectedCharacter,
UnexpectedToken,
MissingDelimiter,
OutOfScope,
VariableAlreadyDeclaredVariable,
VariableAlreadyDeclaredFunction,
FunctionAlreadyDeclaredVariable,
FunctionAlreadyDeclaredFunction,
IncorrectArity,
}
impl std::fmt::Display for ErrorKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use ErrorKind::*;
match self {
UnexpectedEof => f.write_str("Unexpected End of File"),
UnexpectedCharacter => f.write_str("Unrecognized Charcter"),
UnexpectedToken => f.write_str("Unrecognized Token"),
MissingDelimiter => f.write_str("Missing delimiter"),
OutOfScope => f.write_str("Out of scope"),
VariableAlreadyDeclaredVariable => f.write_str("Variable already declared variable"),
VariableAlreadyDeclaredFunction => f.write_str("Variable already declared function"),
FunctionAlreadyDeclaredVariable => f.write_str("Function already declared variable"),
FunctionAlreadyDeclaredFunction => f.write_str("Function already declared function"),
IncorrectArity => f.write_str("Incorrect arity"),
}
}
}
impl From<ErrorKind> for usize {
fn from(value: ErrorKind) -> Self {
use ErrorKind::*;
match value {
UnexpectedEof => 0x00,
UnexpectedCharacter => 0x01,
UnexpectedToken => 0x02,
MissingDelimiter => 0x03,
OutOfScope => 0x04,
VariableAlreadyDeclaredVariable => 0x05,
VariableAlreadyDeclaredFunction => 0x06,
FunctionAlreadyDeclaredVariable => 0x07,
FunctionAlreadyDeclaredFunction => 0x08,
IncorrectArity => 0x09,
}
}
}