mirror of https://github.com/kdl-org/kdl-rs.git
feat(draft): 2.0.0-draft.6 support (#92)
This just adds support for the new multiline string syntax. There's no other necessary changes to support draft.6.
This commit is contained in:
parent
71bd07b57d
commit
4d4ef75954
|
|
@ -15,6 +15,9 @@ check out [`knuffel`](https://crates.io/crates/knuffel) or
|
||||||
[`kaydle`](https://crates.io/crates/kaydle) instead for serde (or
|
[`kaydle`](https://crates.io/crates/kaydle) instead for serde (or
|
||||||
serde-like) parsing.
|
serde-like) parsing.
|
||||||
|
|
||||||
|
This crate supports parsing [KDL
|
||||||
|
2.0.0-draft.6](https://github.com/kdl-org/kdl/releases/tag/2.0.0-draft.6)
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
|
|
||||||
|
|
@ -42,11 +42,11 @@ jobs {
|
||||||
}
|
}
|
||||||
step Clippy { run cargo clippy --all -- -D warnings }
|
step Clippy { run cargo clippy --all -- -D warnings }
|
||||||
step "Run tests" { run cargo test --all --verbose }
|
step "Run tests" { run cargo test --all --verbose }
|
||||||
step "Other Stuff" run="
|
step "Other Stuff" run="""
|
||||||
echo foo
|
echo foo
|
||||||
echo bar
|
echo bar
|
||||||
echo baz
|
echo baz
|
||||||
"
|
"""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,9 @@
|
||||||
//! [`kaydle`](https://crates.io/crates/kaydle) instead for serde (or
|
//! [`kaydle`](https://crates.io/crates/kaydle) instead for serde (or
|
||||||
//! serde-like) parsing.
|
//! serde-like) parsing.
|
||||||
//!
|
//!
|
||||||
|
//! This crate supports parsing [KDL
|
||||||
|
//! 2.0.0-draft.6](https://github.com/kdl-org/kdl/releases/tag/2.0.0-draft.6)
|
||||||
|
//!
|
||||||
//! ## Example
|
//! ## Example
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
|
|
|
||||||
|
|
@ -766,13 +766,13 @@ fn equals_sign(input: &mut Input<'_>) -> PResult<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ```text
|
/// ```text
|
||||||
/// quoted-string := '"' (single-line-string-body | newline multi-line-string-body newline unicode-space*) '"'
|
/// quoted-string := '"' single-line-string-body '"' | '"""' newline multi-line-string-body newline unicode-space*) '"""'
|
||||||
/// single-line-string-body := (string-character - newline)*
|
/// single-line-string-body := (string-character - newline)*
|
||||||
/// multi-line-string-body := string-character*
|
/// multi-line-string-body := string-character*
|
||||||
/// ```
|
/// ```
|
||||||
fn quoted_string<'s>(input: &mut Input<'s>) -> PResult<Option<KdlValue>> {
|
fn quoted_string<'s>(input: &mut Input<'s>) -> PResult<Option<KdlValue>> {
|
||||||
"\"".parse_next(input)?;
|
let quotes = alt((("\"\"\"", newline).take(), "\"")).parse_next(input)?;
|
||||||
let is_multiline = opt(newline).parse_next(input)?.is_some();
|
let is_multiline = quotes.len() > 1;
|
||||||
let ml_prefix: Option<String> = if is_multiline {
|
let ml_prefix: Option<String> = if is_multiline {
|
||||||
Some(
|
Some(
|
||||||
peek(preceded(
|
peek(preceded(
|
||||||
|
|
@ -782,10 +782,13 @@ fn quoted_string<'s>(input: &mut Input<'s>) -> PResult<Option<KdlValue>> {
|
||||||
repeat(0.., (not(newline), opt(ws_escape), string_char)).map(|()| ()),
|
repeat(0.., (not(newline), opt(ws_escape), string_char)).map(|()| ()),
|
||||||
newline,
|
newline,
|
||||||
),
|
),
|
||||||
peek(terminated(repeat(0.., unicode_space).map(|()| ()), "\"")),
|
peek(terminated(
|
||||||
|
repeat(0.., unicode_space).map(|()| ()),
|
||||||
|
"\"\"\"",
|
||||||
|
)),
|
||||||
)
|
)
|
||||||
.map(|((), ())| ()),
|
.map(|((), ())| ()),
|
||||||
terminated(repeat(0.., unicode_space).map(|()| ()).take(), "\""),
|
terminated(repeat(0.., unicode_space).map(|()| ()).take(), "\"\"\""),
|
||||||
))
|
))
|
||||||
.parse_next(input)?
|
.parse_next(input)?
|
||||||
.to_string(),
|
.to_string(),
|
||||||
|
|
@ -814,7 +817,7 @@ fn quoted_string<'s>(input: &mut Input<'s>) -> PResult<Option<KdlValue>> {
|
||||||
(
|
(
|
||||||
&prefix[..],
|
&prefix[..],
|
||||||
repeat(0.., unicode_space).map(|()| ()).take(),
|
repeat(0.., unicode_space).map(|()| ()).take(),
|
||||||
peek("\""),
|
peek("\"\"\""),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.map(|(s, _): (Vec<String>, (_, _, _))| {
|
.map(|(s, _): (Vec<String>, (_, _, _))| {
|
||||||
|
|
@ -836,9 +839,12 @@ fn quoted_string<'s>(input: &mut Input<'s>) -> PResult<Option<KdlValue>> {
|
||||||
.resume_after(quoted_string_badval)
|
.resume_after(quoted_string_badval)
|
||||||
.parse_next(input)?
|
.parse_next(input)?
|
||||||
};
|
};
|
||||||
cut_err("\"")
|
let closing_quotes = if is_multiline {
|
||||||
.context(lbl("closing quote"))
|
"\"\"\"".context(lbl("multiline string closing quotes"))
|
||||||
.parse_next(input)?;
|
} else {
|
||||||
|
"\"".context(lbl("string closing quote"))
|
||||||
|
};
|
||||||
|
cut_err(closing_quotes).parse_next(input)?;
|
||||||
Ok(body.map(KdlValue::String))
|
Ok(body.map(KdlValue::String))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -903,13 +909,15 @@ fn escaped_char(input: &mut Input<'_>) -> PResult<char> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `raw-string := '#' raw-string-quotes '#' | '#' raw-string '#'`
|
/// `raw-string := '#' raw-string-quotes '#' | '#' raw-string '#'`
|
||||||
/// `raw-string-quotes := '"' (single-line-raw-string-body | newline multi-line-raw-string-body newline unicode-space*) '"'`
|
/// `raw-string-quotes := '"' single-line-raw-string-body '"' | '"""' newline multi-line-raw-string-body newline unicode-space*) '"""'`
|
||||||
/// `single-line-raw-string-body := (unicode - newline - disallowed-literal-code-points)*`
|
/// `single-line-raw-string-body := (unicode - newline - disallowed-literal-code-points)*`
|
||||||
/// `multi-line-raw-string-body := (unicode - disallowed-literal-code-points)`
|
/// `multi-line-raw-string-body := (unicode - disallowed-literal-code-points)`
|
||||||
fn raw_string(input: &mut Input<'_>) -> PResult<Option<KdlValue>> {
|
fn raw_string(input: &mut Input<'_>) -> PResult<Option<KdlValue>> {
|
||||||
let hashes: String = repeat(1.., "#").parse_next(input)?;
|
let hashes: String = repeat(1.., "#").parse_next(input)?;
|
||||||
"\"".parse_next(input)?;
|
let quotes = alt((("\"\"\"", newline).take(), "\"")).parse_next(input)?;
|
||||||
let is_multiline = opt(newline).parse_next(input)?.is_some();
|
let is_multiline = quotes.len() > 1;
|
||||||
|
dbg!("es);
|
||||||
|
dbg!(is_multiline);
|
||||||
let ml_prefix: Option<String> = if is_multiline {
|
let ml_prefix: Option<String> = if is_multiline {
|
||||||
Some(
|
Some(
|
||||||
peek(preceded(
|
peek(preceded(
|
||||||
|
|
@ -921,7 +929,7 @@ fn raw_string(input: &mut Input<'_>) -> PResult<Option<KdlValue>> {
|
||||||
(
|
(
|
||||||
not(newline),
|
not(newline),
|
||||||
not(disallowed_unicode),
|
not(disallowed_unicode),
|
||||||
not(("\"", &hashes[..])),
|
not(("\"\"\"", &hashes[..])),
|
||||||
any,
|
any,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -930,13 +938,13 @@ fn raw_string(input: &mut Input<'_>) -> PResult<Option<KdlValue>> {
|
||||||
),
|
),
|
||||||
peek(terminated(
|
peek(terminated(
|
||||||
repeat(0.., unicode_space).map(|()| ()),
|
repeat(0.., unicode_space).map(|()| ()),
|
||||||
("\"", &hashes[..]),
|
("\"\"\"", &hashes[..]),
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
.map(|((), ())| ()),
|
.map(|((), ())| ()),
|
||||||
terminated(
|
terminated(
|
||||||
repeat(0.., unicode_space).map(|()| ()).take(),
|
repeat(0.., unicode_space).map(|()| ()).take(),
|
||||||
("\"", &hashes[..]),
|
("\"\"\"", &hashes[..]),
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
.parse_next(input)?
|
.parse_next(input)?
|
||||||
|
|
@ -945,6 +953,7 @@ fn raw_string(input: &mut Input<'_>) -> PResult<Option<KdlValue>> {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
dbg!(&ml_prefix);
|
||||||
let body: Option<String> = if let Some(prefix) = ml_prefix {
|
let body: Option<String> = if let Some(prefix) = ml_prefix {
|
||||||
repeat_till(
|
repeat_till(
|
||||||
0..,
|
0..,
|
||||||
|
|
@ -955,7 +964,7 @@ fn raw_string(input: &mut Input<'_>) -> PResult<Option<KdlValue>> {
|
||||||
newline.take().map(|_| "\n".to_string()),
|
newline.take().map(|_| "\n".to_string()),
|
||||||
repeat_till(
|
repeat_till(
|
||||||
0..,
|
0..,
|
||||||
(not(newline), not(("\"", &hashes[..])), any)
|
(not(newline), not(("\"\"\"", &hashes[..])), any)
|
||||||
.map(|((), (), _)| ())
|
.map(|((), (), _)| ())
|
||||||
.take(),
|
.take(),
|
||||||
newline,
|
newline,
|
||||||
|
|
@ -968,7 +977,7 @@ fn raw_string(input: &mut Input<'_>) -> PResult<Option<KdlValue>> {
|
||||||
(
|
(
|
||||||
&prefix[..],
|
&prefix[..],
|
||||||
repeat(0.., unicode_space).map(|()| ()).take(),
|
repeat(0.., unicode_space).map(|()| ()).take(),
|
||||||
peek(("\"", &hashes[..])),
|
peek(("\"\"\"", &hashes[..])),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.map(|(s, _): (Vec<String>, (_, _, _))| {
|
.map(|(s, _): (Vec<String>, (_, _, _))| {
|
||||||
|
|
@ -996,9 +1005,12 @@ fn raw_string(input: &mut Input<'_>) -> PResult<Option<KdlValue>> {
|
||||||
.resume_after(raw_string_badval)
|
.resume_after(raw_string_badval)
|
||||||
.parse_next(input)?
|
.parse_next(input)?
|
||||||
};
|
};
|
||||||
cut_err(("\"", &hashes[..]))
|
let closing_quotes = if is_multiline {
|
||||||
.context(lbl("closing quote"))
|
"\"\"\"".context(lbl("multiline raw string closing quotes"))
|
||||||
.parse_next(input)?;
|
} else {
|
||||||
|
"\"".context(lbl("raw string closing quotes"))
|
||||||
|
};
|
||||||
|
cut_err((closing_quotes, &hashes[..])).parse_next(input)?;
|
||||||
Ok(body.map(KdlValue::String))
|
Ok(body.map(KdlValue::String))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1044,40 +1056,46 @@ mod string_tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn multiline_quoted_string() {
|
fn multiline_quoted_string() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
string.parse(new_input("\"\nfoo\nbar\nbaz\n\"")).unwrap(),
|
string
|
||||||
|
.parse(new_input("\"\"\"\nfoo\nbar\nbaz\n\"\"\""))
|
||||||
|
.unwrap(),
|
||||||
Some(KdlValue::String("foo\nbar\nbaz".into()))
|
Some(KdlValue::String("foo\nbar\nbaz".into()))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
string
|
string
|
||||||
.parse(new_input("\"\n foo\n bar\n baz\n \""))
|
.parse(new_input("\"\"\"\n foo\n bar\n baz\n \"\"\""))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
Some(KdlValue::String("foo\n bar\nbaz".into()))
|
Some(KdlValue::String("foo\n bar\nbaz".into()))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
string.parse(new_input("\"\nfoo\r\nbar\nbaz\n\"")).unwrap(),
|
string
|
||||||
|
.parse(new_input("\"\"\"\nfoo\r\nbar\nbaz\n\"\"\""))
|
||||||
|
.unwrap(),
|
||||||
Some(KdlValue::String("foo\nbar\nbaz".into()))
|
Some(KdlValue::String("foo\nbar\nbaz".into()))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
string
|
string
|
||||||
.parse(new_input("\"\n foo\n bar\n baz\n \""))
|
.parse(new_input("\"\"\"\n foo\n bar\n baz\n \"\"\""))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
Some(KdlValue::String("foo\n bar\n baz".into()))
|
Some(KdlValue::String("foo\n bar\n baz".into()))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
string
|
string
|
||||||
.parse(new_input("\"\n \\ foo\n \\ bar\n \\ baz\n \""))
|
.parse(new_input(
|
||||||
|
"\"\"\"\n \\ foo\n \\ bar\n \\ baz\n \"\"\""
|
||||||
|
))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
Some(KdlValue::String("foo\n bar\n baz".into()))
|
Some(KdlValue::String("foo\n bar\n baz".into()))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
string
|
string
|
||||||
.parse(new_input("\"\n\n string\t\n \""))
|
.parse(new_input("\"\"\"\n\n string\t\n \"\"\""))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
Some(KdlValue::String("\nstring\t".into())),
|
Some(KdlValue::String("\nstring\t".into())),
|
||||||
"Empty line without any indentation"
|
"Empty line without any indentation"
|
||||||
);
|
);
|
||||||
assert!(string
|
assert!(string
|
||||||
.parse(new_input("\"\nfoo\n bar\n baz\n \""))
|
.parse(new_input("\"\"\"\nfoo\n bar\n baz\n \"\"\""))
|
||||||
.is_err());
|
.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1091,31 +1109,36 @@ mod string_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn multiline_raw_string() {
|
fn multiline_raw_string() {
|
||||||
assert_eq!(
|
|
||||||
string.parse(new_input("#\"\nfoo\nbar\nbaz\n\"#")).unwrap(),
|
|
||||||
Some(KdlValue::String("foo\nbar\nbaz".into()))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
string
|
string
|
||||||
.parse(new_input("#\"\nfoo\r\nbar\nbaz\n\"#"))
|
.parse(new_input("#\"\"\"\nfoo\nbar\nbaz\n\"\"\"#"))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
Some(KdlValue::String("foo\nbar\nbaz".into()))
|
Some(KdlValue::String("foo\nbar\nbaz".into()))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
string
|
string
|
||||||
.parse(new_input("##\"\n foo\n bar\n baz\n \"##"))
|
.parse(new_input("#\"\"\"\nfoo\r\nbar\nbaz\n\"\"\"#"))
|
||||||
|
.unwrap(),
|
||||||
|
Some(KdlValue::String("foo\nbar\nbaz".into()))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
string
|
||||||
|
.parse(new_input("##\"\"\"\n foo\n bar\n baz\n \"\"\"##"))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
Some(KdlValue::String("foo\n bar\nbaz".into()))
|
Some(KdlValue::String("foo\n bar\nbaz".into()))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
string
|
string
|
||||||
.parse(new_input("#\"\n foo\n \\nbar\n baz\n \"#"))
|
.parse(new_input("#\"\"\"\n foo\n \\nbar\n baz\n \"\"\"#"))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
Some(KdlValue::String("foo\n \\nbar\n baz".into()))
|
Some(KdlValue::String("foo\n \\nbar\n baz".into()))
|
||||||
);
|
);
|
||||||
assert!(string
|
assert!(string
|
||||||
.parse(new_input("#\"\nfoo\n bar\n baz\n \"#"))
|
.parse(new_input("#\"\"\"\nfoo\n bar\n baz\n \"\"\"#"))
|
||||||
.is_err());
|
.is_err());
|
||||||
|
|
||||||
|
assert!(string.parse(new_input("#\"\nfoo\nbar\nbaz\n\"#")).is_err());
|
||||||
|
assert!(string.parse(new_input("\"\nfoo\nbar\nbaz\n\"")).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
ノード お名前=ฅ^•ﻌ•^ฅ
|
ノード お名前=ฅ^•ﻌ•^ฅ
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
// All of these strings are the same
|
// All of these strings are the same
|
||||||
node \
|
node \
|
||||||
"Hello\n\tWorld" \
|
"Hello\n\tWorld" \
|
||||||
"
|
"""
|
||||||
Hello
|
Hello
|
||||||
World
|
World
|
||||||
" \
|
""" \
|
||||||
"Hello\n\ \tWorld" \
|
"Hello\n\ \tWorld" \
|
||||||
"Hello\n\
|
"Hello\n\
|
||||||
\tWorld" \
|
\tWorld" \
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
node #"
|
node #"""
|
||||||
hey
|
hey
|
||||||
everyone
|
everyone
|
||||||
how goes?
|
how goes?
|
||||||
"#
|
"""#
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
node #"
|
node #"""
|
||||||
hey
|
hey
|
||||||
everyone
|
everyone
|
||||||
how goes?
|
how goes?
|
||||||
"#
|
"""#
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
node #"
|
node #"""
|
||||||
hey
|
hey
|
||||||
everyone
|
everyone
|
||||||
how goes?
|
how goes?
|
||||||
"#
|
"""#
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
node #"
|
node #"""
|
||||||
hey
|
hey
|
||||||
everyone
|
everyone
|
||||||
how goes?
|
how goes?
|
||||||
"#
|
"""#
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
node #"""one line"""#
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
node #"
|
||||||
|
hey
|
||||||
|
everyone
|
||||||
|
how goes?
|
||||||
|
"#
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
node "
|
node """
|
||||||
hey
|
hey
|
||||||
everyone
|
everyone
|
||||||
how goes?
|
how goes?
|
||||||
"
|
"""
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
node "
|
node """
|
||||||
hey
|
hey
|
||||||
everyone
|
everyone
|
||||||
how goes?
|
how goes?
|
||||||
"
|
"""
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
node "
|
node """
|
||||||
hey
|
hey
|
||||||
everyone
|
everyone
|
||||||
how goes?
|
how goes?
|
||||||
"
|
"""
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
node "
|
node """
|
||||||
hey
|
hey
|
||||||
everyone
|
everyone
|
||||||
how goes?
|
how goes?
|
||||||
"
|
"""
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
node """one line"""
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
node "
|
||||||
|
hey
|
||||||
|
everyone
|
||||||
|
how goes?
|
||||||
|
"
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
node #"
|
node #"""
|
||||||
hello
|
hello
|
||||||
world
|
world
|
||||||
"#
|
"""#
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
/- node 1.0 "a" b="
|
/- node 1.0 "a" b="""
|
||||||
b
|
b
|
||||||
"
|
"""
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue