1use super::{Error, PestError};
2use crate::Scdlang;
3use pest::{
4 error::{ErrorVariant::CustomError, InputLocation},
5 Position, Span,
6};
7use std::{error, fmt, iter};
8
9pub(crate) trait Offset: error::Error {
11 fn with_offset(self, offset: usize, source: &str) -> Self;
12}
13
14impl<'t> Scdlang<'t> {
15 pub(crate) fn err_from_span(&self, span: Span, message: String) -> PestError {
17 let source = span.as_str();
18 self.reformat_error(source, PestError::new_from_span(CustomError { message }, span))
19 }
20}
21
22impl Offset for PestError {
23 fn with_offset(self, offset: usize, source: &str) -> Self {
24 match self.location {
25 InputLocation::Span((start, end)) => PestError::new_from_span(
26 self.variant,
27 Span::new(
28 &format!(
29 "{offset}{src}",
30 offset = iter::repeat('\n').take(offset).collect::<String>(),
31 src = source
32 ),
33 start + offset,
34 end + offset,
35 )
36 .expect("Index (offset) must NOT out of bound"),
37 ),
38 InputLocation::Pos(line) => PestError::new_from_pos(
39 self.variant,
40 Position::new(
41 &format!(
42 "{offset}{src}",
43 offset = iter::repeat('\n').take(offset).collect::<String>(),
44 src = source
45 ),
46 line + offset,
47 )
48 .expect("Index (offset) must NOT out of bound"),
49 ),
50 }
51 }
52}
53
54impl From<PestError> for Error {
55 fn from(err: PestError) -> Self {
56 Error::Parse(err.into())
57 }
58}
59
60impl error::Error for Error {}
61impl fmt::Display for Error {
62 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63 match self {
64 Error::Parse(err) => write!(f, "{}", err),
65 _ => write!(f, "{:#?}", self), }
67 }
68}