use std::io::Error as IOError;
use pest::error::Error as PestError;
use thiserror::Error;
use pest::Span;
use crate::ast::*;
use crate::syntax::Rule;
#[derive(Debug, Eq, Error, PartialEq)]
pub enum CardinalityError {
#[error("missing {name} clause")]
MissingClause { name: String },
#[error("duplicate {name} clauses")]
DuplicateClauses { name: String },
#[error("invalid single {name} clause")]
SingleClause { name: String },
}
impl CardinalityError {
pub fn missing<S: Into<String>>(name: S) -> Self {
CardinalityError::MissingClause { name: name.into() }
}
pub fn duplicate<S: Into<String>>(name: S) -> Self {
CardinalityError::DuplicateClauses { name: name.into() }
}
pub fn single<S: Into<String>>(name: S) -> Self {
CardinalityError::SingleClause { name: name.into() }
}
}
#[derive(Debug, Eq, Error, PartialEq)]
pub enum SyntaxError {
#[error("unexpected rule: {actual:?} (expected {expected:?})")]
UnexpectedRule { expected: Rule, actual: Rule },
#[error("parser error: {error}")]
ParserError {
#[from]
error: Box<PestError<Rule>>,
},
}
impl SyntaxError {
pub(crate) fn with_offsets(self, line_offset: usize, offset: usize) -> Self {
use self::SyntaxError::*;
use pest::error::InputLocation;
use pest::error::LineColLocation;
match self {
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::SyntaxError::*;
match self {
e @ UnexpectedRule { .. } => e,
ParserError { error } => ParserError {
error: Box::new(error.with_path(path)),
},
}
}
pub(crate) fn with_span(self, span: Span) -> Self {
use self::SyntaxError::*;
match self {
e @ UnexpectedRule { .. } => e,
ParserError { error } => {
ParserError {
error: Box::new(PestError::new_from_span(error.variant, span)),
}
}
}
}
}
impl From<PestError<Rule>> for SyntaxError {
fn from(error: PestError<Rule>) -> Self {
Self::from(Box::new(error))
}
}
#[cfg(feature = "threading")]
#[cfg_attr(feature = "_doc", doc(cfg(feature = "threading")))]
#[derive(Debug, Eq, Error, PartialEq)]
pub enum ThreadingError {
#[error("disconnected channel")]
DisconnectedChannel,
}
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Error)]
pub enum Error {
#[error("syntax error: {error}")]
SyntaxError {
#[from]
error: SyntaxError,
},
#[error("IO error: {error}")]
IOError {
#[from]
error: IOError,
},
#[error("cardinality error: {inner}")]
CardinalityError {
id: Option<Ident>,
#[source]
inner: CardinalityError,
},
#[cfg(feature = "threading")]
#[cfg_attr(feature = "_doc", doc(cfg(feature = "threading")))]
#[error("threading error: {error}")]
ThreadingError {
#[from]
error: ThreadingError,
},
}