2006-08-17 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / mbas / mb-tokenizer.cs
index 612f8a04f3c422e3de5c6a0ad8dc6b51408aa478..f1f2c267e5595615f0e5d8618cfde863ed3e3dce 100644 (file)
@@ -2,7 +2,7 @@
 // Mono.MonoBASIC.Tokenizer.cs: The Tokenizer for the MonoBASIC compiler
 //
 // Author: A Rafael D Teixeira (rafaelteixeirabr@hotmail.com)
-//        
+//      : Manjula GHM (mmanjula@novell.com)  
 // Based on cs-tokenizer.cs by Miguel de Icaza (miguel@gnu.org)
 //
 // Licensed under the terms of the GNU GPL
@@ -33,6 +33,7 @@ namespace Mono.MonoBASIC
                int line = 0;
                int col = 1;
                public int current_token = Token.ERROR;
+               public int last_token = Token.ERROR;
                bool handle_get_set = false;
                bool cant_have_a_type_character = false;
 
@@ -76,6 +77,7 @@ namespace Mono.MonoBASIC
                StringBuilder number;
                int putback_char = -1;
                Object val;
+               long lon = 0;
                
                //
                // Details about the error encoutered by the tokenizer
@@ -210,7 +212,7 @@ namespace Mono.MonoBASIC
                        keywords.Add ("is", Token.IS);
                        keywords.Add ("let ", Token.LET ); // An unused VB.NET keyword
                        keywords.Add ("lib ", Token.LIB );
-                       keywords.Add ("like ", Token.LIKE );
+                       keywords.Add ("like", Token.LIKE );
                        keywords.Add ("long", Token.LONG);
                        keywords.Add ("loop", Token.LOOP);
                        keywords.Add ("me", Token.ME);
@@ -498,7 +500,6 @@ namespace Mono.MonoBASIC
                        
                        if (c != -1)
                                number.Append ((char) c);
-                       
                        while ((d = peekChar ()) != -1){
                                if (Char.IsDigit ((char)d)){
                                        number.Append ((char) d);
@@ -541,7 +542,16 @@ namespace Mono.MonoBASIC
                                switch (c){
                                case 'S': case 's':
                                        t =  Token.LITERAL_INTEGER; // SHORT ?
-                                       val = ((IConvertible)val).ToInt16(null);
+                       
+                               // hexadecimal literals - like &H8000S is "-32768" 
+                               // and not an overflow exception 
+                               // Check for other literals ???
+
+                                       if(lon == 32768) {
+                                                val = (short) lon;
+                                       }
+                                       else 
+                                               val = ((IConvertible)val).ToInt16(null);
                                        break;
                                case 'I': case 'i':
                                        t = Token.LITERAL_INTEGER;
@@ -615,7 +625,8 @@ namespace Mono.MonoBASIC
                                } else
                                        break;
                        }
-                       return System.Int64.Parse (hexNumber.ToString(), NumberStyles.HexNumber);
+                       lon = System.Int64.Parse (hexNumber.ToString(), NumberStyles.HexNumber);
+                       return lon;
                }
 
                long octal_digits ()
@@ -662,12 +673,14 @@ namespace Mono.MonoBASIC
                        bool is_real = false;
                        number = new StringBuilder ();
                        int type;
+                       bool non_prefixdecimal = false; //To capture decimals like .50
 
                        number.Length = 0;
 
                        if (Char.IsDigit ((char)c)){
                                decimal_digits (c);
-                               c = peekChar ();
+                               c = peekChar ();        
+                               non_prefixdecimal = true;
                        }
 
                        //
@@ -675,6 +688,8 @@ namespace Mono.MonoBASIC
                        // "1.1" vs "1.ToString()" (LITERAL_SINGLE vs NUMBER DOT IDENTIFIER)
                        //
                        if (c == '.'){
+                               if (non_prefixdecimal == false)
+                                        putback ('.');
                                if (decimal_digits (getChar())){
                                        is_real = true;
                                        c = peekChar ();
@@ -731,6 +746,7 @@ namespace Mono.MonoBASIC
                                return putback_char;
                        return reader.Peek ();
                }
+               
 
                void putback (int c)
                {
@@ -778,24 +794,51 @@ namespace Mono.MonoBASIC
 
                private int DropComments()              
                {
-                       int d;
-                       while (!IsEOL(d = getChar ()))
+                       //int d;
+                       while (!IsEOL(/*d =*/ getChar ()))
                                col++;
 
                        return Token.EOL;
                }       
+               
+               public bool putbacktoken = false;
+               public bool flag = false;               
+               int next_token;
                        
                public int token ()
                {
-                       int lastToken = current_token;
+                       int before_last_token = last_token;
+                       last_token = current_token;
                        do
                        {
                                current_token = xtoken ();
+                               if(current_token == Token.END) {
+                                       next_token = xtoken();
+                                       putbacktoken = true;
+                                       if (next_token == Token.EOL) 
+                                               return Token.END_EOL;
+                                        else 
+                                               return Token.END;
+                               }       
+                               if (current_token == Token.COLON) {
+                                       next_token = xtoken();
+                                       putbacktoken = true;
+                                       if (next_token == Token.EOL) {
+                                               if (last_token != Token.LABELNAME && last_token != Token.LITERAL_INTEGER) {
+                                                       current_token = Token.EOL;
+                                                       putbacktoken = false;
+                                               }
+                                               else if (before_last_token == Token.GOTO) {
+                                                       current_token = Token.EOL;
+                                                       putbacktoken = false;
+                                               }
+                                       }
+                               }
                                if (current_token == 0) 
                                        return Token.EOF;
                                if (current_token == Token.REM)
                                        current_token = DropComments();
-                       } while (lastToken == Token.EOL && current_token == Token.EOL);
+                       } while (last_token == Token.EOL && current_token == Token.EOL);
 
                        return current_token;
                }
@@ -809,6 +852,13 @@ namespace Mono.MonoBASIC
                                return null;
                }
 
+               private bool IsLabel ()
+               {
+                       char c = (char) peekChar();
+                       //putback (c);
+                       return (c == ':');
+               }
+
                private string GetIdentifier(int c)
                {
                        StringBuilder id = new StringBuilder ();
@@ -860,6 +910,11 @@ namespace Mono.MonoBASIC
                        bool doread = false;
                        int c;
 
+                       if (putbacktoken == true) {
+                               putbacktoken = false;
+                               return next_token;
+                       }
+       
                        val = null;
                        for (;(c = getChar ()) != -1; col++) {
                        
@@ -869,10 +924,12 @@ namespace Mono.MonoBASIC
                                        int d = peekChar();
                                        if (!is_identifier_part_character((char)d)) {
                                                while ((c = getChar ()) != -1 && !IsEOL(c)) {}
-                                               c = getChar ();                 
-                                       }               
+                                               c = getChar ();
+                                               tokens_seen = true;
+                                       }
                                }
-
+                                       
+                               
                                // white space
                                if (is_whitespace(c)) {
                                        // expand tabs for location
@@ -897,11 +954,17 @@ namespace Mono.MonoBASIC
                                // Handle escaped identifiers
                                if (c == '[')
                                {
+                                       bool is_first_token_in_line = !tokens_seen;
                                        if ((val = GetIdentifier()) == null)
                                                break;
                                        if ((c = getChar()) != ']')
                                                break;
                                        tokens_seen = true;
+                                       if (IsLabel() && is_first_token_in_line)
+                                               return Token.LABELNAME;
+
+                                       if (last_token == Token.GOTO)
+                                               return Token.LABELNAME;
                                        return Token.IDENTIFIER;
                                }
 
@@ -909,12 +972,19 @@ namespace Mono.MonoBASIC
                                if (is_identifier_start_character ((char) c))
                                {
                                        string id;
+                                       bool is_first_token_in_line = !tokens_seen;
                                        if ((id = GetIdentifier(c)) == null)
                                                break;
                                        val = id;
                                        tokens_seen = true;
                                        if (is_keyword(id) && (current_token != Token.DOT))
                                                return getKeyword(id);
+
+                                       if (IsLabel() && is_first_token_in_line)
+                                               return Token.LABELNAME;
+
+                                       if (last_token == Token.GOTO)
+                                               return Token.LABELNAME;
                                        return Token.IDENTIFIER;
                                }
 
@@ -925,6 +995,14 @@ namespace Mono.MonoBASIC
                                }
                        
                                // handle numeric literals
+
+                               if (Char.IsDigit ((char) c))
+                                {
+                                        cant_have_a_type_character = false;
+                                        tokens_seen = true;
+                                        return is_number (c);
+                                }
+
                                if (c == '.')
                                {
                                        cant_have_a_type_character = true;
@@ -933,14 +1011,6 @@ namespace Mono.MonoBASIC
                                                return is_number (c);
                                        return Token.DOT;
                                }
-                               
-                               if (Char.IsDigit ((char) c))
-                               {
-                                       cant_have_a_type_character = true;
-                                       tokens_seen = true;
-                                       return is_number (c);
-                               }
-
                                if ((t = is_punct ((char)c, ref doread)) != Token.ERROR) {
                                        cant_have_a_type_character = true;
 
@@ -1051,7 +1121,7 @@ namespace Mono.MonoBASIC
                {
                        int t;
                        
-                       for(t = token(); t != Token.HASH && t != Token.EOF; t = token());
+                       for(t = token(); t != Token.HASH && t != Token.EOF ; t = token()); 
 
                        if(t == Token.EOF)
                                throw new ApplicationException("Unexpected EOF while looking for a pre-processor directive");