From a1555949ed4764f356a8afeb41ea6fe2bfa7e562 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Fri, 22 Apr 2022 21:29:37 -0700 Subject: [PATCH] refactor: clean up parser/FromStr toplevel stuff and add one for KdlIdentifier --- src/document.rs | 30 ++---------------------------- src/entry.rs | 28 ++-------------------------- src/identifier.rs | 12 +++++++++++- src/node.rs | 29 ++--------------------------- src/parser.rs | 33 +++++++++++++++++++++++++++++---- 5 files changed, 46 insertions(+), 86 deletions(-) diff --git a/src/document.rs b/src/document.rs index 7171ebe..c913a2c 100644 --- a/src/document.rs +++ b/src/document.rs @@ -1,8 +1,6 @@ use std::{fmt::Display, str::FromStr}; -use nom::{combinator::all_consuming, Finish}; - -use crate::{parser::document, KdlError, KdlErrorKind, KdlNode, KdlValue}; +use crate::{parser, KdlError, KdlNode, KdlValue}; /// Represents a KDL /// [`Document`](https://github.com/kdl-org/kdl/blob/main/SPEC.md#document). @@ -13,7 +11,6 @@ use crate::{parser::document, KdlError, KdlErrorKind, KdlNode, KdlValue}; #[derive(Debug, Default, Clone, PartialEq)] pub struct KdlDocument { pub(crate) leading: Option, - // TODO: Consider using `hashlink` for this, later? pub(crate) nodes: Vec, pub(crate) trailing: Option, } @@ -209,34 +206,11 @@ impl IntoIterator for KdlDocument { } } -impl KdlDocument { - /// Parse a KDL document from a string into a [`KdlDocument`] object model. - fn parse(input: &str) -> Result { - all_consuming(document)(input) - .finish() - .map(|(_, arg)| arg) - .map_err(|e| { - let prefix = &input[..(input.len() - e.input.len())]; - KdlError { - input: input.into(), - offset: prefix.chars().count(), - kind: if let Some(kind) = e.kind { - kind - } else if let Some(ctx) = e.context { - KdlErrorKind::Context(ctx) - } else { - KdlErrorKind::Other - }, - } - }) - } -} - impl FromStr for KdlDocument { type Err = KdlError; fn from_str(input: &str) -> Result { - KdlDocument::parse(input) + parser::parse(input, parser::document) } } diff --git a/src/entry.rs b/src/entry.rs index 0f05870..316fa16 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -1,8 +1,6 @@ use std::{fmt::Display, str::FromStr}; -use nom::{combinator::all_consuming, Finish}; - -use crate::{KdlError, KdlErrorKind, KdlIdentifier, KdlValue}; +use crate::{parser, KdlError, KdlIdentifier, KdlValue}; /// KDL Entries are the "arguments" to KDL nodes: either a (positional) /// [`Argument`](https://github.com/kdl-org/kdl/blob/main/SPEC.md#argument) or @@ -149,32 +147,10 @@ impl FromStr for KdlEntry { type Err = KdlError; fn from_str(s: &str) -> Result { - KdlEntry::parse(s) + parser::parse(s, parser::entry) } } -impl KdlEntry { - /// Parse a KDL document from a string into a [`KdlDocument`] object model. - fn parse(input: &str) -> Result { - all_consuming(crate::parser::entry)(input) - .finish() - .map(|(_, arg)| arg) - .map_err(|e| { - let prefix = &input[..(input.len() - e.input.len())]; - KdlError { - input: input.into(), - offset: prefix.chars().count(), - kind: if let Some(kind) = e.kind { - kind - } else if let Some(ctx) = e.context { - KdlErrorKind::Context(ctx) - } else { - KdlErrorKind::Other - }, - } - }) - } -} #[cfg(test)] mod test { use super::*; diff --git a/src/identifier.rs b/src/identifier.rs index 85baed8..5d69d41 100644 --- a/src/identifier.rs +++ b/src/identifier.rs @@ -1,4 +1,6 @@ -use std::fmt::Display; +use std::{fmt::Display, str::FromStr}; + +use crate::{parser, KdlError}; /// Represents a KDL /// [Identifier](https://github.com/kdl-org/kdl/blob/main/SPEC.md#identifier). @@ -139,6 +141,14 @@ impl From for String { } } +impl FromStr for KdlIdentifier { + type Err = KdlError; + + fn from_str(s: &str) -> Result { + parser::parse(s, parser::identifier) + } +} + #[cfg(test)] mod test { use super::*; diff --git a/src/node.rs b/src/node.rs index 1f10415..8a0d4cb 100644 --- a/src/node.rs +++ b/src/node.rs @@ -4,9 +4,7 @@ use std::{ str::FromStr, }; -use nom::{combinator::all_consuming, Finish}; - -use crate::{KdlDocument, KdlEntry, KdlError, KdlErrorKind, KdlIdentifier, KdlValue}; +use crate::{parser, KdlDocument, KdlEntry, KdlError, KdlIdentifier, KdlValue}; /// Represents an individual KDL /// [`Node`](https://github.com/kdl-org/kdl/blob/main/SPEC.md#node) inside a @@ -393,34 +391,11 @@ impl IndexMut<&str> for KdlNode { } } -impl KdlNode { - /// Parse a KDL document from a string into a [`KdlDocument`] object model. - fn parse(input: &str) -> Result { - all_consuming(crate::parser::node)(input) - .finish() - .map(|(_, arg)| arg) - .map_err(|e| { - let prefix = &input[..(input.len() - e.input.len())]; - KdlError { - input: input.into(), - offset: prefix.chars().count(), - kind: if let Some(kind) = e.kind { - kind - } else if let Some(ctx) = e.context { - KdlErrorKind::Context(ctx) - } else { - KdlErrorKind::Other - }, - } - }) - } -} - impl FromStr for KdlNode { type Err = KdlError; fn from_str(input: &str) -> Result { - KdlNode::parse(input) + parser::parse(input, parser::node) } } diff --git a/src/parser.rs b/src/parser.rs index 8f510cc..55aef16 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -4,12 +4,37 @@ use crate::nom_compat::{many0, many1, many_till}; use nom::branch::alt; use nom::bytes::complete::{tag, take_until, take_until1, take_while, take_while_m_n}; use nom::character::complete::{anychar, char, none_of, one_of}; -use nom::combinator::{cut, eof, map, map_opt, map_res, opt, recognize}; +use nom::combinator::{all_consuming, cut, eof, map, map_opt, map_res, opt, recognize}; use nom::error::{context, ParseError}; use nom::sequence::{delimited, preceded, terminated, tuple}; -use nom::{IResult, Offset, Parser, Slice}; +use nom::{Finish, IResult, Offset, Parser, Slice}; -use crate::{KdlDocument, KdlEntry, KdlIdentifier, KdlNode, KdlParseError, KdlValue}; +use crate::{ + KdlDocument, KdlEntry, KdlError, KdlErrorKind, KdlIdentifier, KdlNode, KdlParseError, KdlValue, +}; + +pub(crate) fn parse<'a, T, P>(input: &'a str, parser: P) -> Result +where + P: Parser<&'a str, T, KdlParseError<&'a str>>, +{ + all_consuming(parser)(input) + .finish() + .map(|(_, arg)| arg) + .map_err(|e| { + let prefix = &input[..(input.len() - e.input.len())]; + KdlError { + input: input.into(), + offset: prefix.chars().count(), + kind: if let Some(kind) = e.kind { + kind + } else if let Some(ctx) = e.context { + KdlErrorKind::Context(ctx) + } else { + KdlErrorKind::Other + }, + } + }) +} pub(crate) fn document(input: &str) -> IResult<&str, KdlDocument, KdlParseError<&str>> { let (input, nodes) = many0(node)(input)?; @@ -51,7 +76,7 @@ pub(crate) fn node(input: &str) -> IResult<&str, KdlNode, KdlParseError<&str>> { Ok((input, node)) } -fn identifier(input: &str) -> IResult<&str, KdlIdentifier, KdlParseError<&str>> { +pub(crate) fn identifier(input: &str) -> IResult<&str, KdlIdentifier, KdlParseError<&str>> { alt((plain_identifier, quoted_identifier))(input) }