// Token.cs // // Copyright (C) 2002-2004 Ryan Seghers // // This software is provided AS IS. No warranty is granted, // neither expressed nor implied. USE THIS SOFTWARE AT YOUR OWN RISK. // NO REPRESENTATION OF MERCHANTABILITY or FITNESS FOR ANY // PURPOSE is given. // // License to use this software is limited by the following terms: // 1) This code may be used in any program, including programs developed // for commercial purposes, provided that this notice is included verbatim. // // Also, in return for using this code, please attempt to make your fixes and // updates available in some way, such as by sending your updates to the // author. // // To-do: // more Equals methods? using System; using System.Globalization; namespace RTools_NTS.Util { /// /// Token class used by StreamTokenizer. /// This represents a single token in the input stream. /// This is subclassed to provide specific token types, /// such as CharToken, FloatToken, etc. /// abstract public class Token { #region Properties /// /// The line number in the input stream where this token originated. /// This is base-1. /// protected int lineNumber; /// /// The line number where this token was found. This is base-1. /// public int LineNumber { get { return(lineNumber); }} /// /// A storage object for the data of this token. /// protected object obj; /// /// The Object stored by this token. This will be /// a primitive C# type. /// public object Object { get { return(obj); }} /// /// Backer for UntermError. /// bool untermError; /// /// Whether or not there was an unterminated token problem /// when creating this token. See UntermErrorMessage for /// a message associated with the problem. /// public bool UntermError { get { return(untermError); } set { untermError = value; } } /// An error message associated with unterm error. string untermErrorMsg; /// /// The error message if there was an unterminated token error /// creating this token. /// public string UntermErrorMsg { get { return(untermErrorMsg); } set { untermError = true; untermErrorMsg = value; } } #endregion #region Constructors /// /// Construct a Token with the specified line number. /// /// The line number where this /// token comes from. public Token(int line) { obj = null; untermError = false; lineNumber = line; } #endregion #region Operator overloads and Equals /// /// Equals override. /// /// The object to compare to. /// bool - true for equals, false otherwise. public override bool Equals(object other) { if (other == null) return(false); else if (!(other is Token)) return(false); else return(obj.Equals(((Token)other).obj)); } /// /// Equals overload. /// /// The string to compare to. /// bool public bool Equals(string s) { if (s == null) return(false); else return(StringValue.Equals(s)); } /// /// Equals overload. /// /// The char to compare to. /// bool public bool Equals(char c) { if (!(this is CharToken)) return(false); CharToken ct = this as CharToken; return(ct.Object.Equals(c)); } /// /// Operator== overload. Compare a token and an object. /// /// The token to compare. /// The other object. /// bool public static bool operator == (Token t, Object o) { if ((object)t == null) if (o == null) return(true); else return(false); else if (o == null) return(false); return(t.Equals(o)); } /// /// Operator!= overload. Compare a token and an object. /// /// The token to compare. /// The other object. /// bool public static bool operator != (Token t, Object o) { if ((object)t == null) if (o == null) return(false); else return(true); return(!t.Equals(o)); } /// /// Operator== overload. Compare a token and a char. /// /// The token to compare. /// The char. /// bool public static bool operator == (Token t, char c) { if ((object)t == null) return(false); return(t.Equals(c)); } /// /// Operator!= overload. Compare a token and a char. /// /// The token to compare. /// The char. /// bool public static bool operator != (Token t, char c) { if ((object)t == null) return(false); return(!t.Equals(c)); } /// /// Operator== overload. Compare a token and a string. /// /// The token to compare. /// The string. /// bool public static bool operator == (Token t, string s) { if ((object)t == null) if (s == null) return(true); else return(false); return(t.Equals(s)); } /// /// Operator!= overload. Compare a token and a string. /// /// The token to compare. /// The string. /// bool public static bool operator != (Token t, string s) { if ((object)t == null) if (s == null) return(false); else return(true); return(!t.Equals(s)); } #endregion #region Standard Methods /// /// Override. Returns the ToString().GetHashCode(). /// /// The hash code. public override int GetHashCode() { return(ToString().GetHashCode()); } /// /// Return this token's value as a string. /// /// This token's value as a string. public virtual string StringValue { get { return("unset"); } } /// /// Produce a string which includes the line number. /// /// public string ToLineString() { return(String.Format("{0}: line {1}", ToDebugString(), lineNumber)); } /// /// Produce a string which includes the token type. /// /// public virtual string ToDebugString() { return(String.Format("{0}: line {1}", ToString(), lineNumber)); } /// /// Create an object of the specified type corresponding to /// this token. /// /// The type of object to create. /// The new object, or null for error. public Object ConvertToType(Type t) { return Convert.ChangeType(StringValue, t); } #endregion } #region EolToken /// /// Represents end-of-lines (line separator characters). /// public class EolToken : Token { /// Default constructor. public EolToken() : base(0) {} /// Constructor that takes line number. public EolToken(int line) : base(line) {} /// Override, see base public override string ToDebugString() { return("Eol"); } /// Override, see base public override string ToString() { return("\n"); } /// Override, see base public override bool Equals(object other) { if (!(other is EolToken)) return(false); else return(true); } /// Override, see base public override string StringValue { get { return(ToString()); } } /// Override, see base public override int GetHashCode() { return(ToString().GetHashCode()); } } #endregion #region EofToken /// /// Represents end of file/stream. /// public class EofToken : Token { /// Default constructor. public EofToken() : base(0) {} /// Constructor that takes line number. public EofToken(int line) : base(line) {} /// Override, see base public override string ToString() { return(String.Empty); } /// Override, see base public override string ToDebugString() { return("Eof"); } /// Override, see base public override bool Equals(object other) { if (!(other is EofToken)) return(false); else return(true); } /// Override, see base public override string StringValue { get { return(ToString()); } } /// Override, see base public override int GetHashCode() { return(ToString().GetHashCode()); } } #endregion #region StringToken /// /// Abstract base class for string tokens. /// public abstract class StringToken : Token { /// Default constructor. public StringToken(string s) : base(0) { obj = s; } /// Constructor with the specified value /// and line number. public StringToken(string s, int line) : base(line) { obj = s; } /// Override, see base public override string ToDebugString() { return(GetType().Name + ":'" + (string)obj + "'"); } /// Override, see base public override string ToString() { return((string)obj); } /// Override, see base public override string StringValue { get { return((string)obj); } } /// Override, see base public override int GetHashCode() { return(ToString().GetHashCode()); } } #endregion #region WordToken /// /// Token type for words, meaning sequences of word /// characters. /// public class WordToken : StringToken { /// Constructor with the specified value. public WordToken(string s) : base(s) {} /// Constructor with the specified value /// and line number. public WordToken(string s, int line) : base(s, line) {} } #endregion #region QuoteToken /// /// Token type for Quotes such as "this is a quote". /// public class QuoteToken : StringToken { /// Constructor with the specified value. public QuoteToken(string s) : base(s) {} /// Constructor with the specified value /// and line number. public QuoteToken(string s, int line) : base(s, line) {} } #endregion #region CommentToken /// /// Token type for comments, including line and block /// comments. /// public class CommentToken : StringToken { /// Constructor with the specified value. public CommentToken(string s) : base(s) {} /// Constructor with the specified value /// and line number. public CommentToken(string s, int line) : base(s, line) {} } #endregion #region WhitespaceToken /// /// Token type for whitespace such as spaces and tabs. /// public class WhitespaceToken : StringToken { /// Constructor with the specified value. public WhitespaceToken(string s) : base(s) {} /// Constructor with the specified value /// and line number. public WhitespaceToken(string s, int line) : base(s, line) {} } #endregion #region CharToken /// /// Token type for characters, meaning non-word characters. /// public class CharToken : Token { /// Constructor with the specified value /// and line number. public CharToken(string s, int line) : base(line) { if (s.Length > 0) obj = s[0]; } /// Constructor with the specified value. public CharToken(char c) : base(0) { obj = c; } /// Constructor with the specified value. public CharToken(char c, int line) : base(line) { obj = c; } /// Override, see base public override string ToDebugString() { return(String.Format("CharToken: {0}", (Char)obj)); } /// Override, see base public override string ToString() { return(String.Format("{0}", (Char)obj)); } /// Override, see base public override int GetHashCode() { return(ToString().GetHashCode()); } /// Override, see base public override string StringValue { get { return(String.Format("{0}", (Char)obj)); } } /// Override, see base public override bool Equals(object other) { if ((object)other == null) return(false); if (!GetType().Equals(other.GetType())) return(false); if ((obj == null) || (((CharToken)other).obj == null)) return(false); if (((Char)obj).Equals((Char)((CharToken)other).Object)) return(true); else return(false); } } #endregion #region FloatToken /// /// Token type for floating point numbers, stored internally as a Double. /// public class FloatToken : Token { // NOTE: modified for "safe" assembly in Sql 2005 // Static field now is an instance field! private NumberFormatInfo numberFormatInfo = null; // Static method now is an instance method! private NumberFormatInfo GetNumberFormatInfo() { if (numberFormatInfo == null) { numberFormatInfo = new NumberFormatInfo(); numberFormatInfo.NumberDecimalSeparator = "."; } return numberFormatInfo; } /// /// Constructor with the specified value. /// public FloatToken(string s) : base(0) { try { obj = Double.Parse(s, GetNumberFormatInfo()); } catch(Exception) { obj = null; } } /// /// Constructor with the specified value. /// public FloatToken(float f) : base(0) { try { obj = (double)f; } catch (Exception) { obj = null; } } /// /// Constructor with the specified value. /// public FloatToken(double d) : base(0) { try { obj = d; } catch (Exception) { obj = null; } } /// /// Constructor with the specified value and line number. /// public FloatToken(string s, int line) : base(line) { try { obj = Double.Parse(s, GetNumberFormatInfo()); } catch (Exception) { obj = null; } } /// /// Constructor with the specified value and line number. /// public FloatToken(double f, int line) : base(line) { try { obj = (double) f; } catch (Exception) { obj = null; } } /// /// Override, see base /// public override string ToDebugString() { if (obj != null) return(String.Format("FloatToken: {0:R}", (Double) obj)); else return(String.Format("FloatToken: null")); } /// /// Override, see base /// public override string ToString() { if (obj != null) return(String.Format("{0:R}", (Double) obj)); else return(String.Format("null")); } /// /// Override, see base /// public override int GetHashCode() { return(ToString().GetHashCode()); } /// /// Override, see base /// public override string StringValue { get { if (obj != null) // return(String.Format("{0:f9}", (Double)obj)); return (String.Format("{0:R}", (Double) obj)); else return(String.Format("null")); } } /// /// Override, see base /// public override bool Equals(object other) { if ((object)other == null) return false; if (!GetType().Equals(other.GetType())) return false; if ((obj == null) || (((FloatToken)other).obj == null)) return false ; if (((Double) obj).Equals((Double) ((FloatToken) other).Object)) return true; else return false; } } #endregion #region IntToken /// /// Token type for integer tokens. This handles both Int32 and Int64. /// public class IntToken : Token { /// Constructor with the specified value. public IntToken(int i) : base(0) { obj = i; } /// Constructor with the specified value. public IntToken(long i) : base(0) { obj = i; } /// Constructor with the specified value. public IntToken(string s) : base(0) { Parse(s); } /// Constructor with the specified value /// and line number. public IntToken(string s, int line) : base(line) { Parse(s); } /// Constructor with the specified value /// and line number. public IntToken(int i, int line) : base(line) { obj = i; } /// /// Constructor for a 64 bit int /// public IntToken(long l, int line) : base(line) { obj = l; } /// /// Parse a string known to be a hex string. This is faster /// than Parse which doesn't assume the number is Hex. This will /// throw an exception if the input number isn't hex. /// /// The hex number as a string. /// The line where this token was found. /// A new IntToken set to the value in the input string. public static IntToken ParseHex(string s, int lineNumber) { IntToken it = null; try { it = new IntToken(Convert.ToInt32(s, 16), lineNumber); } catch { it = new IntToken(Convert.ToInt64(s, 16), lineNumber); } return(it); } /// /// Convert the input string to an integer, if possible /// /// The string to parse. private void Parse(string s) { // try base 10 separately since it will be the most // common case try { obj = Int32.Parse(s); return; } catch(Exception) { // try 64 bit base 10 try { obj = Int64.Parse(s); return; } catch(Exception) { } // don't give up yet } // not a normal int, try other bases int[] bases = {16, 2, 8}; foreach(int b in bases) { try { obj = Convert.ToInt32(s, b); return; } catch { // try 64 bit base 10 try { obj = Convert.ToInt64(s, b); return; } catch { } // don't give up yet } } obj = null; } /// Override, see base public override string ToDebugString() { if (obj != null) return(String.Format("IntToken: {0}", obj)); else return(String.Format("IntToken: null")); } /// Override, see base public override string ToString() { if (obj != null) return(String.Format("{0}", obj)); else return(String.Format("null")); } /// Override, see base public override int GetHashCode() { return(ToString().GetHashCode()); } /// Override, see base public override string StringValue { get { if (obj != null) return(String.Format("{0}", obj)); else return(String.Format("null")); } } /// Override, see base public override bool Equals(object other) { if ((object)other == null) return(false); if (!GetType().Equals(other.GetType())) return(false); if ((obj == null) || (((IntToken)other).obj == null)) return(false); if (!obj.GetType().Equals(((IntToken)other).obj.GetType())) return(false); if (obj is Int32) { if (((Int32)obj).Equals((Int32)((IntToken)other).Object)) return(true); } else { if (((Int64)obj).Equals((Int64)((IntToken)other).Object)) return(true); } return(false); } } #endregion }