diff --git a/src/v2_parser.rs b/src/v2_parser.rs index dfced19..8a3d3cd 100644 --- a/src/v2_parser.rs +++ b/src/v2_parser.rs @@ -882,9 +882,8 @@ fn node_space1(input: &mut Input<'_>) -> PResult<()> { repeat(1.., node_space).parse_next(input) } -/// `string := identifier-string | quoted-string | raw-string` +/// string := identifier-string | quoted-string | raw-string ¶ pub(crate) fn string(input: &mut Input<'_>) -> PResult> { - // TODO: shouldn't put the `resume_after_cut`s here, because they mess with context from higher levels. trace( "string", alt(( @@ -1018,32 +1017,65 @@ fn equals_sign(input: &mut Input<'_>) -> PResult<()> { } /// ```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 | ('\' (unicode-space | 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 { - let quotes = alt((("\"\"\"", newline).take(), "\"")).parse_next(input)?; +fn quoted_string(input: &mut Input<'_>) -> PResult { + let quotes = + alt(( + ( + "\"\"\"", + cut_err(newline).context(cx().lbl("multi-line string newline").msg( + "Multi-line string opening quotes must be immediately followed by a newline", + )), + ) + .take(), + "\"", + )) + .parse_next(input)?; let is_multiline = quotes.len() > 1; let ml_prefix: Option = if is_multiline { Some( - peek(preceded( + cut_err(peek(preceded( repeat_till( 0.., ( - repeat(0.., (not(newline), opt(ws_escape), string_char)).map(|()| ()), + repeat( + 0.., + ( + not(newline), + alt(( + ws_escape.void(), + trace( + "valid string body char(s)", + alt(( + ('\"', not("\"\"")).void(), + ('\"', not("\"")).void(), + string_char.void(), + )), + ) + .void(), + )), + ), + ) + .map(|()| ()), newline, ), peek(terminated( - repeat(0.., unicode_space).map(|()| ()), + repeat(0.., alt((ws_escape, unicode_space))).map(|()| ()), "\"\"\"", )), ) .map(|((), ())| ()), - terminated(repeat(0.., unicode_space).map(|()| ()).take(), "\"\"\""), - )) - .parse_next(input)? - .to_string(), + terminated( + repeat(0.., alt((ws_escape.map(|_| ""), unicode_space.take()))) + .map(|s: String| s), + "\"\"\"", + ), + ))) + .context(cx().lbl("multi-line string")) + .parse_next(input)?, ) } else { None @@ -1052,30 +1084,40 @@ fn quoted_string<'s>(input: &mut Input<'s>) -> PResult { let parser = repeat_till( 0.., ( - cut_err(alt((&prefix[..], peek(newline).take()))) + cut_err(alt(((&prefix[..]).void(), peek(empty_line).void()))) .context(cx().msg("matching multiline string prefix").lbl("bad prefix").hlp("Multi-line string bodies must be prefixed by the exact same whitespace as the leading whitespace before the closing '\"\"\"'")), alt(( - newline.take().map(|_| "\n".to_string()), + empty_line.map(|s| s.to_string()), repeat_till( 0.., - (not(newline), opt(ws_escape), string_char).map(|(_, _, s)| s), + ( + not(newline), + alt(( + ws_escape.map(|_| None), + alt(( + ('\"', not("\"\"")).map(|(c, ())| Some(c)), + ('\"', not("\"")).map(|(c, ())| Some(c)), + string_char.map(Some), + )) + )) + ).map(|(_, c)| c), newline, ) // multiline string literal newlines are normalized to `\n` - .map(|(s, _): (String, _)| format!("{s}\n")), + .map(|(cs, _): (Vec>, _)| cs.into_iter().flatten().chain(vec!['\n']).collect::()), )), ) .map(|(_, s)| s), ( &prefix[..], - repeat(0.., unicode_space).map(|()| ()).take(), + repeat(0.., ws_escape.void()).map(|()| ()), peek("\"\"\""), ), ) .map(|(s, _): (Vec, (_, _, _))| { let mut s = s.join(""); // Slice off the `\n` at the end of the last line. - s.truncate(s.len() - 1); + s.truncate(s.len().saturating_sub(1)); s }) .context(cx().lbl("multi-line quoted string")); @@ -1090,13 +1132,14 @@ fn quoted_string<'s>(input: &mut Input<'s>) -> PResult { .hlp("You can make a string multi-line by wrapping it in '\"\"\"', with a newline immediately after the opening quotes."), ), ), - opt(ws_escape), - string_char, - ) - .map(|(_, _, s)| s), - (repeat(0.., unicode_space).map(|()| ()).take(), peek("\"")), + alt(( + ws_escape.map(|_| None), + string_char.map(Some), + )) + ).map(|(_, c)| c), + peek("\"") ) - .map(|(s, (end, _)): (String, (&'s str, _))| format!("{s}{end}")) + .map(|(cs, _): (Vec>, _)| cs.into_iter().flatten().collect::()) .context(cx().lbl("quoted string")); cut_err(parser).parse_next(input)? }; @@ -1112,8 +1155,19 @@ fn quoted_string<'s>(input: &mut Input<'s>) -> PResult { Ok(KdlValue::String(body)) } +fn empty_line(input: &mut Input<'_>) -> PResult<&'static str> { + repeat(0.., alt((ws_escape.void(), unicode_space.void()))) + .map(|()| ()) + .parse_next(input)?; + newline.parse_next(input)?; + Ok("\n") +} + /// Like badval, but is able to slurp up invalid raw strings, which contain whitespace. fn quoted_string_badval(input: &mut Input<'_>) -> PResult<()> { + // TODO(@zkat): this should have different behavior based on whether we're + // resuming a single or multi-line string. Right now, multi-liners end up + // with silly errors. ( repeat_till( 0.., @@ -1135,19 +1189,25 @@ fn quoted_string_terminator(input: &mut Input<'_>) -> PResult<()> { /// ``` fn string_char(input: &mut Input<'_>) -> PResult { alt(( - escaped_char, - (not(disallowed_unicode), none_of(['\\', '"'])).map(|(_, c)| c), + trace("escaped char", escaped_char), + trace( + "regular string char", + (not(disallowed_unicode), none_of(['\\', '"'])).map(|(_, c)| c), + ), )) .parse_next(input) } fn ws_escape(input: &mut Input<'_>) -> PResult<()> { - ( - "\\", - repeat(1.., alt((unicode_space, newline))).map(|()| ()), + trace( + "ws_escape", + ( + "\\", + repeat(1.., alt((unicode_space, newline))).map(|()| ()), + ), ) - .void() - .parse_next(input) + .void() + .parse_next(input) } /// ```text @@ -1182,10 +1242,13 @@ fn escaped_char(input: &mut Input<'_>) -> PResult { .parse_next(input) } -/// `raw-string := '#' raw-string-quotes '#' | '#' raw-string '#'` -/// `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)*` -/// `multi-line-raw-string-body := (unicode - disallowed-literal-code-points)` +/// ```text +/// raw-string := '#' raw-string-quotes '#' | '#' raw-string '#' +/// raw-string-quotes := '"' single-line-raw-string-body '"' | '"""' newline multi-line-raw-string-body '"""' +/// single-line-raw-string-body := '' | (single-line-raw-string-char - '"') single-line-raw-string-char*? | '"' (single-line-raw-string-char - '"') single-line-raw-string-char*? +/// single-line-raw-string-char := unicode - newline - disallowed-literal-code-points +/// multi-line-raw-string-body := (unicode - disallowed-literal-code-points)*? +/// ``` fn raw_string(input: &mut Input<'_>) -> PResult { let hashes: String = repeat(1.., "#").parse_next(input)?; let quotes = alt((("\"\"\"", newline).take(), "\"")).parse_next(input)?; @@ -1229,10 +1292,10 @@ fn raw_string(input: &mut Input<'_>) -> PResult { repeat_till( 0.., ( - cut_err(alt((&prefix[..], peek(newline).take()))) + cut_err(alt(((&prefix[..]).void(), peek(empty_line).void()))) .context(cx().lbl("matching multiline raw string prefix")), alt(( - newline.take().map(|_| "\n".to_string()), + empty_line.map(|s| s.to_string()), repeat_till( 0.., (not(newline), not(("\"\"\"", &hashes[..])), any) @@ -1254,7 +1317,7 @@ fn raw_string(input: &mut Input<'_>) -> PResult { .map(|(s, _): (Vec, (_, _, _))| { let mut s = s.join(""); // Slice off the `\n` at the end of the last line. - s.truncate(s.len() - 1); + s.truncate(s.len().saturating_sub(1)); s }) .parse_next(input)? @@ -1311,7 +1374,7 @@ mod string_tests { } #[test] - fn quoted_string() { + fn single_line_quoted_string() { assert_eq!( string.parse(new_input("\"foo\"")).unwrap(), Some(KdlValue::String("foo".into())) @@ -1363,6 +1426,14 @@ mod string_tests { Some(KdlValue::String("\nstring\t".into())), "Empty line without any indentation" ); + assert_eq!( + string + .parse(new_input("\"\"\"\n   \\\n   \n   \"\"\"")) + .unwrap(), + Some(KdlValue::String("".into())), + "Escaped whitespace with proper prefix" + ); + assert!(string .parse(new_input("\"\"\"\nfoo\n bar\n baz\n \"\"\"")) .is_err()); @@ -1491,9 +1562,9 @@ fn disallowed_unicode(input: &mut Input<'_>) -> PResult<()> { /// `escline := '\\' ws* (single-line-comment | newline | eof)` fn escline(input: &mut Input<'_>) -> PResult<()> { "\\".parse_next(input)?; - repeat(0.., ws).map(|_: ()| ()).parse_next(input)?; + wss.parse_next(input)?; alt((single_line_comment, newline, eof.void())).parse_next(input)?; - repeat(0.., ws).map(|_: ()| ()).parse_next(input) + wss.parse_next(input) } #[cfg(test)] @@ -1596,9 +1667,12 @@ fn multi_line_comment_test() { .is_ok()); } -/// slashdash := '/-' line-space* +/// slashdash := '/-' (node-space | line-space)* fn slashdash(input: &mut Input<'_>) -> PResult<()> { - ("/-", repeat(0.., line_space).map(|()| ())) + ( + "/-", + repeat(0.., alt((node_space, line_space))).map(|()| ()), + ) .void() .parse_next(input) } diff --git a/tests/test_cases/expected_kdl/multiline_raw_string_containing_quotes.kdl b/tests/test_cases/expected_kdl/multiline_raw_string_containing_quotes.kdl new file mode 100644 index 0000000..6b04c7c --- /dev/null +++ b/tests/test_cases/expected_kdl/multiline_raw_string_containing_quotes.kdl @@ -0,0 +1 @@ +node "\"\"\"triple-quote\"\"\"\n##\"too few quotes\"##\n#\"\"\"too few #\"\"\"#" diff --git a/tests/test_cases/expected_kdl/multiline_string_containing_quotes.kdl b/tests/test_cases/expected_kdl/multiline_string_containing_quotes.kdl new file mode 100644 index 0000000..03dc73b --- /dev/null +++ b/tests/test_cases/expected_kdl/multiline_string_containing_quotes.kdl @@ -0,0 +1 @@ +node "this string contains \"quotes\", twice\"\"" diff --git a/tests/test_cases/expected_kdl/multiline_string_escape_in_closing_line.kdl b/tests/test_cases/expected_kdl/multiline_string_escape_in_closing_line.kdl new file mode 100644 index 0000000..e7186a6 --- /dev/null +++ b/tests/test_cases/expected_kdl/multiline_string_escape_in_closing_line.kdl @@ -0,0 +1 @@ +node "foo bar\nbaz" diff --git a/tests/test_cases/expected_kdl/multiline_string_escape_in_closing_line_shallow.kdl b/tests/test_cases/expected_kdl/multiline_string_escape_in_closing_line_shallow.kdl new file mode 100644 index 0000000..314069e --- /dev/null +++ b/tests/test_cases/expected_kdl/multiline_string_escape_in_closing_line_shallow.kdl @@ -0,0 +1 @@ +node " foo bar\n baz" diff --git a/tests/test_cases/expected_kdl/multiline_string_whitespace_only.kdl b/tests/test_cases/expected_kdl/multiline_string_whitespace_only.kdl new file mode 100644 index 0000000..4d04294 --- /dev/null +++ b/tests/test_cases/expected_kdl/multiline_string_whitespace_only.kdl @@ -0,0 +1 @@ +node "" "" "" "\n\n " "\n" diff --git a/tests/test_cases/expected_kdl/raw_string_just_quote.kdl b/tests/test_cases/expected_kdl/raw_string_just_quote.kdl deleted file mode 100644 index 0a76315..0000000 --- a/tests/test_cases/expected_kdl/raw_string_just_quote.kdl +++ /dev/null @@ -1 +0,0 @@ -node "\"" diff --git a/tests/test_cases/expected_kdl/slashdash_escline_before_arg_type.kdl b/tests/test_cases/expected_kdl/slashdash_escline_before_arg_type.kdl new file mode 100644 index 0000000..2e98005 --- /dev/null +++ b/tests/test_cases/expected_kdl/slashdash_escline_before_arg_type.kdl @@ -0,0 +1 @@ +node arg2 diff --git a/tests/test_cases/expected_kdl/slashdash_escline_before_children.kdl b/tests/test_cases/expected_kdl/slashdash_escline_before_children.kdl new file mode 100644 index 0000000..dd5fe2e --- /dev/null +++ b/tests/test_cases/expected_kdl/slashdash_escline_before_children.kdl @@ -0,0 +1 @@ +node arg1 diff --git a/tests/test_cases/expected_kdl/slashdash_escline_before_node.kdl b/tests/test_cases/expected_kdl/slashdash_escline_before_node.kdl new file mode 100644 index 0000000..6810417 --- /dev/null +++ b/tests/test_cases/expected_kdl/slashdash_escline_before_node.kdl @@ -0,0 +1 @@ +node2 diff --git a/tests/test_cases/expected_kdl/slashdash_false_node.kdl b/tests/test_cases/expected_kdl/slashdash_false_node.kdl new file mode 100644 index 0000000..8f69eb8 --- /dev/null +++ b/tests/test_cases/expected_kdl/slashdash_false_node.kdl @@ -0,0 +1 @@ +node foo bar diff --git a/tests/test_cases/expected_kdl/unusual_bare_id_chars_in_quoted_id.kdl b/tests/test_cases/expected_kdl/unusual_bare_id_chars_in_quoted_id.kdl index 8321632..ef66d22 100644 --- a/tests/test_cases/expected_kdl/unusual_bare_id_chars_in_quoted_id.kdl +++ b/tests/test_cases/expected_kdl/unusual_bare_id_chars_in_quoted_id.kdl @@ -1 +1 @@ -foo123~!@$%^&*.:'|?+<>, weeee +foo123~!@$%^&*.:'|?+<>,`-_ weeee diff --git a/tests/test_cases/expected_kdl/unusual_chars_in_bare_id.kdl b/tests/test_cases/expected_kdl/unusual_chars_in_bare_id.kdl index 8321632..ef66d22 100644 --- a/tests/test_cases/expected_kdl/unusual_chars_in_bare_id.kdl +++ b/tests/test_cases/expected_kdl/unusual_chars_in_bare_id.kdl @@ -1 +1 @@ -foo123~!@$%^&*.:'|?+<>, weeee +foo123~!@$%^&*.:'|?+<>,`-_ weeee diff --git a/tests/test_cases/expected_kdl/zero_arg.kdl b/tests/test_cases/expected_kdl/zero_arg.kdl deleted file mode 100644 index 74405b6..0000000 --- a/tests/test_cases/expected_kdl/zero_arg.kdl +++ /dev/null @@ -1 +0,0 @@ -node 0 diff --git a/tests/test_cases/input/bare_ident_numeric_dot.kdl b/tests/test_cases/input/bare_ident_numeric_dot_fail.kdl similarity index 100% rename from tests/test_cases/input/bare_ident_numeric_dot.kdl rename to tests/test_cases/input/bare_ident_numeric_dot_fail.kdl diff --git a/tests/test_cases/input/bare_ident_numeric.kdl b/tests/test_cases/input/bare_ident_numeric_fail.kdl similarity index 100% rename from tests/test_cases/input/bare_ident_numeric.kdl rename to tests/test_cases/input/bare_ident_numeric_fail.kdl diff --git a/tests/test_cases/input/bare_ident_numeric_sign.kdl b/tests/test_cases/input/bare_ident_numeric_sign_fail.kdl similarity index 100% rename from tests/test_cases/input/bare_ident_numeric_sign.kdl rename to tests/test_cases/input/bare_ident_numeric_sign_fail.kdl diff --git a/tests/test_cases/input/bom_later.kdl b/tests/test_cases/input/bom_later_fail.kdl similarity index 100% rename from tests/test_cases/input/bom_later.kdl rename to tests/test_cases/input/bom_later_fail.kdl diff --git a/tests/test_cases/input/brackets_in_bare_id.kdl b/tests/test_cases/input/brackets_in_bare_id_fail.kdl similarity index 100% rename from tests/test_cases/input/brackets_in_bare_id.kdl rename to tests/test_cases/input/brackets_in_bare_id_fail.kdl diff --git a/tests/test_cases/input/dot_but_no_fraction_before_exponent.kdl b/tests/test_cases/input/dot_but_no_fraction_before_exponent_fail.kdl similarity index 100% rename from tests/test_cases/input/dot_but_no_fraction_before_exponent.kdl rename to tests/test_cases/input/dot_but_no_fraction_before_exponent_fail.kdl diff --git a/tests/test_cases/input/dot_but_no_fraction.kdl b/tests/test_cases/input/dot_but_no_fraction_fail.kdl similarity index 100% rename from tests/test_cases/input/dot_but_no_fraction.kdl rename to tests/test_cases/input/dot_but_no_fraction_fail.kdl diff --git a/tests/test_cases/input/dot_in_exponent.kdl b/tests/test_cases/input/dot_in_exponent_fail.kdl similarity index 100% rename from tests/test_cases/input/dot_in_exponent.kdl rename to tests/test_cases/input/dot_in_exponent_fail.kdl diff --git a/tests/test_cases/input/dot_zero.kdl b/tests/test_cases/input/dot_zero_fail.kdl similarity index 100% rename from tests/test_cases/input/dot_zero.kdl rename to tests/test_cases/input/dot_zero_fail.kdl diff --git a/tests/test_cases/input/empty_arg_type.kdl b/tests/test_cases/input/empty_arg_type_fail.kdl similarity index 100% rename from tests/test_cases/input/empty_arg_type.kdl rename to tests/test_cases/input/empty_arg_type_fail.kdl diff --git a/tests/test_cases/input/empty_node_type.kdl b/tests/test_cases/input/empty_node_type_fail.kdl similarity index 100% rename from tests/test_cases/input/empty_node_type.kdl rename to tests/test_cases/input/empty_node_type_fail.kdl diff --git a/tests/test_cases/input/empty_prop_type.kdl b/tests/test_cases/input/empty_prop_type_fail.kdl similarity index 100% rename from tests/test_cases/input/empty_prop_type.kdl rename to tests/test_cases/input/empty_prop_type_fail.kdl diff --git a/tests/test_cases/input/eof_after_escape.kdl b/tests/test_cases/input/eof_after_escape.kdl index eed8d72..0136726 100644 --- a/tests/test_cases/input/eof_after_escape.kdl +++ b/tests/test_cases/input/eof_after_escape.kdl @@ -1 +1 @@ -node \ +node \ \ No newline at end of file diff --git a/tests/test_cases/input/err_backslash_in_bare_id.kdl b/tests/test_cases/input/err_backslash_in_bare_id_fail.kdl similarity index 100% rename from tests/test_cases/input/err_backslash_in_bare_id.kdl rename to tests/test_cases/input/err_backslash_in_bare_id_fail.kdl diff --git a/tests/test_cases/input/false_prop_key.kdl b/tests/test_cases/input/false_prop_key_fail.kdl similarity index 100% rename from tests/test_cases/input/false_prop_key.kdl rename to tests/test_cases/input/false_prop_key_fail.kdl diff --git a/tests/test_cases/input/floating_point_keyword_identifier_strings_error.kdl.kdl b/tests/test_cases/input/floating_point_keyword_identifier_strings_fail.kdl similarity index 100% rename from tests/test_cases/input/floating_point_keyword_identifier_strings_error.kdl.kdl rename to tests/test_cases/input/floating_point_keyword_identifier_strings_fail.kdl diff --git a/tests/test_cases/input/hash_in_id.kdl b/tests/test_cases/input/hash_in_id_fail.kdl similarity index 100% rename from tests/test_cases/input/hash_in_id.kdl rename to tests/test_cases/input/hash_in_id_fail.kdl diff --git a/tests/test_cases/input/hex.kdl b/tests/test_cases/input/hex.kdl new file mode 100644 index 0000000..ec764dd --- /dev/null +++ b/tests/test_cases/input/hex.kdl @@ -0,0 +1 @@ +node 0xabcdef1234567890 \ No newline at end of file diff --git a/tests/test_cases/input/illegal_char_in_binary.kdl b/tests/test_cases/input/illegal_char_in_binary_fail.kdl similarity index 100% rename from tests/test_cases/input/illegal_char_in_binary.kdl rename to tests/test_cases/input/illegal_char_in_binary_fail.kdl diff --git a/tests/test_cases/input/illegal_char_in_hex.kdl b/tests/test_cases/input/illegal_char_in_hex_fail.kdl similarity index 100% rename from tests/test_cases/input/illegal_char_in_hex.kdl rename to tests/test_cases/input/illegal_char_in_hex_fail.kdl diff --git a/tests/test_cases/input/illegal_char_in_octal.kdl b/tests/test_cases/input/illegal_char_in_octal_fail.kdl similarity index 100% rename from tests/test_cases/input/illegal_char_in_octal.kdl rename to tests/test_cases/input/illegal_char_in_octal_fail.kdl diff --git a/tests/test_cases/input/just_space_in_arg_type.kdl b/tests/test_cases/input/just_space_in_arg_type_fail.kdl similarity index 100% rename from tests/test_cases/input/just_space_in_arg_type.kdl rename to tests/test_cases/input/just_space_in_arg_type_fail.kdl diff --git a/tests/test_cases/input/just_space_in_node_type.kdl b/tests/test_cases/input/just_space_in_node_type_fail.kdl similarity index 100% rename from tests/test_cases/input/just_space_in_node_type.kdl rename to tests/test_cases/input/just_space_in_node_type_fail.kdl diff --git a/tests/test_cases/input/just_space_in_prop_type.kdl b/tests/test_cases/input/just_space_in_prop_type_fail.kdl similarity index 100% rename from tests/test_cases/input/just_space_in_prop_type.kdl rename to tests/test_cases/input/just_space_in_prop_type_fail.kdl diff --git a/tests/test_cases/input/just_type_no_arg.kdl b/tests/test_cases/input/just_type_no_arg_fail.kdl similarity index 100% rename from tests/test_cases/input/just_type_no_arg.kdl rename to tests/test_cases/input/just_type_no_arg_fail.kdl diff --git a/tests/test_cases/input/just_type_no_node_id.kdl b/tests/test_cases/input/just_type_no_node_id_fail.kdl similarity index 100% rename from tests/test_cases/input/just_type_no_node_id.kdl rename to tests/test_cases/input/just_type_no_node_id_fail.kdl diff --git a/tests/test_cases/input/just_type_no_prop.kdl b/tests/test_cases/input/just_type_no_prop_fail.kdl similarity index 100% rename from tests/test_cases/input/just_type_no_prop.kdl rename to tests/test_cases/input/just_type_no_prop_fail.kdl diff --git a/tests/test_cases/input/legacy_raw_string_fail.kdl b/tests/test_cases/input/legacy_raw_string_fail.kdl new file mode 100644 index 0000000..3a8695d --- /dev/null +++ b/tests/test_cases/input/legacy_raw_string_fail.kdl @@ -0,0 +1 @@ +node r"foo" diff --git a/tests/test_cases/input/legacy_raw_string_hash_fail.kdl b/tests/test_cases/input/legacy_raw_string_hash_fail.kdl new file mode 100644 index 0000000..529037a --- /dev/null +++ b/tests/test_cases/input/legacy_raw_string_hash_fail.kdl @@ -0,0 +1 @@ +node r#"foo"# diff --git a/tests/test_cases/input/multiline_raw_string_containing_quotes.kdl b/tests/test_cases/input/multiline_raw_string_containing_quotes.kdl new file mode 100644 index 0000000..44b4ad2 --- /dev/null +++ b/tests/test_cases/input/multiline_raw_string_containing_quotes.kdl @@ -0,0 +1,5 @@ +node ##""" +"""triple-quote""" +##"too few quotes"## +#"""too few #"""# +"""## diff --git a/tests/test_cases/input/multiline_raw_string_non_matching_prefix_character_error.kdl b/tests/test_cases/input/multiline_raw_string_non_matching_prefix_character_error_fail.kdl similarity index 100% rename from tests/test_cases/input/multiline_raw_string_non_matching_prefix_character_error.kdl rename to tests/test_cases/input/multiline_raw_string_non_matching_prefix_character_error_fail.kdl diff --git a/tests/test_cases/input/multiline_raw_string_non_matching_prefix_count_error.kdl b/tests/test_cases/input/multiline_raw_string_non_matching_prefix_count_error_fail.kdl similarity index 100% rename from tests/test_cases/input/multiline_raw_string_non_matching_prefix_count_error.kdl rename to tests/test_cases/input/multiline_raw_string_non_matching_prefix_count_error_fail.kdl diff --git a/tests/test_cases/input/multiline_raw_string_single_line_err.kdl b/tests/test_cases/input/multiline_raw_string_single_line_err_fail.kdl similarity index 100% rename from tests/test_cases/input/multiline_raw_string_single_line_err.kdl rename to tests/test_cases/input/multiline_raw_string_single_line_err_fail.kdl diff --git a/tests/test_cases/input/multiline_raw_string_single_quote_err.kdl b/tests/test_cases/input/multiline_raw_string_single_quote_err_fail.kdl similarity index 100% rename from tests/test_cases/input/multiline_raw_string_single_quote_err.kdl rename to tests/test_cases/input/multiline_raw_string_single_quote_err_fail.kdl diff --git a/tests/test_cases/input/multiline_string_containing_quotes.kdl b/tests/test_cases/input/multiline_string_containing_quotes.kdl new file mode 100644 index 0000000..d13c3e7 --- /dev/null +++ b/tests/test_cases/input/multiline_string_containing_quotes.kdl @@ -0,0 +1,3 @@ +node """ +this string contains "quotes", twice"" +""" diff --git a/tests/test_cases/input/multiline_string_escape_in_closing_line.kdl b/tests/test_cases/input/multiline_string_escape_in_closing_line.kdl new file mode 100644 index 0000000..23a5796 --- /dev/null +++ b/tests/test_cases/input/multiline_string_escape_in_closing_line.kdl @@ -0,0 +1,5 @@ +node """ + foo \ +bar + baz + \ """ diff --git a/tests/test_cases/input/multiline_string_escape_in_closing_line_shallow.kdl b/tests/test_cases/input/multiline_string_escape_in_closing_line_shallow.kdl new file mode 100644 index 0000000..fba22a4 --- /dev/null +++ b/tests/test_cases/input/multiline_string_escape_in_closing_line_shallow.kdl @@ -0,0 +1,5 @@ +node """ + foo \ +bar + baz +\ """ diff --git a/tests/test_cases/input/multiline_string_final_whitespace_escape_fail.kdl b/tests/test_cases/input/multiline_string_final_whitespace_escape_fail.kdl new file mode 100644 index 0000000..84310da --- /dev/null +++ b/tests/test_cases/input/multiline_string_final_whitespace_escape_fail.kdl @@ -0,0 +1,4 @@ +node """ + foo + bar\ + """ \ No newline at end of file diff --git a/tests/test_cases/input/multiline_string_non_matching_prefix_character_error.kdl b/tests/test_cases/input/multiline_string_non_matching_prefix_character_error_fail.kdl similarity index 100% rename from tests/test_cases/input/multiline_string_non_matching_prefix_character_error.kdl rename to tests/test_cases/input/multiline_string_non_matching_prefix_character_error_fail.kdl diff --git a/tests/test_cases/input/multiline_string_non_matching_prefix_count_error.kdl b/tests/test_cases/input/multiline_string_non_matching_prefix_count_error_fail.kdl similarity index 100% rename from tests/test_cases/input/multiline_string_non_matching_prefix_count_error.kdl rename to tests/test_cases/input/multiline_string_non_matching_prefix_count_error_fail.kdl diff --git a/tests/test_cases/input/multiline_string_single_line_err.kdl b/tests/test_cases/input/multiline_string_single_line_err_fail.kdl similarity index 100% rename from tests/test_cases/input/multiline_string_single_line_err.kdl rename to tests/test_cases/input/multiline_string_single_line_err_fail.kdl diff --git a/tests/test_cases/input/multiline_string_single_quote_err.kdl b/tests/test_cases/input/multiline_string_single_quote_err_fail.kdl similarity index 100% rename from tests/test_cases/input/multiline_string_single_quote_err.kdl rename to tests/test_cases/input/multiline_string_single_quote_err_fail.kdl diff --git a/tests/test_cases/input/multiline_string_whitespace_only.kdl b/tests/test_cases/input/multiline_string_whitespace_only.kdl new file mode 100644 index 0000000..db8fee5 --- /dev/null +++ b/tests/test_cases/input/multiline_string_whitespace_only.kdl @@ -0,0 +1,19 @@ +// This file deliberately contains unusual whitespace +// The first three strings are empty, because whitespace-only lines collapse to +// just `\n`. +node """ +  """ """ +   \ +     +   """ """ +     + """\ + \ // The next two strings contains only whitespace + """ +    +    +    \s +    """ #""" +      + + """# diff --git a/tests/test_cases/input/multiline_string_whitespace_only_non_matching_prefix_fail.kdl b/tests/test_cases/input/multiline_string_whitespace_only_non_matching_prefix_fail.kdl new file mode 100644 index 0000000..29e36df --- /dev/null +++ b/tests/test_cases/input/multiline_string_whitespace_only_non_matching_prefix_fail.kdl @@ -0,0 +1,19 @@ +// This file deliberately contains unusual whitespace +// Parsing should fail because not all strings have a matching multiline prefix, +// which must be exact, down to the codepoint, _before_ newline normalization. +node """ +  """ """ +   \ +    +   """ """ +    + """\ + \ // The next two strings contains only whitespace + """ +    + +    \s +    """ #""" +     + + """# diff --git a/tests/test_cases/input/multiple_dots_in_float_before_exponent.kdl b/tests/test_cases/input/multiple_dots_in_float_before_exponent_fail.kdl similarity index 100% rename from tests/test_cases/input/multiple_dots_in_float_before_exponent.kdl rename to tests/test_cases/input/multiple_dots_in_float_before_exponent_fail.kdl diff --git a/tests/test_cases/input/multiple_dots_in_float.kdl b/tests/test_cases/input/multiple_dots_in_float_fail.kdl similarity index 100% rename from tests/test_cases/input/multiple_dots_in_float.kdl rename to tests/test_cases/input/multiple_dots_in_float_fail.kdl diff --git a/tests/test_cases/input/multiple_es_in_float.kdl b/tests/test_cases/input/multiple_es_in_float_fail.kdl similarity index 100% rename from tests/test_cases/input/multiple_es_in_float.kdl rename to tests/test_cases/input/multiple_es_in_float_fail.kdl diff --git a/tests/test_cases/input/multiple_x_in_hex.kdl b/tests/test_cases/input/multiple_x_in_hex_fail.kdl similarity index 100% rename from tests/test_cases/input/multiple_x_in_hex.kdl rename to tests/test_cases/input/multiple_x_in_hex_fail.kdl diff --git a/tests/test_cases/input/no_digits_in_hex.kdl b/tests/test_cases/input/no_digits_in_hex_fail.kdl similarity index 100% rename from tests/test_cases/input/no_digits_in_hex.kdl rename to tests/test_cases/input/no_digits_in_hex_fail.kdl diff --git a/tests/test_cases/input/no_integer_digit.kdl b/tests/test_cases/input/no_integer_digit_fail.kdl similarity index 100% rename from tests/test_cases/input/no_integer_digit.kdl rename to tests/test_cases/input/no_integer_digit_fail.kdl diff --git a/tests/test_cases/input/no_solidus_escape.kdl b/tests/test_cases/input/no_solidus_escape_fail.kdl similarity index 100% rename from tests/test_cases/input/no_solidus_escape.kdl rename to tests/test_cases/input/no_solidus_escape_fail.kdl diff --git a/tests/test_cases/input/null_prop_key.kdl b/tests/test_cases/input/null_prop_key_fail.kdl similarity index 100% rename from tests/test_cases/input/null_prop_key.kdl rename to tests/test_cases/input/null_prop_key_fail.kdl diff --git a/tests/test_cases/input/parens_in_bare_id.kdl b/tests/test_cases/input/parens_in_bare_id_fail.kdl similarity index 100% rename from tests/test_cases/input/parens_in_bare_id.kdl rename to tests/test_cases/input/parens_in_bare_id_fail.kdl diff --git a/tests/test_cases/input/quote_in_bare_id.kdl b/tests/test_cases/input/quote_in_bare_id_fail.kdl similarity index 100% rename from tests/test_cases/input/quote_in_bare_id.kdl rename to tests/test_cases/input/quote_in_bare_id_fail.kdl diff --git a/tests/test_cases/input/raw_string_just_quote.kdl b/tests/test_cases/input/raw_string_just_quote.kdl deleted file mode 100644 index e81bf12..0000000 --- a/tests/test_cases/input/raw_string_just_quote.kdl +++ /dev/null @@ -1 +0,0 @@ -node #"""# diff --git a/tests/test_cases/input/raw_string_just_quote_fail.kdl b/tests/test_cases/input/raw_string_just_quote_fail.kdl new file mode 100644 index 0000000..c2ff2d3 --- /dev/null +++ b/tests/test_cases/input/raw_string_just_quote_fail.kdl @@ -0,0 +1,2 @@ +// This fails because `"""` MUST be followed by a newline. +node #"""# diff --git a/tests/test_cases/input/slash_in_bare_id.kdl b/tests/test_cases/input/slash_in_bare_id_fail.kdl similarity index 100% rename from tests/test_cases/input/slash_in_bare_id.kdl rename to tests/test_cases/input/slash_in_bare_id_fail.kdl diff --git a/tests/test_cases/input/slashdash_after_arg_type_fail.kdl b/tests/test_cases/input/slashdash_after_arg_type_fail.kdl new file mode 100644 index 0000000..edb9250 --- /dev/null +++ b/tests/test_cases/input/slashdash_after_arg_type_fail.kdl @@ -0,0 +1 @@ +node (ty)/-arg1 arg2 diff --git a/tests/test_cases/input/slashdash_after_node_type_fail.kdl b/tests/test_cases/input/slashdash_after_node_type_fail.kdl new file mode 100644 index 0000000..5a27bc3 --- /dev/null +++ b/tests/test_cases/input/slashdash_after_node_type_fail.kdl @@ -0,0 +1,2 @@ +(ty)/-node +other-node diff --git a/tests/test_cases/input/slashdash_after_prop_key_fail.kdl b/tests/test_cases/input/slashdash_after_prop_key_fail.kdl new file mode 100644 index 0000000..241e2e9 --- /dev/null +++ b/tests/test_cases/input/slashdash_after_prop_key_fail.kdl @@ -0,0 +1 @@ +node key /- = value diff --git a/tests/test_cases/input/slashdash_after_prop_val_type_fail.kdl b/tests/test_cases/input/slashdash_after_prop_val_type_fail.kdl new file mode 100644 index 0000000..d4a063e --- /dev/null +++ b/tests/test_cases/input/slashdash_after_prop_val_type_fail.kdl @@ -0,0 +1 @@ +node key=(ty)/-val other-arg diff --git a/tests/test_cases/input/slashdash_after_type_fail.kdl b/tests/test_cases/input/slashdash_after_type_fail.kdl new file mode 100644 index 0000000..32d8a82 --- /dev/null +++ b/tests/test_cases/input/slashdash_after_type_fail.kdl @@ -0,0 +1 @@ +node (type) /- arg1 arg2 diff --git a/tests/test_cases/input/slashdash_before_children_end_fail.kdl b/tests/test_cases/input/slashdash_before_children_end_fail.kdl new file mode 100644 index 0000000..83b97ae --- /dev/null +++ b/tests/test_cases/input/slashdash_before_children_end_fail.kdl @@ -0,0 +1,4 @@ +node { + child1 + /- +} diff --git a/tests/test_cases/input/slashdash_before_eof_fail.kdl b/tests/test_cases/input/slashdash_before_eof_fail.kdl new file mode 100644 index 0000000..694173f --- /dev/null +++ b/tests/test_cases/input/slashdash_before_eof_fail.kdl @@ -0,0 +1 @@ +node foo /- diff --git a/tests/test_cases/input/slashdash_before_prop_value_fail.kdl b/tests/test_cases/input/slashdash_before_prop_value_fail.kdl new file mode 100644 index 0000000..de727dc --- /dev/null +++ b/tests/test_cases/input/slashdash_before_prop_value_fail.kdl @@ -0,0 +1 @@ +node key = /-val etc diff --git a/tests/test_cases/input/slashdash_before_semicolon_fail.kdl b/tests/test_cases/input/slashdash_before_semicolon_fail.kdl new file mode 100644 index 0000000..8c57284 --- /dev/null +++ b/tests/test_cases/input/slashdash_before_semicolon_fail.kdl @@ -0,0 +1 @@ +node foo /-; diff --git a/tests/test_cases/input/slashdash_between_child_blocks_fail.kdl b/tests/test_cases/input/slashdash_between_child_blocks_fail.kdl new file mode 100644 index 0000000..8106b55 --- /dev/null +++ b/tests/test_cases/input/slashdash_between_child_blocks_fail.kdl @@ -0,0 +1 @@ +node { one } /- { two } { three } diff --git a/tests/test_cases/input/slashdash_child_block_before_entry_err.kdl b/tests/test_cases/input/slashdash_child_block_before_entry_err_fail.kdl similarity index 100% rename from tests/test_cases/input/slashdash_child_block_before_entry_err.kdl rename to tests/test_cases/input/slashdash_child_block_before_entry_err_fail.kdl diff --git a/tests/test_cases/input/slashdash_escline_before_arg_type.kdl b/tests/test_cases/input/slashdash_escline_before_arg_type.kdl new file mode 100644 index 0000000..93231ec --- /dev/null +++ b/tests/test_cases/input/slashdash_escline_before_arg_type.kdl @@ -0,0 +1,2 @@ +node /-\ +(ty)arg1 arg2 diff --git a/tests/test_cases/input/slashdash_escline_before_children.kdl b/tests/test_cases/input/slashdash_escline_before_children.kdl new file mode 100644 index 0000000..40a97ee --- /dev/null +++ b/tests/test_cases/input/slashdash_escline_before_children.kdl @@ -0,0 +1,3 @@ +node arg1 /-\ +{ +} diff --git a/tests/test_cases/input/slashdash_escline_before_node.kdl b/tests/test_cases/input/slashdash_escline_before_node.kdl new file mode 100644 index 0000000..f7f7937 --- /dev/null +++ b/tests/test_cases/input/slashdash_escline_before_node.kdl @@ -0,0 +1,3 @@ +/-\ +node1 +node2 diff --git a/tests/test_cases/input/slashdash_false_node.kdl b/tests/test_cases/input/slashdash_false_node.kdl new file mode 100644 index 0000000..5e38eb7 --- /dev/null +++ b/tests/test_cases/input/slashdash_false_node.kdl @@ -0,0 +1,2 @@ +node foo /- +not-a-node bar diff --git a/tests/test_cases/input/slashdash_inside_arg_type_fail.kdl b/tests/test_cases/input/slashdash_inside_arg_type_fail.kdl new file mode 100644 index 0000000..649bcca --- /dev/null +++ b/tests/test_cases/input/slashdash_inside_arg_type_fail.kdl @@ -0,0 +1 @@ +node (/-bad)nope diff --git a/tests/test_cases/input/slashdash_inside_node_type_fail.kdl b/tests/test_cases/input/slashdash_inside_node_type_fail.kdl new file mode 100644 index 0000000..3ed584c --- /dev/null +++ b/tests/test_cases/input/slashdash_inside_node_type_fail.kdl @@ -0,0 +1 @@ +(/-ty)node diff --git a/tests/test_cases/input/square_bracket_in_bare_id.kdl b/tests/test_cases/input/square_bracket_in_bare_id_fail.kdl similarity index 100% rename from tests/test_cases/input/square_bracket_in_bare_id.kdl rename to tests/test_cases/input/square_bracket_in_bare_id_fail.kdl diff --git a/tests/test_cases/input/true_prop_key.kdl b/tests/test_cases/input/true_prop_key_fail.kdl similarity index 100% rename from tests/test_cases/input/true_prop_key.kdl rename to tests/test_cases/input/true_prop_key_fail.kdl diff --git a/tests/test_cases/input/type_before_prop_key.kdl b/tests/test_cases/input/type_before_prop_key_fail.kdl similarity index 100% rename from tests/test_cases/input/type_before_prop_key.kdl rename to tests/test_cases/input/type_before_prop_key_fail.kdl diff --git a/tests/test_cases/input/unbalanced_raw_hashes.kdl b/tests/test_cases/input/unbalanced_raw_hashes_fail.kdl similarity index 100% rename from tests/test_cases/input/unbalanced_raw_hashes.kdl rename to tests/test_cases/input/unbalanced_raw_hashes_fail.kdl diff --git a/tests/test_cases/input/underscore_at_start_of_fraction.kdl b/tests/test_cases/input/underscore_at_start_of_fraction_fail.kdl similarity index 100% rename from tests/test_cases/input/underscore_at_start_of_fraction.kdl rename to tests/test_cases/input/underscore_at_start_of_fraction_fail.kdl diff --git a/tests/test_cases/input/underscore_at_start_of_hex.kdl b/tests/test_cases/input/underscore_at_start_of_hex_fail.kdl similarity index 100% rename from tests/test_cases/input/underscore_at_start_of_hex.kdl rename to tests/test_cases/input/underscore_at_start_of_hex_fail.kdl diff --git a/tests/test_cases/input/unicode_delete.kdl b/tests/test_cases/input/unicode_delete_fail.kdl similarity index 100% rename from tests/test_cases/input/unicode_delete.kdl rename to tests/test_cases/input/unicode_delete_fail.kdl diff --git a/tests/test_cases/input/unicode_fsi.kdl b/tests/test_cases/input/unicode_fsi_fail.kdl similarity index 100% rename from tests/test_cases/input/unicode_fsi.kdl rename to tests/test_cases/input/unicode_fsi_fail.kdl diff --git a/tests/test_cases/input/unicode_lre.kdl b/tests/test_cases/input/unicode_lre_fail.kdl similarity index 100% rename from tests/test_cases/input/unicode_lre.kdl rename to tests/test_cases/input/unicode_lre_fail.kdl diff --git a/tests/test_cases/input/unicode_lri.kdl b/tests/test_cases/input/unicode_lri_fail.kdl similarity index 100% rename from tests/test_cases/input/unicode_lri.kdl rename to tests/test_cases/input/unicode_lri_fail.kdl diff --git a/tests/test_cases/input/unicode_lrm.kdl b/tests/test_cases/input/unicode_lrm_fail.kdl similarity index 100% rename from tests/test_cases/input/unicode_lrm.kdl rename to tests/test_cases/input/unicode_lrm_fail.kdl diff --git a/tests/test_cases/input/unicode_lro.kdl b/tests/test_cases/input/unicode_lro_fail.kdl similarity index 100% rename from tests/test_cases/input/unicode_lro.kdl rename to tests/test_cases/input/unicode_lro_fail.kdl diff --git a/tests/test_cases/input/unicode_pdf.kdl b/tests/test_cases/input/unicode_pdf_fail.kdl similarity index 100% rename from tests/test_cases/input/unicode_pdf.kdl rename to tests/test_cases/input/unicode_pdf_fail.kdl diff --git a/tests/test_cases/input/unicode_pdi.kdl b/tests/test_cases/input/unicode_pdi_fail.kdl similarity index 100% rename from tests/test_cases/input/unicode_pdi.kdl rename to tests/test_cases/input/unicode_pdi_fail.kdl diff --git a/tests/test_cases/input/unicode_rle.kdl b/tests/test_cases/input/unicode_rle_fail.kdl similarity index 100% rename from tests/test_cases/input/unicode_rle.kdl rename to tests/test_cases/input/unicode_rle_fail.kdl diff --git a/tests/test_cases/input/unicode_rli.kdl b/tests/test_cases/input/unicode_rli_fail.kdl similarity index 100% rename from tests/test_cases/input/unicode_rli.kdl rename to tests/test_cases/input/unicode_rli_fail.kdl diff --git a/tests/test_cases/input/unicode_rlm.kdl b/tests/test_cases/input/unicode_rlm_fail.kdl similarity index 100% rename from tests/test_cases/input/unicode_rlm.kdl rename to tests/test_cases/input/unicode_rlm_fail.kdl diff --git a/tests/test_cases/input/unicode_rlo.kdl b/tests/test_cases/input/unicode_rlo_fail.kdl similarity index 100% rename from tests/test_cases/input/unicode_rlo.kdl rename to tests/test_cases/input/unicode_rlo_fail.kdl diff --git a/tests/test_cases/input/unicode_under_0x20.kdl b/tests/test_cases/input/unicode_under_0x20_fail.kdl similarity index 100% rename from tests/test_cases/input/unicode_under_0x20.kdl rename to tests/test_cases/input/unicode_under_0x20_fail.kdl diff --git a/tests/test_cases/input/unterminated_empty_node.kdl b/tests/test_cases/input/unterminated_empty_node_fail.kdl similarity index 100% rename from tests/test_cases/input/unterminated_empty_node.kdl rename to tests/test_cases/input/unterminated_empty_node_fail.kdl diff --git a/tests/test_cases/input/unusual_bare_id_chars_in_quoted_id.kdl b/tests/test_cases/input/unusual_bare_id_chars_in_quoted_id.kdl index d3262b8..56c85c6 100644 --- a/tests/test_cases/input/unusual_bare_id_chars_in_quoted_id.kdl +++ b/tests/test_cases/input/unusual_bare_id_chars_in_quoted_id.kdl @@ -1 +1 @@ -"foo123~!@$%^&*.:'|?+<>," weeee +"foo123~!@$%^&*.:'|?+<>,`-_" weeee diff --git a/tests/test_cases/input/unusual_chars_in_bare_id.kdl b/tests/test_cases/input/unusual_chars_in_bare_id.kdl index 8321632..ef66d22 100644 --- a/tests/test_cases/input/unusual_chars_in_bare_id.kdl +++ b/tests/test_cases/input/unusual_chars_in_bare_id.kdl @@ -1 +1 @@ -foo123~!@$%^&*.:'|?+<>, weeee +foo123~!@$%^&*.:'|?+<>,`-_ weeee diff --git a/tests/test_cases/input/zero_arg.kdl b/tests/test_cases/input/zero_arg.kdl deleted file mode 100644 index 74405b6..0000000 --- a/tests/test_cases/input/zero_arg.kdl +++ /dev/null @@ -1 +0,0 @@ -node 0