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}