Copying latest mcs to the branch.
[mono.git] / mcs / gmcs / cs-tokenizer.cs
index d7111584049c4bfc5f69caaa2ec8b52371f14463..8f9e3d89a17757e5239cdd2d1f92280df0eb81c1 100644 (file)
@@ -255,6 +255,55 @@ namespace Mono.CSharp
                        }
                }
 
+               //
+               // This is used when the tokenizer needs to save
+               // the current position as it needs to do some parsing
+               // on its own to deamiguate a token in behalf of the
+               // parser.
+               //
+               Stack position_stack = new Stack ();
+               class Position {
+                       public int position;
+                       public int ref_line;
+                       public int col;
+                       public int putback_char;
+                       public int previous_col;
+                       public int parsing_generic_less_than;
+                       
+                       public Position (Tokenizer t)
+                       {
+                               position = t.reader.Position;
+                               ref_line = t.ref_line;
+                               col = t.col;
+                               putback_char = t.putback_char;
+                               previous_col = t.previous_col;
+                               parsing_generic_less_than = t.parsing_generic_less_than;
+                       }
+               }
+               
+               public void PushPosition ()
+               {
+                       position_stack.Push (new Position (this));
+               }
+
+               public void PopPosition ()
+               {
+                       Position p = (Position) position_stack.Pop ();
+
+                       reader.Position = p.position;
+                       ref_line = p.ref_line;
+                       col = p.col;
+                       putback_char = p.putback_char;
+                       previous_col = p.previous_col;
+
+               }
+
+               // Do not reset the position, ignore it.
+               public void DiscardPosition ()
+               {
+                       position_stack.Pop ();
+               }
+               
                static void AddKeyword (string kw, int token) {
                        keywordStrings.Add (kw, kw);
                        if (keywords [kw.Length] == null) {
@@ -429,7 +478,7 @@ namespace Mono.CSharp
                        // FIXME: This could be `Location.Push' but we have to
                        // find out why the MS compiler allows this
                        //
-                       Mono.CSharp.Location.Push (file, 0);
+                       Mono.CSharp.Location.Push (file);
                }
 
                static bool is_identifier_start_character (char c)
@@ -482,6 +531,12 @@ namespace Mono.CSharp
                {
                start:
                        int the_token = token ();
+                       if (the_token == Token.OPEN_BRACKET) {
+                               do {
+                                       the_token = token ();
+                               } while (the_token != Token.CLOSE_BRACKET);
+                               the_token = token ();
+                       }
                        switch (the_token) {
                        case Token.IDENTIFIER:
                        case Token.OBJECT:
@@ -512,7 +567,7 @@ namespace Mono.CSharp
                                return true;
                        else if ((the_token == Token.COMMA) || (the_token == Token.DOT))
                                goto start;
-                       else if (the_token == Token.INTERR)
+                       else if (the_token == Token.INTERR || the_token == Token.STAR)
                                goto again;
                        else if (the_token == Token.OP_GENERICS_LT) {
                                if (!parse_less_than ())
@@ -562,16 +617,9 @@ namespace Mono.CSharp
 
                                --deambiguate_close_parens;
 
-                               // Save current position and parse next token.
-                               int old = reader.Position;
-                               int old_ref_line = ref_line;
-                               int old_col = col;
-
+                               PushPosition ();
                                int new_token = token ();
-                               reader.Position = old;
-                               ref_line = old_ref_line;
-                               col = old_col;
-                               putback_char = -1;
+                               PopPosition ();
 
                                if (new_token == Token.OPEN_PARENS)
                                        return Token.CLOSE_PARENS_OPEN_PARENS;
@@ -599,22 +647,21 @@ namespace Mono.CSharp
                                if (parsing_generic_less_than++ > 0)
                                        return Token.OP_GENERICS_LT;
 
-                               int old = reader.Position;
                                if (handle_typeof) {
                                        int dimension;
+                                       PushPosition ();
                                        if (parse_generic_dimension (out dimension)) {
                                                val = dimension;
+                                               DiscardPosition ();
                                                return Token.GENERIC_DIMENSION;
                                        }
-                                       reader.Position = old;
-                                       putback_char = -1;
+                                       PopPosition ();
                                }
 
                                // Save current position and parse next token.
-                               old = reader.Position;
+                               PushPosition ();
                                bool is_generic_lt = parse_less_than ();
-                               reader.Position = old;
-                               putback_char = -1;
+                               PopPosition ();
 
                                if (is_generic_lt) {
                                        parsing_generic_less_than++;
@@ -847,12 +894,12 @@ namespace Mono.CSharp
                        return seen_digits;
                }
 
-               bool is_hex (int e)
+               static bool is_hex (int e)
                {
                        return (e >= '0' && e <= '9') || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f');
                }
                                
-               int real_type_suffix (int c)
+               static int real_type_suffix (int c)
                {
                        int t;
 
@@ -894,7 +941,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
@@ -1009,7 +1056,7 @@ namespace Mono.CSharp
                                break;
                        case Token.LITERAL_FLOAT:
                                try {
-                                       val = (float) System.Double.Parse (s, styles, csharp_format_info);
+                                       val = float.Parse (s, styles, csharp_format_info);
                                } catch (OverflowException) {
                                        val = 0.0f;     
                                        Report.Error (594, Location, error_details, "float");
@@ -1233,7 +1280,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 ();
@@ -1246,8 +1293,7 @@ namespace Mono.CSharp
                        if (putback_char != -1) {
                                x = putback_char;
                                putback_char = -1;
-                       }
-                       else
+                       } else
                                x = reader.Read ();
                        if (x == '\n') {
                                line++;
@@ -1311,7 +1357,7 @@ namespace Mono.CSharp
                        return val;
                }
 
-               bool IsCastToken (int token)
+               static bool IsCastToken (int token)
                {
                        switch (token) {
                        case Token.BANG:
@@ -1432,13 +1478,13 @@ namespace Mono.CSharp
                //
                bool PreProcessLine (string arg)
                {
-                       if (arg == "")
+                       if (arg.Length == 0)
                                return false;
 
                        if (arg == "default"){
                                ref_line = line;
                                ref_name = file_name;
-                               Location.Push (ref_name, line);
+                               Location.Push (ref_name);
                                return true;
                        } else if (arg == "hidden"){
                                //
@@ -1460,7 +1506,7 @@ namespace Mono.CSharp
                                        ref_name = Location.LookupFile (name);
                                        file_name.HasLineDirective = true;
                                        ref_name.HasLineDirective = true;
-                                       Location.Push (ref_name, ref_line);
+                                       Location.Push (ref_name);
                                } else {
                                        ref_line = System.Int32.Parse (arg);
                                }
@@ -1476,7 +1522,7 @@ namespace Mono.CSharp
                //
                void PreProcessDefinition (bool is_define, string arg)
                {
-                       if (arg == "" || arg == "true" || arg == "false"){
+                       if (arg.Length == 0 || arg == "true" || arg == "false"){
                                Report.Error (1001, Location, "Missing identifer to pre-processor directive");
                                return;
                        }
@@ -1542,7 +1588,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;
@@ -1566,7 +1612,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;
@@ -1801,13 +1847,13 @@ namespace Mono.CSharp
                                goto case "endif";
                                
                        case "if":
-                               if (arg == ""){
+                               if (arg.Length == 0){
                                        Error_InvalidDirective ();
                                        return true;
                                }
                                bool taking = false;
                                if (ifstack == null)
-                                       ifstack = new Stack ();
+                                       ifstack = new Stack (2);
 
                                if (ifstack.Count == 0){
                                        taking = true;
@@ -1951,7 +1997,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;
                        }
 
@@ -2009,12 +2055,7 @@ namespace Mono.CSharp
 
                        if (res == Token.PARTIAL) {
                                // 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;
+                               PushPosition ();
 
                                int next_token = token ();
                                bool ok = (next_token == Token.CLASS) ||
@@ -2022,10 +2063,7 @@ namespace Mono.CSharp
                                        (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;
+                               PopPosition ();
 
                                if (ok)
                                        return res;
@@ -2048,6 +2086,7 @@ namespace Mono.CSharp
                        current_location = new Location (ref_line, Col);
 
                        while ((c = getChar ()) != -1) {
+                       loop:
                                if (is_identifier_part_character ((char) c)){
                                        if (pos == max_id_size){
                                                Report.Error (645, Location, "Identifier too long (limit is 512 chars)");
@@ -2056,6 +2095,9 @@ namespace Mono.CSharp
                                        
                                        id_builder [pos++] = (char) c;
 //                                     putback_char = -1;
+                               } else if (c == '\\') {
+                                       c = escape (c);
+                                       goto loop;
                                } else {
 //                                     putback_char = c;
                                        putback (c);
@@ -2097,7 +2139,7 @@ namespace Mono.CSharp
                                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);
+                                                       "`{0}': Any identifier with double underscores cannot be used when ISO language version mode is specified", val.ToString ());
                                                break;
                                        }
                                }
@@ -2291,9 +2333,9 @@ namespace Mono.CSharp
                        if (c == -1)
                                return Token.EOF;
 
-                       if (is_identifier_start_character ((char)c)){
+                       if (c == '\\' || is_identifier_start_character ((char)c)){
                                tokens_seen = true;
-                                       return consume_identifier (c);
+                               return consume_identifier (c);
                        }
 
                        current_location = new Location (ref_line, Col);
@@ -2494,7 +2536,7 @@ 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");
                        }
                                
                }