Merge pull request #1448 from ericvergnaud/optimize-javascript-runtime
Optimize javascript runtime
This commit is contained in:
commit
7f4bb06adf
|
@ -30,13 +30,12 @@
|
|||
|
||||
// A lexer is recognizer that draws input symbols from a character stream.
|
||||
// lexer grammars result in a subclass of this object. A Lexer object
|
||||
// uses simplified match() and error recovery mechanisms in the interest
|
||||
// of speed.
|
||||
///
|
||||
// uses simplified match() and error recovery mechanisms in the interest of speed.
|
||||
|
||||
var Token = require('./Token').Token;
|
||||
var Recognizer = require('./Recognizer').Recognizer;
|
||||
var CommonTokenFactory = require('./CommonTokenFactory').CommonTokenFactory;
|
||||
var RecognitionException = require('./error/Errors').RecognitionException;
|
||||
var LexerNoViableAltException = require('./error/Errors').LexerNoViableAltException;
|
||||
|
||||
function TokenSource() {
|
||||
|
@ -152,8 +151,13 @@ Lexer.prototype.nextToken = function() {
|
|||
try {
|
||||
ttype = this._interp.match(this._input, this._mode);
|
||||
} catch (e) {
|
||||
this.notifyListeners(e); // report error
|
||||
this.recover(e);
|
||||
if(e instanceof RecognitionException) {
|
||||
this.notifyListeners(e); // report error
|
||||
this.recover(e);
|
||||
} else {
|
||||
console.log(e.stack);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
if (this._input.LA(1) === Token.EOF) {
|
||||
this._hitEOF = true;
|
||||
|
|
|
@ -30,9 +30,10 @@
|
|||
///
|
||||
|
||||
var RuleContext = require('./RuleContext').RuleContext;
|
||||
var Hash = require('./Utils').Hash;
|
||||
|
||||
function PredictionContext(cachedHashString) {
|
||||
this.cachedHashString = cachedHashString;
|
||||
function PredictionContext(cachedHashCode) {
|
||||
this.cachedHashCode = cachedHashCode;
|
||||
}
|
||||
|
||||
// Represents {@code $} in local context prediction, which means wildcard.
|
||||
|
@ -83,17 +84,19 @@ PredictionContext.prototype.hasEmptyPath = function() {
|
|||
return this.getReturnState(this.length - 1) === PredictionContext.EMPTY_RETURN_STATE;
|
||||
};
|
||||
|
||||
PredictionContext.prototype.hashString = function() {
|
||||
return this.cachedHashString;
|
||||
PredictionContext.prototype.hashCode = function() {
|
||||
return this.cachedHashCode;
|
||||
};
|
||||
|
||||
|
||||
PredictionContext.prototype.updateHashCode = function(hash) {
|
||||
hash.update(this.cachedHashCode);
|
||||
};
|
||||
/*
|
||||
function calculateHashString(parent, returnState) {
|
||||
return "" + parent + returnState;
|
||||
}
|
||||
|
||||
function calculateEmptyHashString() {
|
||||
return "";
|
||||
}
|
||||
*/
|
||||
|
||||
// Used to cache {@link PredictionContext} objects. Its used for the shared
|
||||
// context cash associated with contexts in DFA states. This cache
|
||||
|
@ -131,9 +134,13 @@ Object.defineProperty(PredictionContextCache.prototype, "length", {
|
|||
});
|
||||
|
||||
function SingletonPredictionContext(parent, returnState) {
|
||||
var hashString = parent !== null ? calculateHashString(parent, returnState)
|
||||
: calculateEmptyHashString();
|
||||
PredictionContext.call(this, hashString);
|
||||
var hashCode = 0;
|
||||
if(parent !== null) {
|
||||
var hash = new Hash();
|
||||
hash.update(parent, returnState);
|
||||
hashCode = hash.finish();
|
||||
}
|
||||
PredictionContext.call(this, hashCode);
|
||||
this.parentCtx = parent;
|
||||
this.returnState = returnState;
|
||||
}
|
||||
|
@ -169,7 +176,7 @@ SingletonPredictionContext.prototype.equals = function(other) {
|
|||
return true;
|
||||
} else if (!(other instanceof SingletonPredictionContext)) {
|
||||
return false;
|
||||
} else if (this.hashString() !== other.hashString()) {
|
||||
} else if (this.hashCode() !== other.hashCode()) {
|
||||
return false; // can't be same if hash is different
|
||||
} else {
|
||||
if(this.returnState !== other.returnState)
|
||||
|
@ -181,10 +188,6 @@ SingletonPredictionContext.prototype.equals = function(other) {
|
|||
}
|
||||
};
|
||||
|
||||
SingletonPredictionContext.prototype.hashString = function() {
|
||||
return this.cachedHashString;
|
||||
};
|
||||
|
||||
SingletonPredictionContext.prototype.toString = function() {
|
||||
var up = this.parentCtx === null ? "" : this.parentCtx.toString();
|
||||
if (up.length === 0) {
|
||||
|
@ -233,8 +236,10 @@ function ArrayPredictionContext(parents, returnStates) {
|
|||
// from {@link //EMPTY} and non-empty. We merge {@link //EMPTY} by using
|
||||
// null parent and
|
||||
// returnState == {@link //EMPTY_RETURN_STATE}.
|
||||
var hash = calculateHashString(parents, returnStates);
|
||||
PredictionContext.call(this, hash);
|
||||
var h = new Hash();
|
||||
h.update(parents, returnStates);
|
||||
var hashCode = h.finish();
|
||||
PredictionContext.call(this, hashCode);
|
||||
this.parents = parents;
|
||||
this.returnStates = returnStates;
|
||||
return this;
|
||||
|
@ -268,7 +273,7 @@ ArrayPredictionContext.prototype.equals = function(other) {
|
|||
return true;
|
||||
} else if (!(other instanceof ArrayPredictionContext)) {
|
||||
return false;
|
||||
} else if (this.hashString !== other.hashString()) {
|
||||
} else if (this.hashCode() !== other.hashCode()) {
|
||||
return false; // can't be same if hash is different
|
||||
} else {
|
||||
return this.returnStates === other.returnStates &&
|
||||
|
@ -318,7 +323,7 @@ function predictionContextFromRuleContext(atn, outerContext) {
|
|||
var transition = state.transitions[0];
|
||||
return SingletonPredictionContext.create(parent, transition.followState.stateNumber);
|
||||
}
|
||||
|
||||
/*
|
||||
function calculateListsHashString(parents, returnStates) {
|
||||
var s = "";
|
||||
parents.map(function(p) {
|
||||
|
@ -329,7 +334,7 @@ function calculateListsHashString(parents, returnStates) {
|
|||
});
|
||||
return s;
|
||||
}
|
||||
|
||||
*/
|
||||
function merge(a, b, rootIsWildcard, mergeCache) {
|
||||
// share same graph if both same
|
||||
if (a === b) {
|
||||
|
|
|
@ -78,7 +78,7 @@ Recognizer.prototype.getTokenTypeMap = function() {
|
|||
// <p>Used for XPath and tree pattern compilation.</p>
|
||||
//
|
||||
Recognizer.prototype.getRuleIndexMap = function() {
|
||||
var ruleNames = this.getRuleNames();
|
||||
var ruleNames = this.ruleNames;
|
||||
if (ruleNames===null) {
|
||||
throw("The current recognizer does not provide a list of rule names.");
|
||||
}
|
||||
|
|
|
@ -1,252 +1,441 @@
|
|||
function arrayToString(a) {
|
||||
return "[" + a.join(", ") + "]";
|
||||
return "[" + a.join(", ") + "]";
|
||||
}
|
||||
|
||||
String.prototype.seed = String.prototype.seed || Math.round(Math.random() * Math.pow(2, 32));;
|
||||
String.prototype.seed = String.prototype.seed || Math.round(Math.random() * Math.pow(2, 32));
|
||||
|
||||
String.prototype.hashCode = function () {
|
||||
var remainder, bytes, h1, h1b, c1, c1b, c2, c2b, k1, i,
|
||||
key = this.toString();
|
||||
String.prototype.hashCode = function () {
|
||||
var remainder, bytes, h1, h1b, c1, c1b, c2, c2b, k1, i,
|
||||
key = this.toString();
|
||||
|
||||
remainder = key.length & 3; // key.length % 4
|
||||
bytes = key.length - remainder;
|
||||
h1 = String.prototype.seed;
|
||||
c1 = 0xcc9e2d51;
|
||||
c2 = 0x1b873593;
|
||||
i = 0;
|
||||
remainder = key.length & 3; // key.length % 4
|
||||
bytes = key.length - remainder;
|
||||
h1 = String.prototype.seed;
|
||||
c1 = 0xcc9e2d51;
|
||||
c2 = 0x1b873593;
|
||||
i = 0;
|
||||
|
||||
while (i < bytes) {
|
||||
k1 =
|
||||
((key.charCodeAt(i) & 0xff)) |
|
||||
((key.charCodeAt(++i) & 0xff) << 8) |
|
||||
((key.charCodeAt(++i) & 0xff) << 16) |
|
||||
((key.charCodeAt(++i) & 0xff) << 24);
|
||||
++i;
|
||||
while (i < bytes) {
|
||||
k1 =
|
||||
((key.charCodeAt(i) & 0xff)) |
|
||||
((key.charCodeAt(++i) & 0xff) << 8) |
|
||||
((key.charCodeAt(++i) & 0xff) << 16) |
|
||||
((key.charCodeAt(++i) & 0xff) << 24);
|
||||
++i;
|
||||
|
||||
k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff;
|
||||
k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff;
|
||||
k1 = (k1 << 15) | (k1 >>> 17);
|
||||
k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff;
|
||||
|
||||
h1 ^= k1;
|
||||
h1 = (h1 << 13) | (h1 >>> 19);
|
||||
h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff;
|
||||
h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16));
|
||||
}
|
||||
|
||||
k1 = 0;
|
||||
|
||||
switch (remainder) {
|
||||
case 3:
|
||||
k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
|
||||
case 2:
|
||||
k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
|
||||
case 1:
|
||||
k1 ^= (key.charCodeAt(i) & 0xff);
|
||||
|
||||
k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
|
||||
k1 = (k1 << 15) | (k1 >>> 17);
|
||||
k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff;
|
||||
|
||||
k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
|
||||
h1 ^= k1;
|
||||
h1 = (h1 << 13) | (h1 >>> 19);
|
||||
h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff;
|
||||
h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16));
|
||||
}
|
||||
}
|
||||
|
||||
k1 = 0;
|
||||
h1 ^= key.length;
|
||||
|
||||
switch (remainder) {
|
||||
case 3:
|
||||
k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
|
||||
case 2:
|
||||
k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
|
||||
case 1:
|
||||
k1 ^= (key.charCodeAt(i) & 0xff);
|
||||
h1 ^= h1 >>> 16;
|
||||
h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
|
||||
h1 ^= h1 >>> 13;
|
||||
h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff;
|
||||
h1 ^= h1 >>> 16;
|
||||
|
||||
k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
|
||||
k1 = (k1 << 15) | (k1 >>> 17);
|
||||
k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
|
||||
h1 ^= k1;
|
||||
}
|
||||
return h1 >>> 0;
|
||||
};
|
||||
|
||||
h1 ^= key.length;
|
||||
|
||||
h1 ^= h1 >>> 16;
|
||||
h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
|
||||
h1 ^= h1 >>> 13;
|
||||
h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff;
|
||||
h1 ^= h1 >>> 16;
|
||||
|
||||
return h1 >>> 0;
|
||||
};
|
||||
|
||||
function standardEqualsFunction(a,b) {
|
||||
return a.equals(b);
|
||||
function standardEqualsFunction(a, b) {
|
||||
return a.equals(b);
|
||||
}
|
||||
|
||||
function standardHashFunction(a) {
|
||||
return a.hashString();
|
||||
function standardHashCodeFunction(a) {
|
||||
return a.hashCode();
|
||||
}
|
||||
|
||||
function Set(hashFunction, equalsFunction) {
|
||||
this.data = {};
|
||||
this.hashFunction = hashFunction || standardHashFunction;
|
||||
this.equalsFunction = equalsFunction || standardEqualsFunction;
|
||||
return this;
|
||||
this.data = {};
|
||||
this.hashFunction = hashFunction || standardHashCodeFunction;
|
||||
this.equalsFunction = equalsFunction || standardEqualsFunction;
|
||||
return this;
|
||||
}
|
||||
|
||||
Object.defineProperty(Set.prototype, "length", {
|
||||
get : function() {
|
||||
return this.values().length;
|
||||
}
|
||||
get: function () {
|
||||
var l = 0;
|
||||
for (var key in this.data) {
|
||||
if (key.indexOf("hash_") === 0) {
|
||||
l = l + this.data[key].length;
|
||||
}
|
||||
}
|
||||
return l;
|
||||
}
|
||||
});
|
||||
|
||||
Set.prototype.add = function(value) {
|
||||
var hash = this.hashFunction(value);
|
||||
var key = "hash_" + hash.hashCode();
|
||||
if(key in this.data) {
|
||||
var i;
|
||||
var values = this.data[key];
|
||||
for(i=0;i<values.length; i++) {
|
||||
if(this.equalsFunction(value, values[i])) {
|
||||
return values[i];
|
||||
}
|
||||
}
|
||||
values.push(value);
|
||||
return value;
|
||||
} else {
|
||||
this.data[key] = [ value ];
|
||||
return value;
|
||||
}
|
||||
Set.prototype.add = function (value) {
|
||||
var hash = this.hashFunction(value);
|
||||
var key = "hash_" + hash;
|
||||
if (key in this.data) {
|
||||
var values = this.data[key];
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (this.equalsFunction(value, values[i])) {
|
||||
return values[i];
|
||||
}
|
||||
}
|
||||
values.push(value);
|
||||
return value;
|
||||
} else {
|
||||
this.data[key] = [value];
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
Set.prototype.contains = function(value) {
|
||||
var hash = this.hashFunction(value);
|
||||
var key = hash.hashCode();
|
||||
if(key in this.data) {
|
||||
var i;
|
||||
var values = this.data[key];
|
||||
for(i=0;i<values.length; i++) {
|
||||
if(this.equalsFunction(value, values[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
Set.prototype.contains = function (value) {
|
||||
return this.get(value) != null;
|
||||
};
|
||||
|
||||
Set.prototype.values = function() {
|
||||
var l = [];
|
||||
for(var key in this.data) {
|
||||
if(key.indexOf("hash_")===0) {
|
||||
l = l.concat(this.data[key]);
|
||||
}
|
||||
}
|
||||
return l;
|
||||
Set.prototype.get = function (value) {
|
||||
var hash = this.hashFunction(value);
|
||||
var key = "hash_" + hash;
|
||||
if (key in this.data) {
|
||||
var values = this.data[key];
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (this.equalsFunction(value, values[i])) {
|
||||
return values[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
Set.prototype.toString = function() {
|
||||
return arrayToString(this.values());
|
||||
Set.prototype.values = function () {
|
||||
var l = [];
|
||||
for (var key in this.data) {
|
||||
if (key.indexOf("hash_") === 0) {
|
||||
l = l.concat(this.data[key]);
|
||||
}
|
||||
}
|
||||
return l;
|
||||
};
|
||||
|
||||
Set.prototype.toString = function () {
|
||||
return arrayToString(this.values());
|
||||
};
|
||||
|
||||
function BitSet() {
|
||||
this.data = [];
|
||||
return this;
|
||||
this.data = [];
|
||||
return this;
|
||||
}
|
||||
|
||||
BitSet.prototype.add = function(value) {
|
||||
this.data[value] = true;
|
||||
BitSet.prototype.add = function (value) {
|
||||
this.data[value] = true;
|
||||
};
|
||||
|
||||
BitSet.prototype.or = function(set) {
|
||||
var bits = this;
|
||||
Object.keys(set.data).map( function(alt) { bits.add(alt); });
|
||||
BitSet.prototype.or = function (set) {
|
||||
var bits = this;
|
||||
Object.keys(set.data).map(function (alt) {
|
||||
bits.add(alt);
|
||||
});
|
||||
};
|
||||
|
||||
BitSet.prototype.remove = function(value) {
|
||||
delete this.data[value];
|
||||
BitSet.prototype.remove = function (value) {
|
||||
delete this.data[value];
|
||||
};
|
||||
|
||||
BitSet.prototype.contains = function(value) {
|
||||
return this.data[value] === true;
|
||||
BitSet.prototype.contains = function (value) {
|
||||
return this.data[value] === true;
|
||||
};
|
||||
|
||||
BitSet.prototype.values = function() {
|
||||
return Object.keys(this.data);
|
||||
BitSet.prototype.values = function () {
|
||||
return Object.keys(this.data);
|
||||
};
|
||||
|
||||
BitSet.prototype.minValue = function() {
|
||||
return Math.min.apply(null, this.values());
|
||||
BitSet.prototype.minValue = function () {
|
||||
return Math.min.apply(null, this.values());
|
||||
};
|
||||
|
||||
BitSet.prototype.hashString = function() {
|
||||
return this.values().toString();
|
||||
BitSet.prototype.hashCode = function () {
|
||||
var hash = new Hash();
|
||||
hash.update(this.values());
|
||||
return hash.finish();
|
||||
};
|
||||
|
||||
BitSet.prototype.equals = function(other) {
|
||||
if(!(other instanceof BitSet)) {
|
||||
return false;
|
||||
}
|
||||
return this.hashString()===other.hashString();
|
||||
BitSet.prototype.equals = function (other) {
|
||||
if (!(other instanceof BitSet)) {
|
||||
return false;
|
||||
}
|
||||
return this.hashCode() === other.hashCode();
|
||||
};
|
||||
|
||||
Object.defineProperty(BitSet.prototype, "length", {
|
||||
get : function() {
|
||||
return this.values().length;
|
||||
}
|
||||
get: function () {
|
||||
return this.values().length;
|
||||
}
|
||||
});
|
||||
|
||||
BitSet.prototype.toString = function() {
|
||||
return "{" + this.values().join(", ") + "}";
|
||||
BitSet.prototype.toString = function () {
|
||||
return "{" + this.values().join(", ") + "}";
|
||||
};
|
||||
|
||||
function AltDict() {
|
||||
this.data = {};
|
||||
return this;
|
||||
function Map(hashFunction, equalsFunction) {
|
||||
this.data = {};
|
||||
this.hashFunction = hashFunction || standardHashCodeFunction;
|
||||
this.equalsFunction = equalsFunction || standardEqualsFunction;
|
||||
return this;
|
||||
}
|
||||
|
||||
AltDict.prototype.get = function(key) {
|
||||
key = "k-" + key;
|
||||
if(key in this.data){
|
||||
return this.data[key];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
Object.defineProperty(Map.prototype, "length", {
|
||||
get: function () {
|
||||
var l = 0;
|
||||
for (var hashKey in this.data) {
|
||||
if (hashKey.indexOf("hash_") === 0) {
|
||||
l = l + this.data[hashKey].length;
|
||||
}
|
||||
}
|
||||
return l;
|
||||
}
|
||||
});
|
||||
|
||||
Map.prototype.put = function (key, value) {
|
||||
var hashKey = "hash_" + this.hashFunction(key);
|
||||
if (hashKey in this.data) {
|
||||
var entries = this.data[hashKey];
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
var entry = entries[i];
|
||||
if (this.equalsFunction(key, entry.key)) {
|
||||
var oldValue = entry.value;
|
||||
entry.value = value;
|
||||
return oldValue;
|
||||
}
|
||||
}
|
||||
entries.push({key:key, value:value});
|
||||
return value;
|
||||
} else {
|
||||
this.data[hashKey] = [{key:key, value:value}];
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
AltDict.prototype.put = function(key, value) {
|
||||
key = "k-" + key;
|
||||
this.data[key] = value;
|
||||
Map.prototype.containsKey = function (key) {
|
||||
var hashKey = "hash_" + this.hashFunction(key);
|
||||
if(hashKey in this.data) {
|
||||
var entries = this.data[hashKey];
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
var entry = entries[i];
|
||||
if (this.equalsFunction(key, entry.key))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
AltDict.prototype.values = function() {
|
||||
var data = this.data;
|
||||
var keys = Object.keys(this.data);
|
||||
return keys.map(function(key) {
|
||||
return data[key];
|
||||
});
|
||||
Map.prototype.get = function (key) {
|
||||
var hashKey = "hash_" + this.hashFunction(key);
|
||||
if(hashKey in this.data) {
|
||||
var entries = this.data[hashKey];
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
var entry = entries[i];
|
||||
if (this.equalsFunction(key, entry.key))
|
||||
return entry.value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
Map.prototype.entries = function () {
|
||||
var l = [];
|
||||
for (var key in this.data) {
|
||||
if (key.indexOf("hash_") === 0) {
|
||||
l = l.concat(this.data[key]);
|
||||
}
|
||||
}
|
||||
return l;
|
||||
};
|
||||
|
||||
|
||||
Map.prototype.getKeys = function () {
|
||||
return this.entries().map(function(e) {
|
||||
return e.key;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Map.prototype.getValues = function () {
|
||||
return this.entries().map(function(e) {
|
||||
return e.value;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Map.prototype.toString = function () {
|
||||
var ss = this.entries().map(function(entry) {
|
||||
return '{' + entry.key + ':' + entry.value + '}';
|
||||
});
|
||||
return '[' + ss.join(", ") + ']';
|
||||
};
|
||||
|
||||
|
||||
function AltDict() {
|
||||
this.data = {};
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
AltDict.prototype.get = function (key) {
|
||||
key = "k-" + key;
|
||||
if (key in this.data) {
|
||||
return this.data[key];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
AltDict.prototype.put = function (key, value) {
|
||||
key = "k-" + key;
|
||||
this.data[key] = value;
|
||||
};
|
||||
|
||||
AltDict.prototype.values = function () {
|
||||
var data = this.data;
|
||||
var keys = Object.keys(this.data);
|
||||
return keys.map(function (key) {
|
||||
return data[key];
|
||||
});
|
||||
};
|
||||
|
||||
function DoubleDict() {
|
||||
return this;
|
||||
return this;
|
||||
}
|
||||
|
||||
DoubleDict.prototype.get = function(a, b) {
|
||||
var d = this[a] || null;
|
||||
return d===null ? null : (d[b] || null);
|
||||
function Hash() {
|
||||
this.count = 0;
|
||||
this.hash = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
Hash.prototype.update = function () {
|
||||
for(var i=0;i<arguments.length;i++) {
|
||||
var value = arguments[i];
|
||||
if (value == null)
|
||||
continue;
|
||||
if(Array.isArray(value))
|
||||
this.update.apply(value);
|
||||
else {
|
||||
var k = 0;
|
||||
switch (typeof(value)) {
|
||||
case 'undefined':
|
||||
case 'function':
|
||||
continue;
|
||||
case 'number':
|
||||
case 'boolean':
|
||||
k = value;
|
||||
break;
|
||||
case 'string':
|
||||
k = value.hashCode();
|
||||
break;
|
||||
default:
|
||||
value.updateHashCode(this);
|
||||
continue;
|
||||
}
|
||||
k = k * 0xCC9E2D51;
|
||||
k = (k << 15) | (k >>> (32 - 15));
|
||||
k = k * 0x1B873593;
|
||||
this.count = this.count + 1;
|
||||
hash = this.hash ^ k;
|
||||
hash = (hash << 13) | (hash >>> (32 - 13));
|
||||
hash = hash * 5 + 0xE6546B64;
|
||||
this.hash = hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Hash.prototype.finish = function () {
|
||||
var hash = this.hash ^ (this.count * 4);
|
||||
hash = hash ^ (hash >>> 16);
|
||||
hash = hash * 0x85EBCA6B;
|
||||
hash = hash ^ (hash >>> 13);
|
||||
hash = hash * 0xC2B2AE35;
|
||||
hash = hash ^ (hash >>> 16);
|
||||
return hash;
|
||||
}
|
||||
|
||||
function hashStuff() {
|
||||
var hash = new Hash();
|
||||
hash.update.apply(arguments);
|
||||
return hash.finish();
|
||||
}
|
||||
|
||||
DoubleDict.prototype.get = function (a, b) {
|
||||
var d = this[a] || null;
|
||||
return d === null ? null : (d[b] || null);
|
||||
};
|
||||
|
||||
DoubleDict.prototype.set = function(a, b, o) {
|
||||
var d = this[a] || null;
|
||||
if(d===null) {
|
||||
d = {};
|
||||
this[a] = d;
|
||||
}
|
||||
d[b] = o;
|
||||
DoubleDict.prototype.set = function (a, b, o) {
|
||||
var d = this[a] || null;
|
||||
if (d === null) {
|
||||
d = {};
|
||||
this[a] = d;
|
||||
}
|
||||
d[b] = o;
|
||||
};
|
||||
|
||||
|
||||
function escapeWhitespace(s, escapeSpaces) {
|
||||
s = s.replace("\t","\\t");
|
||||
s = s.replace("\n","\\n");
|
||||
s = s.replace("\r","\\r");
|
||||
if(escapeSpaces) {
|
||||
s = s.replace(" ","\u00B7");
|
||||
}
|
||||
return s;
|
||||
s = s.replace("\t", "\\t");
|
||||
s = s.replace("\n", "\\n");
|
||||
s = s.replace("\r", "\\r");
|
||||
if (escapeSpaces) {
|
||||
s = s.replace(" ", "\u00B7");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
exports.isArray = function (entity) {
|
||||
return Object.prototype.toString.call( entity ) === '[object Array]'
|
||||
function titleCase(str) {
|
||||
return str.replace(/\w\S*/g, function (txt) {
|
||||
return txt.charAt(0).toUpperCase() + txt.substr(1);
|
||||
});
|
||||
};
|
||||
|
||||
exports.titleCase = function(str) {
|
||||
return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1);});
|
||||
function equalArrays(a, b)
|
||||
{
|
||||
if (!Array.isArray(a) || !Array.isArray(b))
|
||||
return false;
|
||||
if (a == b)
|
||||
return true;
|
||||
if (a.length != b.length)
|
||||
return false;
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
if (a[i] == b[i])
|
||||
continue;
|
||||
if (!a[i].equals(b[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
exports.Hash = Hash;
|
||||
exports.Set = Set;
|
||||
exports.Map = Map;
|
||||
exports.BitSet = BitSet;
|
||||
exports.AltDict = AltDict;
|
||||
exports.DoubleDict = DoubleDict;
|
||||
exports.hashStuff = hashStuff;
|
||||
exports.escapeWhitespace = escapeWhitespace;
|
||||
exports.arrayToString = arrayToString;
|
||||
exports.titleCase = titleCase;
|
||||
exports.equalArrays = equalArrays;
|
|
@ -39,6 +39,8 @@
|
|||
|
||||
var DecisionState = require('./ATNState').DecisionState;
|
||||
var SemanticContext = require('./SemanticContext').SemanticContext;
|
||||
var Hash = require("../Utils").Hash;
|
||||
|
||||
|
||||
function checkParams(params, isCfg) {
|
||||
if(params===null) {
|
||||
|
@ -96,10 +98,16 @@ ATNConfig.prototype.checkContext = function(params, config) {
|
|||
}
|
||||
};
|
||||
|
||||
ATNConfig.prototype.hashString = function() {
|
||||
return "" + this.state.stateNumber + "/" + this.alt + "/" +
|
||||
(this.context===null ? "" : this.context.hashString()) +
|
||||
"/" + this.semanticContext.hashString();
|
||||
|
||||
ATNConfig.prototype.hashCode = function() {
|
||||
var hash = new Hash();
|
||||
this.updateHashCode(hash);
|
||||
return hash.finish();
|
||||
};
|
||||
|
||||
|
||||
ATNConfig.prototype.updateHashCode = function(hash) {
|
||||
hash.update(this.state.stateNumber, this.alt, this.context, this.semanticContext);
|
||||
};
|
||||
|
||||
// An ATN configuration is equal to another if both have
|
||||
|
@ -120,10 +128,14 @@ ATNConfig.prototype.equals = function(other) {
|
|||
}
|
||||
};
|
||||
|
||||
ATNConfig.prototype.hashStringForConfigSet = function() {
|
||||
return "" + this.state.stateNumber + "/" + this.alt + "/" + this.semanticContext;
|
||||
|
||||
ATNConfig.prototype.hashCodeForConfigSet = function() {
|
||||
var hash = new Hash();
|
||||
hash.update(this.state.stateNumber, this.alt, this.semanticContext);
|
||||
return hash.finish();
|
||||
};
|
||||
|
||||
|
||||
ATNConfig.prototype.equalsForConfigSet = function(other) {
|
||||
if (this === other) {
|
||||
return true;
|
||||
|
@ -162,31 +174,21 @@ function LexerATNConfig(params, config) {
|
|||
LexerATNConfig.prototype = Object.create(ATNConfig.prototype);
|
||||
LexerATNConfig.prototype.constructor = LexerATNConfig;
|
||||
|
||||
LexerATNConfig.prototype.hashString = function() {
|
||||
return "" + this.state.stateNumber + this.alt + this.context +
|
||||
this.semanticContext + (this.passedThroughNonGreedyDecision ? 1 : 0) +
|
||||
this.lexerActionExecutor;
|
||||
LexerATNConfig.prototype.updateHashCode = function(hash) {
|
||||
hash.update(this.state.stateNumber, this.alt, this.context, this.semanticContext, this.passedThroughNonGreedyDecision, this.lexerActionExecutor);
|
||||
};
|
||||
|
||||
LexerATNConfig.prototype.equals = function(other) {
|
||||
if (this === other) {
|
||||
return true;
|
||||
} else if (!(other instanceof LexerATNConfig)) {
|
||||
return false;
|
||||
} else if (this.passedThroughNonGreedyDecision !== other.passedThroughNonGreedyDecision) {
|
||||
return false;
|
||||
} else if (this.lexerActionExecutor ?
|
||||
!this.lexerActionExecutor.equals(other.lexerActionExecutor)
|
||||
: !other.lexerActionExecutor) {
|
||||
return false;
|
||||
} else {
|
||||
return ATNConfig.prototype.equals.call(this, other);
|
||||
}
|
||||
return this === other ||
|
||||
(other instanceof LexerATNConfig &&
|
||||
this.passedThroughNonGreedyDecision == other.passedThroughNonGreedyDecision &&
|
||||
(this.lexerActionExecutor ? this.lexerActionExecutor.equals(other.lexerActionExecutor) : !other.lexerActionExecutor) &&
|
||||
ATNConfig.prototype.equals.call(this, other));
|
||||
};
|
||||
|
||||
LexerATNConfig.prototype.hashStringForConfigSet = LexerATNConfig.prototype.hashString;
|
||||
LexerATNConfig.prototype.hashCodeForConfigSet = LexerATNConfig.prototype.hashCode;
|
||||
|
||||
LexerATNConfig.prototype.equalsForConfigSet = LexerATNConfig.prototype.eqials;
|
||||
LexerATNConfig.prototype.equalsForConfigSet = LexerATNConfig.prototype.equals;
|
||||
|
||||
|
||||
LexerATNConfig.prototype.checkNonGreedyDecision = function(source, target) {
|
||||
|
|
|
@ -36,12 +36,13 @@
|
|||
|
||||
var ATN = require('./ATN').ATN;
|
||||
var Utils = require('./../Utils');
|
||||
var Hash = Utils.Hash;
|
||||
var Set = Utils.Set;
|
||||
var SemanticContext = require('./SemanticContext').SemanticContext;
|
||||
var merge = require('./../PredictionContext').merge;
|
||||
|
||||
function hashATNConfig(c) {
|
||||
return c.hashStringForConfigSet();
|
||||
return c.hashCodeForConfigSet();
|
||||
}
|
||||
|
||||
function equalATNConfigs(a, b) {
|
||||
|
@ -92,7 +93,7 @@ function ATNConfigSet(fullCtx) {
|
|||
this.hasSemanticContext = false;
|
||||
this.dipsIntoOuterContext = false;
|
||||
|
||||
this.cachedHashString = "-1";
|
||||
this.cachedHashCode = -1;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
@ -121,7 +122,7 @@ ATNConfigSet.prototype.add = function(config, mergeCache) {
|
|||
}
|
||||
var existing = this.configLookup.add(config);
|
||||
if (existing === config) {
|
||||
this.cachedHashString = "-1";
|
||||
this.cachedHashCode = -1;
|
||||
this.configs.push(config); // track order here
|
||||
return true;
|
||||
}
|
||||
|
@ -186,37 +187,36 @@ ATNConfigSet.prototype.addAll = function(coll) {
|
|||
};
|
||||
|
||||
ATNConfigSet.prototype.equals = function(other) {
|
||||
if (this === other) {
|
||||
return true;
|
||||
} else if (!(other instanceof ATNConfigSet)) {
|
||||
return false;
|
||||
}
|
||||
return this.configs !== null && this.configs.equals(other.configs) &&
|
||||
this.fullCtx === other.fullCtx &&
|
||||
this.uniqueAlt === other.uniqueAlt &&
|
||||
this.conflictingAlts === other.conflictingAlts &&
|
||||
this.hasSemanticContext === other.hasSemanticContext &&
|
||||
this.dipsIntoOuterContext === other.dipsIntoOuterContext;
|
||||
return this === other ||
|
||||
(other instanceof ATNConfigSet &&
|
||||
Utils.equalArrays(this.configs, other.configs) &&
|
||||
this.fullCtx === other.fullCtx &&
|
||||
this.uniqueAlt === other.uniqueAlt &&
|
||||
this.conflictingAlts === other.conflictingAlts &&
|
||||
this.hasSemanticContext === other.hasSemanticContext &&
|
||||
this.dipsIntoOuterContext === other.dipsIntoOuterContext);
|
||||
};
|
||||
|
||||
ATNConfigSet.prototype.hashString = function() {
|
||||
ATNConfigSet.prototype.hashCode = function() {
|
||||
var hash = new Hash();
|
||||
this.updateHashCode(hash);
|
||||
return hash.finish();
|
||||
};
|
||||
|
||||
|
||||
ATNConfigSet.prototype.updateHashCode = function(hash) {
|
||||
if (this.readOnly) {
|
||||
if (this.cachedHashString === "-1") {
|
||||
this.cachedHashString = this.hashConfigs();
|
||||
if (this.cachedHashCode === -1) {
|
||||
var hash = new Hash();
|
||||
hash.update(this.configs);
|
||||
this.cachedHashCode = hash.finish();
|
||||
}
|
||||
return this.cachedHashString;
|
||||
hash.update(this.cachedHashCode);
|
||||
} else {
|
||||
return this.hashConfigs();
|
||||
hash.update(this.configs);
|
||||
}
|
||||
};
|
||||
|
||||
ATNConfigSet.prototype.hashConfigs = function() {
|
||||
var s = "";
|
||||
this.configs.map(function(c) {
|
||||
s += c.toString();
|
||||
});
|
||||
return s;
|
||||
};
|
||||
|
||||
Object.defineProperty(ATNConfigSet.prototype, "length", {
|
||||
get : function() {
|
||||
|
@ -247,7 +247,7 @@ ATNConfigSet.prototype.clear = function() {
|
|||
throw "This set is readonly";
|
||||
}
|
||||
this.configs = [];
|
||||
this.cachedHashString = "-1";
|
||||
this.cachedHashCode = -1;
|
||||
this.configLookup = new Set();
|
||||
};
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ LexerATNSimulator.prototype.reset = function() {
|
|||
LexerATNSimulator.prototype.matchATN = function(input) {
|
||||
var startState = this.atn.modeToStartState[this.mode];
|
||||
|
||||
if (this.debug) {
|
||||
if (LexerATNSimulator.debug) {
|
||||
console.log("matchATN mode " + this.mode + " start: " + startState);
|
||||
}
|
||||
var old_mode = this.mode;
|
||||
|
@ -160,14 +160,14 @@ LexerATNSimulator.prototype.matchATN = function(input) {
|
|||
|
||||
var predict = this.execATN(input, next);
|
||||
|
||||
if (this.debug) {
|
||||
if (LexerATNSimulator.debug) {
|
||||
console.log("DFA after matchATN: " + this.decisionToDFA[old_mode].toLexerString());
|
||||
}
|
||||
return predict;
|
||||
};
|
||||
|
||||
LexerATNSimulator.prototype.execATN = function(input, ds0) {
|
||||
if (this.debug) {
|
||||
if (LexerATNSimulator.debug) {
|
||||
console.log("start state closure=" + ds0.configs);
|
||||
}
|
||||
if (ds0.isAcceptState) {
|
||||
|
@ -178,7 +178,7 @@ LexerATNSimulator.prototype.execATN = function(input, ds0) {
|
|||
var s = ds0; // s is current/from DFA state
|
||||
|
||||
while (true) { // while more work
|
||||
if (this.debug) {
|
||||
if (LexerATNSimulator.debug) {
|
||||
console.log("execATN loop starting closure: " + s.configs);
|
||||
}
|
||||
|
||||
|
@ -246,7 +246,7 @@ LexerATNSimulator.prototype.getExistingTargetState = function(s, t) {
|
|||
if(target===undefined) {
|
||||
target = null;
|
||||
}
|
||||
if (this.debug && target !== null) {
|
||||
if (LexerATNSimulator.debug && target !== null) {
|
||||
console.log("reuse state " + s.stateNumber + " edge to " + target.stateNumber);
|
||||
}
|
||||
return target;
|
||||
|
@ -310,7 +310,7 @@ LexerATNSimulator.prototype.getReachableConfigSet = function(input, closure,
|
|||
if (currentAltReachedAcceptState && cfg.passedThroughNonGreedyDecision) {
|
||||
continue;
|
||||
}
|
||||
if (this.debug) {
|
||||
if (LexerATNSimulator.debug) {
|
||||
console.log("testing %s at %s\n", this.getTokenName(t), cfg
|
||||
.toString(this.recog, true));
|
||||
}
|
||||
|
@ -337,7 +337,7 @@ LexerATNSimulator.prototype.getReachableConfigSet = function(input, closure,
|
|||
|
||||
LexerATNSimulator.prototype.accept = function(input, lexerActionExecutor,
|
||||
startIndex, index, line, charPos) {
|
||||
if (this.debug) {
|
||||
if (LexerATNSimulator.debug) {
|
||||
console.log("ACTION %s\n", lexerActionExecutor);
|
||||
}
|
||||
// seek to after last char in token
|
||||
|
@ -379,13 +379,13 @@ LexerATNSimulator.prototype.computeStartState = function(input, p) {
|
|||
LexerATNSimulator.prototype.closure = function(input, config, configs,
|
||||
currentAltReachedAcceptState, speculative, treatEofAsEpsilon) {
|
||||
var cfg = null;
|
||||
if (this.debug) {
|
||||
if (LexerATNSimulator.debug) {
|
||||
console.log("closure(" + config.toString(this.recog, true) + ")");
|
||||
}
|
||||
if (config.state instanceof RuleStopState) {
|
||||
if (this.debug) {
|
||||
if (LexerATNSimulator.debug) {
|
||||
if (this.recog !== null) {
|
||||
console.log("closure at %s rule stop %s\n", this.recog.getRuleNames()[config.state.ruleIndex], config);
|
||||
console.log("closure at %s rule stop %s\n", this.recog.ruleNames[config.state.ruleIndex], config);
|
||||
} else {
|
||||
console.log("closure at rule stop %s\n", config);
|
||||
}
|
||||
|
@ -458,7 +458,7 @@ LexerATNSimulator.prototype.getEpsilonTarget = function(input, config, trans,
|
|||
// states reached by traversing predicates. Since this is when we
|
||||
// test them, we cannot cash the DFA state target of ID.
|
||||
|
||||
if (this.debug) {
|
||||
if (LexerATNSimulator.debug) {
|
||||
console.log("EVAL rule " + trans.ruleIndex + ":" + trans.predIndex);
|
||||
}
|
||||
configs.hasSemanticContext = true;
|
||||
|
@ -584,7 +584,7 @@ LexerATNSimulator.prototype.addDFAEdge = function(from_, tk, to, cfgs) {
|
|||
// Only track edges within the DFA bounds
|
||||
return to;
|
||||
}
|
||||
if (this.debug) {
|
||||
if (LexerATNSimulator.debug) {
|
||||
console.log("EDGE " + from_ + " -> " + to + " upon " + tk);
|
||||
}
|
||||
if (from_.edges === null) {
|
||||
|
@ -615,9 +615,8 @@ LexerATNSimulator.prototype.addDFAState = function(configs) {
|
|||
proposed.lexerActionExecutor = firstConfigWithRuleStopState.lexerActionExecutor;
|
||||
proposed.prediction = this.atn.ruleToTokenType[firstConfigWithRuleStopState.state.ruleIndex];
|
||||
}
|
||||
var hash = proposed.hashString();
|
||||
var dfa = this.decisionToDFA[this.mode];
|
||||
var existing = dfa.states[hash] || null;
|
||||
var existing = dfa.states.get(proposed);
|
||||
if (existing!==null) {
|
||||
return existing;
|
||||
}
|
||||
|
@ -625,7 +624,7 @@ LexerATNSimulator.prototype.addDFAState = function(configs) {
|
|||
newState.stateNumber = dfa.states.length;
|
||||
configs.setReadonly(true);
|
||||
newState.configs = configs;
|
||||
dfa.states[hash] = newState;
|
||||
dfa.states.add(newState);
|
||||
return newState;
|
||||
};
|
||||
|
||||
|
|
|
@ -47,8 +47,14 @@ function LexerAction(action) {
|
|||
return this;
|
||||
}
|
||||
|
||||
LexerAction.prototype.hashString = function() {
|
||||
return "" + this.actionType;
|
||||
LexerAction.prototype.hashCode = function() {
|
||||
var hash = new Hash();
|
||||
this.updateHashCode(hash);
|
||||
return hash.finish()
|
||||
};
|
||||
|
||||
LexerAction.prototype.updateHashCode = function(hash) {
|
||||
hash.update(this.actionType);
|
||||
};
|
||||
|
||||
LexerAction.prototype.equals = function(other) {
|
||||
|
@ -96,8 +102,8 @@ LexerTypeAction.prototype.execute = function(lexer) {
|
|||
lexer.type = this.type;
|
||||
};
|
||||
|
||||
LexerTypeAction.prototype.hashString = function() {
|
||||
return "" + this.actionType + this.type;
|
||||
LexerTypeAction.prototype.updateHashCode = function(hash) {
|
||||
hash.update(this.actionType, this.type);
|
||||
};
|
||||
|
||||
|
||||
|
@ -132,8 +138,8 @@ LexerPushModeAction.prototype.execute = function(lexer) {
|
|||
lexer.pushMode(this.mode);
|
||||
};
|
||||
|
||||
LexerPushModeAction.prototype.hashString = function() {
|
||||
return "" + this.actionType + this.mode;
|
||||
LexerPushModeAction.prototype.updateHashCode = function(hash) {
|
||||
hash.update(this.actionType, this.mode);
|
||||
};
|
||||
|
||||
LexerPushModeAction.prototype.equals = function(other) {
|
||||
|
@ -215,8 +221,8 @@ LexerModeAction.prototype.execute = function(lexer) {
|
|||
lexer.mode(this.mode);
|
||||
};
|
||||
|
||||
LexerModeAction.prototype.hashString = function() {
|
||||
return "" + this.actionType + this.mode;
|
||||
LexerModeAction.prototype.updateHashCode = function(hash) {
|
||||
hash.update(this.actionType, this.mode);
|
||||
};
|
||||
|
||||
LexerModeAction.prototype.equals = function(other) {
|
||||
|
@ -268,8 +274,8 @@ LexerCustomAction.prototype.execute = function(lexer) {
|
|||
lexer.action(null, this.ruleIndex, this.actionIndex);
|
||||
};
|
||||
|
||||
LexerCustomAction.prototype.hashString = function() {
|
||||
return "" + this.actionType + this.ruleIndex + this.actionIndex;
|
||||
LexerCustomAction.prototype.updateHashCode = function(hash) {
|
||||
hash.update(this.actionType, this.ruleIndex, this.actionIndex);
|
||||
};
|
||||
|
||||
LexerCustomAction.prototype.equals = function(other) {
|
||||
|
@ -301,8 +307,8 @@ LexerChannelAction.prototype.execute = function(lexer) {
|
|||
lexer._channel = this.channel;
|
||||
};
|
||||
|
||||
LexerChannelAction.prototype.hashString = function() {
|
||||
return "" + this.actionType + this.channel;
|
||||
LexerChannelAction.prototype.updateHashCode = function(hash) {
|
||||
hash.update(this.actionType, this.channel);
|
||||
};
|
||||
|
||||
LexerChannelAction.prototype.equals = function(other) {
|
||||
|
@ -357,8 +363,8 @@ LexerIndexedCustomAction.prototype.execute = function(lexer) {
|
|||
this.action.execute(lexer);
|
||||
};
|
||||
|
||||
LexerIndexedCustomAction.prototype.hashString = function() {
|
||||
return "" + this.actionType + this.offset + this.action;
|
||||
LexerIndexedCustomAction.prototype.updateHashCode = function(hash) {
|
||||
hash.update(this.actionType, this.offset, this.action);
|
||||
};
|
||||
|
||||
LexerIndexedCustomAction.prototype.equals = function(other) {
|
||||
|
|
|
@ -36,13 +36,14 @@
|
|||
// efficiently, ensuring that actions appearing only at the end of the rule do
|
||||
// not cause bloating of the {@link DFA} created for the lexer.</p>
|
||||
|
||||
var hashStuff = require("../Utils").hashStuff;
|
||||
var LexerIndexedCustomAction = require('./LexerAction').LexerIndexedCustomAction;
|
||||
|
||||
function LexerActionExecutor(lexerActions) {
|
||||
this.lexerActions = lexerActions === null ? [] : lexerActions;
|
||||
// Caches the result of {@link //hashCode} since the hash code is an element
|
||||
// of the performance-critical {@link LexerATNConfig//hashCode} operation.
|
||||
this._hashString = lexerActions.toString(); // "".join([str(la) for la in
|
||||
this.cachedHashCode = hashStuff(lexerActions); // "".join([str(la) for la in
|
||||
// lexerActions]))
|
||||
return this;
|
||||
}
|
||||
|
@ -157,16 +158,21 @@ LexerActionExecutor.prototype.execute = function(lexer, input, startIndex) {
|
|||
}
|
||||
};
|
||||
|
||||
LexerActionExecutor.prototype.hashString = function() {
|
||||
return this._hashString;
|
||||
LexerActionExecutor.prototype.hashCode = function() {
|
||||
return this.cachedHashCode;
|
||||
};
|
||||
|
||||
LexerActionExecutor.prototype.updateHashCode = function(hash) {
|
||||
hash.update(this.cachedHashCode);
|
||||
};
|
||||
|
||||
|
||||
LexerActionExecutor.prototype.equals = function(other) {
|
||||
if (this === other) {
|
||||
return true;
|
||||
} else if (!(other instanceof LexerActionExecutor)) {
|
||||
return false;
|
||||
} else if (this._hashString != other._hashString) {
|
||||
} else if (this.cachedHashCode != other.cachedHashCode) {
|
||||
return false;
|
||||
} else if (this.lexerActions.length != other.lexerActions.length) {
|
||||
return false;
|
||||
|
|
|
@ -315,6 +315,8 @@ ParserATNSimulator.prototype = Object.create(ATNSimulator.prototype);
|
|||
ParserATNSimulator.prototype.constructor = ParserATNSimulator;
|
||||
|
||||
ParserATNSimulator.prototype.debug = false;
|
||||
ParserATNSimulator.prototype.debug_closure = false;
|
||||
ParserATNSimulator.prototype.debug_add = false;
|
||||
ParserATNSimulator.prototype.debug_list_atn_decisions = false;
|
||||
ParserATNSimulator.prototype.dfa_debug = false;
|
||||
ParserATNSimulator.prototype.retry_debug = false;
|
||||
|
@ -746,7 +748,7 @@ ParserATNSimulator.prototype.computeReachSet = function(closure, t, fullCtx) {
|
|||
// First figure out where we can reach on input t
|
||||
for (var i=0; i<closure.items.length;i++) {
|
||||
var c = closure.items[i];
|
||||
if(this.debug) {
|
||||
if(this.debug_add) {
|
||||
console.log("testing " + this.getTokenName(t) + " at " + c);
|
||||
}
|
||||
if (c.state instanceof RuleStopState) {
|
||||
|
@ -755,7 +757,7 @@ ParserATNSimulator.prototype.computeReachSet = function(closure, t, fullCtx) {
|
|||
skippedStopStates = [];
|
||||
}
|
||||
skippedStopStates.push(c);
|
||||
if(this.debug) {
|
||||
if(this.debug_add) {
|
||||
console.log("added " + c + " to skippedStopStates");
|
||||
}
|
||||
}
|
||||
|
@ -767,7 +769,7 @@ ParserATNSimulator.prototype.computeReachSet = function(closure, t, fullCtx) {
|
|||
if (target!==null) {
|
||||
var cfg = new ATNConfig({state:target}, c);
|
||||
intermediate.add(cfg, this.mergeCache);
|
||||
if(this.debug) {
|
||||
if(this.debug_add) {
|
||||
console.log("added " + cfg + " to intermediate");
|
||||
}
|
||||
}
|
||||
|
@ -1225,9 +1227,9 @@ ParserATNSimulator.prototype.closure = function(config, configs, closureBusy, co
|
|||
|
||||
|
||||
ParserATNSimulator.prototype.closureCheckingStopState = function(config, configs, closureBusy, collectPredicates, fullCtx, depth, treatEofAsEpsilon) {
|
||||
if (this.debug) {
|
||||
if (this.debug || this.debug_closure) {
|
||||
console.log("closure(" + config.toString(this.parser,true) + ")");
|
||||
console.log("configs(" + configs.toString() + ")");
|
||||
// console.log("configs(" + configs.toString() + ")");
|
||||
if(config.reachesIntoOuterContext>50) {
|
||||
throw "problem";
|
||||
}
|
||||
|
@ -1276,6 +1278,7 @@ ParserATNSimulator.prototype.closureCheckingStopState = function(config, configs
|
|||
this.closure_(config, configs, closureBusy, collectPredicates, fullCtx, depth, treatEofAsEpsilon);
|
||||
};
|
||||
|
||||
|
||||
// Do the actual work of walking epsilon edges//
|
||||
ParserATNSimulator.prototype.closure_ = function(config, configs, closureBusy, collectPredicates, fullCtx, depth, treatEofAsEpsilon) {
|
||||
var p = config.state;
|
||||
|
@ -1342,6 +1345,8 @@ ParserATNSimulator.prototype.canDropLoopEntryEdgeInLeftRecursiveRule = function(
|
|||
// the context has an empty stack case. If so, it would mean
|
||||
// global FOLLOW so we can't perform optimization
|
||||
// Are we the special loop entry/exit state? or SLL wildcard
|
||||
if(p.stateType != ATNState.STAR_LOOP_ENTRY)
|
||||
return false;
|
||||
if(p.stateType != ATNState.STAR_LOOP_ENTRY || !p.isPrecedenceDecision ||
|
||||
config.context.isEmpty() || config.context.hasEmptyPath())
|
||||
return false;
|
||||
|
@ -1434,7 +1439,8 @@ ParserATNSimulator.prototype.getEpsilonTarget = function(config, t, collectPredi
|
|||
|
||||
ParserATNSimulator.prototype.actionTransition = function(config, t) {
|
||||
if (this.debug) {
|
||||
console.log("ACTION edge " + t.ruleIndex + ":" + t.actionIndex);
|
||||
var index = t.actionIndex==-1 ? 65535 : t.actionIndex;
|
||||
console.log("ACTION edge " + t.ruleIndex + ":" + index);
|
||||
}
|
||||
return new ATNConfig({state:t.target}, config);
|
||||
};
|
||||
|
@ -1575,11 +1581,12 @@ ParserATNSimulator.prototype.getTokenName = function( t) {
|
|||
return "EOF";
|
||||
}
|
||||
if( this.parser!==null && this.parser.literalNames!==null) {
|
||||
if (t >= this.parser.literalNames.length) {
|
||||
if (t >= this.parser.literalNames.length && t >= this.parser.symbolicNames.length) {
|
||||
console.log("" + t + " ttype out of range: " + this.parser.literalNames);
|
||||
console.log("" + this.parser.getInputStream().getTokens());
|
||||
} else {
|
||||
return this.parser.literalNames[t] + "<" + t + ">";
|
||||
var name = this.parser.literalNames[t] || this.parser.symbolicNames[t];
|
||||
return name + "<" + t + ">";
|
||||
}
|
||||
}
|
||||
return "" + t;
|
||||
|
@ -1666,8 +1673,9 @@ ParserATNSimulator.prototype.addDFAEdge = function(dfa, from_, t, to) {
|
|||
from_.edges[t+1] = to; // connect
|
||||
|
||||
if (this.debug) {
|
||||
var names = this.parser===null ? null : this.parser.literalNames;
|
||||
console.log("DFA=\n" + dfa.toString(names));
|
||||
var literalNames = this.parser===null ? null : this.parser.literalNames;
|
||||
var symbolicNames = this.parser===null ? null : this.parser.symbolicNames;
|
||||
console.log("DFA=\n" + dfa.toString(literalNames, symbolicNames));
|
||||
}
|
||||
return to;
|
||||
};
|
||||
|
@ -1690,8 +1698,7 @@ ParserATNSimulator.prototype.addDFAState = function(dfa, D) {
|
|||
if (D == ATNSimulator.ERROR) {
|
||||
return D;
|
||||
}
|
||||
var hash = D.hashString();
|
||||
var existing = dfa.states[hash] || null;
|
||||
var existing = dfa.states.get(D);
|
||||
if(existing!==null) {
|
||||
return existing;
|
||||
}
|
||||
|
@ -1700,7 +1707,7 @@ ParserATNSimulator.prototype.addDFAState = function(dfa, D) {
|
|||
D.configs.optimizeConfigs(this);
|
||||
D.configs.setReadonly(true);
|
||||
}
|
||||
dfa.states[hash] = D;
|
||||
dfa.states.add(D);
|
||||
if (this.debug) {
|
||||
console.log("adding new DFA state: " + D);
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
// ambiguities.
|
||||
|
||||
var Set = require('./../Utils').Set;
|
||||
var Map = require('./../Utils').Map;
|
||||
var BitSet = require('./../Utils').BitSet;
|
||||
var AltDict = require('./../Utils').AltDict;
|
||||
var ATN = require('./ATN').ATN;
|
||||
|
@ -41,6 +42,9 @@ var RuleStopState = require('./ATNState').RuleStopState;
|
|||
var ATNConfigSet = require('./ATNConfigSet').ATNConfigSet;
|
||||
var ATNConfig = require('./ATNConfig').ATNConfig;
|
||||
var SemanticContext = require('./SemanticContext').SemanticContext;
|
||||
var Hash = require("../Utils").Hash;
|
||||
var hashStuff = require('./../Utils').hashStuff;
|
||||
var equalArrays = require('./../Utils').equalArrays;
|
||||
|
||||
function PredictionMode() {
|
||||
return this;
|
||||
|
@ -515,27 +519,20 @@ PredictionMode.getAlts = function(altsets) {
|
|||
// map[c] U= c.{@link ATNConfig//alt alt} // map hash/equals uses s and x, not
|
||||
// alt and not pred
|
||||
// </pre>
|
||||
//
|
||||
|
||||
PredictionMode.getConflictingAltSubsets = function(configs) {
|
||||
var configToAlts = {};
|
||||
for(var i=0;i<configs.items.length;i++) {
|
||||
var c = configs.items[i];
|
||||
var key = "key_" + c.state.stateNumber + "/" + c.context;
|
||||
var alts = configToAlts[key] || null;
|
||||
var configToAlts = new Map();
|
||||
configToAlts.hashFunction = function(cfg) { hashStuff(cfg.state.stateNumber, cfg.context); };
|
||||
configToAlts.equalsFunction = function(c1, c2) { return c1.state.stateNumber==c2.state.stateNumber && c1.context.equals(c2.context);}
|
||||
configs.items.map(function(cfg) {
|
||||
var alts = configToAlts.get(cfg);
|
||||
if (alts === null) {
|
||||
alts = new BitSet();
|
||||
configToAlts[key] = alts;
|
||||
configToAlts.put(cfg, alts);
|
||||
}
|
||||
alts.add(c.alt);
|
||||
}
|
||||
var values = [];
|
||||
for(var k in configToAlts) {
|
||||
if(k.indexOf("key_")!==0) {
|
||||
continue;
|
||||
}
|
||||
values.push(configToAlts[k]);
|
||||
}
|
||||
return values;
|
||||
alts.add(cfg.alt);
|
||||
});
|
||||
return configToAlts.getValues();
|
||||
};
|
||||
|
||||
//
|
||||
|
|
|
@ -38,11 +38,18 @@
|
|||
//
|
||||
|
||||
var Set = require('./../Utils').Set;
|
||||
var Hash = require('./../Utils').Hash;
|
||||
|
||||
function SemanticContext() {
|
||||
return this;
|
||||
}
|
||||
|
||||
SemanticContext.prototype.hashCode = function() {
|
||||
var hash = new Hash();
|
||||
this.updateHashCode(hash);
|
||||
return hash.finish();
|
||||
};
|
||||
|
||||
// For context independent predicates, we evaluate them without a local
|
||||
// context (i.e., null context). That way, we can evaluate them without
|
||||
// having to create proper rule-specific context during prediction (as
|
||||
|
@ -135,8 +142,8 @@ Predicate.prototype.evaluate = function(parser, outerContext) {
|
|||
return parser.sempred(localctx, this.ruleIndex, this.predIndex);
|
||||
};
|
||||
|
||||
Predicate.prototype.hashString = function() {
|
||||
return "" + this.ruleIndex + "/" + this.predIndex + "/" + this.isCtxDependent;
|
||||
Predicate.prototype.updateHashCode = function(hash) {
|
||||
hash.update(this.ruleIndex, this.predIndex, this.isCtxDependent);
|
||||
};
|
||||
|
||||
Predicate.prototype.equals = function(other) {
|
||||
|
@ -179,8 +186,8 @@ PrecedencePredicate.prototype.compareTo = function(other) {
|
|||
return this.precedence - other.precedence;
|
||||
};
|
||||
|
||||
PrecedencePredicate.prototype.hashString = function() {
|
||||
return "31";
|
||||
PrecedencePredicate.prototype.updateHashCode = function(hash) {
|
||||
hash.update(31);
|
||||
};
|
||||
|
||||
PrecedencePredicate.prototype.equals = function(other) {
|
||||
|
@ -258,8 +265,8 @@ AND.prototype.equals = function(other) {
|
|||
}
|
||||
};
|
||||
|
||||
AND.prototype.hashString = function() {
|
||||
return "" + this.opnds + "/AND";
|
||||
AND.prototype.updateHashCode = function(hash) {
|
||||
hash.update(this.opnds, "AND");
|
||||
};
|
||||
//
|
||||
// {@inheritDoc}
|
||||
|
@ -362,8 +369,8 @@ OR.prototype.constructor = function(other) {
|
|||
}
|
||||
};
|
||||
|
||||
OR.prototype.hashString = function() {
|
||||
return "" + this.opnds + "/OR";
|
||||
OR.prototype.updateHashCode = function(hash) {
|
||||
hash.update(this.opnds, "OR");
|
||||
};
|
||||
|
||||
// <p>
|
||||
|
|
|
@ -28,21 +28,14 @@
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
var Set = require("../Utils").Set;
|
||||
var DFAState = require('./DFAState').DFAState;
|
||||
var StarLoopEntryState = require('../atn/ATNState').StarLoopEntryState;
|
||||
var ATNConfigSet = require('./../atn/ATNConfigSet').ATNConfigSet;
|
||||
var DFASerializer = require('./DFASerializer').DFASerializer;
|
||||
var LexerDFASerializer = require('./DFASerializer').LexerDFASerializer;
|
||||
|
||||
function DFAStatesSet() {
|
||||
return this;
|
||||
}
|
||||
|
||||
Object.defineProperty(DFAStatesSet.prototype, "length", {
|
||||
get : function() {
|
||||
return Object.keys(this).length;
|
||||
}
|
||||
});
|
||||
|
||||
function DFA(atnStartState, decision) {
|
||||
if (decision === undefined) {
|
||||
|
@ -53,7 +46,7 @@ function DFA(atnStartState, decision) {
|
|||
this.decision = decision;
|
||||
// A set of all DFA states. Use {@link Map} so we can get old state back
|
||||
// ({@link Set} only allows you to see if it's there).
|
||||
this._states = new DFAStatesSet();
|
||||
this._states = new Set();
|
||||
this.s0 = null;
|
||||
// {@code true} if this DFA is for a precedence decision; otherwise,
|
||||
// {@code false}. This is the backing field for {@link //isPrecedenceDfa},
|
||||
|
@ -157,12 +150,7 @@ Object.defineProperty(DFA.prototype, "states", {
|
|||
|
||||
// Return a list of all states in this DFA, ordered by state number.
|
||||
DFA.prototype.sortedStates = function() {
|
||||
// states_ is a map of state/state, where key=value
|
||||
var keys = Object.keys(this._states);
|
||||
var list = [];
|
||||
for(var i=0;i<keys.length;i++) {
|
||||
list.push(this._states[keys[i]]);
|
||||
}
|
||||
var list = this._states.values();
|
||||
return list.sort(function(a, b) {
|
||||
return a.stateNumber - b.stateNumber;
|
||||
});
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
var ATNConfigSet = require('./../atn/ATNConfigSet').ATNConfigSet;
|
||||
var Utils = require('./../Utils');
|
||||
var Hash = Utils.Hash;
|
||||
var Set = Utils.Set;
|
||||
|
||||
// Map a predicate to a predicted alternative.///
|
||||
|
@ -142,26 +143,33 @@ DFAState.prototype.getAltSet = function() {
|
|||
// {@link //stateNumber} is irrelevant.</p>
|
||||
DFAState.prototype.equals = function(other) {
|
||||
// compare set of ATN configurations in this set with other
|
||||
if (this === other) {
|
||||
return true;
|
||||
} else if (!(other instanceof DFAState)) {
|
||||
return false;
|
||||
} else {
|
||||
return this.configs.equals(other.configs);
|
||||
}
|
||||
return this === other ||
|
||||
(other instanceof DFAState &&
|
||||
this.configs.equals(other.configs));
|
||||
};
|
||||
|
||||
DFAState.prototype.toString = function() {
|
||||
return "" + this.stateNumber + ":" + this.hashString();
|
||||
var s = "" + this.stateNumber + ":" + this.configs;
|
||||
if(this.isAcceptState) {
|
||||
s = s + "=>";
|
||||
if (this.predicates !== null)
|
||||
s = s + this.predicates;
|
||||
else
|
||||
s = s + this.prediction;
|
||||
}
|
||||
return s;
|
||||
};
|
||||
|
||||
DFAState.prototype.hashString = function() {
|
||||
return "" + this.configs +
|
||||
(this.isAcceptState ?
|
||||
"=>" + (this.predicates !== null ?
|
||||
this.predicates :
|
||||
this.prediction) :
|
||||
"");
|
||||
DFAState.prototype.hashCode = function() {
|
||||
var hash = new Hash();
|
||||
hash.update(this.configs);
|
||||
if(this.isAcceptState) {
|
||||
if (this.predicates !== null)
|
||||
hash.update(this.predicates);
|
||||
else
|
||||
hash.update(this.prediction);
|
||||
}
|
||||
return hash.finish();
|
||||
};
|
||||
|
||||
exports.DFAState = DFAState;
|
||||
|
|
|
@ -87,7 +87,7 @@ function ParseTreeVisitor() {
|
|||
}
|
||||
|
||||
ParseTreeVisitor.prototype.visit = function(ctx) {
|
||||
if (Utils.isArray(ctx)) {
|
||||
if (Array.isArray(ctx)) {
|
||||
return ctx.map(function(child) {
|
||||
return ctx.accept(this);
|
||||
}, this);
|
||||
|
|
Loading…
Reference in New Issue