Skip to main content

perl_parser_pest/
error.rs

1//! Error types for tree-sitter Perl parser
2
3use thiserror::Error;
4
5/// Kinds of parse errors
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub enum ParseErrorKind {
8    UnexpectedToken,
9    UnexpectedEndOfInput,
10    InvalidSyntax,
11    InvalidNumber,
12    InvalidString,
13    InvalidRegex,
14    InvalidVariable,
15    MissingToken(String),
16    InvalidOperator,
17    InvalidIdentifier,
18}
19
20/// Error types for tree-sitter Perl parser
21#[derive(Error, Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
22pub enum ParseError {
23    /// Failed to parse the input
24    #[error("Failed to parse input")]
25    ParseFailed,
26
27    /// Failed to serialize scanner state
28    #[error("Failed to serialize scanner state")]
29    SerializationFailed,
30
31    /// Failed to deserialize scanner state
32    #[error("Failed to deserialize scanner state")]
33    DeserializationFailed,
34
35    /// Invalid token encountered
36    #[error("Invalid token: {0}")]
37    InvalidToken(String),
38
39    /// Unexpected end of input
40    #[error("Unexpected end of input")]
41    UnexpectedEof,
42
43    /// Invalid Unicode sequence
44    #[error("Invalid Unicode sequence")]
45    InvalidUnicode,
46
47    /// Invalid UTF-8 sequence encountered
48    #[error("Invalid UTF-8: {0}")]
49    InvalidUtf8(String),
50
51    /// Scanner error occurred
52    #[error("Scanner error: {0}")]
53    ScannerError(String),
54
55    /// Language loading failed
56    #[error("Failed to load language")]
57    LanguageLoadFailed,
58}
59
60/// Result type for parsing operations
61pub type ParseResult<T> = Result<T, ParseError>;
62
63/// Errors that can occur during scanning
64#[derive(Error, Debug, Clone, PartialEq)]
65pub enum ScannerError {
66    /// Invalid character encountered
67    #[error("Invalid character: {0}")]
68    InvalidCharacter(char),
69
70    /// Unterminated string
71    #[error("Unterminated string")]
72    UnterminatedString,
73
74    /// Unterminated comment
75    #[error("Unterminated comment")]
76    UnterminatedComment,
77
78    /// Invalid escape sequence
79    #[error("Invalid escape sequence: {0}")]
80    InvalidEscape(String),
81
82    /// Invalid Unicode sequence
83    #[error("Invalid Unicode sequence: {0}")]
84    InvalidUnicode(String),
85
86    /// Scanner state error
87    #[error("Scanner state error: {0}")]
88    StateError(String),
89}
90
91/// Errors that can occur during Unicode processing
92#[derive(Error, Debug, Clone, PartialEq)]
93pub enum UnicodeError {
94    /// Invalid Unicode code point
95    #[error("Invalid Unicode code point: {0}")]
96    InvalidCodePoint(u32),
97
98    /// Invalid UTF-8 sequence
99    #[error("Invalid UTF-8 sequence")]
100    InvalidUtf8,
101
102    /// Unicode normalization failed
103    #[error("Unicode normalization failed: {0}")]
104    NormalizationFailed(String),
105}
106
107impl From<ScannerError> for ParseError {
108    fn from(err: ScannerError) -> Self {
109        ParseError::ScannerError(err.to_string())
110    }
111}
112
113impl From<UnicodeError> for ParseError {
114    fn from(err: UnicodeError) -> Self {
115        ParseError::ScannerError(err.to_string())
116    }
117}
118
119impl From<std::str::Utf8Error> for ParseError {
120    fn from(err: std::str::Utf8Error) -> Self {
121        ParseError::InvalidUtf8(err.to_string())
122    }
123}
124
125impl From<std::string::FromUtf8Error> for ParseError {
126    fn from(err: std::string::FromUtf8Error) -> Self {
127        ParseError::InvalidUtf8(err.to_string())
128    }
129}
130
131impl From<std::io::Error> for ParseError {
132    fn from(err: std::io::Error) -> Self {
133        ParseError::ScannerError(format!("I/O error: {}", err))
134    }
135}
136
137impl ParseError {
138    /// Create a new parse error
139    pub fn new(kind: ParseErrorKind, position: usize, message: String) -> Self {
140        let error_msg = match kind {
141            ParseErrorKind::UnexpectedToken => {
142                format!("Unexpected token at position {}: {}", position, message)
143            }
144            ParseErrorKind::UnexpectedEndOfInput => {
145                format!("Unexpected end of input at position {}: {}", position, message)
146            }
147            ParseErrorKind::InvalidSyntax => {
148                format!("Invalid syntax at position {}: {}", position, message)
149            }
150            ParseErrorKind::InvalidNumber => {
151                format!("Invalid number at position {}: {}", position, message)
152            }
153            ParseErrorKind::InvalidString => {
154                format!("Invalid string at position {}: {}", position, message)
155            }
156            ParseErrorKind::InvalidRegex => {
157                format!("Invalid regex at position {}: {}", position, message)
158            }
159            ParseErrorKind::InvalidVariable => {
160                format!("Invalid variable at position {}: {}", position, message)
161            }
162            ParseErrorKind::MissingToken(ref token) => {
163                format!("Missing {} at position {}: {}", token, position, message)
164            }
165            ParseErrorKind::InvalidOperator => {
166                format!("Invalid operator at position {}: {}", position, message)
167            }
168            ParseErrorKind::InvalidIdentifier => {
169                format!("Invalid identifier at position {}: {}", position, message)
170            }
171        };
172        ParseError::InvalidToken(error_msg)
173    }
174
175    /// Create an error for unterminated string literals
176    pub fn unterminated_string(position: (usize, usize)) -> Self {
177        ParseError::ScannerError(format!(
178            "Unterminated string literal at line {}, column {}",
179            position.0, position.1
180        ))
181    }
182
183    /// Create an error for invalid tokens
184    pub fn invalid_token(token: String, position: (usize, usize)) -> Self {
185        ParseError::InvalidToken(format!(
186            "Invalid token '{}' at line {}, column {}",
187            token, position.0, position.1
188        ))
189    }
190
191    /// Create an error for Unicode-related issues
192    pub fn unicode_error(_message: &str) -> Self {
193        ParseError::InvalidUnicode
194    }
195
196    /// Create a simple scanner error
197    pub fn scanner_error_simple(message: &str) -> Self {
198        ParseError::ScannerError(message.to_string())
199    }
200}