use std::io::Error as IOError;
use pest::Span;
use pest::Position;
use pest::error::Error as PestError;
use pest::error::InputLocation;
use pest::error::LineColLocation;
use crate::ast::*;
use crate::parser::Rule;
#[derive(Debug, Eq, Fail, PartialEq)]
pub enum CardinalityError {
#[fail(display = "missing {:?} clause", name)]
MissingClause { name: String },
#[fail(display = "duplicate {:?} clauses", name)]
DuplicateClauses { name: String },
#[fail(display = "invalid single {:?} clause", name)]
SingleClause { name: String }
}
impl CardinalityError {
pub(crate) fn missing<S: Into<String>>(name: S) -> Self {
CardinalityError::MissingClause {
name: name.into()
}
}
pub(crate) fn duplicate<S: Into<String>>(name: S) -> Self {
CardinalityError::DuplicateClauses {
name: name.into()
}
}
pub(crate) fn single<S: Into<String>>(name: S) -> Self {
CardinalityError::DuplicateClauses {
name: name.into()
}
}
}
#[derive(Debug, Fail)]
pub enum Error {
#[fail(display = "unexpected rule: {:?} (expected {:?})", actual, expected)]
UnexpectedRule { expected: Rule, actual: Rule },
#[fail(display = "parser error: {}", error)]
ParserError { error: PestError<Rule> },
#[fail(display = "IO error: {}", error)]
IOError { error: IOError },
#[fail(display = "cardinality error")]
#[cause(inner)]
CardinalityError { id: Option<Ident>, inner: CardinalityError }
}
impl Error {
pub(crate) fn with_offsets(self, line_offset: usize, offset: usize) -> Self {
use self::Error::*;
use pest::error::InputLocation;
use pest::error::LineColLocation;
match self {
e @ IOError { .. } => e,
e @ CardinalityError { .. } => e,
e @ UnexpectedRule { .. } => e,
ParserError { mut error } => {
error.location = match error.location {
InputLocation::Pos(s) =>
InputLocation::Pos(s + offset),
InputLocation::Span((s, e)) =>
InputLocation::Span((s + offset, e + offset))
};
error.line_col = match error.line_col {
LineColLocation::Pos((l, c)) =>
LineColLocation::Pos((l + line_offset, c)),
LineColLocation::Span((ls, cs), (le, ce)) =>
LineColLocation::Span((ls + line_offset, cs), (le + line_offset, ce))
};
ParserError { error }
}
}
}
pub(crate) fn with_path(self, path: &str) -> Self {
use self::Error::*;
match self {
e @ IOError { .. } => e,
e @ UnexpectedRule { .. } => e,
e @ CardinalityError { .. } => e,
ParserError { error } => ParserError { error: error.with_path(path) },
}
}
pub(crate) fn with_span<'i>(self, span: Span<'i>) -> Self {
use self::Error::*;
match self {
e @ IOError { .. } => e,
e @ UnexpectedRule { .. } => e,
e @ CardinalityError { .. } => e,
ParserError { error } => {
ParserError {
error: PestError::new_from_span(error.variant, span)
}
}
}
}
}
impl From<PestError<Rule>> for Error {
fn from(error: PestError<Rule>) -> Self {
Error::ParserError { error }
}
}
impl From<IOError> for Error {
fn from(error: IOError) -> Self {
Error::IOError { error }
}
}
pub type Result<T> = std::result::Result<T, Error>;