use crate::parser::Rule;
use pest::error::{Error, ErrorVariant};
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Span(usize);
impl Default for Span {
fn default() -> Self {
Self(usize::MAX)
}
}
#[derive(Default, Debug, Clone)]
pub struct Registry(Vec<Error<Rule>>);
impl Registry {
pub fn register(&mut self, span: pest::Span<'_>) -> Span {
let res = Span(self.0.len());
self.0.push(Error::new_from_span(
ErrorVariant::CustomError { message: "".to_owned() },
span,
));
res
}
pub fn describe<E: std::error::Error + 'static>(&self, err: &S<E>) -> String {
use std::fmt::Write;
let mut buf = format!("Error: {}\n", err.inner);
if let Some(e) = self.0.get(err.span.0) {
writeln!(&mut buf, "{}\n", e).unwrap();
}
let mut err: &(dyn std::error::Error + 'static) = &err.inner;
while let Some(source) = err.source() {
writeln!(&mut buf, "Cause: {}", source).unwrap();
err = source;
}
buf
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct S<T> {
pub inner: T,
pub span: Span,
}
pub trait SpanExt: Sized {
fn span(self, span: Span) -> S<Self>;
fn no_span(self) -> S<Self>;
}
impl<T> SpanExt for T {
fn span(self, span: Span) -> S<Self> {
S { span, inner: self }
}
fn no_span(self) -> S<Self> {
self.span(Span::default())
}
}
pub trait ResultExt {
type Ok;
type Err;
fn span_ok_err<U: From<Self::Err>>(self, span: Span) -> Result<S<Self::Ok>, S<U>>;
fn span_err<U: From<Self::Err>>(self, span: Span) -> Result<Self::Ok, S<U>>;
fn no_span_err<U: From<Self::Err>>(self) -> Result<Self::Ok, S<U>>;
}
impl<T, E> ResultExt for Result<T, E> {
type Ok = T;
type Err = E;
fn span_ok_err<U: From<E>>(self, span: Span) -> Result<S<T>, S<U>> {
match self {
Ok(t) => Ok(S { span, inner: t }),
Err(e) => Err(S { span, inner: e.into() }),
}
}
fn span_err<U: From<E>>(self, span: Span) -> Result<T, S<U>> {
self.map_err(|e| S { span, inner: e.into() })
}
fn no_span_err<U: From<E>>(self) -> Result<T, S<U>> {
self.span_err(Span::default())
}
}