antlr4ng
Version:
Alternative JavaScript/TypeScript runtime for ANTLR4
873 lines (863 loc) • 22.1 kB
JavaScript
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
// src/utils/MurmurHash.ts
var c1 = 3432918353;
var c2 = 461845907;
var r1 = 15;
var r2 = 13;
var m = 5;
var n = 3864292196;
var MurmurHash = class _MurmurHash {
static {
__name(this, "MurmurHash");
}
static defaultSeed = 701;
constructor() {
}
/**
* Initialize the hash using the specified {@code seed}.
*
* @param seed the seed
*
* @returns the intermediate hash value
*/
static initialize(seed = _MurmurHash.defaultSeed) {
return seed;
}
static updateFromComparable(hash, value) {
return this.update(hash, value?.hashCode() ?? 0);
}
/**
* Update the intermediate hash value for the next input {@code value}.
*
* @param hash The intermediate hash value.
* @param value the value to add to the current hash.
*
* @returns the updated intermediate hash value
*/
static update(hash, value) {
value = Math.imul(value, c1);
value = value << r1 | value >>> 32 - r1;
value = Math.imul(value, c2);
hash = hash ^ value;
hash = hash << r2 | hash >>> 32 - r2;
hash = Math.imul(hash, m) + n;
return hash;
}
/**
* Apply the final computation steps to the intermediate value {@code hash}
* to form the final result of the MurmurHash 3 hash function.
*
* @param hash The intermediate hash value.
* @param entryCount The number of values added to the hash.
*
* @returns the final hash result
*/
static finish(hash, entryCount) {
hash ^= entryCount * 4;
hash ^= hash >>> 16;
hash = Math.imul(hash, 2246822507);
hash ^= hash >>> 13;
hash = Math.imul(hash, 3266489909);
hash ^= hash >>> 16;
return hash;
}
/**
* An all-in-one convenience method to compute a hash for a single value.
*
* @param value The value to hash.
* @param seed The seed for the hash value.
*
* @returns The computed hash.
*/
static hashCode(value, seed) {
return _MurmurHash.finish(_MurmurHash.update(seed ?? _MurmurHash.defaultSeed, value), 1);
}
};
// src/misc/ObjectEqualityComparator.ts
var ObjectEqualityComparator = class _ObjectEqualityComparator {
static {
__name(this, "ObjectEqualityComparator");
}
static instance = new _ObjectEqualityComparator();
hashCode(obj) {
if (obj == null) {
return 0;
}
return obj.hashCode();
}
equals(a, b) {
if (a == null) {
return b == null;
}
return a.equals(b);
}
};
// src/misc/DefaultEqualityComparator.ts
var DefaultEqualityComparator = class _DefaultEqualityComparator {
static {
__name(this, "DefaultEqualityComparator");
}
static instance = new _DefaultEqualityComparator();
hashCode(obj) {
if (obj == null) {
return 0;
}
return ObjectEqualityComparator.instance.hashCode(obj);
}
equals(a, b) {
if (a == null) {
return b == null;
}
if (typeof a === "string" || typeof a === "number") {
return a === b;
}
return ObjectEqualityComparator.instance.equals(a, b);
}
};
// src/misc/HashSet.ts
var HashSet = class _HashSet {
static {
__name(this, "HashSet");
}
static defaultLoadFactor = 0.75;
static initialCapacity = 16;
// must be power of 2
comparator;
buckets;
threshold;
/** How many elements in set */
itemCount = 0;
constructor(comparatorOrSet, initialCapacity = _HashSet.initialCapacity) {
if (comparatorOrSet instanceof _HashSet) {
this.comparator = comparatorOrSet.comparator;
this.buckets = comparatorOrSet.buckets.slice(0);
for (let i = 0; i < this.buckets.length; i++) {
const bucket = this.buckets[i];
if (bucket) {
this.buckets[i] = bucket.slice(0);
}
}
this.itemCount = comparatorOrSet.itemCount;
this.threshold = comparatorOrSet.threshold;
} else {
this.comparator = comparatorOrSet ?? DefaultEqualityComparator.instance;
this.buckets = this.createBuckets(initialCapacity);
this.threshold = Math.floor(_HashSet.initialCapacity * _HashSet.defaultLoadFactor);
}
}
/**
* Add `o` to set if not there; return existing value if already
* there. This method performs the same operation as {@link #add} aside from
* the return value.
*
* @param o the object to add to the set.
*
* @returns An existing element that equals to `o` if already in set, otherwise `o`.
*/
getOrAdd(o) {
if (this.itemCount > this.threshold) {
this.expand();
}
const b = this.getBucket(o);
let bucket = this.buckets[b];
if (!bucket) {
bucket = [o];
this.buckets[b] = bucket;
++this.itemCount;
return o;
}
for (const existing of bucket) {
if (this.comparator.equals(existing, o)) {
return existing;
}
}
bucket.push(o);
++this.itemCount;
return o;
}
get(o) {
if (o == null) {
return o;
}
const b = this.getBucket(o);
const bucket = this.buckets[b];
if (!bucket) {
return void 0;
}
for (const e of bucket) {
if (this.comparator.equals(e, o)) {
return e;
}
}
return void 0;
}
/**
* Removes the specified element from this set if it is present.
*
* @param o object to be removed from this set, if present.
*
* @returns `true` if the set contained the specified element.
*/
remove(o) {
if (o == null) {
return false;
}
const b = this.getBucket(o);
const bucket = this.buckets[b];
if (!bucket) {
return false;
}
for (let i = 0; i < bucket.length; i++) {
const existing = bucket[i];
if (this.comparator.equals(existing, o)) {
bucket.splice(i, 1);
--this.itemCount;
return true;
}
}
return false;
}
hashCode() {
let hash = MurmurHash.initialize();
for (const bucket of this.buckets) {
if (bucket == null) {
continue;
}
for (const o of bucket) {
if (o == null) {
break;
}
hash = MurmurHash.update(hash, this.comparator.hashCode(o));
}
}
hash = MurmurHash.finish(hash, this.size);
return hash;
}
equals(o) {
if (o === this) {
return true;
}
if (!(o instanceof _HashSet)) {
return false;
}
if (o.size !== this.size) {
return false;
}
return this.containsAll(o);
}
add(t) {
const existing = this.getOrAdd(t);
return existing === t;
}
contains(o) {
return this.containsFast(o);
}
containsFast(obj) {
if (obj == null) {
return false;
}
return this.get(obj) !== void 0;
}
*[Symbol.iterator]() {
yield* this.toArray();
}
toArray() {
const a = new Array(this.size);
let i = 0;
for (const bucket of this.buckets) {
if (bucket == null) {
continue;
}
for (const o of bucket) {
if (o == null) {
break;
}
a[i++] = o;
}
}
return a;
}
containsAll(collection) {
if (collection instanceof _HashSet) {
for (const bucket of collection.buckets) {
if (bucket == null) {
continue;
}
for (const o of bucket) {
if (o == null) {
break;
}
if (!this.containsFast(o)) {
return false;
}
}
}
} else {
for (const o of collection) {
if (!this.containsFast(o)) {
return false;
}
}
}
return true;
}
addAll(c) {
let changed = false;
for (const o of c) {
const existing = this.getOrAdd(o);
if (existing !== o) {
changed = true;
}
}
return changed;
}
clear() {
this.buckets = this.createBuckets(_HashSet.initialCapacity);
this.itemCount = 0;
this.threshold = Math.floor(_HashSet.initialCapacity * _HashSet.defaultLoadFactor);
}
toString() {
if (this.size === 0) {
return "{}";
}
let buf = "{";
let first = true;
for (const bucket of this.buckets) {
if (bucket == null) {
continue;
}
for (const o of bucket) {
if (o == null) {
break;
}
if (first) {
first = false;
} else {
buf += ", ";
}
buf += o.toString();
}
}
buf += "}";
return buf;
}
toTableString() {
let buf = "";
for (const bucket of this.buckets) {
if (bucket == null) {
buf += "null\n";
continue;
}
buf += "[";
let first = true;
for (const o of bucket) {
if (first) {
first = false;
} else {
buf += " ";
}
if (o == null) {
buf += "_";
} else {
buf += o.toString();
}
}
buf += "]\n";
}
return buf;
}
getBucket(o) {
const hash = this.comparator.hashCode(o);
const b = hash & this.buckets.length - 1;
return b;
}
expand() {
const old = this.buckets;
const newCapacity = this.buckets.length * 2;
const newTable = this.createBuckets(newCapacity);
this.buckets = newTable;
this.threshold = Math.floor(newCapacity * _HashSet.defaultLoadFactor);
for (const bucket of old) {
if (!bucket) {
continue;
}
for (const o of bucket) {
const b = this.getBucket(o);
let newBucket = this.buckets[b];
if (!newBucket) {
newBucket = [];
this.buckets[b] = newBucket;
}
newBucket.push(o);
}
}
}
get size() {
return this.itemCount;
}
get isEmpty() {
return this.itemCount === 0;
}
/**
* Return an array of `T[]` with length `capacity`.
*
* @param capacity the length of the array to return
* @returns the newly constructed array
*/
createBuckets(capacity) {
return new Array(capacity);
}
};
// src/utils/helpers.ts
var equalArrays = /* @__PURE__ */ __name((a, b) => {
if (a === b) {
return true;
}
if (a.length !== b.length) {
return false;
}
for (let i = 0; i < a.length; i++) {
const left = a[i];
const right = b[i];
if (left === right) {
continue;
}
if (!left || !left.equals(right)) {
return false;
}
}
return true;
}, "equalArrays");
// src/atn/SemanticContext.ts
var SemanticContext = class _SemanticContext {
static {
__name(this, "SemanticContext");
}
cachedHashCode;
static andContext(a, b) {
if (a === null || a === _SemanticContext.NONE) {
return b;
}
if (b === null || b === _SemanticContext.NONE) {
return a;
}
const result = new AND(a, b);
if (result.operands.length === 1) {
return result.operands[0];
}
return result;
}
static orContext(a, b) {
if (a === null) {
return b;
}
if (b === null) {
return a;
}
if (a === _SemanticContext.NONE || b === _SemanticContext.NONE) {
return _SemanticContext.NONE;
}
const result = new OR(a, b);
if (result.operands.length === 1) {
return result.operands[0];
} else {
return result;
}
}
static filterPrecedencePredicates(set) {
const result = [];
for (const context of set) {
if (context instanceof _SemanticContext.PrecedencePredicate) {
result.push(context);
}
}
return result;
}
/**
* Evaluate the precedence predicates for the context and reduce the result.
*
* @param _parser The parser instance.
* @param _parserCallStack The current parser context object.
* @returns The simplified semantic context after precedence predicates are
* evaluated, which will be one of the following values.
* - {@link NONE}: if the predicate simplifies to `true` after
* precedence predicates are evaluated.
* - `null`: if the predicate simplifies to `false` after
* precedence predicates are evaluated.
* - `this`: if the semantic context is not changed as a result of
* precedence predicate evaluation.
* - A non-`null` {@link SemanticContext}: the new simplified
* semantic context after precedence predicates are evaluated.
*/
evalPrecedence(_parser, _parserCallStack) {
return this;
}
};
var AND = class _AND extends SemanticContext {
static {
__name(this, "AND");
}
operands;
/**
* A semantic context which is true whenever none of the contained contexts
* is false
*/
constructor(a, b) {
super();
const operands = new HashSet();
if (a instanceof _AND) {
a.operands.forEach((o) => {
operands.add(o);
});
} else {
operands.add(a);
}
if (b instanceof _AND) {
b.operands.forEach((o) => {
operands.add(o);
});
} else {
operands.add(b);
}
const precedencePredicates = SemanticContext.filterPrecedencePredicates(operands);
if (precedencePredicates.length > 0) {
let reduced = null;
precedencePredicates.forEach((p) => {
if (reduced === null || p.precedence < reduced.precedence) {
reduced = p;
}
});
if (reduced) {
operands.add(reduced);
}
}
this.operands = operands.toArray();
}
equals(other) {
if (this === other) {
return true;
}
if (!(other instanceof _AND)) {
return false;
}
return equalArrays(this.operands, other.operands);
}
hashCode() {
if (this.cachedHashCode === void 0) {
let hash = MurmurHash.initialize();
for (const operand of this.operands) {
hash = MurmurHash.updateFromComparable(hash, operand);
}
hash = MurmurHash.update(hash, 3813686060);
this.cachedHashCode = MurmurHash.finish(hash, this.operands.length + 1);
}
return this.cachedHashCode;
}
/**
* {@inheritDoc}
*
*
* The evaluation of predicates by this context is short-circuiting, but
* unordered.
*/
evaluate(parser, parserCallStack) {
for (const operand of this.operands) {
if (!operand.evaluate(parser, parserCallStack)) {
return false;
}
}
return true;
}
evalPrecedence(parser, parserCallStack) {
let differs = false;
const operands = [];
for (const context of this.operands) {
const evaluated = context.evalPrecedence(parser, parserCallStack);
differs ||= evaluated !== context;
if (evaluated === null) {
return null;
} else if (evaluated !== SemanticContext.NONE) {
operands.push(evaluated);
}
}
if (!differs) {
return this;
}
if (operands.length === 0) {
return SemanticContext.NONE;
}
let result = null;
operands.forEach((o) => {
result = result === null ? o : SemanticContext.andContext(result, o);
});
return result;
}
toString() {
const s = this.operands.map((o) => {
return o.toString();
});
return (s.length > 3 ? s.slice(3) : s).join("&&");
}
};
var OR = class _OR extends SemanticContext {
static {
__name(this, "OR");
}
operands;
/**
* A semantic context which is true whenever at least one of the contained
* contexts is true
*/
constructor(a, b) {
super();
const operands = new HashSet();
if (a instanceof _OR) {
a.operands.forEach((o) => {
operands.add(o);
});
} else {
operands.add(a);
}
if (b instanceof _OR) {
b.operands.forEach((o) => {
operands.add(o);
});
} else {
operands.add(b);
}
const precedencePredicates = SemanticContext.filterPrecedencePredicates(operands);
if (precedencePredicates.length > 0) {
const s = precedencePredicates.sort((a2, b2) => {
return a2.compareTo(b2);
});
const reduced = s[s.length - 1];
operands.add(reduced);
}
this.operands = operands.toArray();
}
equals(other) {
if (this === other) {
return true;
} else if (!(other instanceof _OR)) {
return false;
} else {
return equalArrays(this.operands, other.operands);
}
}
hashCode() {
if (this.cachedHashCode === void 0) {
let hash = MurmurHash.initialize();
for (const operand of this.operands) {
hash = MurmurHash.updateFromComparable(hash, operand);
}
hash = MurmurHash.update(hash, 3383313031);
this.cachedHashCode = MurmurHash.finish(hash, this.operands.length + 1);
}
return this.cachedHashCode;
}
/**
* The evaluation of predicates by this context is short-circuiting, but unordered.
*/
evaluate(parser, parserCallStack) {
for (const operand of this.operands) {
if (operand.evaluate(parser, parserCallStack)) {
return true;
}
}
return false;
}
evalPrecedence(parser, parserCallStack) {
let differs = false;
const operands = [];
for (const context of this.operands) {
const evaluated = context.evalPrecedence(parser, parserCallStack);
differs ||= evaluated !== context;
if (evaluated === SemanticContext.NONE) {
return SemanticContext.NONE;
} else if (evaluated !== null) {
operands.push(evaluated);
}
}
if (!differs) {
return this;
}
if (operands.length === 0) {
return null;
}
let result = null;
operands.forEach((o) => {
result = result === null ? o : SemanticContext.orContext(result, o);
});
return result;
}
toString() {
const s = this.operands.map((o) => {
return o.toString();
});
return (s.length > 3 ? s.slice(3) : s).join("||");
}
};
((SemanticContext2) => {
class Predicate extends SemanticContext2 {
static {
__name(this, "Predicate");
}
ruleIndex;
predIndex;
isCtxDependent;
// e.g., $i ref in pred
constructor(ruleIndex, predIndex, isCtxDependent) {
super();
this.ruleIndex = ruleIndex ?? -1;
this.predIndex = predIndex ?? -1;
this.isCtxDependent = isCtxDependent ?? false;
}
evaluate(parser, outerContext) {
const localctx = this.isCtxDependent ? outerContext : null;
return parser.sempred(localctx, this.ruleIndex, this.predIndex);
}
hashCode() {
if (this.cachedHashCode === void 0) {
let hashCode = MurmurHash.initialize();
hashCode = MurmurHash.update(hashCode, this.ruleIndex);
hashCode = MurmurHash.update(hashCode, this.predIndex);
hashCode = MurmurHash.update(hashCode, this.isCtxDependent ? 1 : 0);
hashCode = MurmurHash.finish(hashCode, 3);
this.cachedHashCode = hashCode;
}
return this.cachedHashCode;
}
equals(other) {
if (this === other) {
return true;
}
return this.ruleIndex === other.ruleIndex && this.predIndex === other.predIndex && this.isCtxDependent === other.isCtxDependent;
}
toString() {
return "{" + this.ruleIndex + ":" + this.predIndex + "}?";
}
}
SemanticContext2.Predicate = Predicate;
class PrecedencePredicate extends SemanticContext2 {
static {
__name(this, "PrecedencePredicate");
}
precedence;
constructor(precedence) {
super();
this.precedence = precedence ?? 0;
}
evaluate(parser, outerContext) {
return parser.precpred(outerContext, this.precedence);
}
evalPrecedence(parser, outerContext) {
if (parser.precpred(outerContext ?? null, this.precedence)) {
return SemanticContext2.NONE;
}
return null;
}
compareTo(other) {
return this.precedence - other.precedence;
}
hashCode() {
return 31 + this.precedence;
}
equals(other) {
if (this === other) {
return true;
}
return this.precedence === other.precedence;
}
toString() {
return "{" + this.precedence + ">=prec}?";
}
}
SemanticContext2.PrecedencePredicate = PrecedencePredicate;
SemanticContext2.NONE = new Predicate();
})(SemanticContext || (SemanticContext = {}));
// src/atn/Transition.ts
var Transition = class {
static {
__name(this, "Transition");
}
static INVALID = 0;
static EPSILON = 1;
static RANGE = 2;
static RULE = 3;
static PREDICATE = 4;
// e.g., {isType(input.LT(1))}
static ATOM = 5;
static ACTION = 6;
static SET = 7;
// ~(A|B) or ~atom, wildcard, which convert to next
static NOT_SET = 8;
static WILDCARD = 9;
static PRECEDENCE = 10;
/** The target of this transition. */
target;
constructor(target) {
this.target = target;
}
/**
* Determines if the transition is an "epsilon" transition.
*
* The default implementation returns `false`.
*
* @returns `true` if traversing this transition in the ATN does not
* consume an input symbol; otherwise, `false` if traversing this
* transition consumes (matches) an input symbol.
*/
get isEpsilon() {
return false;
}
get label() {
return null;
}
toString() {
return "";
}
};
// src/atn/AbstractPredicateTransition.ts
var AbstractPredicateTransition = class extends Transition {
static {
__name(this, "AbstractPredicateTransition");
}
constructor(target) {
super(target);
}
};
// src/atn/PredicateTransition.ts
var PredicateTransition = class extends AbstractPredicateTransition {
static {
__name(this, "PredicateTransition");
}
ruleIndex;
predIndex;
isCtxDependent;
// e.g., $i ref in pred
constructor(target, ruleIndex, predIndex, isCtxDependent) {
super(target);
this.ruleIndex = ruleIndex;
this.predIndex = predIndex;
this.isCtxDependent = isCtxDependent;
}
get isEpsilon() {
return true;
}
matches(_symbol, _minVocabSymbol, _maxVocabSymbol) {
return false;
}
get transitionType() {
return Transition.PREDICATE;
}
getPredicate() {
return new SemanticContext.Predicate(this.ruleIndex, this.predIndex, this.isCtxDependent);
}
toString() {
return "pred_" + this.ruleIndex + ":" + this.predIndex;
}
};
export {
PredicateTransition
};