diff --git a/malva/src/error.rs b/malva/src/error.rs index 748947f..324dc3e 100644 --- a/malva/src/error.rs +++ b/malva/src/error.rs @@ -4,21 +4,20 @@ use std::fmt::Display; #[derive(Clone, Debug)] pub enum Error { /// Error from the parser, usually related to syntax error. - Parser(raffia::error::Error), + /// The first component is the error type from Raffia, + /// and the second component is error line number, + /// and the third component is error column number. + Parser(raffia::error::Error, usize, usize), } impl Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Error::Parser(error) => write!(f, "syntax error: {}", error.kind), + Error::Parser(error, line, col) => { + write!(f, "syntax error at line {line}, col {col}: {}", error.kind) + } } } } impl std::error::Error for Error {} - -impl From for Error { - fn from(error: raffia::error::Error) -> Self { - Error::Parser(error) - } -} diff --git a/malva/src/lib.rs b/malva/src/lib.rs index 56020da..1bd2447 100644 --- a/malva/src/lib.rs +++ b/malva/src/lib.rs @@ -28,7 +28,10 @@ pub fn format_text(input: &str, syntax: Syntax, options: &FormatOptions) -> Resu .build(); let stylesheet = match parser.parse::() { Ok(stylesheet) => stylesheet, - Err(error) => return Err(error.into()), + Err(error) => { + let (line, col) = line_bounds.get_line_col(error.span.start); + return Err(Error::Parser(error, line, col)); + } }; Ok(print_stylesheet( diff --git a/malva/src/line_bounds.rs b/malva/src/line_bounds.rs index 9433648..4d3acf1 100644 --- a/malva/src/line_bounds.rs +++ b/malva/src/line_bounds.rs @@ -19,23 +19,23 @@ impl LineBounds { end >= start, "end {end} must be greater than or equal start {start}" ); + self.get_line_at(end) - self.get_line_at(start) + } - let (ControlFlow::Break(start) | ControlFlow::Continue(start)) = - self.0 - .iter() - .try_fold(0, |i, offset| match start.cmp(offset) { - Ordering::Less => ControlFlow::Break(i), - Ordering::Equal => ControlFlow::Continue(i), - Ordering::Greater => ControlFlow::Continue(i + 1), - }); - let (ControlFlow::Break(end) | ControlFlow::Continue(end)) = + pub(crate) fn get_line_col(&self, pos: usize) -> (usize, usize) { + let line = self.get_line_at(pos); + (line, pos - self.0[line - 1]) + } + + fn get_line_at(&self, pos: usize) -> usize { + let (ControlFlow::Break(line) | ControlFlow::Continue(line)) = self.0 .iter() - .try_fold(0, |i, offset| match end.cmp(offset) { + .try_fold(0, |i, offset| match pos.cmp(offset) { Ordering::Less => ControlFlow::Break(i), Ordering::Equal => ControlFlow::Continue(i), Ordering::Greater => ControlFlow::Continue(i + 1), }); - end - start + line } }