jetcrab\parser/
error.rs

1use crate::ast::{Position, Span};
2use crate::lexer::Token;
3use thiserror::Error;
4
5pub type ParseResult<T> = Result<T, ParserError>;
6
7#[derive(Error, Debug, Clone, PartialEq)]
8pub enum ParserError {
9    #[error("Unexpected token '{token}' at {position}")]
10    UnexpectedToken {
11        token: String,
12        position: Position,
13        expected: Option<String>,
14    },
15
16    #[error("Unexpected end of input at {position}")]
17    UnexpectedEndOfInput {
18        position: Position,
19        expected: Option<String>,
20    },
21
22    #[error("Invalid syntax: {message} at {position}")]
23    InvalidSyntax { message: String, position: Position },
24
25    #[error("Invalid expression: {message} at {position}")]
26    InvalidExpression { message: String, position: Position },
27
28    #[error("Invalid statement: {message} at {position}")]
29    InvalidStatement { message: String, position: Position },
30
31    #[error("Invalid declaration: {message} at {position}")]
32    InvalidDeclaration { message: String, position: Position },
33
34    #[error("Invalid function: {message} at {position}")]
35    InvalidFunction { message: String, position: Position },
36
37    #[error("Invalid class: {message} at {position}")]
38    InvalidClass { message: String, position: Position },
39
40    #[error("Invalid module: {message} at {position}")]
41    InvalidModule { message: String, position: Position },
42
43    #[error("Lexer error: {message} at {position}")]
44    LexerError { message: String, position: Position },
45
46    #[error("Internal parser error: {message}")]
47    InternalError { message: String },
48}
49
50impl ParserError {
51    pub fn unexpected_token(token: &Token, expected: Option<&str>) -> Self {
52        let position = Position {
53            line: token.start().line,
54            column: token.start().column,
55        };
56        ParserError::UnexpectedToken {
57            token: format!("{:?}", token.kind),
58            position,
59            expected: expected.map(|s| s.to_string()),
60        }
61    }
62
63    pub fn unexpected_end_of_input(expected: Option<&str>) -> Self {
64        ParserError::UnexpectedEndOfInput {
65            position: Position::new(1, 1),
66            expected: expected.map(|s| s.to_string()),
67        }
68    }
69
70    pub fn invalid_syntax(message: &str, position: Position) -> Self {
71        ParserError::InvalidSyntax {
72            message: message.to_string(),
73            position,
74        }
75    }
76
77    pub fn invalid_expression(message: &str, position: Position) -> Self {
78        ParserError::InvalidExpression {
79            message: message.to_string(),
80            position,
81        }
82    }
83
84    pub fn invalid_statement(message: &str, position: Position) -> Self {
85        ParserError::InvalidStatement {
86            message: message.to_string(),
87            position,
88        }
89    }
90
91    pub fn invalid_declaration(message: &str, position: Position) -> Self {
92        ParserError::InvalidDeclaration {
93            message: message.to_string(),
94            position,
95        }
96    }
97
98    pub fn invalid_function(message: &str, position: Position) -> Self {
99        ParserError::InvalidFunction {
100            message: message.to_string(),
101            position,
102        }
103    }
104
105    pub fn invalid_class(message: &str, position: Position) -> Self {
106        ParserError::InvalidClass {
107            message: message.to_string(),
108            position,
109        }
110    }
111
112    pub fn invalid_module(message: &str, position: Position) -> Self {
113        ParserError::InvalidModule {
114            message: message.to_string(),
115            position,
116        }
117    }
118
119    pub fn lexer_error(message: &str, position: Position) -> Self {
120        ParserError::LexerError {
121            message: message.to_string(),
122            position,
123        }
124    }
125
126    pub fn internal_error(message: &str) -> Self {
127        ParserError::InternalError {
128            message: message.to_string(),
129        }
130    }
131
132    pub fn position(&self) -> Option<Position> {
133        match self {
134            ParserError::UnexpectedToken { position, .. } => Some(*position),
135            ParserError::UnexpectedEndOfInput { position, .. } => Some(*position),
136            ParserError::InvalidSyntax { position, .. } => Some(*position),
137            ParserError::InvalidExpression { position, .. } => Some(*position),
138            ParserError::InvalidStatement { position, .. } => Some(*position),
139            ParserError::InvalidDeclaration { position, .. } => Some(*position),
140            ParserError::InvalidFunction { position, .. } => Some(*position),
141            ParserError::InvalidClass { position, .. } => Some(*position),
142            ParserError::InvalidModule { position, .. } => Some(*position),
143            ParserError::LexerError { position, .. } => Some(*position),
144            ParserError::InternalError { .. } => None,
145        }
146    }
147
148    pub fn span(&self) -> Option<Span> {
149        self.position().map(|pos| Span::new(pos, pos))
150    }
151}