Browse Source

Add tests for nested interpolation

Mads Møller Jensen 3 months ago
parent
commit
5bf7679636
2 changed files with 74 additions and 0 deletions
  1. 34 0
      numbat/src/parser.rs
  2. 40 0
      numbat/src/tokenizer.rs

+ 34 - 0
numbat/src/parser.rs

@@ -3425,6 +3425,40 @@ mod tests {
             ),
         );
 
+        parse_as_expression(
+            &["\"{\"foo\"}\""],
+            Expression::String(
+                Span::dummy(),
+                vec![StringPart::Interpolation {
+                    span: Span::dummy(),
+                    expr: Box::new(Expression::String(Span::dummy(), vec![StringPart::Fixed("foo".into())])),
+                    format_specifiers: None,
+                }],
+            ),
+        );
+
+        parse_as_expression(
+            &["\"{\"foo {\"bar\"}\"}\""],
+            Expression::String(
+                Span::dummy(),
+                vec![StringPart::Interpolation {
+                    span: Span::dummy(),
+                    expr: Box::new(Expression::String(
+                        Span::dummy(), 
+                        vec![
+                            StringPart::Fixed("foo ".into()),
+                            StringPart::Interpolation { 
+                                span: Span::dummy(), 
+                                expr: Box::new(Expression::String(Span::dummy(), vec![StringPart::Fixed("bar".into())])), 
+                                format_specifiers: None 
+                            }
+                        ]
+                    )),
+                    format_specifiers: None,
+                }],
+            ),
+        );
+
         should_fail_with(&["\"test {1"], ParseErrorKind::UnterminatedString);
         should_fail_with(
             &[

+ 40 - 0
numbat/src/tokenizer.rs

@@ -1198,6 +1198,30 @@ fn test_tokenize_string() {
         ]
     );
 
+    assert_eq!(
+        tokenize_reduced("\"foo = {\"foo\"}, and bar = {\"bar\"}\"").unwrap(),
+        [
+            ("\"foo = {", StringInterpolationStart, ByteIndex(0)),
+            ("\"foo\"", StringFixed, ByteIndex(8)),
+            ("}, and bar = {", StringInterpolationMiddle, ByteIndex(13)),
+            ("\"bar\"", StringFixed, ByteIndex(27)),
+            ("}\"", StringInterpolationEnd, ByteIndex(32)),
+            ("", Eof, ByteIndex(34))
+        ]
+    );
+
+    assert_eq!(
+        tokenize_reduced("\"foo = {\"foo, and bar = {\"bar\"}\"}\"").unwrap(),
+        [
+            ("\"foo = {", StringInterpolationStart, ByteIndex(0)),
+            ("\"foo, and bar = {", StringInterpolationStart, ByteIndex(8)),
+            ("\"bar\"", StringFixed, ByteIndex(25)),
+            ("}\"", StringInterpolationEnd, ByteIndex(30)),
+            ("}\"", StringInterpolationEnd, ByteIndex(32)),
+            ("", Eof, ByteIndex(34))
+        ]
+    );
+
     assert_eq!(
         tokenize("\"foo", 0).unwrap_err().kind,
         TokenizerErrorKind::UnterminatedString
@@ -1206,10 +1230,26 @@ fn test_tokenize_string() {
         tokenize("\"foo = {foo\"", 0).unwrap_err().kind,
         TokenizerErrorKind::UnterminatedStringInterpolation
     );
+    assert_eq!(
+        tokenize("\"foobar = {\"foo{\"bar\"}\"\"", 0).unwrap_err().kind,
+        TokenizerErrorKind::UnterminatedStringInterpolation
+    );
     assert_eq!(
         tokenize("\"foo = {foo}.", 0).unwrap_err().kind,
         TokenizerErrorKind::UnterminatedString
     );
+    assert_eq!(
+        tokenize("\"foo = {\"foo\"}.", 0).unwrap_err().kind,
+        TokenizerErrorKind::UnterminatedString
+    );
+    assert_eq!(
+        tokenize("\"foo = {\"foo}.\"", 0).unwrap_err().kind,
+        TokenizerErrorKind::UnterminatedString
+    );
+    assert_eq!(
+        tokenize("\"foobar = {\"foo{\"bar}\"}.\"", 0).unwrap_err().kind,
+        TokenizerErrorKind::UnterminatedString
+    );
 
     insta::assert_snapshot!(
         tokenize_reduced_pretty(r#""start \"inner\" end""#).unwrap(),