#![deny(missing_docs)]
#![deny(unsafe_code)]
use std::{error, fmt, io};
pub enum ParseError {
EndOfFile(usize, usize),
TrailingGarbage(usize, usize),
ClosingParen(usize, usize),
NoExtensions(usize, usize),
ConsWithoutRight(usize, usize),
ConsWithoutClose(usize, usize),
StringLiteral(usize, usize),
EmptySymbol(usize, usize),
SymbolEncode(usize, usize),
BufferError(usize, usize, io::Error),
}
impl ParseError {
pub fn position(&self) -> (usize, usize) {
match *self {
ParseError::EndOfFile(l, c) => (l, c),
ParseError::TrailingGarbage(l, c) => (l, c),
ParseError::ClosingParen(l, c) => (l, c),
ParseError::NoExtensions(l, c) => (l, c),
ParseError::ConsWithoutRight(l, c) => (l, c),
ParseError::ConsWithoutClose(l, c) => (l, c),
ParseError::StringLiteral(l, c) => (l, c),
ParseError::EmptySymbol(l, c) => (l, c),
ParseError::SymbolEncode(l, c) => (l, c),
ParseError::BufferError(l, c, _) => (l, c),
}
}
pub fn line(&self) -> usize {
let (line, _) = self.position();
line
}
pub fn column(&self) -> usize {
let (_, column) = self.position();
column
}
}
impl error::Error for ParseError {
fn description(&self) -> &str {
match *self {
ParseError::EndOfFile(_, _) =>
"Unexpected end of file",
ParseError::TrailingGarbage(_, _) =>
"Trailing garbage text",
ParseError::ClosingParen(_, _) =>
"Unexpected closing paren",
ParseError::NoExtensions(_, _) =>
"Extensions are not currently in use",
ParseError::ConsWithoutRight(_, _) =>
"Cons pair closed without right side",
ParseError::ConsWithoutClose(_, _) =>
"Cons pair not closed after right side",
ParseError::StringLiteral(_, _) =>
"Error unescaping string literal",
ParseError::EmptySymbol(_, _) =>
"Encountered symbol with zero length",
ParseError::SymbolEncode(_, _) =>
"Error resolving symbol",
ParseError::BufferError(_, _, _) =>
"Error buffering text"
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
ParseError::BufferError(_, _, ref e) => Some(e),
_ => None
}
}
}
pub type ParseResult<T> = Result<T, ParseError>;
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
use std::error::Error;
write!(f, "{}:{}: {}", self.line(), self.column(), self.description())
}
}
impl fmt::Debug for ParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "{}", self)
}
}
#[test]
fn error_display() {
let error = ParseError::EndOfFile(1usize, 4usize);
assert_eq!(format!("{:?}", error), "1:4: Unexpected end of file");
assert_eq!(format!("{:?}", Box::new(error)), "1:4: Unexpected end of file");
}