// 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
}