Skip to content

Commit

Permalink
Refactor ParseError.
Browse files Browse the repository at this point in the history
  • Loading branch information
kaj committed Oct 20, 2020
1 parent 5380596 commit b7fd683
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 73 deletions.
48 changes: 5 additions & 43 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::css::Value;
use crate::parser::{ParseError, SourcePos};
use crate::parser::ParseError;
use std::convert::From;
use std::path::PathBuf;
use std::string::FromUtf8Error;
Expand All @@ -13,7 +13,7 @@ pub enum Error {
Encoding(FromUtf8Error),
BadValue(String),
BadArguments(String),
ParseError { msg: String, pos: SourcePos },
ParseError(ParseError),
S(String),
UndefinedVariable(String),
}
Expand Down Expand Up @@ -66,54 +66,16 @@ impl fmt::Display for Error {
Error::UndefinedVariable(ref name) => {
write!(out, "Undefined variable: \"${}\"", name)
}
Error::ParseError { ref msg, ref pos } => {
let line_no = pos.line_no.to_string();
write!(
out,
"{msg}\
\n{0:lnw$} ,\
\n{ln} | {line}\
\n{0:lnw$} |{0:>lpos$}^\
\n{0:lnw$} '",
"",
line = pos.line,
msg = msg,
ln = line_no,
lnw = line_no.len(),
lpos = pos.line_pos,
)?;
let mut nextpos = Some(pos);
while let Some(pos) = nextpos {
write!(
out,
"\n{0:lnw$} {file} {row}:{col} {cause}",
"",
lnw = line_no.len(),
file = pos.file.name(),
row = pos.line_no,
col = pos.line_pos,
cause = if pos.file.imported_from().is_some() {
"import"
} else {
"root stylesheet"
},
)?;
nextpos = pos.file.imported_from();
}
Ok(())
}
Error::ParseError(ref err) => err.fmt(out),
// fallback
ref x => write!(out, "{:?}", x),
}
}
}

impl<'a> From<ParseError<'a>> for Error {
impl From<ParseError> for Error {
fn from(err: ParseError) -> Self {
Error::ParseError {
msg: format!("Parse error: {:?}", err.err),
pos: err.span.into(),
}
Error::ParseError(err)
}
}

Expand Down
68 changes: 68 additions & 0 deletions src/parser/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use super::{code_span, SourcePos, Span};
use std::fmt;

#[derive(Debug)]
pub struct ParseError {
msg: String,
pos: SourcePos,
}

impl ParseError {
pub fn remaining(span: Span) -> ParseError {
ParseError {
msg: "Expected end of file.".into(),
pos: span.into(),
}
}
pub fn incomplete() -> ParseError {
ParseError {
msg: "Unexpected end of file.".into(),
pos: code_span(b"").into(), // This should not happen?
}
}
pub fn err(kind: nom::error::ErrorKind, span: Span) -> ParseError {
ParseError {
msg: format!("Parse Error: {:?}", kind),
pos: span.into(),
}
}
}

impl fmt::Display for ParseError {
fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
let line_no = self.pos.line_no.to_string();
write!(
out,
"{msg}\
\n{0:lnw$} ,\
\n{ln} | {line}\
\n{0:lnw$} |{0:>lpos$}^\
\n{0:lnw$} '",
"",
line = self.pos.line,
msg = self.msg,
ln = line_no,
lnw = line_no.len(),
lpos = self.pos.line_pos,
)?;
let mut nextpos = Some(&self.pos);
while let Some(pos) = nextpos {
write!(
out,
"\n{0:lnw$} {file} {row}:{col} {cause}",
"",
lnw = line_no.len(),
file = pos.file.name(),
row = pos.line_no,
col = pos.line_pos,
cause = if pos.file.imported_from().is_some() {
"import"
} else {
"root stylesheet"
},
)?;
nextpos = pos.file.imported_from();
}
Ok(())
}
}
38 changes: 8 additions & 30 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod error;
pub mod formalargs;
mod pos;
pub mod selectors;
Expand All @@ -6,6 +7,8 @@ mod unit;
mod util;
pub mod value;

pub use error::ParseError;

use self::formalargs::{call_args, formal_args};
use self::selectors::selectors;
use self::strings::{
Expand Down Expand Up @@ -126,43 +129,18 @@ pub fn check_all_parsed<'a, T>(
(Span<'a>, T),
nom::Err<(Span<'a>, nom::error::ErrorKind)>,
>,
) -> Result<T, ParseError<'a>> {
) -> Result<T, ParseError> {
match result {
Ok((rest, items)) => {
if rest.fragment().is_empty() {
Ok(items)
} else {
Err(ParseError {
err: None,
span: rest,
})
Err(ParseError::remaining(rest))
}
}
Err(Err::Error((span, err))) => Err(ParseError {
err: Some(err),
span,
}),
Err(Err::Incomplete(_needed)) => Err(ParseError {
err: None,
span: code_span(&[]), // TODO: Make end-span from intput?
}),
Err(Err::Failure((span, err))) => Err(ParseError {
err: Some(err),
span,
}),
}
}

#[derive(Debug)]
pub struct ParseError<'a> {
pub err: Option<nom::error::ErrorKind>,
pub span: Span<'a>,
}

use std::fmt;
impl<'a> fmt::Display for ParseError<'a> {
fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
write!(out, "{:?}: {:?}", self.span, self.err)
Err(Err::Error((span, err))) => Err(ParseError::err(err, span)),
Err(Err::Incomplete(_needed)) => Err(ParseError::incomplete()),
Err(Err::Failure((span, err))) => Err(ParseError::err(err, span)),
}
}

Expand Down

0 comments on commit b7fd683

Please sign in to comment.