From 1a8eb351685dc368c55d992d719e6bad34398df2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Fri, 22 Apr 2022 23:29:45 -0700 Subject: [PATCH] fix(parse): small parser tweaks + more tests --- src/entry.rs | 33 ++++++++++++++++++++++++++++++++- src/identifier.rs | 35 +++++++++++++++++++++++++++++++++++ src/node.rs | 16 +++++++++++++++- src/parser.rs | 20 +++++++++++++++++--- 4 files changed, 99 insertions(+), 5 deletions(-) diff --git a/src/entry.rs b/src/entry.rs index 4062fe4..0cf5c04 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -155,7 +155,7 @@ impl FromStr for KdlEntry { type Err = KdlError; fn from_str(s: &str) -> Result { - parser::parse(s, parser::entry) + parser::parse(s, parser::entry_with_node_space) } } @@ -192,6 +192,37 @@ mod test { ); } + #[test] + fn parsing() -> miette::Result<()> { + let entry: KdlEntry = " \\\n (\"m\\\"eh\")0xDEADbeef\t\\\n".parse()?; + assert_eq!( + entry, + KdlEntry { + leading: Some(" \\\n ".into()), + ty: Some("\"m\\\"eh\"".parse()?), + value: KdlValue::Base16(0xdeadbeef), + value_repr: Some("0xDEADbeef".into()), + name: None, + trailing: Some("\t\\\n".into()), + } + ); + + let entry: KdlEntry = " \\\n (\"m\\\"eh\")\"foo\"=0xDEADbeef\t\\\n".parse()?; + assert_eq!( + entry, + KdlEntry { + leading: Some(" \\\n ".into()), + ty: Some("\"m\\\"eh\"".parse()?), + value: KdlValue::Base16(0xdeadbeef), + value_repr: Some("0xDEADbeef".into()), + name: Some("\"foo\"".parse()?), + trailing: Some("\t\\\n".into()), + } + ); + + Ok(()) + } + #[test] fn display() { let entry = KdlEntry::new(KdlValue::Base10(42)); diff --git a/src/identifier.rs b/src/identifier.rs index 739dbde..ef260f1 100644 --- a/src/identifier.rs +++ b/src/identifier.rs @@ -160,6 +160,41 @@ impl FromStr for KdlIdentifier { mod test { use super::*; + #[test] + fn parsing() -> miette::Result<()> { + let plain = "foo"; + assert_eq!( + plain.parse::()?, + KdlIdentifier { + value: plain.to_string(), + repr: Some(plain.to_string()), + } + ); + + let quoted = "\"foo\\\"bar\""; + assert_eq!( + quoted.parse::()?, + KdlIdentifier { + value: "foo\"bar".to_string(), + repr: Some(quoted.to_string()), + } + ); + + let invalid = "123"; + assert!(invalid.parse::().is_err()); + + let invalid = " space "; + assert!(invalid.parse::().is_err()); + + let invalid = "\"x"; + assert!(invalid.parse::().is_err()); + + let invalid = "r#\"foo\"#"; + assert!(invalid.parse::().is_err()); + + Ok(()) + } + #[test] fn formatting() { let plain = KdlIdentifier::from("foo"); diff --git a/src/node.rs b/src/node.rs index f28511c..93e2fce 100644 --- a/src/node.rs +++ b/src/node.rs @@ -441,7 +441,9 @@ impl KdlNode { space_before_children = entry.trailing.is_none(); } if let Some(children) = &self.children { - if space_before_children { + if let Some(before) = self.before_children() { + write!(f, "{}", before)?; + } else if space_before_children { write!(f, " ")?; } write!(f, "{{")?; @@ -462,6 +464,18 @@ impl KdlNode { mod test { use super::*; + #[test] + fn parsing() -> miette::Result<()> { + let node: KdlNode = "\n\t (\"ty\")\"node\" 0xDEADbeef;\n".parse()?; + assert_eq!(node.leading(), Some("\n\t ")); + assert_eq!(node.trailing(), Some(";\n")); + assert_eq!(node.ty(), Some(&"\"ty\"".parse()?)); + assert_eq!(node.name(), &"\"node\"".parse()?); + assert_eq!(node.get(0), Some(&"0xDEADbeef".parse()?)); + + Ok(()) + } + #[test] fn indexing() { let mut node = KdlNode::new("foo"); diff --git a/src/parser.rs b/src/parser.rs index 55aef16..3a58206 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -97,7 +97,17 @@ fn quoted_identifier(input: &str) -> IResult<&str, KdlIdentifier, KdlParseError< Ok((input, ident)) } -pub(crate) fn entry(input: &str) -> IResult<&str, KdlEntry, KdlParseError<&str>> { +pub(crate) fn entry_with_node_space(input: &str) -> IResult<&str, KdlEntry, KdlParseError<&str>> { + let (input, leading) = recognize(many0(node_space))(input)?; + let leading = if leading.is_empty() { " " } else { leading }; + let (input, mut entry) = entry(input)?; + let (input, trailing) = recognize(many0(node_space))(input)?; + entry.set_leading(leading); + entry.set_trailing(trailing); + Ok((input, entry)) +} + +fn entry(input: &str) -> IResult<&str, KdlEntry, KdlParseError<&str>> { alt((property, argument))(input) } @@ -109,7 +119,8 @@ fn property(input: &str) -> IResult<&str, KdlEntry, KdlParseError<&str>> { let (input, (raw, value)) = context("property value", cut(value))(input)?; let mut entry = KdlEntry::new_prop(name, value); entry.ty = ty; - entry.set_leading(if leading.is_empty() { " " } else { leading }); + entry.set_leading(leading); + entry.set_trailing(""); entry.set_value_repr(raw); Ok((input, entry)) } @@ -124,7 +135,8 @@ fn argument(input: &str) -> IResult<&str, KdlEntry, KdlParseError<&str>> { }?; let mut entry = KdlEntry::new(value); entry.ty = ty; - entry.set_leading(if leading.is_empty() { " " } else { leading }); + entry.set_leading(leading); + entry.set_trailing(""); entry.set_value_repr(raw); Ok((input, entry)) } @@ -530,6 +542,7 @@ mod node_tests { let mut one = KdlEntry::new(1); one.set_leading(" "); + one.set_trailing(""); one.set_value_repr("1"); assert_eq!(entries.next(), Some(&one)); @@ -537,6 +550,7 @@ mod node_tests { ident.set_repr("\"bar\""); let mut bar = KdlEntry::new_prop(ident, false); bar.set_leading(" "); + bar.set_trailing(""); bar.set_value_repr("false"); assert_eq!(entries.next(), Some(&bar)); }