slex 0.2.4

A simple lexer for Rust
Documentation
use std::{
    error,
    fmt::{Debug, Display},
    ops::Range,
};

#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct Position {
    pub idx: Range<usize>,
    pub ln: Range<usize>,
    pub col: Range<usize>,
}
impl Position {
    pub fn new(idx: Range<usize>, ln: Range<usize>, col: Range<usize>) -> Self {
        Self { idx, ln, col }
    }
    pub fn extend(&mut self, other: &Self) {
        self.idx.end = other.idx.end;
        self.ln.end = other.ln.end;
        self.col.end = other.col.end;
    }
}
pub struct Located<T> {
    pub value: T,
    pub pos: Position,
}
impl<T> Located<T> {
    pub fn new(value: T, pos: Position) -> Self {
        Self { value, pos }
    }
}
impl<T: Clone> Clone for Located<T> {
    fn clone(&self) -> Self {
        Self {
            value: self.value.clone(),
            pos: self.pos.clone(),
        }
    }
}
impl<T: Display> Display for Located<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.value)
    }
}
impl<T: Debug> Debug for Located<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{:?}", self.value)
    }
}
impl<T: PartialEq> PartialEq for Located<T> {
    fn eq(&self, other: &Self) -> bool {
        self.value == other.value
    }
}
impl<T: Eq> Eq for Located<T> {}
impl<T> std::ops::Deref for Located<T> {
    type Target = T;
    fn deref(&self) -> &Self::Target {
        &self.value
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum ErrorType {
    BadChar(char),
    UnclosedString,
    InvalidSymbol(String),
}
#[derive(Debug, Clone, PartialEq)]
pub struct Error {
    pub error_type: ErrorType,
    pub pos: Position,
}
impl Error {
    pub fn new(error_type: ErrorType, pos: Position) -> Self {
        Self { error_type, pos }
    }
}
impl Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match &self.error_type {
            ErrorType::BadChar(c) => write!(
                f,
                "bad character '{}' at {}, (ln: {}, col: {})",
                c, self.pos.idx.start, self.pos.ln.start, self.pos.col.start
            ),
            ErrorType::UnclosedString => write!(
                f,
                "unclosed string at {}, (ln: {}, col: {})",
                self.pos.idx.start, self.pos.ln.start, self.pos.col.start
            ),
            ErrorType::InvalidSymbol(s) => write!(
                f,
                "invalid symbol '{}' at {}, (ln: {}, col: {})",
                s, self.pos.idx.start, self.pos.ln.start, self.pos.col.start
            ),
        }
    }
}
impl error::Error for Error {
    fn cause(&self) -> Option<&dyn error::Error> {
        None
    }
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        None
    }
    fn description(&self) -> &str {
        match &self.error_type {
            ErrorType::BadChar(_) => "bad character",
            ErrorType::UnclosedString => "unclosed string",
            ErrorType::InvalidSymbol(_) => "invalid symbol",
        }
    }
}