1/* 2 * [The "BSD licence"] 3 * Copyright (c) 2005-2008 Terence Parr 4 * All rights reserved. 5 * 6 * Conversion to C#: 7 * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33namespace Antlr.Runtime 34{ 35 using System.Collections.Generic; 36 37 using Array = System.Array; 38 using CLSCompliant = System.CLSCompliantAttribute; 39 using ICloneable = System.ICloneable; 40 using Math = System.Math; 41 using StringBuilder = System.Text.StringBuilder; 42 43 /** <summary> 44 * A stripped-down version of org.antlr.misc.BitSet that is just 45 * good enough to handle runtime requirements such as FOLLOW sets 46 * for automatic error recovery. 47 * </summary> 48 */ 49 [System.Serializable] 50 public sealed class BitSet : ICloneable 51 { 52 private const int BITS = 64; // number of bits / long 53 private const int LOG_BITS = 6; // 2^6 == 64 54 55 /** <summary> 56 * We will often need to do a mod operator (i mod nbits). Its 57 * turns out that, for powers of two, this mod operation is 58 * same as (i & (nbits-1)). Since mod is slow, we use a 59 * precomputed mod mask to do the mod instead. 60 * </summary> 61 */ 62 private const int MOD_MASK = BITS - 1; 63 64 /** <summary>The actual data bits</summary> */ 65 ulong[] _bits; 66 67 /** <summary>Construct a bitset of size one word (64 bits)</summary> */ 68 public BitSet() 69 : this( BITS ) 70 { 71 } 72 73 /** <summary>Construction from a static array of longs</summary> */ 74 [CLSCompliant( false )] 75 public BitSet( ulong[] bits ) 76 { 77 _bits = bits; 78 } 79 80 /** <summary>Construction from a list of integers</summary> */ 81 public BitSet( IEnumerable<int> items ) 82 : this() 83 { 84 foreach ( int i in items ) 85 Add( i ); 86 } 87 88 /** <summary>Construct a bitset given the size</summary> 89 * <param name="nbits">The size of the bitset in bits</param> 90 */ 91 public BitSet( int nbits ) 92 { 93 _bits = new ulong[( ( nbits - 1 ) >> LOG_BITS ) + 1]; 94 } 95 96 public static BitSet Of( int el ) 97 { 98 BitSet s = new BitSet( el + 1 ); 99 s.Add( el ); 100 return s; 101 } 102 103 public static BitSet Of( int a, int b ) 104 { 105 BitSet s = new BitSet( Math.Max( a, b ) + 1 ); 106 s.Add( a ); 107 s.Add( b ); 108 return s; 109 } 110 111 public static BitSet Of( int a, int b, int c ) 112 { 113 BitSet s = new BitSet(); 114 s.Add( a ); 115 s.Add( b ); 116 s.Add( c ); 117 return s; 118 } 119 120 public static BitSet Of( int a, int b, int c, int d ) 121 { 122 BitSet s = new BitSet(); 123 s.Add( a ); 124 s.Add( b ); 125 s.Add( c ); 126 s.Add( d ); 127 return s; 128 } 129 130 /** <summary>return this | a in a new set</summary> */ 131 public BitSet Or( BitSet a ) 132 { 133 if ( a == null ) 134 { 135 return this; 136 } 137 BitSet s = (BitSet)this.Clone(); 138 s.OrInPlace( a ); 139 return s; 140 } 141 142 /** <summary>or this element into this set (grow as necessary to accommodate)</summary> */ 143 public void Add( int el ) 144 { 145 int n = WordNumber( el ); 146 if ( n >= _bits.Length ) 147 { 148 GrowToInclude( el ); 149 } 150 _bits[n] |= BitMask( el ); 151 } 152 153 /** <summary>Grows the set to a larger number of bits.</summary> 154 * <param name="bit">element that must fit in set</param> 155 */ 156 public void GrowToInclude( int bit ) 157 { 158 int newSize = Math.Max( _bits.Length << 1, NumWordsToHold( bit ) ); 159 SetSize(newSize); 160 } 161 162 public void OrInPlace( BitSet a ) 163 { 164 if ( a == null ) 165 { 166 return; 167 } 168 // If this is smaller than a, grow this first 169 if ( a._bits.Length > _bits.Length ) 170 { 171 SetSize( a._bits.Length ); 172 } 173 int min = Math.Min( _bits.Length, a._bits.Length ); 174 for ( int i = min - 1; i >= 0; i-- ) 175 { 176 _bits[i] |= a._bits[i]; 177 } 178 } 179 180 /** <summary>Sets the size of a set.</summary> 181 * <param name="nwords">how many words the new set should be</param> 182 */ 183 private void SetSize( int nwords ) 184 { 185 Array.Resize(ref _bits, nwords); 186 } 187 188 private static ulong BitMask( int bitNumber ) 189 { 190 int bitPosition = bitNumber & MOD_MASK; // bitNumber mod BITS 191 return 1UL << bitPosition; 192 } 193 194 public object Clone() 195 { 196 return new BitSet( (ulong[])_bits.Clone() ); 197 } 198 199 public int Size() 200 { 201 int deg = 0; 202 for ( int i = _bits.Length - 1; i >= 0; i-- ) 203 { 204 ulong word = _bits[i]; 205 if ( word != 0L ) 206 { 207 for ( int bit = BITS - 1; bit >= 0; bit-- ) 208 { 209 if ( ( word & ( 1UL << bit ) ) != 0 ) 210 { 211 deg++; 212 } 213 } 214 } 215 } 216 return deg; 217 } 218 219 public override int GetHashCode() 220 { 221 throw new System.NotImplementedException(); 222 } 223 224 public override bool Equals( object other ) 225 { 226 if ( other == null || !( other is BitSet ) ) 227 { 228 return false; 229 } 230 231 BitSet otherSet = (BitSet)other; 232 233 int n = Math.Min( this._bits.Length, otherSet._bits.Length ); 234 235 // for any bits in common, compare 236 for ( int i = 0; i < n; i++ ) 237 { 238 if ( this._bits[i] != otherSet._bits[i] ) 239 { 240 return false; 241 } 242 } 243 244 // make sure any extra bits are off 245 246 if ( this._bits.Length > n ) 247 { 248 for ( int i = n + 1; i < this._bits.Length; i++ ) 249 { 250 if ( this._bits[i] != 0 ) 251 { 252 return false; 253 } 254 } 255 } 256 else if ( otherSet._bits.Length > n ) 257 { 258 for ( int i = n + 1; i < otherSet._bits.Length; i++ ) 259 { 260 if ( otherSet._bits[i] != 0 ) 261 { 262 return false; 263 } 264 } 265 } 266 267 return true; 268 } 269 270 public bool Member( int el ) 271 { 272 if ( el < 0 ) 273 { 274 return false; 275 } 276 int n = WordNumber( el ); 277 if ( n >= _bits.Length ) 278 return false; 279 return ( _bits[n] & BitMask( el ) ) != 0; 280 } 281 282 // remove this element from this set 283 public void Remove( int el ) 284 { 285 int n = WordNumber( el ); 286 if ( n < _bits.Length ) 287 { 288 _bits[n] &= ~BitMask( el ); 289 } 290 } 291 292 public bool IsNil() 293 { 294 for ( int i = _bits.Length - 1; i >= 0; i-- ) 295 { 296 if ( _bits[i] != 0 ) 297 return false; 298 } 299 return true; 300 } 301 302 private static int NumWordsToHold( int el ) 303 { 304 return ( el >> LOG_BITS ) + 1; 305 } 306 307 public int NumBits() 308 { 309 return _bits.Length << LOG_BITS; // num words * bits per word 310 } 311 312 /** <summary>return how much space is being used by the bits array not how many actually have member bits on.</summary> */ 313 public int LengthInLongWords() 314 { 315 return _bits.Length; 316 } 317 318 /**Is this contained within a? */ 319 /* 320 public boolean subset(BitSet a) { 321 if (a == null || !(a instanceof BitSet)) return false; 322 return this.and(a).equals(this); 323 } 324 */ 325 326 public int[] ToArray() 327 { 328 int[] elems = new int[Size()]; 329 int en = 0; 330 for ( int i = 0; i < ( _bits.Length << LOG_BITS ); i++ ) 331 { 332 if ( Member( i ) ) 333 { 334 elems[en++] = i; 335 } 336 } 337 return elems; 338 } 339 340 private static int WordNumber( int bit ) 341 { 342 return bit >> LOG_BITS; // bit / BITS 343 } 344 345 public override string ToString() 346 { 347 return ToString( null ); 348 } 349 350 public string ToString( string[] tokenNames ) 351 { 352 StringBuilder buf = new StringBuilder(); 353 string separator = ","; 354 bool havePrintedAnElement = false; 355 buf.Append( '{' ); 356 357 for ( int i = 0; i < ( _bits.Length << LOG_BITS ); i++ ) 358 { 359 if ( Member( i ) ) 360 { 361 if ( i > 0 && havePrintedAnElement ) 362 { 363 buf.Append( separator ); 364 } 365 if ( tokenNames != null ) 366 { 367 buf.Append( tokenNames[i] ); 368 } 369 else 370 { 371 buf.Append( i ); 372 } 373 havePrintedAnElement = true; 374 } 375 } 376 buf.Append( '}' ); 377 return buf.ToString(); 378 } 379 } 380} 381