use std::fmt;
pub type ParseResult<T> = Result<T, ParseError>;
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ParseError {
pub message: String,
pub position: Option<usize>,
pub line: Option<usize>,
pub column: Option<usize>,
}
impl ParseError {
pub fn new(message: impl Into<String>) -> Self {
ParseError {
message: message.into(),
position: None,
line: None,
column: None,
}
}
pub fn at_position(message: impl Into<String>, position: usize) -> Self {
ParseError {
message: message.into(),
position: Some(position),
line: None,
column: None,
}
}
pub fn at_location(message: impl Into<String>, line: usize, column: usize) -> Self {
ParseError {
message: message.into(),
position: None,
line: Some(line),
column: Some(column),
}
}
pub fn with_position(mut self, position: usize) -> Self {
self.position = Some(position);
self
}
pub fn with_location(mut self, line: usize, column: usize) -> Self {
self.line = Some(line);
self.column = Some(column);
self
}
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let (Some(line), Some(column)) = (self.line, self.column) {
write!(f, "Parse error at line {}, column {}: {}", line, column, self.message)
} else if let Some(position) = self.position {
write!(f, "Parse error at position {}: {}", position, self.message)
} else {
write!(f, "Parse error: {}", self.message)
}
}
}
impl std::error::Error for ParseError {}