From 547f0c97e4882ba33ae952096b8444ef13cbf921 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Thu, 18 Jun 2020 12:57:55 +0200 Subject: [PATCH] src/tools/nom.rs: new helper parse_complete_line() for single line parsers Like parse_complete(), but generates simpler error messages. --- src/tools/nom.rs | 21 +++++++++++++++++++++ src/tools/systemd/parse_time.rs | 13 +++++-------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/tools/nom.rs b/src/tools/nom.rs index 0b0fe816..ca03c5d7 100644 --- a/src/tools/nom.rs +++ b/src/tools/nom.rs @@ -41,6 +41,7 @@ pub fn parse_u64(i: &str) -> IResult<&str, u64> { map_res(recognize(digit1), str::parse)(i) } +/// Parse complete input, generate vervose error message with line numbers pub fn parse_complete<'a, F, O>(what: &str, i: &'a str, parser: F) -> Result where F: Fn(&'a str) -> IResult<&'a str, O>, { @@ -56,3 +57,23 @@ pub fn parse_complete<'a, F, O>(what: &str, i: &'a str, parser: F) -> Result(what: &str, i: &'a str, parser: F) -> Result + where F: Fn(&'a str) -> IResult<&'a str, O>, +{ + match all_consuming(parser)(i) { + Err(nom::Err::Error(VerboseError { errors })) | + Err(nom::Err::Failure(VerboseError { errors })) => { + if errors.is_empty() { + bail!("unable to parse {}", what); + } else { + bail!("unable to parse {} at '{}' - {:?}", what, errors[0].0, errors[0].1); + } + } + Err(err) => { + bail!("unable to parse {} - {}", what, err); + } + Ok((_, data)) => Ok(data), + } +} diff --git a/src/tools/systemd/parse_time.rs b/src/tools/systemd/parse_time.rs index 00bcbfba..b1cbc38d 100644 --- a/src/tools/systemd/parse_time.rs +++ b/src/tools/systemd/parse_time.rs @@ -1,18 +1,18 @@ use std::collections::HashMap; -use anyhow::{bail, Error}; +use anyhow::{Error}; use lazy_static::lazy_static; use super::time::*; use crate::tools::nom::{ - parse_complete, parse_u64, parse_error, IResult, + parse_complete_line, parse_u64, parse_error, IResult, }; use nom::{ error::{context}, bytes::complete::{tag, take_while1}, - combinator::{map_res, all_consuming, opt, recognize}, + combinator::{map_res, opt, recognize}, sequence::{pair, preceded, tuple}, character::complete::{alpha1, space0, digit1}, multi::separated_nonempty_list, @@ -184,7 +184,7 @@ fn parse_time_spec(i: &str) -> IResult<&str, (Vec, Vec Result { - parse_complete("calendar event", i, parse_calendar_event_incomplete) + parse_complete_line("calendar event", i, parse_calendar_event_incomplete) } fn parse_calendar_event_incomplete(mut i: &str) -> IResult<&str, CalendarEvent> { @@ -269,10 +269,7 @@ fn parse_time_unit(i: &str) -> IResult<&str, &str> { pub fn parse_time_span(i: &str) -> Result { - match all_consuming(parse_time_span_incomplete)(i) { - Err(err) => bail!("unable to parse time span: {}", err), - Ok((_, ts)) => Ok(ts), - } + parse_complete_line("time span", i, parse_time_span_incomplete) } fn parse_time_span_incomplete(mut i: &str) -> IResult<&str, TimeSpan> {