documented parsererror

This commit is contained in:
Edward Shen 2021-02-26 18:35:49 -05:00
parent ba312b9244
commit 531b28ed2b
Signed by: edward
GPG key ID: 19182661E818369F

View file

@ -159,7 +159,9 @@ impl Display for ParsedComment<'_> {
} }
} }
/// The various parsing failure reasons. /// A parser error reports the one-indexed line number where the parsing error
/// occurred, as well as the last parser node and the remaining data to be
/// parsed.
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
pub struct ParserError<'a> { pub struct ParserError<'a> {
line_number: usize, line_number: usize,
@ -167,22 +169,16 @@ pub struct ParserError<'a> {
parsed_until: &'a [u8], parsed_until: &'a [u8],
} }
#[derive(PartialEq, Debug, Clone, Copy)] impl ParserError<'_> {
enum ParserNode { /// The one-indexed line number where the error occurred. This is determined
SectionHeader, /// by the number of newlines that were successfully parsed.
ConfigName, pub fn line_number(&self) -> usize {
ConfigValue, self.line_number + 1
Comment, }
}
impl Display for ParserNode { /// The remaining data that was left unparsed.
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { pub fn remaining_data(&self) -> &[u8] {
match self { self.parsed_until
Self::SectionHeader => write!(f, "section header"),
Self::ConfigName => write!(f, "config name"),
Self::ConfigValue => write!(f, "config value"),
Self::Comment => write!(f, "comment"),
}
} }
} }
@ -218,6 +214,25 @@ impl Display for ParserError<'_> {
impl Error for ParserError<'_> {} impl Error for ParserError<'_> {}
#[derive(PartialEq, Debug, Clone, Copy)]
enum ParserNode {
SectionHeader,
ConfigName,
ConfigValue,
Comment,
}
impl Display for ParserNode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::SectionHeader => write!(f, "section header"),
Self::ConfigName => write!(f, "config name"),
Self::ConfigValue => write!(f, "config value"),
Self::Comment => write!(f, "comment"),
}
}
}
/// A zero-copy `git-config` file parser. /// A zero-copy `git-config` file parser.
/// ///
/// This is parser exposes low-level syntactic events from a `git-config` file. /// This is parser exposes low-level syntactic events from a `git-config` file.
@ -572,18 +587,20 @@ pub fn parse_from_bytes(input: &[u8]) -> Result<Parser<'_>, ParserError> {
let maybe_sections = many1(|i| section(i, &mut node))(i); let maybe_sections = many1(|i| section(i, &mut node))(i);
let (i, sections) = maybe_sections.map_err(|_| ParserError { let (i, sections) = maybe_sections.map_err(|_| ParserError {
line_number: newlines, line_number: newlines,
last_attempted_parser: node.clone(), last_attempted_parser: node,
parsed_until: i, parsed_until: i,
})?; })?;
let sections = sections let sections = sections
.into_iter() .into_iter()
.map(|(s, c)| { .map(|(section, additional_newlines)| {
newlines += c; newlines += additional_newlines;
s section
}) })
.collect(); .collect();
// This needs to happen after we collect sections, otherwise the line number
// will be off.
if !i.is_empty() { if !i.is_empty() {
return Err(ParserError { return Err(ParserError {
line_number: newlines, line_number: newlines,
@ -863,7 +880,7 @@ fn take_spaces(i: &[u8]) -> IResult<&[u8], &[u8]> {
fn take_newline(i: &[u8]) -> IResult<&[u8], (&[u8], usize)> { fn take_newline(i: &[u8]) -> IResult<&[u8], (&[u8], usize)> {
let mut counter = 0; let mut counter = 0;
let (i, v) = take_while(is_char_newline)(i)?; let (i, v) = take_while(|c| (c as char).is_ascii() && is_newline(c))(i)?;
counter += v.len(); counter += v.len();
if v.is_empty() { if v.is_empty() {
Err(nom::Err::Error(NomError { Err(nom::Err::Error(NomError {
@ -875,10 +892,6 @@ fn take_newline(i: &[u8]) -> IResult<&[u8], (&[u8], usize)> {
} }
} }
fn is_char_newline(c: u8) -> bool {
(c as char).is_ascii() && is_newline(c)
}
#[cfg(test)] #[cfg(test)]
mod comments { mod comments {
use super::*; use super::*;