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