forked from jasder/antlr
fix various hashing issues
This commit is contained in:
parent
e850b4d97f
commit
7332c1eb02
|
@ -35,6 +35,7 @@
|
||||||
var Token = require('./Token').Token;
|
var Token = require('./Token').Token;
|
||||||
var Recognizer = require('./Recognizer').Recognizer;
|
var Recognizer = require('./Recognizer').Recognizer;
|
||||||
var CommonTokenFactory = require('./CommonTokenFactory').CommonTokenFactory;
|
var CommonTokenFactory = require('./CommonTokenFactory').CommonTokenFactory;
|
||||||
|
var RecognitionException = require('./error/Errors').RecognitionException;
|
||||||
var LexerNoViableAltException = require('./error/Errors').LexerNoViableAltException;
|
var LexerNoViableAltException = require('./error/Errors').LexerNoViableAltException;
|
||||||
|
|
||||||
function TokenSource() {
|
function TokenSource() {
|
||||||
|
@ -150,9 +151,13 @@ Lexer.prototype.nextToken = function() {
|
||||||
try {
|
try {
|
||||||
ttype = this._interp.match(this._input, this._mode);
|
ttype = this._interp.match(this._input, this._mode);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e.stack);
|
if(e instanceof RecognitionException) {
|
||||||
this.notifyListeners(e); // report error
|
this.notifyListeners(e); // report error
|
||||||
this.recover(e);
|
this.recover(e);
|
||||||
|
} else {
|
||||||
|
console.log(e.stack);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (this._input.LA(1) === Token.EOF) {
|
if (this._input.LA(1) === Token.EOF) {
|
||||||
this._hitEOF = true;
|
this._hitEOF = true;
|
||||||
|
|
|
@ -64,13 +64,13 @@ function standardEqualsFunction(a, b) {
|
||||||
return a.equals(b);
|
return a.equals(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
function standardHashFunction(a) {
|
function standardHashCodeFunction(a) {
|
||||||
return a.hashCode();
|
return a.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
function Set(hashFunction, equalsFunction) {
|
function Set(hashFunction, equalsFunction) {
|
||||||
this.data = {};
|
this.data = {};
|
||||||
this.hashFunction = hashFunction || standardHashFunction;
|
this.hashFunction = hashFunction || standardHashCodeFunction;
|
||||||
this.equalsFunction = equalsFunction || standardEqualsFunction;
|
this.equalsFunction = equalsFunction || standardEqualsFunction;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -91,9 +91,8 @@ Set.prototype.add = function (value) {
|
||||||
var hash = this.hashFunction(value);
|
var hash = this.hashFunction(value);
|
||||||
var key = "hash_" + hash;
|
var key = "hash_" + hash;
|
||||||
if (key in this.data) {
|
if (key in this.data) {
|
||||||
var i;
|
|
||||||
var values = this.data[key];
|
var values = this.data[key];
|
||||||
for (i = 0; i < values.length; i++) {
|
for (var i = 0; i < values.length; i++) {
|
||||||
if (this.equalsFunction(value, values[i])) {
|
if (this.equalsFunction(value, values[i])) {
|
||||||
return values[i];
|
return values[i];
|
||||||
}
|
}
|
||||||
|
@ -114,9 +113,8 @@ Set.prototype.get = function (value) {
|
||||||
var hash = this.hashFunction(value);
|
var hash = this.hashFunction(value);
|
||||||
var key = "hash_" + hash;
|
var key = "hash_" + hash;
|
||||||
if (key in this.data) {
|
if (key in this.data) {
|
||||||
var i;
|
|
||||||
var values = this.data[key];
|
var values = this.data[key];
|
||||||
for (i = 0; i < values.length; i++) {
|
for (var i = 0; i < values.length; i++) {
|
||||||
if (this.equalsFunction(value, values[i])) {
|
if (this.equalsFunction(value, values[i])) {
|
||||||
return values[i];
|
return values[i];
|
||||||
}
|
}
|
||||||
|
@ -194,11 +192,110 @@ BitSet.prototype.toString = function () {
|
||||||
return "{" + this.values().join(", ") + "}";
|
return "{" + this.values().join(", ") + "}";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function Map(hashFunction, equalsFunction) {
|
||||||
|
this.data = {};
|
||||||
|
this.hashFunction = hashFunction || standardHashCodeFunction;
|
||||||
|
this.equalsFunction = equalsFunction || standardEqualsFunction;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
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() {
|
function AltDict() {
|
||||||
this.data = {};
|
this.data = {};
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AltDict.prototype.get = function (key) {
|
AltDict.prototype.get = function (key) {
|
||||||
key = "k-" + key;
|
key = "k-" + key;
|
||||||
if (key in this.data) {
|
if (key in this.data) {
|
||||||
|
@ -248,8 +345,12 @@ Hash.prototype.update = function () {
|
||||||
case 'boolean':
|
case 'boolean':
|
||||||
k = value;
|
k = value;
|
||||||
break;
|
break;
|
||||||
default:
|
case 'string':
|
||||||
k = value.hashCode();
|
k = value.hashCode();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
value.updateHashCode(this);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
k = k * 0xCC9E2D51;
|
k = k * 0xCC9E2D51;
|
||||||
k = (k << 15) | (k >>> (32 - 15));
|
k = (k << 15) | (k >>> (32 - 15));
|
||||||
|
@ -273,7 +374,7 @@ Hash.prototype.finish = function () {
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.hashStuff = function() {
|
function hashStuff() {
|
||||||
var hash = new Hash();
|
var hash = new Hash();
|
||||||
hash.update.apply(arguments);
|
hash.update.apply(arguments);
|
||||||
return hash.finish();
|
return hash.finish();
|
||||||
|
@ -304,13 +405,13 @@ function escapeWhitespace(s, escapeSpaces) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.titleCase = function (str) {
|
function titleCase(str) {
|
||||||
return str.replace(/\w\S*/g, function (txt) {
|
return str.replace(/\w\S*/g, function (txt) {
|
||||||
return txt.charAt(0).toUpperCase() + txt.substr(1);
|
return txt.charAt(0).toUpperCase() + txt.substr(1);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.equalArrays = function(a, b)
|
function equalArrays(a, b)
|
||||||
{
|
{
|
||||||
if (!Array.isArray(a) || !Array.isArray(b))
|
if (!Array.isArray(a) || !Array.isArray(b))
|
||||||
return false;
|
return false;
|
||||||
|
@ -327,10 +428,14 @@ exports.equalArrays = function(a, b)
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.Hash = Hash;
|
||||||
exports.Set = Set;
|
exports.Set = Set;
|
||||||
|
exports.Map = Map;
|
||||||
exports.BitSet = BitSet;
|
exports.BitSet = BitSet;
|
||||||
exports.AltDict = AltDict;
|
exports.AltDict = AltDict;
|
||||||
exports.DoubleDict = DoubleDict;
|
exports.DoubleDict = DoubleDict;
|
||||||
|
exports.hashStuff = hashStuff;
|
||||||
exports.escapeWhitespace = escapeWhitespace;
|
exports.escapeWhitespace = escapeWhitespace;
|
||||||
exports.arrayToString = arrayToString;
|
exports.arrayToString = arrayToString;
|
||||||
exports.Hash = Hash;
|
exports.titleCase = titleCase;
|
||||||
|
exports.equalArrays = equalArrays;
|
|
@ -198,21 +198,25 @@ ATNConfigSet.prototype.equals = function(other) {
|
||||||
};
|
};
|
||||||
|
|
||||||
ATNConfigSet.prototype.hashCode = 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.readOnly) {
|
||||||
if (this.cachedHashCode === -1) {
|
if (this.cachedHashCode === -1) {
|
||||||
this.cachedHashCode = this.hashConfigs();
|
var hash = new Hash();
|
||||||
|
hash.update(this.configs);
|
||||||
|
this.cachedHashCode = hash.finish();
|
||||||
}
|
}
|
||||||
return this.cachedHashCode;
|
hash.update(this.cachedHashCode);
|
||||||
} else {
|
} else {
|
||||||
return this.hashConfigs();
|
hash.update(this.configs);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ATNConfigSet.prototype.hashConfigs = function() {
|
|
||||||
var hash = new Hash();
|
|
||||||
hash.update(this.configs);
|
|
||||||
return hash.finish();
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.defineProperty(ATNConfigSet.prototype, "length", {
|
Object.defineProperty(ATNConfigSet.prototype, "length", {
|
||||||
get : function() {
|
get : function() {
|
||||||
|
|
|
@ -162,6 +162,11 @@ LexerActionExecutor.prototype.hashCode = function() {
|
||||||
return this.cachedHashCode;
|
return this.cachedHashCode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
LexerActionExecutor.prototype.updateHashCode = function(hash) {
|
||||||
|
hash.update(this.cachedHashCode);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
LexerActionExecutor.prototype.equals = function(other) {
|
LexerActionExecutor.prototype.equals = function(other) {
|
||||||
if (this === other) {
|
if (this === other) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1703,8 +1703,7 @@ ParserATNSimulator.prototype.addDFAState = function(dfa, D) {
|
||||||
if (D == ATNSimulator.ERROR) {
|
if (D == ATNSimulator.ERROR) {
|
||||||
return D;
|
return D;
|
||||||
}
|
}
|
||||||
var hash = "key_" + D.hashCode();
|
var existing = dfa.states.get(D);
|
||||||
var existing = dfa.states[hash] || null;
|
|
||||||
if(existing!==null) {
|
if(existing!==null) {
|
||||||
return existing;
|
return existing;
|
||||||
}
|
}
|
||||||
|
@ -1713,7 +1712,7 @@ ParserATNSimulator.prototype.addDFAState = function(dfa, D) {
|
||||||
D.configs.optimizeConfigs(this);
|
D.configs.optimizeConfigs(this);
|
||||||
D.configs.setReadonly(true);
|
D.configs.setReadonly(true);
|
||||||
}
|
}
|
||||||
dfa.states[hash] = D;
|
dfa.states.add(D);
|
||||||
if (this.debug) {
|
if (this.debug) {
|
||||||
console.log("adding new DFA state: " + D);
|
console.log("adding new DFA state: " + D);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
// ambiguities.
|
// ambiguities.
|
||||||
|
|
||||||
var Set = require('./../Utils').Set;
|
var Set = require('./../Utils').Set;
|
||||||
|
var Map = require('./../Utils').Map;
|
||||||
var BitSet = require('./../Utils').BitSet;
|
var BitSet = require('./../Utils').BitSet;
|
||||||
var AltDict = require('./../Utils').AltDict;
|
var AltDict = require('./../Utils').AltDict;
|
||||||
var ATN = require('./ATN').ATN;
|
var ATN = require('./ATN').ATN;
|
||||||
|
@ -42,6 +43,8 @@ var ATNConfigSet = require('./ATNConfigSet').ATNConfigSet;
|
||||||
var ATNConfig = require('./ATNConfig').ATNConfig;
|
var ATNConfig = require('./ATNConfig').ATNConfig;
|
||||||
var SemanticContext = require('./SemanticContext').SemanticContext;
|
var SemanticContext = require('./SemanticContext').SemanticContext;
|
||||||
var Hash = require("../Utils").Hash;
|
var Hash = require("../Utils").Hash;
|
||||||
|
var hashStuff = require('./../Utils').hashStuff;
|
||||||
|
var equalArrays = require('./../Utils').equalArrays;
|
||||||
|
|
||||||
function PredictionMode() {
|
function PredictionMode() {
|
||||||
return this;
|
return this;
|
||||||
|
@ -516,33 +519,20 @@ PredictionMode.getAlts = function(altsets) {
|
||||||
// map[c] U= c.{@link ATNConfig//alt alt} // map hash/equals uses s and x, not
|
// map[c] U= c.{@link ATNConfig//alt alt} // map hash/equals uses s and x, not
|
||||||
// alt and not pred
|
// alt and not pred
|
||||||
// </pre>
|
// </pre>
|
||||||
//
|
|
||||||
PredictionMode.getConflictingAltSubsets = function(configs) {
|
PredictionMode.getConflictingAltSubsets = function(configs) {
|
||||||
var configToAlts = {};
|
var configToAlts = new Map();
|
||||||
for(var i=0;i<configs.items.length;i++) {
|
configToAlts.hashFunction = function(cfg) { hashStuff(cfg.state.stateNumber, cfg.context); };
|
||||||
var c = configs.items[i];
|
configToAlts.equalsFunction = function(c1, c2) { return c1.state.stateNumber==c2.state.stateNumber && c1.context.equals(c2.context);}
|
||||||
var hash = new Hash();
|
configs.items.map(function(cfg) {
|
||||||
hash.update(c.state.stateNumber);
|
var alts = configToAlts.get(cfg);
|
||||||
if(!c.context.updateHashCode)
|
|
||||||
c;
|
|
||||||
c.context.updateHashCode(hash);
|
|
||||||
var hashed = hash.finish()
|
|
||||||
var key = "key_" + hashed;
|
|
||||||
var alts = configToAlts[key] || null;
|
|
||||||
if (alts === null) {
|
if (alts === null) {
|
||||||
alts = new BitSet();
|
alts = new BitSet();
|
||||||
configToAlts[key] = alts;
|
configToAlts.put(cfg, alts);
|
||||||
}
|
}
|
||||||
alts.add(c.alt);
|
alts.add(cfg.alt);
|
||||||
}
|
});
|
||||||
var values = [];
|
return configToAlts.getValues();
|
||||||
for(var k in configToAlts) {
|
|
||||||
if(k.indexOf("key_")!==0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
values.push(configToAlts[k]);
|
|
||||||
}
|
|
||||||
return values;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in New Issue