Fix #77035.
[mono.git] / mcs / mcs / cs-tokenizer.cs
index 46aa49aa591fed5e227209dc2342580b12b35310..83b92d2f9aa6dd9bab28880a8ea3aa241784e65e 100644 (file)
@@ -31,7 +31,7 @@ namespace Mono.CSharp
 
        public class Tokenizer : yyParser.yyInput
        {
-               StreamReader reader;
+               SeekableStreamReader reader;
                SourceFile ref_name;
                SourceFile file_name;
                int ref_line = 1;
@@ -45,8 +45,6 @@ namespace Mono.CSharp
                Location current_location;
                Location current_comment_location = Location.Null;
                ArrayList escapedIdentifiers = new ArrayList ();
-               SavedToken saved_token = SavedToken.Null;
-               bool putback_ambiguous_close_parens = false;
 
                //
                // XML documentation buffer. The save point is used to divide
@@ -387,7 +385,7 @@ namespace Mono.CSharp
                        defines [def] = true;
                }
                
-               public Tokenizer (StreamReader input, SourceFile file, ArrayList defs)
+               public Tokenizer (SeekableStreamReader input, SourceFile file, ArrayList defs)
                {
                        this.ref_name = file;
                        this.file_name = file;
@@ -469,11 +467,19 @@ namespace Mono.CSharp
 
                                --deambiguate_close_parens;
 
-                               // Save next token.
-                               Location cur_loc = current_location;
+                               // Save current position and parse next token.
+                               int old = reader.Position;
+                               int old_ref_line = ref_line;
+                               int old_col = col;
+
+                               // disable preprocessing directives when peeking
+                               process_directives = false;
                                int new_token = token ();
-                               saved_token = new SavedToken (new_token, val, Location);
-                               current_location = cur_loc;
+                               process_directives = true;
+                               reader.Position = old;
+                               ref_line = old_ref_line;
+                               col = old_col;
+                               putback_char = -1;
 
                                if (new_token == Token.OPEN_PARENS)
                                        return Token.CLOSE_PARENS_OPEN_PARENS;
@@ -652,7 +658,7 @@ namespace Mono.CSharp
 
                public void Deambiguate_CloseParens ()
                {
-                       putback_ambiguous_close_parens = true;
+                       putback (')');
                        deambiguate_close_parens++;
                }
 
@@ -737,7 +743,7 @@ namespace Mono.CSharp
                                                        // if we have not seen anything in between
                                                        // report this error
                                                        //
-                                                       Report.Warning (78, Location, "The 'l' suffix is easily confused with the digit '1' (use 'L' for clarity)");
+                                                       Report.Warning (78, 4, Location, "The 'l' suffix is easily confused with the digit '1' (use 'L' for clarity)");
                                                }
                                                //
                                                // This goto statement causes the MS CLR 2.0 beta 1 csc to report an error, so
@@ -829,6 +835,11 @@ namespace Mono.CSharp
                                val = 0ul;
                                return Token.LITERAL_INTEGER;
                        }
+                       catch (FormatException) {
+                               Report.Error (1013, Location, "Invalid number");
+                               val = 0ul;
+                               return Token.LITERAL_INTEGER;
+                       }
                }
                
                int adjust_real (int t)
@@ -1071,7 +1082,7 @@ namespace Mono.CSharp
                                        goto default;
                                return v;
                        default:
-                               Report.Error (1009, Location, "Unrecognized escape sequence `\\{0}'", (char)d);
+                               Report.Error (1009, Location, "Unrecognized escape sequence `\\{0}'", ((char)d).ToString ());
                                return d;
                        }
                        getChar ();
@@ -1081,10 +1092,6 @@ namespace Mono.CSharp
                int getChar ()
                {
                        int x;
-                       if (putback_ambiguous_close_parens) {
-                               putback_ambiguous_close_parens = false;
-                               return ')';
-                       }
                        if (putback_char != -1) {
                                x = putback_char;
                                putback_char = -1;
@@ -1104,8 +1111,6 @@ namespace Mono.CSharp
 
                int peekChar ()
                {
-                       if (putback_ambiguous_close_parens)
-                               return ')';
                        if (putback_char != -1)
                                return putback_char;
                        putback_char = reader.Read ();
@@ -1114,8 +1119,6 @@ namespace Mono.CSharp
 
                int peekChar2 ()
                {
-                       if (putback_ambiguous_close_parens)
-                               return ')';
                        if (putback_char != -1)
                                return putback_char;
                        return reader.Peek ();
@@ -1204,14 +1207,7 @@ namespace Mono.CSharp
 
                public int token ()
                 {
-                       if (!saved_token.Location.IsNull) {
-                               current_token = saved_token.Token;
-                               val = saved_token.Value;
-                               current_location = saved_token.Location;
-                               saved_token = SavedToken.Null;
-                       }
-                       else
-                               current_token = xtoken ();
+                       current_token = xtoken ();
                         return current_token;
                 }
 
@@ -1384,7 +1380,7 @@ namespace Mono.CSharp
                                Hashtable w_table = Report.warning_ignore_table;
                                foreach (int code in codes) {
                                        if (w_table != null && w_table.Contains (code))
-                                               Report.Warning (1635, 1, Location, "Cannot restore warning 'CS{0:0000}' because it was disabled globally", code);
+                                               Report.Warning (1635, 1, Location, String.Format ("Cannot restore warning `CS{0:0000}' because it was disabled globally", code));
                                        Report.RegisterWarningRegion (Location).WarningEnable (Location, code);
                                }
                                return;
@@ -1408,7 +1404,7 @@ namespace Mono.CSharp
                                        values[index++] = int.Parse (string_code, System.Globalization.CultureInfo.InvariantCulture);
                                }
                                catch (FormatException) {
-                                       Report.Warning (1692, Location, "Invalid number");
+                                       Report.Warning (1692, 1, Location, "Invalid number");
                                }
                        }
                        return values;
@@ -1796,7 +1792,7 @@ namespace Mono.CSharp
                                return true;
 
                        case "warning":
-                               Report.Warning (1030, Location, "#warning: `{0}'", arg);
+                               Report.Warning (1030, 1, Location, "#warning: `{0}'", arg);
                                return true;
                        }
 
@@ -1853,16 +1849,25 @@ namespace Mono.CSharp
                        }
 
                        if (res == Token.PARTIAL) {
-                               // Save next token.
-                               Location cur_loc = Location;
+                               // Save current position and parse next token.
+                               int old = reader.Position;
+                               int old_putback = putback_char;
+                               int old_ref_line = ref_line;
+                               int old_col = col;
+
+                               putback_char = -1;
+
                                int next_token = token ();
-                               saved_token = new SavedToken (next_token, val, Location);
-                               current_location = cur_loc;
                                bool ok = (next_token == Token.CLASS) ||
                                        (next_token == Token.STRUCT) ||
                                        (next_token == Token.INTERFACE) ||
                                        (next_token == Token.ENUM); // "partial" is a keyword in 'partial enum', even though it's not valid
 
+                               reader.Position = old;
+                               ref_line = old_ref_line;
+                               col = old_col;
+                               putback_char = old_putback;
+
                                if (ok)
                                        return res;
                                else {
@@ -1929,9 +1934,14 @@ namespace Mono.CSharp
                                identifiers [pos] = new CharArrayHashtable (pos);
 
                        val = new String (id_builder, 0, pos);
-                       if (RootContext.Version == LanguageVersion.ISO_1 && id_builder [0] == '_' && id_builder [1] == '_') {
-                               Report.Error (1638, Location, 
-                                       "`{0}': Any identifier with double underscores cannot be used when ISO language version mode is specified", val);
+                       if (RootContext.Version == LanguageVersion.ISO_1) {
+                               for (int i = 1; i < id_builder.Length; i += 3) {
+                                       if (id_builder [i] == '_' && (id_builder [i - 1] == '_' || id_builder [i + 1] == '_')) {
+                                               Report.Error (1638, Location, 
+                                                       "`{0}': Any identifier with double underscores cannot be used when ISO language version mode is specified", val.ToString ());
+                                               break;
+                                       }
+                               }
                        }
 
                        char [] chars = new char [pos];
@@ -2305,27 +2315,10 @@ namespace Mono.CSharp
                                if ((state & REGION) != 0)
                                        Report.Error (1038, Location, "#endregion directive expected");
                                else 
-                                       Report.Error (1027, "Expected `#endif' directive");
+                                       Report.Error (1027, Location, "Expected `#endif' directive");
                        }
                                
                }
-
-               public struct SavedToken
-               {
-                       public static readonly SavedToken Null =
-                               new SavedToken (0, null, Location.Null);
-
-                       public readonly int Token;
-                       public readonly object Value;
-                       public readonly Location Location;
-
-                       public SavedToken (int token, object value, Location loc)
-                       {
-                               Token = token;
-                               Value = value;
-                               Location = loc;
-                       }
-               }
        }
 
        //