@@ -766,13 +766,13 @@ fn equals_sign(input: &mut Input<'_>) -> PResult<()> {
766
766
}
767
767
768
768
/// ```text
769
- /// quoted-string := '"' ( single-line-string-body | newline multi-line-string-body newline unicode-space*) '"'
769
+ /// quoted-string := '"' single-line-string-body '"' | '"""' newline multi-line-string-body newline unicode-space*) '"" "'
770
770
/// single-line-string-body := (string-character - newline)*
771
771
/// multi-line-string-body := string-character*
772
772
/// ```
773
773
fn quoted_string < ' s > ( input : & mut Input < ' s > ) -> PResult < Option < KdlValue > > {
774
- "\" " . parse_next ( input) ?;
775
- let is_multiline = opt ( newline ) . parse_next ( input ) ? . is_some ( ) ;
774
+ let quotes = alt ( ( ( "\" \" \" " , newline ) . take ( ) , " \" " ) ) . parse_next ( input) ?;
775
+ let is_multiline = quotes . len ( ) > 1 ;
776
776
let ml_prefix: Option < String > = if is_multiline {
777
777
Some (
778
778
peek ( preceded (
@@ -782,10 +782,13 @@ fn quoted_string<'s>(input: &mut Input<'s>) -> PResult<Option<KdlValue>> {
782
782
repeat ( 0 .., ( not ( newline) , opt ( ws_escape) , string_char) ) . map ( |( ) | ( ) ) ,
783
783
newline,
784
784
) ,
785
- peek ( terminated ( repeat ( 0 .., unicode_space) . map ( |( ) | ( ) ) , "\" " ) ) ,
785
+ peek ( terminated (
786
+ repeat ( 0 .., unicode_space) . map ( |( ) | ( ) ) ,
787
+ "\" \" \" " ,
788
+ ) ) ,
786
789
)
787
790
. map ( |( ( ) , ( ) ) | ( ) ) ,
788
- terminated ( repeat ( 0 .., unicode_space) . map ( |( ) | ( ) ) . take ( ) , "\" " ) ,
791
+ terminated ( repeat ( 0 .., unicode_space) . map ( |( ) | ( ) ) . take ( ) , "\" \" \" " ) ,
789
792
) )
790
793
. parse_next ( input) ?
791
794
. to_string ( ) ,
@@ -814,7 +817,7 @@ fn quoted_string<'s>(input: &mut Input<'s>) -> PResult<Option<KdlValue>> {
814
817
(
815
818
& prefix[ ..] ,
816
819
repeat ( 0 .., unicode_space) . map ( |( ) | ( ) ) . take ( ) ,
817
- peek ( "\" " ) ,
820
+ peek ( "\" \" \" " ) ,
818
821
) ,
819
822
)
820
823
. map ( |( s, _) : ( Vec < String > , ( _ , _ , _ ) ) | {
@@ -836,9 +839,12 @@ fn quoted_string<'s>(input: &mut Input<'s>) -> PResult<Option<KdlValue>> {
836
839
. resume_after ( quoted_string_badval)
837
840
. parse_next ( input) ?
838
841
} ;
839
- cut_err ( "\" " )
840
- . context ( lbl ( "closing quote" ) )
841
- . parse_next ( input) ?;
842
+ let closing_quotes = if is_multiline {
843
+ "\" \" \" " . context ( lbl ( "multiline string closing quotes" ) )
844
+ } else {
845
+ "\" " . context ( lbl ( "string closing quote" ) )
846
+ } ;
847
+ cut_err ( closing_quotes) . parse_next ( input) ?;
842
848
Ok ( body. map ( KdlValue :: String ) )
843
849
}
844
850
@@ -903,13 +909,15 @@ fn escaped_char(input: &mut Input<'_>) -> PResult<char> {
903
909
}
904
910
905
911
/// `raw-string := '#' raw-string-quotes '#' | '#' raw-string '#'`
906
- /// `raw-string-quotes := '"' ( single-line-raw-string-body | newline multi-line-raw-string-body newline unicode-space*) '"'`
912
+ /// `raw-string-quotes := '"' single-line-raw-string-body '"' | '"""' newline multi-line-raw-string-body newline unicode-space*) '"" "'`
907
913
/// `single-line-raw-string-body := (unicode - newline - disallowed-literal-code-points)*`
908
914
/// `multi-line-raw-string-body := (unicode - disallowed-literal-code-points)`
909
915
fn raw_string ( input : & mut Input < ' _ > ) -> PResult < Option < KdlValue > > {
910
916
let hashes: String = repeat ( 1 .., "#" ) . parse_next ( input) ?;
911
- "\" " . parse_next ( input) ?;
912
- let is_multiline = opt ( newline) . parse_next ( input) ?. is_some ( ) ;
917
+ let quotes = alt ( ( ( "\" \" \" " , newline) . take ( ) , "\" " ) ) . parse_next ( input) ?;
918
+ let is_multiline = quotes. len ( ) > 1 ;
919
+ dbg ! ( & quotes) ;
920
+ dbg ! ( is_multiline) ;
913
921
let ml_prefix: Option < String > = if is_multiline {
914
922
Some (
915
923
peek ( preceded (
@@ -921,7 +929,7 @@ fn raw_string(input: &mut Input<'_>) -> PResult<Option<KdlValue>> {
921
929
(
922
930
not ( newline) ,
923
931
not ( disallowed_unicode) ,
924
- not ( ( "\" " , & hashes[ ..] ) ) ,
932
+ not ( ( "\" \" \" " , & hashes[ ..] ) ) ,
925
933
any,
926
934
) ,
927
935
)
@@ -930,13 +938,13 @@ fn raw_string(input: &mut Input<'_>) -> PResult<Option<KdlValue>> {
930
938
) ,
931
939
peek ( terminated (
932
940
repeat ( 0 .., unicode_space) . map ( |( ) | ( ) ) ,
933
- ( "\" " , & hashes[ ..] ) ,
941
+ ( "\" \" \" " , & hashes[ ..] ) ,
934
942
) ) ,
935
943
)
936
944
. map ( |( ( ) , ( ) ) | ( ) ) ,
937
945
terminated (
938
946
repeat ( 0 .., unicode_space) . map ( |( ) | ( ) ) . take ( ) ,
939
- ( "\" " , & hashes[ ..] ) ,
947
+ ( "\" \" \" " , & hashes[ ..] ) ,
940
948
) ,
941
949
) )
942
950
. parse_next ( input) ?
@@ -945,6 +953,7 @@ fn raw_string(input: &mut Input<'_>) -> PResult<Option<KdlValue>> {
945
953
} else {
946
954
None
947
955
} ;
956
+ dbg ! ( & ml_prefix) ;
948
957
let body: Option < String > = if let Some ( prefix) = ml_prefix {
949
958
repeat_till (
950
959
0 ..,
@@ -955,7 +964,7 @@ fn raw_string(input: &mut Input<'_>) -> PResult<Option<KdlValue>> {
955
964
newline. take ( ) . map ( |_| "\n " . to_string ( ) ) ,
956
965
repeat_till (
957
966
0 ..,
958
- ( not ( newline) , not ( ( "\" " , & hashes[ ..] ) ) , any)
967
+ ( not ( newline) , not ( ( "\" \" \" " , & hashes[ ..] ) ) , any)
959
968
. map ( |( ( ) , ( ) , _) | ( ) )
960
969
. take ( ) ,
961
970
newline,
@@ -968,7 +977,7 @@ fn raw_string(input: &mut Input<'_>) -> PResult<Option<KdlValue>> {
968
977
(
969
978
& prefix[ ..] ,
970
979
repeat ( 0 .., unicode_space) . map ( |( ) | ( ) ) . take ( ) ,
971
- peek ( ( "\" " , & hashes[ ..] ) ) ,
980
+ peek ( ( "\" \" \" " , & hashes[ ..] ) ) ,
972
981
) ,
973
982
)
974
983
. map ( |( s, _) : ( Vec < String > , ( _ , _ , _ ) ) | {
@@ -996,9 +1005,12 @@ fn raw_string(input: &mut Input<'_>) -> PResult<Option<KdlValue>> {
996
1005
. resume_after ( raw_string_badval)
997
1006
. parse_next ( input) ?
998
1007
} ;
999
- cut_err ( ( "\" " , & hashes[ ..] ) )
1000
- . context ( lbl ( "closing quote" ) )
1001
- . parse_next ( input) ?;
1008
+ let closing_quotes = if is_multiline {
1009
+ "\" \" \" " . context ( lbl ( "multiline raw string closing quotes" ) )
1010
+ } else {
1011
+ "\" " . context ( lbl ( "raw string closing quotes" ) )
1012
+ } ;
1013
+ cut_err ( ( closing_quotes, & hashes[ ..] ) ) . parse_next ( input) ?;
1002
1014
Ok ( body. map ( KdlValue :: String ) )
1003
1015
}
1004
1016
@@ -1044,40 +1056,46 @@ mod string_tests {
1044
1056
#[ test]
1045
1057
fn multiline_quoted_string ( ) {
1046
1058
assert_eq ! (
1047
- string. parse( new_input( "\" \n foo\n bar\n baz\n \" " ) ) . unwrap( ) ,
1059
+ string
1060
+ . parse( new_input( "\" \" \" \n foo\n bar\n baz\n \" \" \" " ) )
1061
+ . unwrap( ) ,
1048
1062
Some ( KdlValue :: String ( "foo\n bar\n baz" . into( ) ) )
1049
1063
) ;
1050
1064
assert_eq ! (
1051
1065
string
1052
- . parse( new_input( "\" \n foo\n bar\n baz\n \" " ) )
1066
+ . parse( new_input( "\" \" \" \ n foo\n bar\n baz\n \" \" \" " ) )
1053
1067
. unwrap( ) ,
1054
1068
Some ( KdlValue :: String ( "foo\n bar\n baz" . into( ) ) )
1055
1069
) ;
1056
1070
assert_eq ! (
1057
- string. parse( new_input( "\" \n foo\r \n bar\n baz\n \" " ) ) . unwrap( ) ,
1071
+ string
1072
+ . parse( new_input( "\" \" \" \n foo\r \n bar\n baz\n \" \" \" " ) )
1073
+ . unwrap( ) ,
1058
1074
Some ( KdlValue :: String ( "foo\n bar\n baz" . into( ) ) )
1059
1075
) ;
1060
1076
assert_eq ! (
1061
1077
string
1062
- . parse( new_input( "\" \n foo\n bar\n baz\n \" " ) )
1078
+ . parse( new_input( "\" \" \" \ n foo\n bar\n baz\n \" \" \" " ) )
1063
1079
. unwrap( ) ,
1064
1080
Some ( KdlValue :: String ( "foo\n bar\n baz" . into( ) ) )
1065
1081
) ;
1066
1082
assert_eq ! (
1067
1083
string
1068
- . parse( new_input( "\" \n \\ foo\n \\ bar\n \\ baz\n \" " ) )
1084
+ . parse( new_input(
1085
+ "\" \" \" \n \\ foo\n \\ bar\n \\ baz\n \" \" \" "
1086
+ ) )
1069
1087
. unwrap( ) ,
1070
1088
Some ( KdlValue :: String ( "foo\n bar\n baz" . into( ) ) )
1071
1089
) ;
1072
1090
assert_eq ! (
1073
1091
string
1074
- . parse( new_input( "\" \n \n string\t \n \" " ) )
1092
+ . parse( new_input( "\" \" \" \ n\n string\t \n \" \" \" " ) )
1075
1093
. unwrap( ) ,
1076
1094
Some ( KdlValue :: String ( "\n string\t " . into( ) ) ) ,
1077
1095
"Empty line without any indentation"
1078
1096
) ;
1079
1097
assert ! ( string
1080
- . parse( new_input( "\" \n foo\n bar\n baz\n \" " ) )
1098
+ . parse( new_input( "\" \" \" \ n foo\n bar\n baz\n \" \" \" " ) )
1081
1099
. is_err( ) ) ;
1082
1100
}
1083
1101
@@ -1092,30 +1110,35 @@ mod string_tests {
1092
1110
#[ test]
1093
1111
fn multiline_raw_string ( ) {
1094
1112
assert_eq ! (
1095
- string. parse( new_input( "#\" \n foo\n bar\n baz\n \" #" ) ) . unwrap( ) ,
1113
+ string
1114
+ . parse( new_input( "#\" \" \" \n foo\n bar\n baz\n \" \" \" #" ) )
1115
+ . unwrap( ) ,
1096
1116
Some ( KdlValue :: String ( "foo\n bar\n baz" . into( ) ) )
1097
1117
) ;
1098
1118
assert_eq ! (
1099
1119
string
1100
- . parse( new_input( "#\" \n foo\r \n bar\n baz\n \" #" ) )
1120
+ . parse( new_input( "#\" \" \" \ n foo\r \n bar\n baz\n \" \" \" #" ) )
1101
1121
. unwrap( ) ,
1102
1122
Some ( KdlValue :: String ( "foo\n bar\n baz" . into( ) ) )
1103
1123
) ;
1104
1124
assert_eq ! (
1105
1125
string
1106
- . parse( new_input( "##\" \n foo\n bar\n baz\n \" ##" ) )
1126
+ . parse( new_input( "##\" \" \" \ n foo\n bar\n baz\n \" \" \" ##" ) )
1107
1127
. unwrap( ) ,
1108
1128
Some ( KdlValue :: String ( "foo\n bar\n baz" . into( ) ) )
1109
1129
) ;
1110
1130
assert_eq ! (
1111
1131
string
1112
- . parse( new_input( "#\" \n foo\n \\ nbar\n baz\n \" #" ) )
1132
+ . parse( new_input( "#\" \" \" \ n foo\n \\ nbar\n baz\n \" \" \" #" ) )
1113
1133
. unwrap( ) ,
1114
1134
Some ( KdlValue :: String ( "foo\n \\ nbar\n baz" . into( ) ) )
1115
1135
) ;
1116
1136
assert ! ( string
1117
- . parse( new_input( "#\" \n foo\n bar\n baz\n \" #" ) )
1137
+ . parse( new_input( "#\" \" \" \ n foo\n bar\n baz\n \" \" \" #" ) )
1118
1138
. is_err( ) ) ;
1139
+
1140
+ assert ! ( string. parse( new_input( "#\" \n foo\n bar\n baz\n \" #" ) ) . is_err( ) ) ;
1141
+ assert ! ( string. parse( new_input( "\" \n foo\n bar\n baz\n \" " ) ) . is_err( ) ) ;
1119
1142
}
1120
1143
1121
1144
#[ test]
0 commit comments