@@ -26,6 +26,12 @@ pub enum Node<'input> {
26
26
/// Boolean constant
27
27
Bool ( bool ) ,
28
28
29
+ /// String with embedded expressions (interpolated string, f-string).
30
+ ///
31
+ /// Literal parts represented by [`Node::Str`] node, interpolated parts
32
+ /// represented by any other nodes.
33
+ InterpolatedStr ( Vec < Node < ' input > > ) ,
34
+
29
35
/// Name of field of the type in which attribute expression is defined
30
36
Attr ( & ' input str ) ,
31
37
/// Built-in variable
@@ -486,6 +492,18 @@ peg::parser! {
486
492
rule quoted_oct( ) -> char = s: $( oct( ) +) { ? to_char( s, 8 ) } ;
487
493
rule quoted_hex( ) -> char = [ 'u' ] s: $( hex( ) * <4 >) { ? to_char( s, 16 ) } ;
488
494
495
+ /// String which interpolates expressions inside `{}`.
496
+ /// Defined as string literal prefixed with `f` character: `f"..."`
497
+ rule fstring( ) -> Vec <Node <' input>> = "f\" " e: fstring_element( ) * "\" " { e} ;
498
+ rule fstring_element( ) -> Node <' input>
499
+ // Interpolated expression inside of f-string (inside `{}`)
500
+ = "{" _ e: expr( ) _ "}" { e}
501
+ // Literal part of interpolated string
502
+ / v: ( fstring_ch( ) / escaped( ) ) + { Node :: Str ( String :: from_iter( v. into_iter( ) ) ) }
503
+ ;
504
+ /// Single non-escaped character in f-string
505
+ rule fstring_ch( ) -> char = [ ^ '"' | '\\' | '{' ] ;
506
+
489
507
rule integer( ) -> BigInt
490
508
= n: $( [ '1' ..='9' ] [ '0' ..='9' | '_' ] * ) { ? to_int( n, 10 ) }
491
509
/ "0" [ 'b' | 'B' ] n: $( bin( ) +) { ? to_int( n, 2 ) }
@@ -608,6 +626,7 @@ peg::parser! {
608
626
/ "[" _ l: list( ) ? _ "]" { Node :: List ( l. unwrap_or_default( ) ) }
609
627
/ "sizeof" _ "<" _ t: type_ref( ) _ ">" { Node :: SizeOf { type_: t, bit: false } }
610
628
/ "bitsizeof" _ "<" _ t: type_ref( ) _ ">" { Node :: SizeOf { type_: t, bit: true } }
629
+ / e: fstring( ) { Node :: InterpolatedStr ( e) }
611
630
/ v: ( s: string( ) _ { s} ) + { Node :: Str ( String :: from_iter( v. into_iter( ) ) ) }
612
631
/ n: special_name( ) !name_part( ) { n }
613
632
/ e: enum_name( ) { e }
@@ -1009,6 +1028,109 @@ mod parse {
1009
1028
}
1010
1029
}
1011
1030
1031
+ mod f_string {
1032
+ use super :: * ;
1033
+ use pretty_assertions:: assert_eq;
1034
+
1035
+ #[ test]
1036
+ fn empty ( ) {
1037
+ assert_eq ! ( parse_single( r#" f"" "# ) , Ok ( InterpolatedStr ( vec![ ] ) ) ) ;
1038
+ }
1039
+
1040
+ #[ test]
1041
+ fn literal ( ) {
1042
+ assert_eq ! ( parse_single( r#" f"\n\r\t 1\n\r\t 2\n\r\t " "# ) , Ok ( InterpolatedStr ( vec![
1043
+ Str ( "\n \r \t 1\n \r \t 2\n \r \t " . into( ) ) ,
1044
+ ] ) ) ) ;
1045
+ }
1046
+
1047
+ #[ test]
1048
+ fn literal_then_expr ( ) {
1049
+ assert_eq ! ( parse_single( r#" f"foo={123}" "# ) , Ok ( InterpolatedStr ( vec![
1050
+ Str ( "foo=" . into( ) ) ,
1051
+ Int ( 123 . into( ) ) ,
1052
+ ] ) ) ) ;
1053
+ }
1054
+
1055
+ #[ test]
1056
+ fn expr_then_literal ( ) {
1057
+ assert_eq ! ( parse_single( r#" f"{123}=abc" "# ) , Ok ( InterpolatedStr ( vec![
1058
+ Int ( 123 . into( ) ) ,
1059
+ Str ( "=abc" . into( ) ) ,
1060
+ ] ) ) ) ;
1061
+ }
1062
+
1063
+ #[ test]
1064
+ fn expr_then_expr ( ) {
1065
+ assert_eq ! ( parse_single( r#" f"{123}{abc}" "# ) , Ok ( InterpolatedStr ( vec![
1066
+ Int ( 123 . into( ) ) ,
1067
+ Attr ( "abc" . into( ) ) ,
1068
+ ] ) ) ) ;
1069
+ }
1070
+
1071
+ mod interpolated {
1072
+ use super :: * ;
1073
+ use pretty_assertions:: assert_eq;
1074
+
1075
+ #[ test]
1076
+ fn int_expr ( ) {
1077
+ assert_eq ! ( parse_single( r#" f"{123}" "# ) , Ok ( InterpolatedStr ( vec![
1078
+ Int ( 123 . into( ) ) ,
1079
+ ] ) ) ) ;
1080
+ }
1081
+
1082
+ #[ test]
1083
+ fn str_expr ( ) {
1084
+ assert_eq ! ( parse_single( r#" f"abc{"def"}ghi" "# ) , Ok ( InterpolatedStr ( vec![
1085
+ Str ( "abc" . into( ) ) ,
1086
+ Str ( "def" . into( ) ) ,
1087
+ Str ( "ghi" . into( ) ) ,
1088
+ ] ) ) ) ;
1089
+ }
1090
+
1091
+ #[ test]
1092
+ fn f_str_literal_expr ( ) {
1093
+ assert_eq ! ( parse_single( r#" f" { f"def" } " "# ) , Ok ( InterpolatedStr ( vec![
1094
+ Str ( " " . into( ) ) ,
1095
+ // f"def"
1096
+ InterpolatedStr ( vec![ Str ( "def" . into( ) ) ] ) ,
1097
+ Str ( " " . into( ) ) ,
1098
+ ] ) ) ) ;
1099
+ }
1100
+
1101
+ #[ test]
1102
+ fn f_str_expr_expr ( ) {
1103
+ assert_eq ! ( parse_single( r#" f" { f"{def}" } " "# ) , Ok ( InterpolatedStr ( vec![
1104
+ Str ( " " . into( ) ) ,
1105
+ // f"abc{def}"
1106
+ InterpolatedStr ( vec![ Attr ( "def" . into( ) ) ] ) ,
1107
+ Str ( " " . into( ) ) ,
1108
+ ] ) ) ) ;
1109
+ }
1110
+ }
1111
+
1112
+ #[ test]
1113
+ fn double_quote_in_literal ( ) {
1114
+ assert_eq ! ( parse_single( r#" f"this \" is a quote" "# ) , Ok ( InterpolatedStr ( vec![
1115
+ Str ( "this \" is a quote" . into( ) )
1116
+ ] ) ) ) ;
1117
+ }
1118
+
1119
+ #[ test]
1120
+ fn starts_with_quote ( ) {
1121
+ assert_eq ! ( parse_single( r#" f"\" is a quote" "# ) , Ok ( InterpolatedStr ( vec![
1122
+ Str ( "\" is a quote" . into( ) )
1123
+ ] ) ) ) ;
1124
+ }
1125
+
1126
+ #[ test]
1127
+ fn starts_with_space_quote ( ) {
1128
+ assert_eq ! ( parse_single( r#" f" \" is a quote" "# ) , Ok ( InterpolatedStr ( vec![
1129
+ Str ( " \" is a quote" . into( ) )
1130
+ ] ) ) ) ;
1131
+ }
1132
+ }
1133
+
1012
1134
mod expr {
1013
1135
use super :: * ;
1014
1136
use pretty_assertions:: assert_eq;
0 commit comments