+ class KeywordEntry<T>
+ {
+ public readonly T Token;
+ public KeywordEntry<T> Next;
+ public readonly char[] Value;
+
+ public KeywordEntry (string value, T token)
+ {
+ this.Value = value.ToCharArray ();
+ this.Token = token;
+ }
+ }
+
+ sealed class IdentifiersComparer : IEqualityComparer<char[]>
+ {
+ readonly int length;
+
+ public IdentifiersComparer (int length)
+ {
+ this.length = length;
+ }
+
+ public bool Equals (char[] x, char[] y)
+ {
+ for (int i = 0; i < length; ++i)
+ if (x [i] != y [i])
+ return false;
+
+ return true;
+ }
+
+ public int GetHashCode (char[] obj)
+ {
+ int h = 0;
+ for (int i = 0; i < length; ++i)
+ h = (h << 5) - h + obj [i];
+
+ return h;
+ }
+ }
+
+ //
+ // This class has to be used in the parser only, it reuses token
+ // details after each parse
+ //
+ public class LocatedToken
+ {
+ int row, column;
+ string value;
+
+ static LocatedToken[] buffer;
+ static int pos;
+
+ private LocatedToken ()
+ {
+ }
+
+ public static LocatedToken Create (int row, int column)
+ {
+ return Create (null, row, column);
+ }
+
+ public static LocatedToken Create (string value, Location loc)
+ {
+ return Create (value, loc.Row, loc.Column);
+ }
+
+ public static LocatedToken Create (string value, int row, int column)
+ {
+ //
+ // TODO: I am not very happy about the logic but it's the best
+ // what I could come up with for now.
+ // Ideally we should be using just tiny buffer (256 elements) which
+ // is enough to hold all details for currect stack and recycle elements
+ // poped from the stack but there is a trick needed to recycle
+ // them properly.
+ //
+ LocatedToken entry;
+ if (pos >= buffer.Length) {
+ entry = new LocatedToken ();
+ } else {
+ entry = buffer [pos];
+ if (entry == null) {
+ entry = new LocatedToken ();
+ buffer [pos] = entry;
+ }
+
+ ++pos;
+ }
+ entry.value = value;
+ entry.row = row;
+ entry.column = column;
+ return entry;
+ }
+
+ //
+ // Used for token not required by expression evaluator
+ //
+ [Conditional ("FULL_AST")]
+ public static void CreateOptional (int row, int col, ref object token)
+ {
+ token = Create (row, col);
+ }
+
+ public static void Initialize ()
+ {
+ if (buffer == null)
+ buffer = new LocatedToken [10000];
+ pos = 0;
+ }
+
+ public Location Location {
+ get { return new Location (row, column); }
+ }
+
+ public string Value {
+ get { return value; }
+ }
+ }
+
+ public enum PreprocessorDirective
+ {
+ Invalid = 0,
+
+ Region = 1,
+ Endregion = 2,
+ If = 3 | RequiresArgument,
+ Endif = 4,
+ Elif = 5 | RequiresArgument,
+ Else = 6,
+ Define = 7 | RequiresArgument,
+ Undef = 8 | RequiresArgument,
+ Error = 9,
+ Warning = 10,
+ Pragma = 11 | CustomArgumentsParsing,
+ Line = 12,
+
+ CustomArgumentsParsing = 1 << 10,
+ RequiresArgument = 1 << 11
+ }
+