use std::{error::Error, fmt::Display};
use thiserror::Error;
use crate::parser::error::{AdditionalHelp, ErrorContext, ErrorContextDisplay};
#[derive(Error, Debug)]
pub enum LexingError {
#[error("No matches were found")]
NoMatchesTaken,
#[error("Expected an token, but reached end of file")]
UnexpectedEOF,
#[error("Char ('{0}') is not a know token!")]
UnknownCharacter(char),
#[error("The Arrow token must be of the form: ->")]
ExpectedArrow,
#[error("The Comment token must start with two slashes")]
ExpectedComment,
#[error("It seams like, you have a un-closed quote")]
RunawayQuote,
}
impl AdditionalHelp for LexingError {
fn additional_help(&self) -> String {
match self {
LexingError::NoMatchesTaken => "This is probably a bug, please open an issue at the issue tracker".to_owned(),
LexingError::UnexpectedEOF => "This eof was completely unexpected".to_owned(),
LexingError::ExpectedArrow => "The `-` token is interpretet as a started arrow (`->`), but we could not find the arrow tip (`>`)".to_owned(),
LexingError::UnknownCharacter(char) => {
format!("This char: `{char}`; is not a valid token")
},
LexingError::ExpectedComment => "The '/' started comment parsing, but I could not find a matching '/'".to_owned(),
LexingError::RunawayQuote => "Add a quote, somewhere.".to_owned(),
}
}
}
#[derive(Debug)]
pub struct SpannedLexingError {
pub source: LexingError,
pub context: ErrorContext,
}
impl Error for SpannedLexingError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
Some(&self.source)
}
}
impl ErrorContextDisplay for SpannedLexingError {
type Error = LexingError;
fn context(&self) -> &crate::parser::error::ErrorContext {
&self.context
}
fn line_number(&self) -> usize {
self.context.line_number
}
fn line_above(&self) -> &str {
&self.context.line_above
}
fn line_below(&self) -> &str {
&self.context.line_below
}
fn line(&self) -> &str {
&self.context.line
}
fn source(&self) -> &<SpannedLexingError as ErrorContextDisplay>::Error {
&self.source
}
}
impl Display for SpannedLexingError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.error_fmt(f)
}
}