/* * [The "BSD licence"] * Copyright (c) 2005-2008 Terence Parr * All rights reserved. * * Conversion to C#: * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ namespace Antlr.Runtime { using System.Collections.Generic; using Array = System.Array; using CLSCompliant = System.CLSCompliantAttribute; using ICloneable = System.ICloneable; using Math = System.Math; using StringBuilder = System.Text.StringBuilder; /** * A stripped-down version of org.antlr.misc.BitSet that is just * good enough to handle runtime requirements such as FOLLOW sets * for automatic error recovery. * */ [System.Serializable] public sealed class BitSet : ICloneable { private const int BITS = 64; // number of bits / long private const int LOG_BITS = 6; // 2^6 == 64 /** * We will often need to do a mod operator (i mod nbits). Its * turns out that, for powers of two, this mod operation is * same as (i & (nbits-1)). Since mod is slow, we use a * precomputed mod mask to do the mod instead. * */ private const int MOD_MASK = BITS - 1; /** The actual data bits */ ulong[] _bits; /** Construct a bitset of size one word (64 bits) */ public BitSet() : this(BITS) { } /** Construction from a static array of longs */ public BitSet(ulong[] bits) { _bits = bits; } /** Construction from a list of integers */ public BitSet(IEnumerable items) : this() { foreach (int i in items) Add(i); } /** Construct a bitset given the size * The size of the bitset in bits */ public BitSet(int nbits) { _bits = new ulong[((nbits - 1) >> LOG_BITS) + 1]; } public static BitSet Of(int el) { BitSet s = new BitSet(el + 1); s.Add(el); return s; } public static BitSet Of(int a, int b) { BitSet s = new BitSet(Math.Max(a, b) + 1); s.Add(a); s.Add(b); return s; } public static BitSet Of(int a, int b, int c) { BitSet s = new BitSet(); s.Add(a); s.Add(b); s.Add(c); return s; } public static BitSet Of(int a, int b, int c, int d) { BitSet s = new BitSet(); s.Add(a); s.Add(b); s.Add(c); s.Add(d); return s; } /** return this | a in a new set */ public BitSet Or(BitSet a) { if (a == null) { return this; } BitSet s = (BitSet)this.Clone(); s.OrInPlace(a); return s; } /** or this element into this set (grow as necessary to accommodate) */ public void Add(int el) { int n = WordNumber(el); if (n >= _bits.Length) { GrowToInclude(el); } _bits[n] |= BitMask(el); } /** Grows the set to a larger number of bits. * element that must fit in set */ public void GrowToInclude(int bit) { int newSize = Math.Max(_bits.Length << 1, NumWordsToHold(bit)); SetSize(newSize); } public void OrInPlace(BitSet a) { if (a == null) { return; } // If this is smaller than a, grow this first if (a._bits.Length > _bits.Length) { SetSize(a._bits.Length); } int min = Math.Min(_bits.Length, a._bits.Length); for (int i = min - 1; i >= 0; i--) { _bits[i] |= a._bits[i]; } } /** Sets the size of a set. * how many words the new set should be */ private void SetSize(int nwords) { Array.Resize(ref _bits, nwords); } private static ulong BitMask(int bitNumber) { int bitPosition = bitNumber & MOD_MASK; // bitNumber mod BITS return 1UL << bitPosition; } public object Clone() { return new BitSet((ulong[])_bits.Clone()); } public int Size() { int deg = 0; for (int i = _bits.Length - 1; i >= 0; i--) { ulong word = _bits[i]; if (word != 0L) { for (int bit = BITS - 1; bit >= 0; bit--) { if ((word & (1UL << bit)) != 0) { deg++; } } } } return deg; } public override int GetHashCode() { throw new System.NotImplementedException(); } public override bool Equals(object other) { if (other == null || !(other is BitSet)) { return false; } BitSet otherSet = (BitSet)other; int n = Math.Min(this._bits.Length, otherSet._bits.Length); // for any bits in common, compare for (int i = 0; i < n; i++) { if (this._bits[i] != otherSet._bits[i]) { return false; } } // make sure any extra bits are off if (this._bits.Length > n) { for (int i = n + 1; i < this._bits.Length; i++) { if (this._bits[i] != 0) { return false; } } } else if (otherSet._bits.Length > n) { for (int i = n + 1; i < otherSet._bits.Length; i++) { if (otherSet._bits[i] != 0) { return false; } } } return true; } public bool Member(int el) { if (el < 0) { return false; } int n = WordNumber(el); if (n >= _bits.Length) return false; return (_bits[n] & BitMask(el)) != 0; } // remove this element from this set public void Remove(int el) { int n = WordNumber(el); if (n < _bits.Length) { _bits[n] &= ~BitMask(el); } } public bool IsNil() { for (int i = _bits.Length - 1; i >= 0; i--) { if (_bits[i] != 0) return false; } return true; } private static int NumWordsToHold(int el) { return (el >> LOG_BITS) + 1; } public int NumBits() { return _bits.Length << LOG_BITS; // num words * bits per word } /** return how much space is being used by the bits array not how many actually have member bits on. */ public int LengthInLongWords() { return _bits.Length; } /**Is this contained within a? */ /* public boolean subset(BitSet a) { if (a == null || !(a instanceof BitSet)) return false; return this.and(a).equals(this); } */ public int[] ToArray() { int[] elems = new int[Size()]; int en = 0; for (int i = 0; i < (_bits.Length << LOG_BITS); i++) { if (Member(i)) { elems[en++] = i; } } return elems; } private static int WordNumber(int bit) { return bit >> LOG_BITS; // bit / BITS } public override string ToString() { return ToString(null); } public string ToString(string[] tokenNames) { StringBuilder buf = new StringBuilder(); string separator = ","; bool havePrintedAnElement = false; buf.Append('{'); for (int i = 0; i < (_bits.Length << LOG_BITS); i++) { if (Member(i)) { if (i > 0 && havePrintedAnElement) { buf.Append(separator); } if (tokenNames != null) { buf.Append(tokenNames[i]); } else { buf.Append(i); } havePrintedAnElement = true; } } buf.Append('}'); return buf.ToString(); } } }