[mcs] Add support for interpolated quoted strings
authorMarek Safar <marek.safar@gmail.com>
Fri, 19 Jun 2015 16:35:38 +0000 (18:35 +0200)
committerMarek Safar <marek.safar@gmail.com>
Fri, 19 Jun 2015 16:37:58 +0000 (18:37 +0200)
mcs/mcs/cs-tokenizer.cs
mcs/tests/test-interpolation-06.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_5.xml

index 3641c6460a69a768b9c0e848471fb757ba395e4a..518e2c5ab8f6d659c4aa15361c6eb008b935d96f 100644 (file)
@@ -240,6 +240,7 @@ namespace Mono.CSharp
                public bool parsing_catch_when;
 
                int parsing_string_interpolation;
+               Stack<bool> parsing_string_interpolation_quoted;
 
                public bool parsing_interpolation_format;
 
@@ -410,6 +411,7 @@ namespace Mono.CSharp
                        public int current_token;
                        public object val;
                        public int parsing_string_interpolation;
+                       public Stack<bool> parsing_string_interpolation_quoted;
 
                        public Position (Tokenizer t)
                        {
@@ -428,9 +430,14 @@ namespace Mono.CSharp
                                        ifstack = new Stack<int> (clone);
                                }
                                parsing_generic_less_than = t.parsing_generic_less_than;
-                               parsing_string_interpolation = t.parsing_string_interpolation;
                                current_token = t.current_token;
                                val = t.val;
+                               parsing_string_interpolation = t.parsing_string_interpolation;
+                               if (t.parsing_string_interpolation_quoted != null && t.parsing_string_interpolation_quoted.Count != 0) {
+                                       var clone = t.parsing_string_interpolation_quoted.ToArray ();
+                                       Array.Reverse (clone);
+                                       parsing_string_interpolation_quoted = new Stack<bool> (clone);
+                               }
                        }
                }
 
@@ -474,6 +481,7 @@ namespace Mono.CSharp
                        ifstack = p.ifstack;
                        parsing_generic_less_than = p.parsing_generic_less_than;
                        parsing_string_interpolation = p.parsing_string_interpolation;
+                       parsing_string_interpolation_quoted = p.parsing_string_interpolation_quoted;
                        current_token = p.current_token;
                        val = p.val;
                }
@@ -3369,7 +3377,14 @@ namespace Mono.CSharp
                                case '}':
                                        if (parsing_string_interpolation > 0) {
                                                --parsing_string_interpolation;
-                                               return TokenizeInterpolatedString ();
+                                               bool quoted;
+                                               if (parsing_string_interpolation_quoted != null && parsing_string_interpolation_quoted.Count > 0) {
+                                                       quoted = parsing_string_interpolation_quoted.Pop ();
+                                               } else {
+                                                       quoted = false;
+                                               }
+
+                                               return TokenizeInterpolatedString (quoted);
                                        }
 
                                        val = ltb.Create (current_source, ref_line, col);
@@ -3791,9 +3806,18 @@ namespace Mono.CSharp
                                        return Token.ERROR;
 
                                case '$':
-                                       if (peek_char () == '"') {
+                                       switch (peek_char ()) {
+                                       case '"':
+                                               get_char ();
+                                               return TokenizeInterpolatedString (false);
+                                       case '@':
                                                get_char ();
-                                               return TokenizeInterpolatedString ();
+                                               if (peek_char () == '"') {
+                                                       get_char ();
+                                                       return TokenizeInterpolatedString (true);
+                                               }
+
+                                               break;
                                        }
 
                                        break;
@@ -3922,7 +3946,7 @@ namespace Mono.CSharp
                        return Token.OP_LT;
                }
 
-               int TokenizeInterpolatedString ()
+               int TokenizeInterpolatedString (bool quoted)
                {
                        int pos = 0;
                        var start_location = Location;
@@ -3931,6 +3955,11 @@ namespace Mono.CSharp
                                var ch = get_char ();
                                switch (ch) {
                                case '"':
+                                       if (quoted && peek_char () == '"') {
+                                               get_char ();
+                                               break;
+                                       }
+
                                        val = new StringLiteral (context.BuiltinTypes, CreateStringFromBuilder (pos), start_location);
                                        return Token.INTERPOLATED_STRING_END;
                                case '{':
@@ -3941,9 +3970,21 @@ namespace Mono.CSharp
                                        }
 
                                        ++parsing_string_interpolation;
+                                       if (quoted) {
+                                               if (parsing_string_interpolation_quoted == null)
+                                                       parsing_string_interpolation_quoted = new Stack<bool> ();
+                                       }
+
+                                       if (parsing_string_interpolation_quoted != null) {
+                                               parsing_string_interpolation_quoted.Push (quoted);
+                                       }
+
                                        val = new StringLiteral (context.BuiltinTypes, CreateStringFromBuilder (pos), start_location);
                                        return Token.INTERPOLATED_STRING;
                                case '\\':
+                                       if (quoted)
+                                               break;
+                                       
                                        ++col;
                                        int surrogate;
                                        ch = escape (ch, out surrogate);
diff --git a/mcs/tests/test-interpolation-06.cs b/mcs/tests/test-interpolation-06.cs
new file mode 100644 (file)
index 0000000..3341f8d
--- /dev/null
@@ -0,0 +1,20 @@
+class X
+{
+       public static int Main ()
+       {
+               int foo = 4;
+               string s = $@"{foo}";
+               if (s != "4")
+                       return 1;
+
+               string s2 = $@"c:\{foo}\temp";
+               if (s2 != "c:\\4\\temp")
+                       return 2;
+
+               string s3 = $@"""{foo}"" ""foo""";
+               if (s3 != "\"4\" \"foo\"")
+                       return 3;
+
+               return 0;
+       }
+}
\ No newline at end of file
index 7bc1d30af967950763f691ea722b9ad06e3cef66..2de0708289be108feb615798881ac07971938548 100644 (file)
       </method>
     </type>
   </test>
+  <test name="test-interpolation-06.cs">
+    <type name="X">
+      <method name="Int32 Main()" attrs="150">
+        <size>134</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="test-iter-01.cs">
     <type name="X">
       <method name="Int32 Main()" attrs="150">