use super::{PResult, SourcePos, Span};
use nom::Finish;
use std::fmt;
#[derive(Debug, PartialEq, Eq)]
pub struct ParseError {
msg: String,
pos: SourcePos,
}
impl std::error::Error for ParseError {}
impl ParseError {
pub fn check<T>(res: PResult<T>) -> Result<T, Self> {
let (rest, value) = res.finish()?;
if rest.fragment().is_empty() {
Ok(value)
} else {
Err(ParseError::new("Expected end of file.", rest))
}
}
fn new<Msg, Pos>(msg: Msg, pos: Pos) -> Self
where
Msg: Into<String>,
Pos: Into<SourcePos>,
{
ParseError {
msg: msg.into(),
pos: pos.into(),
}
}
}
impl From<nom::error::Error<Span<'_>>> for ParseError {
fn from(err: nom::error::Error<Span>) -> Self {
ParseError::new(format!("Parse error: {:?}", err.code), err.input)
}
}
impl fmt::Display for ParseError {
fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
writeln!(out, "{}", self.msg)?;
self.pos.show(out)
}
}