Subversion Repositories AndroidProjects

Rev

Rev 1422 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BauzoidNET.parser
{
    public class Tokenizer
    {
            public const string UNEXPECTED_TOKEN = "Unexpected Token!";
            public const string UNEXPECTED_END_OF_STRING = "Unexpected End of String!";
       
            private string mString;
            private int mPosition = -1;
            private char[] mDelimiters = {';'};
            private char[] mWhitespaces = {' ', '\n', '\r', '\t'};
            private char[] mStringDelimiters = {'"', '\''};
       
            public Tokenizer(string str)
            {
                    mString = str;
                    mPosition = 0;
            }
       
            public string readToken(string token)
            {
                    skipWhitespaces();
               
                    if (isEndOfString())
                            throw new ScanException(UNEXPECTED_END_OF_STRING, getSurroundings());
               
                    if (!isNextString(token))
                            throw new ScanException(UNEXPECTED_TOKEN + " Expected: " + token, getSurroundings());

            mPosition += token.Length;
               
                    return token;
            }
       
            /** Read until a token or the end of the string is encountered. Does not consume the token itself. */
            public string readUntilToken(string token)
            {
                    skipWhitespaces();
               
                    int startPos = mPosition;
               
                    string result = "";
               
                    if (isEndOfString())
                            return result;
               
                    while (!isNextString(token) && !isEndOfString())
                    {
                            skipChar();
                    }
               
                    return mString.Substring(startPos, mPosition);             
            }
       
            /** Read until the end of the string. Advances the string marker to the end. */
            public string readUntilEndOfString()
            {
                    skipWhitespaces();
               
                    if (isEndOfString())
                            return "";
               
                    String result = mString.Substring(mPosition, mString.Length);
                    mPosition = mString.Length-1;
                    return Preprocessor.trim(result, mWhitespaces);
            }
       
            /** Read until the next new line character, or the end of the string. Advances the marker. */
            public string readUntilNewLine()
            {
                    skipWhitespaces();
               
                    if (isEndOfString())
                            return "";
               
                    int prevPos = mPosition;
               
                    while (!isNextString("\n") && !isEndOfString())
                    {
                            skipChar();
                    }
               
                    string result = mString.Substring(prevPos, mPosition);
                    return Preprocessor.trim(result, mWhitespaces);
            }
       
            public bool checkToken(string token)
            {
                    int prevPosition = mPosition;
               
                    try
                    {
                            readToken(token);
                    }
                    catch (ScanException ex)
                    {
                            return false;
                    }
                    finally
                    {
                            mPosition = prevPosition;
                    }
               
                    return true;
            }
       
            public float readNumber()
            {
                    skipWhitespaces();
               
                    if (isEndOfString())
                            throw new ScanException(UNEXPECTED_END_OF_STRING, getSurroundings());
               
                    // read numeric values or . until a delimiter or whitespace occurs
                    float result = 0;
                    float postCommaFactor = 1.0f;
                    bool numberFound = false;
                    bool commaFound = false;
               
                    float sign = 1;
               
                    // check for minus
                    if (getCurrentChar() == '-')
                    {
                            sign = -1;
                            skipChar();
                    }

                    while ((!isEndOfString()) && (isNumeric(getCurrentChar()) || (getCurrentChar() == '.')))
                    {
                            if (isEndOfString())
                                    break;
                       
                            if (isWhitespace(getCurrentChar()))
                                    break;
                       
                            if (isDelimiter(getCurrentChar()))
                                    break;
                       
                            if (isNumeric(getCurrentChar()))
                            {
                                    numberFound = true;
                               
                                    if (!commaFound)
                                    {
                                            //result = result * 10 + Character.digit(getCurrentChar(), 10);
                        result = result * 10 + Convert.ToInt32(getCurrentChar().ToString(), 10);
                                    }
                                    else
                                    {
                                            //result = result + Character.digit(getCurrentChar(), 10) / postCommaFactor;
                        result = result + Convert.ToInt32(getCurrentChar().ToString(), 10) / postCommaFactor;
                                            postCommaFactor *= 10.0f;
                                    }
                            }
                            else if (getCurrentChar() == '.')
                            {
                                    // need a digit first
                                    if (!numberFound)
                                            break;
                               
                                    // check for double commas
                                    if (commaFound)
                                            break;
                               
                                    commaFound = true;
                                    postCommaFactor = 10.0f;
                            }
                            else
                            {
                                    // not a number
                                    break;
                            }
                       
                            skipChar();
                    }
               
                    if (!numberFound)
                    {
                            if (isEndOfString())
                                    throw new ScanException(UNEXPECTED_END_OF_STRING, getSurroundings());
                            else                       
                                    throw new ScanException(UNEXPECTED_TOKEN + " Expected: Number", getSurroundings());
                    }
               
                    return (sign*result);
            }
       
            public bool checkNumber()
            {
                    int prevPosition = mPosition;
               
                    try
                    {
                            readNumber();
                    }
                    catch (ScanException ex)
                    {
                            return false;
                    }
                    finally
                    {
                            mPosition = prevPosition;
                    }
               
                    return true;               
            }
       
            public string readIdentifier()
            {
                    // TODO: read alphanumericwithunderscore (starting with alpha or underscore) until delimiter or whitespace
               
                    skipWhitespaces();
               
                    if (isEndOfString())
                            throw new ScanException(UNEXPECTED_END_OF_STRING, getSurroundings());
               
                    bool idFound = false;
                    int startChar = mPosition;
                    int numChars = 0;

                    while (!isEndOfString() && isAlphaNumericOrUnderscore(getCurrentChar()))
                    {
                            idFound = true;
                            numChars++;
                            skipChar();
                    }
               
                    if (!idFound)
                            throw new ScanException(UNEXPECTED_TOKEN + " Expected: Identifier", getSurroundings());
               
                    return mString.Substring(startChar, startChar + numChars);         
            }
       
            public bool checkIdentifier()
            {
                    int prevPosition = mPosition;
               
                    try
                    {
                            readIdentifier();
                    }
                    catch (ScanException ex)
                    {
                            return false;
                    }
                    finally
                    {
                            mPosition = prevPosition;
                    }
               
                    return true;               
            }
       
            public string readString()
            {          
                    skipWhitespaces();
               
                    if (isEndOfString())
                            throw new ScanException(UNEXPECTED_END_OF_STRING, getSurroundings());
               
                    char usedStringDelimiter = mStringDelimiters[0];
                    bool foundStringDelimiter = false;
                    for (int i = 0; i < mStringDelimiters.Length; i++)
                    {
                char stringDelimiter = mStringDelimiters[i];
                            if (getCurrentChar() == stringDelimiter)
                            {
                                    foundStringDelimiter = true;
                                    usedStringDelimiter = stringDelimiter;                             
                            }                  
                    }
                    if (!foundStringDelimiter)
                            throw new ScanException(UNEXPECTED_TOKEN + " Expected: String", getSurroundings());
               
                    // skip first string delimiter
                    skipChar();
               
                    int startChar = mPosition;
                    int numChars = 0;

                    while (getCurrentChar() != usedStringDelimiter)
                    {
                            if (isEndOfString())
                                    throw new ScanException(UNEXPECTED_END_OF_STRING, getSurroundings());
                       
                            numChars++;
                            skipChar();
                    }
               
                    // skip last string delimiter
                    skipChar();
               
                    return mString.Substring(startChar, startChar + numChars);
            }
       
            public bool checkString()
            {
                    int prevPosition = mPosition;
               
                    try
                    {
                            readString();
                    }
                    catch (ScanException ex)
                    {
                            return false;
                    }
                    finally
                    {
                            mPosition = prevPosition;
                    }
               
                    return true;       
            }

            private bool isWhitespace(char c)
            {
                    for (int i = 0; i < mWhitespaces.Length; i++)
                    {
                char whitespace = mWhitespaces[i];
                            if (c == whitespace)
                                    return true;
                    }
                    return false;
            }
       
            private void skipWhitespaces()
            {
                    if (isEndOfString())
                            return;
               
                    while (isWhitespace(getCurrentChar()))
                    {
                            skipChar();
                       
                            if (isEndOfString())
                                    return;
                    }
            }
       
            private bool isDelimiter(char c)
            {
                    for (int i = 0; i < mDelimiters.Length; i++)
                    {
                char delimiter = mDelimiters[i];
                            if (c == delimiter)
                                    return true;
                    }
                    return false;
            }
       
            private void skipChar()
            {
                    if (isEndOfString())
                            return;
               
                    mPosition++;
            }
       
            public bool isNextString(string str)
            {
                    return Preprocessor.isNextString(mString, mPosition, str);
               
                    /*for (int i = 0; i < str.length(); i++)
                    {
                            if (mString.length() <= (mPosition+i))
                                    return false;
                       
                            if (str.charAt(i) != mString.charAt(mPosition + i))
                                    return false;
                    }
               
                    return true;*/

            }
       
            public bool isEndOfString()
            {
                    return (mPosition >= mString.Length);
            }
       
            public bool checkNoMoreTokens()
            {
                    skipWhitespaces();
                    return isEndOfString();
            }
       
            public static bool isNumeric(char c)
            {
                    return ((c >= '0') && (c <= '9'));
            }
       
            public static bool isUpperCaseAlpha(char c)
            {
                    return ((c >= 'A') && (c <= 'Z'));
            }
       
            public static bool isLowerCaseAlpha(char c)
            {
                    return ((c >= 'a') && (c <= 'z'));
            }
       
            public static bool isAlpha(char c)
            {
                    return (isUpperCaseAlpha(c) || isLowerCaseAlpha(c));
            }
       
            public static bool isAlphaNumeric(char c)
            {
                    return (isAlpha(c) || isNumeric(c));
            }
       
            public static bool isAlphaNumericOrUnderscore(char c)
            {
                    return ((c == '_') || isAlphaNumeric(c));
            }
       
            public char getCurrentChar()
            {
                    return mString[mPosition];
            }
       
            public void setWhitespaces(char[] whitespaces)
            {
                    mWhitespaces = whitespaces;
            }
       
            public void setDelimiters(char[] delimiters)
            {
                    mDelimiters = delimiters;
            }
       
            public void setStringDelimiter(char[] stringDelimiters)
            {
                    mStringDelimiters = stringDelimiters;
            }
       
            public void setPosition(int position)
            {
                    mPosition = position;
            }
       
            public int getPosition()
            {
                    return mPosition;
            }
       
            /** For debugging purposes. */
            public string getSurroundings()
            {
                    // retrieve the line number
                    int numLines = 1;
                    for (int i = 0; i < mPosition; i++)
                    {
                            if (mString[i] == '\n')
                                    numLines++;
                    }
               
                    int startIndex = Math.Max(mPosition - 10, 0);
                    int endIndex = Math.Min(mPosition + 10, mString.Length - 1);
               
                    return "Line " + numLines + " <<<" + mString.Substring(startIndex, endIndex) + ">>>";
            }

    }
}