1use std::fmt;
4
5pub type ParseResult<T> = Result<T, ParseError>;
7
8#[derive(Debug, Clone)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct ParseError {
12 pub message: String,
14 pub position: Option<usize>,
16 pub line: Option<usize>,
18 pub column: Option<usize>,
20}
21
22impl ParseError {
23 pub fn new(message: impl Into<String>) -> Self {
25 ParseError {
26 message: message.into(),
27 position: None,
28 line: None,
29 column: None,
30 }
31 }
32
33 pub fn at_position(message: impl Into<String>, position: usize) -> Self {
35 ParseError {
36 message: message.into(),
37 position: Some(position),
38 line: None,
39 column: None,
40 }
41 }
42
43 pub fn at_location(message: impl Into<String>, line: usize, column: usize) -> Self {
45 ParseError {
46 message: message.into(),
47 position: None,
48 line: Some(line),
49 column: Some(column),
50 }
51 }
52
53 pub fn with_position(mut self, position: usize) -> Self {
55 self.position = Some(position);
56 self
57 }
58
59 pub fn with_location(mut self, line: usize, column: usize) -> Self {
61 self.line = Some(line);
62 self.column = Some(column);
63 self
64 }
65}
66
67impl fmt::Display for ParseError {
68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69 if let (Some(line), Some(column)) = (self.line, self.column) {
70 write!(f, "Parse error at line {}, column {}: {}", line, column, self.message)
71 } else if let Some(position) = self.position {
72 write!(f, "Parse error at position {}: {}", position, self.message)
73 } else {
74 write!(f, "Parse error: {}", self.message)
75 }
76 }
77}
78
79impl std::error::Error for ParseError {}