1/** 2 * A BitSet similar to java.util.BitSet. 3 * 4 * <p>JavaScript Note: There is no good way to implement something like this in 5 * JavaScript. JS has no true int type, arrays are usually implemented as 6 * hashes, etc. This class should probably be nixed for something that is 7 * similarly (in)efficient, but more clear.</p> 8 * 9 * @class 10 * @param {Number|Array} [bits] a 32 bit number or array of 32 bit numbers 11 * representing the bitset. These are typically 12 * generated by the ANTLR Tool. 13 */ 14org.antlr.runtime.BitSet = function(bits) { 15 if (!bits) { 16 bits = org.antlr.runtime.BitSet.BITS; 17 } 18 19 if (org.antlr.lang.isArray(bits)) { 20 /** 21 * An array of Numbers representing the BitSet. 22 * @type Array 23 */ 24 this.bits = bits; 25 } else if(org.antlr.lang.isNumber(bits)) { 26 this.bits = []; 27 } 28}; 29 30org.antlr.lang.augmentObject(org.antlr.runtime.BitSet, { 31 /** 32 * Number of bits in each number. 33 * @constant 34 * @memberOf org.antlr.runtime.BitSet 35 */ 36 BITS: 32, 37 38 /** 39 * Log (base 2) of the number of bits in each number. 40 * @constant 41 * @memberOf org.antlr.runtime.BitSet 42 */ 43 LOG_BITS: 5, // 2^5 == 32 44 45 /** 46 * We will often need to do a mod operator (i mod nbits). Its 47 * turns out that, for powers of two, this mod operation is 48 * same as (i & (nbits-1)). Since mod is slow, we use a 49 * precomputed mod mask to do the mod instead. 50 * @constant 51 * @memberOf org.antlr.runtime.BitSet 52 */ 53 MOD_MASK: 31, // BITS - 1 54 55 /** 56 * Create mask for bit modded to fit in a single word. 57 * @example 58 * bitmask(35) => 00000000000000000000000000000100 59 * bitmask(3) => 00000000000000000000000000000100 60 * @param {Number} bitNumber the bit to create a mask for. 61 * @returns {Number} the bitmask. 62 * @memberOf org.antlr.runtime.BitSet 63 * @private 64 */ 65 bitMask: function(bitNumber) { 66 var bitPosition = bitNumber & org.antlr.runtime.BitSet.MOD_MASK; 67 return 1 << bitPosition; 68 }, 69 70 /** 71 * Calculate the minimum number of bits needed to represent el. 72 * @param {Number} el a number to be included in the BitSet. 73 * @returns {Number} the number of bits need to create a BitSet with member 74 * el. 75 * @memberOf org.antlr.runtime.BitSet 76 * @private 77 */ 78 numWordsToHold: function(el) { 79 return (el >> org.antlr.runtime.BitSet.LOG_BITS) + 1; 80 }, 81 82 /** 83 * @param {Number} bit a number to be included in the BitSet 84 * @returns {Number} the index of the word in the field bits that would 85 * hold bit. 86 * @memberOf org.antlr.runtime.BitSet 87 * @private 88 */ 89 wordNumber: function(bit) { 90 return bit >> org.antlr.runtime.BitSet.LOG_BITS; // bit / BITS 91 }, 92 93 /** 94 * BitSet factory method. 95 * 96 * <p>Operates in a number of modes: 97 * <ul> 98 * <li>If el is a number create the BitSet containing that number.</li> 99 * <li>If el is an array create the BitSet containing each number in the 100 * array.</li> 101 * <li>If el is a BitSet return el.</li> 102 * <li>If el is an Object create the BitSet containing each numeric value 103 * in el.</li> 104 * <li>If el is a number and el2 is a number return a BitSet containing 105 * the numbers between el and el2 (inclusive).</li> 106 * </ul> 107 * </p> 108 * @param {Number|Array|org.antlr.runtime.BitSet|Object} el 109 * @param {Number} el2 110 * @returns {org.antlr.runtime.BitSet} 111 * @memberOf org.antlr.runtime.BitSet 112 */ 113 of: function(el, el2) { 114 var i, n, s, keys; 115 116 if (org.antlr.lang.isNumber(el)) { 117 if (org.antlr.lang.isNumber(el2)) { 118 s = new org.antlr.runtime.BitSet(el2 + 1); 119 for (i = el; i <= el2; i++) { 120 n = org.antlr.runtime.BitSet.wordNumber(i); 121 s.bits[n] |= org.antlr.runtime.BitSet.bitMask(i); 122 } 123 return s; 124 } else { 125 s = new org.antlr.runtime.BitSet(el + 1); 126 s.add(el); 127 return s; 128 } 129 } else if(org.antlr.lang.isArray(el)) { 130 s = new org.antlr.runtime.BitSet(); 131 for (i=el.length-1; i>=0; i--) { 132 s.add(el[i]); 133 } 134 return s; 135 } else if (el instanceof org.antlr.runtime.BitSet) { 136 if (!el) { 137 return null; 138 } 139 return el; 140 } else if (el instanceof org.antlr.runtime.IntervalSet) { 141 if (!el) { 142 return null; 143 } 144 s = new org.antlr.runtime.BitSet(); 145 s.addAll(el); 146 return s; 147 } else if (org.antlr.lang.isObject(el)) { 148 keys = []; 149 for (i in el) { 150 if (org.antlr.lang.isNumber(i)) { 151 keys.push(i); 152 } 153 } 154 return org.antlr.runtime.BitSet.of(keys); 155 } 156 } 157}); 158 159 160 161org.antlr.runtime.BitSet.prototype = { 162 /** 163 * Add el into this set. 164 * @param {Number} el the number to add to the set. 165 */ 166 add: function(el) { 167 var n = org.antlr.runtime.BitSet.wordNumber(el); 168 if (n >= this.bits.length) { 169 this.growToInclude(el); 170 } 171 this.bits[n] |= org.antlr.runtime.BitSet.bitMask(el); 172 }, 173 174 /** 175 * Add multiple elements into this set. 176 * @param {Array|org.antlr.runtime.BitSet} elements the elements to be added to 177 * this set. 178 */ 179 addAll: function(elements) { 180 var other, 181 i, 182 e; 183 184 if ( elements instanceof org.antlr.runtime.BitSet ) { 185 this.orInPlace(elements); 186 } 187 else if ( elements instanceof org.antlr.runtime.IntervalSet ) { 188 other = elements; 189 // walk set and add each interval 190 /* @todo after implementing intervalset 191 for (Iterator iter = other.intervals.iterator(); iter.hasNext();) { 192 Interval I = (Interval) iter.next(); 193 this.orInPlace(BitSet.range(I.a,I.b)); 194 }*/ 195 } else if (org.antlr.lang.isArray(elements)) { 196 for (i = 0; i < elements.length; i++) { 197 e = elements[i]; 198 this.add(e); 199 } 200 } else { 201 return; 202 } 203 }, 204 205 /** 206 * Clone this BitSet and then {@link #andInPlace} with a. 207 * @param {org.antlr.runtime.BitSet} a a bit set. 208 * @returns {org.antlr.runtime.BitSet} 209 */ 210 and: function(a) { 211 var s = this.clone(); 212 s.andInPlace(a); 213 return s; 214 }, 215 216 /** 217 * Perform a logical AND of this target BitSet with the argument BitSet. 218 * 219 * This bit set is modified so that each bit in it has the value true if 220 * and only if it both initially had the value true and the corresponding 221 * bit in the bit set argument also had the value true. 222 * @param {org.antlr.runtime.BitSet} a a bit set. 223 * @returns {org.antlr.runtime.BitSet} 224 */ 225 andInPlace: function(a) { 226 var min = Math.min(this.bits.length, a.bits.length), 227 i; 228 for (i = min - 1; i >= 0; i--) { 229 this.bits[i] &= a.bits[i]; 230 } 231 // clear all bits in this not present in a (if this bigger than a). 232 for (i = min; i < this.bits.length; i++) { 233 this.bits[i] = 0; 234 } 235 }, 236 237 /** 238 * Clear all bits or a specific bit. 239 * 240 * If no arguments given, sets all of the bits in this BitSet to false. 241 * If one argument given, sets the bit specified by the index to false. 242 * @param {Number} [el] the index of the bit to be cleared. 243 */ 244 clear: function(el) { 245 if (arguments.length===0) { 246 var i; 247 for (i = this.bits.length - 1; i >= 0; i--) { 248 this.bits[i] = 0; 249 } 250 return; 251 } 252 253 var n = org.antlr.runtime.BitSet.wordNumber(el); 254 if (n >= this.bits.length) { // grow as necessary to accommodate 255 this.growToInclude(el); 256 } 257 this.bits[n] &= ~org.antlr.runtime.BitSet.bitMask(el); 258 }, 259 260 /** 261 * Cloning this BitSet produces a new BitSet that is equal to it. 262 * 263 * The clone of the bit set is another bit set that has exactly the same 264 * bit set to true as this bit set. 265 * @returns {org.antlr.runtime.BitSet} a clone of this BitSet. 266 */ 267 clone: function() { 268 var i, len, b=[]; 269 for (i=0, len=this.bits.length; i<len; i++) { 270 b[i] = this.bits[i]; 271 } 272 return new org.antlr.runtime.BitSet(b); 273 }, 274 275 /** 276 * Returns the number of bits of space actually in use by this BitSet to 277 * represent bit values. 278 * 279 * The maximum element in the set is the size - 1st element. 280 * @returns {Number} the number of bits currently in this bit set. 281 */ 282 size: function() { 283 var deg = 0, i, word, bit; 284 for (i = this.bits.length - 1; i >= 0; i--) { 285 word = this.bits[i]; 286 if (word !== 0) { 287 for (bit = org.antlr.runtime.BitSet.BITS - 1; bit >= 0; bit--) { 288 if ((word & (1 << bit)) !== 0) { 289 deg++; 290 } 291 } 292 } 293 } 294 return deg; 295 }, 296 297 /** 298 * Compares this object against the specified object. 299 * 300 * The result is true if and only if the argument is not null and is a 301 * BitSet object that has exactly the same set of bits set to true as 302 * this bit set. That is, for every nonnegative int index k, 303 * <pre><code> 304 * ((BitSet)obj).get(k) == this.get(k) 305 * </code></pre> 306 * must be true. The current sizes of the two bit sets are not compared. 307 * @param {Object} other the object to compare with. 308 * @returns {Boolean} if the objects are the same; false otherwise. 309 */ 310 equals: function(other) { 311 if ( !other || !(other instanceof org.antlr.runtime.BitSet) ) { 312 return false; 313 } 314 315 var otherSet = other, 316 i, 317 n = Math.min(this.bits.length, otherSet.bits.length); 318 319 // for any bits in common, compare 320 for (i=0; i<n; i++) { 321 if (this.bits[i] != otherSet.bits[i]) { 322 return false; 323 } 324 } 325 326 // make sure any extra bits are off 327 328 if (this.bits.length > n) { 329 for (i = n+1; i<this.bits.length; i++) { 330 if (this.bits[i] !== 0) { 331 return false; 332 } 333 } 334 } 335 else if (otherSet.bits.length > n) { 336 for (i = n+1; i<otherSet.bits.length; i++) { 337 if (otherSet.bits[i] !== 0) { 338 return false; 339 } 340 } 341 } 342 343 return true; 344 }, 345 346 /** 347 * Grows the set to a larger number of bits. 348 * @param {Number} bit element that must fit in set 349 * @private 350 */ 351 growToInclude: function(bit) { 352 var newSize = Math.max(this.bits.length << 1, org.antlr.runtime.BitSet.numWordsToHold(bit)), 353 newbits = [], //new Array(newSize), 354 i, 355 len; 356 for (i=0, len=this.bits.length; i<len; i++) { 357 newbits[i] = this.bits[i]; 358 } 359 this.bits = newbits; 360 }, 361 362 /** 363 * Returns the value of the bit with the specified index. 364 * 365 * The value is true if the bit with the index el is currently set 366 * in this BitSet; otherwise, the result is false. 367 * @param {Number} el the bit index. 368 * @returns {Boolean} the value of the bit with the specified index. 369 */ 370 member: function(el) { 371 var n = org.antlr.runtime.BitSet.wordNumber(el); 372 if (n >= this.bits.length) { return false; } 373 return (this.bits[n] & org.antlr.runtime.BitSet.bitMask(el)) !== 0; 374 }, 375 376 /** 377 * Returns the index of the first bit that is set to true. 378 * If no such bit exists then -1 is returned. 379 * @returns {Number} the index of the next set bit. 380 */ 381 getSingleElement: function() { 382 var i; 383 for (i = 0; i < (this.bits.length << org.antlr.runtime.BitSet.LOG_BITS); i++) { 384 if (this.member(i)) { 385 return i; 386 } 387 } 388 return -1; //Label.INVALID; 389 }, 390 391 /** 392 * Returns true if this BitSet contains no bits that are set to true. 393 * @returns {Boolean} boolean indicating whether this BitSet is empty. 394 */ 395 isNil: function() { 396 var i; 397 for (i = this.bits.length - 1; i >= 0; i--) { 398 if (this.bits[i] !== 0) { 399 return false; 400 } 401 } 402 return true; 403 }, 404 405 /** 406 * If a bit set argument is passed performs a {@link #subtract} of this bit 407 * set with the argument bit set. If no argument is passed, clone this bit 408 * set and {@link #notInPlace}. 409 * @param {org.antlr.runtime.BitSet} [set] 410 * @returns {org.antlr.runtime.BitSet} 411 */ 412 complement: function(set) { 413 if (set) { 414 return set.subtract(this); 415 } else { 416 var s = this.clone(); 417 s.notInPlace(); 418 return s; 419 } 420 }, 421 422 /** 423 * If no arguments are passed sets all bits to the complement of their 424 * current values. If one argument is passed sets each bit from the 425 * beginning of the bit set to index1 (inclusive) to the complement of its 426 * current value. If two arguments are passed sets each bit from the 427 * specified index1 (inclusive) to the sepcified index2 (inclusive) to the 428 * complement of its current value. 429 * @param {Number} index1 430 * @param {Number} index2 431 */ 432 notInPlace: function() { 433 var minBit, maxBit, i, n; 434 if (arguments.length===0) { 435 for (i = this.bits.length - 1; i >= 0; i--) { 436 this.bits[i] = ~this.bits[i]; 437 } 438 } else { 439 if (arguments.length===1) { 440 minBit = 0; 441 maxBit = arguments[0]; 442 } else { 443 minBit = arguments[0]; 444 maxBit = arguments[1]; 445 } 446 // make sure that we have room for maxBit 447 this.growToInclude(maxBit); 448 for (i = minBit; i <= maxBit; i++) { 449 n = org.antlr.runtime.BitSet.wordNumber(i); 450 this.bits[n] ^= org.antlr.runtime.BitSet.bitMask(i); 451 } 452 } 453 454 }, 455 456 /** 457 * Performs a logical OR of this bit set with the bit set argument. 458 * If no argument is passed, return this bit set. Otherwise a clone of 459 * this bit set is modified so that a bit in it has the value true if and 460 * only if it either already had the value true or the corresponding bit 461 * in the bit set argument has the value true. 462 * @param {org.antlr.runtime.BitSet} [a] a bit set. 463 * @returns {org.antlr.runtime.BitSet} 464 */ 465 or: function(a) { 466 if ( !a ) { 467 return this; 468 } 469 var s = this.clone(); 470 s.orInPlace(a); 471 return s; 472 }, 473 474 /** 475 * Performs a logical {@link #or} in place. 476 * @param {org.antlr.runtime.BitSet} [a] 477 * @returns {org.antlr.runtime.BitSet} 478 */ 479 orInPlace: function(a) { 480 if ( !a ) { 481 return; 482 } 483 // If this is smaller than a, grow this first 484 if (a.bits.length > this.bits.length) { 485 this.setSize(a.bits.length); 486 } 487 var min = Math.min(this.bits.length, a.bits.length), 488 i; 489 for (i = min - 1; i >= 0; i--) { 490 this.bits[i] |= a.bits[i]; 491 } 492 }, 493 494 /** 495 * Sets the bit specified by the index to false. 496 * @param {Number} bitIndex the index of the bit to be cleared. 497 */ 498 remove: function(el) { 499 var n = org.antlr.runtime.BitSet.wordNumber(el); 500 if (n >= this.bits.length) { 501 this.growToInclude(el); 502 } 503 this.bits[n] &= ~org.antlr.runtime.BitSet.bitMask(el); 504 }, 505 506 /** 507 * Grows the internal bits array to include at least nwords numbers. 508 * @param {Number} nwords how many words the new set should be 509 * @private 510 */ 511 setSize: function(nwords) { 512 var n = nwords - this.bits.length; 513 while (n>=0) { 514 this.bits.push(0); 515 n--; 516 } 517 }, 518 519 /** 520 * Returns the number of bits capable of being represented by this bit set 521 * given its current size. 522 * @returns {Number} the maximum number of bits that can be represented at 523 * the moment. 524 * @private 525 */ 526 numBits: function() { 527 return this.bits.length << org.antlr.runtime.BitSet.LOG_BITS; // num words * bits per word 528 }, 529 530 /** 531 * Return how much space is being used by the bits array not 532 * how many actually have member bits on. 533 * @returns {Number} the length of the internal bits array. 534 * @private 535 */ 536 lengthInLongWords: function() { 537 return this.bits.length; 538 }, 539 540 /** 541 * Is this bit set contained within a? 542 * @param {org.antlr.runtime.BitSet} a bit set 543 * @returns {Boolean} true if and only if a is a subset of this bit set. 544 */ 545 subset: function(a) { 546 if (!a) { return false; } 547 return this.and(a).equals(this); 548 }, 549 550 /** 551 * Subtract the elements of the argument bit set from this bit set in place. 552 * That is, for each set bit in the argument bit set, set the corresponding 553 * bit in this bit set to false. 554 * @param {org.antlr.runtime.BitSet} a bit set. 555 */ 556 subtractInPlace: function(a) { 557 if (!a) { return; } 558 // for all words of 'a', turn off corresponding bits of 'this' 559 var i; 560 for (i = 0; i < this.bits.length && i < a.bits.length; i++) { 561 this.bits[i] &= ~a.bits[i]; 562 } 563 }, 564 565 /** 566 * Perform a {@link #subtractInPlace} on a clone of this bit set. 567 * @param {org.antlr.runtime.BitSet} a bit set. 568 * @returns {org.antlr.runtime.BitSet} the new bit set. 569 */ 570 subtract: function(a) { 571 if (!a || !(a instanceof org.antlr.runtime.BitSet)) { return null; } 572 573 var s = this.clone(); 574 s.subtractInPlace(a); 575 return s; 576 }, 577 578 /* antlr-java needs this to make its class hierarchy happy . . . 579 toList: function() { 580 throw new Error("BitSet.toList() unimplemented"); 581 }, 582 */ 583 584 /** 585 * Creates an array of the indexes of each bit set in this bit set. 586 * @returns {Array} 587 */ 588 toArray: function() { 589 var elems = [], //new Array(this.size()), 590 i, 591 en = 0; 592 for (i = 0; i < (this.bits.length << org.antlr.runtime.BitSet.LOG_BITS); i++) { 593 if (this.member(i)) { 594 elems[en++] = i; 595 } 596 } 597 return elems; 598 }, 599 600 /** 601 * Returns the internal representation of this bit set. 602 * This representation is an array of numbers, each representing 32 bits. 603 * @returns {Array} 604 */ 605 toPackedArray: function() { 606 return this.bits; 607 }, 608 609 /** 610 * Returns a string representation of this bit set. 611 * <p>For every index for which this BitSet contains a bit in the set state, 612 * the decimal representation of that index is included in the result. 613 * Such indices are listed in order from lowest to highest, separated by 614 * ", " (a comma and a space) and surrounded by braces, resulting in the 615 * usual mathematical notation for a set of integers.</p> 616 * 617 * <p>If a grammar g is passed, print g.getTokenDisplayName(i) for each set 618 * index instead of the numerical index.</p> 619 * 620 * <>If two arguments are passed, the first will be used as a custom 621 * separator string. The second argument is an array whose i-th element 622 * will be added if the corresponding bit is set.</p> 623 * 624 * @param {Object|String} [arg1] an Object with function property 625 * getTokenDispalyName or a String that will be used as a list 626 * separator. 627 * @param {Array} [vocabulary] array from which the i-th value will be 628 * drawn if the corresponding bit is set. Must pass a string as the 629 * first argument if using this option. 630 * @return A commma-separated list of values 631 */ 632 toString: function() { 633 if (arguments.length===0) { 634 return this.toString1(null); 635 } else { 636 if (org.antlr.lang.isString(arguments[0])) { 637 if (!org.antlr.lang.isValue(arguments[1])) { 638 return this.toString1(null); 639 } else { 640 return this.toString2(arguments[0], arguments[1]); 641 } 642 } else { 643 return this.toString1(arguments[0]); 644 } 645 } 646 }, 647 648 /** 649 * Transform a bit set into a string by formatting each element as an 650 * integer separator The string to put in between elements 651 * @private 652 * @return A commma-separated list of values 653 */ 654 toString1: function(g) { 655 var buf = "{", 656 separator = ",", 657 i, 658 havePrintedAnElement = false; 659 660 for (i = 0; i < (this.bits.length << org.antlr.runtime.BitSet.LOG_BITS); i++) { 661 if (this.member(i)) { 662 if (i > 0 && havePrintedAnElement ) { 663 buf += separator; 664 } 665 if ( g ) { 666 buf += g.getTokenDisplayName(i); 667 } 668 else { 669 buf += i.toString(); 670 } 671 havePrintedAnElement = true; 672 } 673 } 674 return buf + "}"; 675 }, 676 677 /** 678 * Create a string representation where instead of integer elements, the 679 * ith element of vocabulary is displayed instead. Vocabulary is a Vector 680 * of Strings. 681 * separator The string to put in between elements 682 * @private 683 * @return A commma-separated list of character constants. 684 */ 685 toString2: function(separator, vocabulary) { 686 var str = "", 687 i; 688 for (i = 0; i < (this.bits.length << org.antlr.runtime.BitSet.LOG_BITS); i++) { 689 if (this.member(i)) { 690 if (str.length > 0) { 691 str += separator; 692 } 693 if (i >= vocabulary.size()) { 694 str += "'" + i + "'"; 695 } 696 else if (!org.antlr.lang.isValue(vocabulary.get(i))) { 697 str += "'" + i + "'"; 698 } 699 else { 700 str += vocabulary.get(i); 701 } 702 } 703 } 704 return str; 705 } 706}; 707