Merge pull request #1245 from StephenMcConnel/bug-22483
[mono.git] / mcs / mcs / cs-tokenizer.cs
index 7fb9caa018a7a31ed8c7d2d5545a3952c13b940b..2147c145e6c74151380ea0962a61fc614b5f359f 100644 (file)
@@ -202,7 +202,6 @@ namespace Mono.CSharp
                bool handle_get_set = false;
                bool handle_remove_add = false;
                bool handle_where;
-               bool handle_typeof = false;
                bool lambda_arguments_parsing;
                List<Location> escaped_identifiers;
                int parsing_generic_less_than;
@@ -320,11 +319,6 @@ namespace Mono.CSharp
                        get { return handle_where; }
                        set { handle_where = value; }
                }
-
-               public bool TypeOfParsing {
-                       get { return handle_typeof; }
-                       set { handle_typeof = value; }
-               }
        
                public XmlCommentState doc_state {
                        get { return xml_doc_state; }
@@ -729,6 +723,7 @@ namespace Mono.CSharp
                                        case Token.BYTE:
                                        case Token.CHAR:
                                        case Token.DECIMAL:
+                                       case Token.DOUBLE:
                                        case Token.FLOAT:
                                        case Token.LONG:
                                        case Token.OBJECT:
@@ -934,7 +929,27 @@ namespace Mono.CSharp
                        if (c < 0x80)
                                return false;
 
-                       return Char.IsLetter (c) || Char.GetUnicodeCategory (c) == UnicodeCategory.ConnectorPunctuation;
+                       return is_identifier_part_character_slow_part (c);
+               }
+
+               static bool is_identifier_part_character_slow_part (char c)
+               {
+                       if (Char.IsLetter (c))
+                               return true;
+
+                       switch (Char.GetUnicodeCategory (c)) {
+                               case UnicodeCategory.ConnectorPunctuation:
+
+                               // combining-character: A Unicode character of classes Mn or Mc
+                               case UnicodeCategory.NonSpacingMark:
+                               case UnicodeCategory.SpacingCombiningMark:
+
+                               // decimal-digit-character: A Unicode character of the class Nd 
+                               case UnicodeCategory.DecimalDigitNumber:
+                               return true;
+                       }
+
+                       return false;
                }
 
                public static bool IsKeyword (string s)
@@ -1124,7 +1139,7 @@ namespace Mono.CSharp
                        return true;
                }
 
-               bool parse_less_than ()
+               bool parse_less_than (ref int genericDimension)
                {
                start:
                        int the_token = token ();
@@ -1161,10 +1176,23 @@ namespace Mono.CSharp
                        case Token.VOID:
                                break;
                        case Token.OP_GENERICS_GT:
+                               genericDimension = 1;
+                               return true;
                        case Token.IN:
                        case Token.OUT:
                                return true;
+                       case Token.COMMA:
+                               do {
+                                       ++genericDimension;
+                                       the_token = token ();
+                               } while (the_token == Token.COMMA);
 
+                               if (the_token == Token.OP_GENERICS_GT) {
+                                       ++genericDimension;
+                                       return true;
+                               }
+
+                               return false;
                        default:
                                return false;
                        }
@@ -1178,7 +1206,7 @@ namespace Mono.CSharp
                        else if (the_token == Token.INTERR_NULLABLE || the_token == Token.STAR)
                                goto again;
                        else if (the_token == Token.OP_GENERICS_LT) {
-                               if (!parse_less_than ())
+                               if (!parse_less_than (ref genericDimension))
                                        return false;
                                goto again;
                        } else if (the_token == Token.OPEN_BRACKET) {
@@ -1194,22 +1222,6 @@ namespace Mono.CSharp
                        return false;
                }
 
-               bool parse_generic_dimension (out int dimension)
-               {
-                       dimension = 1;
-
-               again:
-                       int the_token = token ();
-                       if (the_token == Token.OP_GENERICS_GT)
-                               return true;
-                       else if (the_token == Token.COMMA) {
-                               dimension++;
-                               goto again;
-                       }
-
-                       return false;
-               }
-               
                public int peek_token ()
                {
                        int the_token;
@@ -1240,13 +1252,8 @@ namespace Mono.CSharp
                                return Token.OP_COALESCING;
                        }
 
-                       switch (current_token) {
-                       case Token.CLOSE_PARENS:
-                       case Token.TRUE:
-                       case Token.FALSE:
-                       case Token.NULL:
-                       case Token.LITERAL:
-                               return Token.INTERR;
+                       if (d == '.') {
+                               return Token.INTERR_OPERATOR;
                        }
 
                        if (d != ' ') {
@@ -1259,7 +1266,15 @@ namespace Mono.CSharp
                        PushPosition ();
                        current_token = Token.NONE;
                        int next_token;
-                       switch (xtoken ()) {
+                       int parens = 0;
+                       int generics = 0;
+
+                       var nt = xtoken ();
+                       switch (nt) {
+                       case Token.DOT:
+                       case Token.OPEN_BRACKET_EXPR:
+                               next_token = Token.INTERR_OPERATOR;
+                               break;
                        case Token.LITERAL:
                        case Token.TRUE:
                        case Token.FALSE:
@@ -1279,7 +1294,21 @@ namespace Mono.CSharp
                        case Token.COLON:
                                next_token = Token.INTERR_NULLABLE;
                                break;
-                               
+
+                       case Token.OPEN_PARENS:
+                       case Token.OPEN_PARENS_CAST:
+                       case Token.OPEN_PARENS_LAMBDA:
+                               next_token = -1;
+                               ++parens;
+                               break;
+
+                       case Token.OP_GENERICS_LT:
+                       case Token.OP_GENERICS_LT_DECL:
+                       case Token.GENERIC_DIMENSION:
+                               next_token = -1;
+                               ++generics;
+                               break;
+
                        default:
                                next_token = -1;
                                break;
@@ -1290,21 +1319,36 @@ namespace Mono.CSharp
                                case Token.COMMA:
                                case Token.SEMICOLON:
                                case Token.OPEN_BRACE:
-                               case Token.CLOSE_PARENS:
                                case Token.IN:
                                        next_token = Token.INTERR_NULLABLE;
                                        break;
                                        
                                case Token.COLON:
                                        next_token = Token.INTERR;
-                                       break;                                                  
-                                       
+                                       break;
+
+                               case Token.OPEN_PARENS:
+                               case Token.OPEN_PARENS_CAST:
+                               case Token.OPEN_PARENS_LAMBDA:
+                                       ++parens;
+                                       goto default;
+
+                               case Token.CLOSE_PARENS:
+                                       --parens;
+                                       goto default;
+
+                               case Token.OP_GENERICS_LT:
+                               case Token.OP_GENERICS_LT_DECL:
+                               case Token.GENERIC_DIMENSION:
+                                       ++generics;
+                                       goto default;
+
                                default:
                                        int ntoken;
                                        int interrs = 1;
                                        int colons = 0;
                                        int braces = 0;
-                                       int parens = 0;
+                                       int brackets = 0;
                                        //
                                        // All shorcuts failed, do it hard way
                                        //
@@ -1321,10 +1365,35 @@ namespace Mono.CSharp
                                                case Token.CLOSE_BRACE:
                                                        --braces;
                                                        continue;
+                                               case Token.OP_GENERICS_LT:
+                                               case Token.OP_GENERICS_LT_DECL:
+                                               case Token.GENERIC_DIMENSION:
+                                                       ++generics;
+                                                       continue;
+                                               case Token.OPEN_BRACKET:
+                                               case Token.OPEN_BRACKET_EXPR:
+                                                       ++brackets;
+                                                       continue;
+                                               case Token.CLOSE_BRACKET:
+                                                       --brackets;
+                                                       continue;
                                                case Token.CLOSE_PARENS:
-                                                       if (parens > 0)
+                                                       if (parens > 0) {
                                                                --parens;
-                                                       continue;
+                                                               continue;
+                                                       }
+
+                                                       PopPosition ();
+                                                       return Token.INTERR_NULLABLE;
+
+                                               case Token.OP_GENERICS_GT:
+                                                       if (generics > 0) {
+                                                               --generics;
+                                                               continue;
+                                                       }
+
+                                                       PopPosition ();
+                                                       return Token.INTERR_NULLABLE;
                                                }
 
                                                if (braces != 0)
@@ -1335,6 +1404,14 @@ namespace Mono.CSharp
 
                                                if (parens != 0)
                                                        continue;
+
+                                               if (ntoken == Token.COMMA) {
+                                                       if (generics != 0 || brackets != 0)
+                                                               continue;
+
+                                                       PopPosition ();
+                                                       return Token.INTERR_NULLABLE;
+                                               }
                                                
                                                if (ntoken == Token.COLON) {
                                                        if (++colons == interrs)
@@ -3039,7 +3116,7 @@ namespace Mono.CSharp
 
                                                        continue;
                                                }
-                                       } else if (Char.IsLetter ((char) c) || Char.GetUnicodeCategory ((char) c) == UnicodeCategory.ConnectorPunctuation) {
+                                       } else if (is_identifier_part_character_slow_part ((char) c)) {
                                                id_builder [pos++] = (char) c;
                                                continue;
                                        }
@@ -3631,22 +3708,20 @@ namespace Mono.CSharp
                int TokenizeLessThan ()
                {
                        int d;
-                       if (handle_typeof) {
-                               PushPosition ();
-                               if (parse_generic_dimension (out d)) {
-                                       val = d;
-                                       DiscardPosition ();
-                                       return Token.GENERIC_DIMENSION;
-                               }
-                               PopPosition ();
-                       }
 
                        // Save current position and parse next token.
                        PushPosition ();
-                       if (parse_less_than ()) {
+                       int generic_dimension = 0;
+                       if (parse_less_than (ref generic_dimension)) {
                                if (parsing_generic_declaration && (parsing_generic_declaration_doc || token () != Token.DOT)) {
                                        d = Token.OP_GENERICS_LT_DECL;
                                } else {
+                                       if (generic_dimension > 0) {
+                                               val = generic_dimension;
+                                               DiscardPosition ();
+                                               return Token.GENERIC_DIMENSION;
+                                       }
+
                                        d = Token.OP_GENERICS_LT;
                                }
                                PopPosition ();