documented parsererror
This commit is contained in:
parent
ba312b9244
commit
531b28ed2b
1 changed files with 38 additions and 25 deletions
|
@ -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 {
|
|
||||||
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"),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The remaining data that was left unparsed.
|
||||||
|
pub fn remaining_data(&self) -> &[u8] {
|
||||||
|
self.parsed_until
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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::*;
|
||||||
|
|
Reference in a new issue