sphinx/lexer/
errors.rs

1use core::fmt;
2use std::error::Error;
3use crate::debug::DebugSymbol;
4
5
6// Lexer Errors
7
8#[derive(Debug)]
9pub enum ErrorKind {
10    IOError,
11    UnexpectedEOF,
12    NoMatchingRule,
13    CouldNotReadToken,
14    MaxTokenLengthExceeded,
15    SourceTooLong,
16}
17
18impl fmt::Display for ErrorKind {
19    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
20        let msg = match self {
21            Self::IOError => "error reading source text",
22            Self::NoMatchingRule => "unrecognized token",
23            Self::UnexpectedEOF => "unexpected end of file",
24            Self::CouldNotReadToken => "invalid token",
25            Self::MaxTokenLengthExceeded => "max token length exceeded",
26            Self::SourceTooLong => "max source length exceeded",
27        };
28        fmt.write_str(msg)
29    }
30}
31
32
33#[derive(Debug)]
34pub struct LexerError {
35    kind: ErrorKind,
36    symbol: DebugSymbol,
37    cause: Option<Box<dyn Error>>,
38}
39
40impl LexerError {
41    pub fn new(kind: ErrorKind, symbol: DebugSymbol) -> Self {
42        LexerError {
43            kind, symbol,
44            cause: None,
45        }
46    }
47    
48    pub fn caused_by(mut self, cause: Box<dyn Error>) -> Self {
49        self.cause = Some(cause); self
50    }
51    
52    pub fn kind(&self) -> &ErrorKind { &self.kind }
53    pub fn debug_symbol(&self) -> &DebugSymbol { &self.symbol }
54    
55}
56
57impl Error for LexerError {
58    fn source(&self) -> Option<&(dyn Error + 'static)> {
59        self.cause.as_ref().map(|o| o.as_ref())
60    }
61}
62
63impl fmt::Display for LexerError {
64    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
65        write!(fmt, "{}", self.kind)?;
66        if let Some(err) = self.source() {
67            write!(fmt, ": {}", err)?;
68        }
69        Ok(())
70    }
71}
72