mago_lexer/
error.rs

1use serde::Deserialize;
2use serde::Serialize;
3
4use mago_reporting::Annotation;
5use mago_reporting::Issue;
6use mago_span::HasPosition;
7use mago_span::HasSpan;
8use mago_span::Position;
9use mago_span::Span;
10
11#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
12pub enum SyntaxError {
13    UnexpectedToken(u8, Position),
14    UnrecognizedToken(u8, Position),
15    UnexpectedEndOfFile(Position),
16}
17
18impl HasSpan for SyntaxError {
19    fn span(&self) -> Span {
20        let position = match self {
21            Self::UnexpectedToken(_, p) => *p,
22            Self::UnrecognizedToken(_, p) => *p,
23            Self::UnexpectedEndOfFile(p) => *p,
24        };
25
26        Span::new(position, Position { offset: position.offset + 1, ..position })
27    }
28}
29
30impl std::fmt::Display for SyntaxError {
31    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32        let message = match self {
33            Self::UnexpectedToken(token, _) => &format!("Unexpected token `{}` (0x{:02X})", *token as char, token),
34            Self::UnrecognizedToken(token, _) => &format!("Unrecognised token `{}` (0x{:02X})", *token as char, token),
35            Self::UnexpectedEndOfFile(_) => "Unexpected end of file",
36        };
37
38        write!(f, "{}", message)
39    }
40}
41
42impl std::error::Error for SyntaxError {}
43
44impl From<SyntaxError> for Issue {
45    fn from(error: SyntaxError) -> Issue {
46        let position = error.position();
47        let span = Span::new(position, Position { offset: position.offset + 1, ..position });
48
49        Issue::error(error.to_string()).with_annotation(Annotation::primary(span).with_message("Syntax error."))
50    }
51}