Merge pull request #498 from Unroll-Me/master
[mono.git] / mcs / mcs / cs-tokenizer.cs
index 4ec1bd9088113a4e25841ef29a188fa2c2773277..189bdea6f55fb10a4a461ae39811604c18e8aefa 100644 (file)
@@ -69,13 +69,14 @@ namespace Mono.CSharp
                }
 
                //
-               // This class has to be used in the parser only, it reuses token
-               // details after each parse
+               // This class has to be used by parser only, it reuses token
+               // details after each file parse completion
                //
                public class LocatedToken
                {
                        public int row, column;
                        public string value;
+                       public SourceFile file;
 
                        public LocatedToken ()
                        {
@@ -84,6 +85,7 @@ namespace Mono.CSharp
                        public LocatedToken (string value, Location loc)
                        {
                                this.value = value;
+                               file = loc.SourceFile;
                                row = loc.Row;
                                column = loc.Column;
                        }
@@ -94,7 +96,7 @@ namespace Mono.CSharp
                        }
                        
                        public Location Location {
-                               get { return new Location (row, column); }
+                               get { return new Location (file, row, column); }
                        }
 
                        public string Value {
@@ -117,17 +119,12 @@ namespace Mono.CSharp
                                this.buffer = buffer ?? new LocatedToken[0];
                        }
 
-                       public LocatedToken Create (int row, int column)
+                       public LocatedToken Create (SourceFile file, int row, int column)
                        {
-                               return Create (null, row, column);
+                               return Create (null, file, row, column);
                        }
 
-                       public LocatedToken Create (string value, Location loc)
-                       {
-                               return Create (value, loc.Row, loc.Column);
-                       }
-
-                       public LocatedToken Create (string value, int row, int column)
+                       public LocatedToken Create (string value, SourceFile file, int row, int column)
                        {
                                //
                                // TODO: I am not very happy about the logic but it's the best
@@ -150,6 +147,7 @@ namespace Mono.CSharp
                                        ++pos;
                                }
                                entry.value = value;
+                               entry.file = file;
                                entry.row = row;
                                entry.column = column;
                                return entry;
@@ -159,9 +157,9 @@ namespace Mono.CSharp
                        // Used for token not required by expression evaluator
                        //
                        [Conditional ("FULL_AST")]
-                       public void CreateOptional (int row, int col, ref object token)
+                       public void CreateOptional (SourceFile file, int row, int col, ref object token)
                        {
-                               token = Create (row, col);
+                               token = Create (file, row, col);
                        }
                }
 
@@ -446,8 +444,6 @@ namespace Mono.CSharp
                        doc_processing = context.Settings.DocumentationFile != null;
 
                        tab_size = context.Settings.TabSize;
-
-                       Mono.CSharp.Location.Push (current_source);
                }
                
                public void PushPosition ()
@@ -831,11 +827,13 @@ namespace Mono.CSharp
                                                PushPosition ();
                                                xtoken ();
                                                if (xtoken () != Token.ARROW)
-                                                       res = -1;
+                                                       goto default;
 
                                                PopPosition ();
                                                break;
                                        default:
+                                               // peek_token could overwrite id_buffer
+                                               id_builder [0] = 'a'; id_builder [1] = 's'; id_builder [2] = 'y'; id_builder [3] = 'n'; id_builder [4] = 'c';
                                                res = -1;
                                                break;
                                        }
@@ -894,7 +892,7 @@ namespace Mono.CSharp
 
                public Location Location {
                        get {
-                               return new Location (ref_line, col);
+                               return new Location (current_source, ref_line, col);
                        }
                }
 
@@ -1107,9 +1105,14 @@ namespace Mono.CSharp
                start:
                        int the_token = token ();
                        if (the_token == Token.OPEN_BRACKET) {
-                               do {
+                               while (true) {
                                        the_token = token ();
-                               } while (the_token != Token.CLOSE_BRACKET);
+                                       if (the_token == Token.EOF)
+                                               return true;
+
+                                       if (the_token == Token.CLOSE_BRACKET)
+                                               break;
+                               }
                                the_token = token ();
                        } else if (the_token == Token.IN || the_token == Token.OUT) {
                                the_token = token ();
@@ -1248,6 +1251,7 @@ namespace Mono.CSharp
                        case Token.OPEN_BRACKET:
                        case Token.OP_GENERICS_GT:
                        case Token.INTERR:
+                       case Token.OP_COALESCING:
                                next_token = Token.INTERR_NULLABLE;
                                break;
                                
@@ -1980,7 +1984,6 @@ namespace Mono.CSharp
                                }
 
                                ref_line = line;
-                               Location.Push (current_source);
                                return true;
                        }
 
@@ -2067,7 +2070,6 @@ namespace Mono.CSharp
                        if (new_file_name != null) {
                                current_source = context.LookupFile (source_file, new_file_name);
                                source_file.AddIncludeFile (current_source);
-                               Location.Push (current_source);
                        }
 
                        if (!hidden_block_start.IsNull) {
@@ -2420,6 +2422,11 @@ namespace Mono.CSharp
                                }
 
                                Report.Warning (1634, 1, Location, "Expected disable or restore");
+
+                               // Eat any remaining characters on the line
+                               while (c != '\n' && c != -1)
+                                       c = get_char ();
+
                                return;
                        }
 
@@ -2857,8 +2864,17 @@ namespace Mono.CSharp
 #endif
 
                        while (true){
-                               c = get_char ();
+                               // Cannot use get_char because of \r in quoted strings
+                               if (putback_char != -1) {
+                                       c = putback_char;
+                                       putback_char = -1;
+                               } else {
+                                       c = reader.Read ();
+                               }
+
                                if (c == '"') {
+                                       ++col;
+
                                        if (quoted && peek_char () == '"') {
                                                if (pos == value_builder.Length)
                                                        Array.Resize (ref value_builder, pos * 2);
@@ -2890,9 +2906,18 @@ namespace Mono.CSharp
                                if (c == '\n') {
                                        if (!quoted) {
                                                Report.Error (1010, Location, "Newline in constant");
+
+                                               advance_line ();
+
+                                               // Don't add \r to string literal
+                                               if (pos > 1 && value_builder [pos - 1] == '\r')
+                                                       --pos;
+
                                                val = new StringLiteral (context.BuiltinTypes, new string (value_builder, 0, pos), start_location);
                                                return Token.LITERAL;
                                        }
+
+                                       advance_line ();
                                } else if (c == '\\' && !quoted) {
                                        int surrogate;
                                        c = escape (c, out surrogate);
@@ -2908,6 +2933,8 @@ namespace Mono.CSharp
                                } else if (c == -1) {
                                        Report.Error (1039, Location, "Unterminated string literal");
                                        return Token.EOF;
+                               } else {
+                                       ++col;
                                }
 
                                if (pos == value_builder.Length)
@@ -2995,13 +3022,13 @@ namespace Mono.CSharp
                        if (id_builder [0] >= '_' && !quoted) {
                                int keyword = GetKeyword (id_builder, pos);
                                if (keyword != -1) {
-                                       val = ltb.Create (keyword == Token.AWAIT ? "await" : null, ref_line, column);
+                                       val = ltb.Create (keyword == Token.AWAIT ? "await" : null, current_source, ref_line, column);
                                        return keyword;
                                }
                        }
 
                        string s = InternIdentifier (id_builder, pos);
-                       val = ltb.Create (s, ref_line, column);
+                       val = ltb.Create (s, current_source, ref_line, column);
                        if (quoted && parsing_attribute_section)
                                AddEscapedIdentifier (((LocatedToken) val).Location);
 
@@ -3072,17 +3099,17 @@ namespace Mono.CSharp
                                        return consume_identifier (c);
 
                                case '{':
-                                       val = ltb.Create (ref_line, col);
+                                       val = ltb.Create (current_source, ref_line, col);
                                        return Token.OPEN_BRACE;
                                case '}':
-                                       val = ltb.Create (ref_line, col);
+                                       val = ltb.Create (current_source, ref_line, col);
                                        return Token.CLOSE_BRACE;
                                case '[':
                                        // To block doccomment inside attribute declaration.
                                        if (doc_state == XmlCommentState.Allowed)
                                                doc_state = XmlCommentState.NotAllowed;
 
-                                       val = ltb.Create (ref_line, col);
+                                       val = ltb.Create (current_source, ref_line, col);
 
                                        if (parsing_block == 0 || lambda_arguments_parsing)
                                                return Token.OPEN_BRACKET;
@@ -3108,10 +3135,10 @@ namespace Mono.CSharp
                                                return Token.OPEN_BRACKET_EXPR;
                                        }
                                case ']':
-                                       ltb.CreateOptional (ref_line, col, ref val);
+                                       ltb.CreateOptional (current_source, ref_line, col, ref val);
                                        return Token.CLOSE_BRACKET;
                                case '(':
-                                       val = ltb.Create (ref_line, col);
+                                       val = ltb.Create (current_source, ref_line, col);
                                        //
                                        // An expression versions of parens can appear in block context only
                                        //
@@ -3156,29 +3183,29 @@ namespace Mono.CSharp
 
                                        return Token.OPEN_PARENS;
                                case ')':
-                                       ltb.CreateOptional (ref_line, col, ref val);
+                                       ltb.CreateOptional (current_source, ref_line, col, ref val);
                                        return Token.CLOSE_PARENS;
                                case ',':
-                                       ltb.CreateOptional (ref_line, col, ref val);
+                                       ltb.CreateOptional (current_source, ref_line, col, ref val);
                                        return Token.COMMA;
                                case ';':
-                                       ltb.CreateOptional (ref_line, col, ref val);
+                                       ltb.CreateOptional (current_source, ref_line, col, ref val);
                                        return Token.SEMICOLON;
                                case '~':
-                                       val = ltb.Create (ref_line, col);
+                                       val = ltb.Create (current_source, ref_line, col);
                                        return Token.TILDE;
                                case '?':
-                                       val = ltb.Create (ref_line, col);
+                                       val = ltb.Create (current_source, ref_line, col);
                                        return TokenizePossibleNullableType ();
                                case '<':
-                                       val = ltb.Create (ref_line, col);
+                                       val = ltb.Create (current_source, ref_line, col);
                                        if (parsing_generic_less_than++ > 0)
                                                return Token.OP_GENERICS_LT;
 
                                        return TokenizeLessThan ();
 
                                case '>':
-                                       val = ltb.Create (ref_line, col);
+                                       val = ltb.Create (current_source, ref_line, col);
                                        d = peek_char ();
 
                                        if (d == '='){
@@ -3205,7 +3232,7 @@ namespace Mono.CSharp
                                        return Token.OP_GT;
 
                                case '+':
-                                       val = ltb.Create (ref_line, col);
+                                       val = ltb.Create (current_source, ref_line, col);
                                        d = peek_char ();
                                        if (d == '+') {
                                                d = Token.OP_INC;
@@ -3218,7 +3245,7 @@ namespace Mono.CSharp
                                        return d;
 
                                case '-':
-                                       val = ltb.Create (ref_line, col);
+                                       val = ltb.Create (current_source, ref_line, col);
                                        d = peek_char ();
                                        if (d == '-') {
                                                d = Token.OP_DEC;
@@ -3233,7 +3260,7 @@ namespace Mono.CSharp
                                        return d;
 
                                case '!':
-                                       val = ltb.Create (ref_line, col);
+                                       val = ltb.Create (current_source, ref_line, col);
                                        if (peek_char () == '='){
                                                get_char ();
                                                return Token.OP_NE;
@@ -3241,7 +3268,7 @@ namespace Mono.CSharp
                                        return Token.BANG;
 
                                case '=':
-                                       val = ltb.Create (ref_line, col);
+                                       val = ltb.Create (current_source, ref_line, col);
                                        d = peek_char ();
                                        if (d == '='){
                                                get_char ();
@@ -3255,7 +3282,7 @@ namespace Mono.CSharp
                                        return Token.ASSIGN;
 
                                case '&':
-                                       val = ltb.Create (ref_line, col);
+                                       val = ltb.Create (current_source, ref_line, col);
                                        d = peek_char ();
                                        if (d == '&'){
                                                get_char ();
@@ -3268,7 +3295,7 @@ namespace Mono.CSharp
                                        return Token.BITWISE_AND;
 
                                case '|':
-                                       val = ltb.Create (ref_line, col);
+                                       val = ltb.Create (current_source, ref_line, col);
                                        d = peek_char ();
                                        if (d == '|'){
                                                get_char ();
@@ -3281,7 +3308,7 @@ namespace Mono.CSharp
                                        return Token.BITWISE_OR;
 
                                case '*':
-                                       val = ltb.Create (ref_line, col);
+                                       val = ltb.Create (current_source, ref_line, col);
                                        if (peek_char () == '='){
                                                get_char ();
                                                return Token.OP_MULT_ASSIGN;
@@ -3291,7 +3318,7 @@ namespace Mono.CSharp
                                case '/':
                                        d = peek_char ();
                                        if (d == '='){
-                                               val = ltb.Create (ref_line, col);
+                                               val = ltb.Create (current_source, ref_line, col);
                                                get_char ();
                                                return Token.OP_DIV_ASSIGN;
                                        }
@@ -3370,11 +3397,11 @@ namespace Mono.CSharp
                                                        update_formatted_doc_comment (current_comment_start);
                                                continue;
                                        }
-                                       val = ltb.Create (ref_line, col);
+                                       val = ltb.Create (current_source, ref_line, col);
                                        return Token.DIV;
 
                                case '%':
-                                       val = ltb.Create (ref_line, col);
+                                       val = ltb.Create (current_source, ref_line, col);
                                        if (peek_char () == '='){
                                                get_char ();
                                                return Token.OP_MOD_ASSIGN;
@@ -3382,7 +3409,7 @@ namespace Mono.CSharp
                                        return Token.PERCENT;
 
                                case '^':
-                                       val = ltb.Create (ref_line, col);
+                                       val = ltb.Create (current_source, ref_line, col);
                                        if (peek_char () == '='){
                                                get_char ();
                                                return Token.OP_XOR_ASSIGN;
@@ -3390,7 +3417,7 @@ namespace Mono.CSharp
                                        return Token.CARRET;
 
                                case ':':
-                                       val = ltb.Create (ref_line, col);
+                                       val = ltb.Create (current_source, ref_line, col);
                                        if (peek_char () == ':') {
                                                get_char ();
                                                return Token.DOUBLE_COLON;
@@ -3414,7 +3441,7 @@ namespace Mono.CSharp
                                        if (d >= '0' && d <= '9')
                                                return is_number (c);
 
-                                       ltb.CreateOptional (ref_line, col, ref val);
+                                       ltb.CreateOptional (current_source, ref_line, col, ref val);
                                        return Token.DOT;
                                
                                case '#':