summaryrefslogtreecommitdiffstats
path: root/src/parse.rs
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2022-01-10 00:57:02 -0500
committerJesse Luehrs <doy@tozt.net>2022-01-10 00:57:02 -0500
commit63d9cd178954a65bd0616ff75164de9872004197 (patch)
tree6171c5fe0f8da1599bff620345608a540c646ea3 /src/parse.rs
parent870c86f4eb5c7a95d169ea564dd1ee205df34c1a (diff)
downloadnbsh-63d9cd178954a65bd0616ff75164de9872004197.tar.gz
nbsh-63d9cd178954a65bd0616ff75164de9872004197.zip
improve parsing error messages
Diffstat (limited to 'src/parse.rs')
-rw-r--r--src/parse.rs43
1 files changed, 39 insertions, 4 deletions
diff --git a/src/parse.rs b/src/parse.rs
index 7abc525..09cdb91 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -102,11 +102,11 @@ impl Direction {
#[derive(Debug)]
pub struct Error {
input: String,
- e: anyhow::Error,
+ e: pest::error::Error<ast::Rule>,
}
impl Error {
- fn new(input: &str, e: anyhow::Error) -> Self {
+ fn new(input: &str, e: pest::error::Error<ast::Rule>) -> Self {
Self {
input: input.to_string(),
e,
@@ -116,12 +116,47 @@ impl Error {
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "failed to parse {}: {}", self.input, self.e)
+ match &self.e.variant {
+ pest::error::ErrorVariant::ParsingError {
+ positives,
+ negatives,
+ } => {
+ if !positives.is_empty() {
+ write!(f, "expected {:?}", positives[0])?;
+ for rule in &positives[1..] {
+ write!(f, ", {:?}", rule)?;
+ }
+ if !negatives.is_empty() {
+ write!(f, "; ")?;
+ }
+ }
+ if !negatives.is_empty() {
+ write!(f, "unexpected {:?}", negatives[0])?;
+ for rule in &negatives[1..] {
+ write!(f, ", {:?}", rule)?;
+ }
+ }
+ writeln!(f)?;
+ writeln!(f, "{}", self.input)?;
+ match &self.e.location {
+ pest::error::InputLocation::Pos(i) => {
+ write!(f, "{}^", " ".repeat(*i))?;
+ }
+ pest::error::InputLocation::Span((i, j)) => {
+ write!(f, "{}{}", " ".repeat(*i), "^".repeat(j - i))?;
+ }
+ }
+ }
+ pest::error::ErrorVariant::CustomError { message } => {
+ write!(f, "{}", message)?;
+ }
+ }
+ Ok(())
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
- Some(&*self.e)
+ Some(&self.e)
}
}