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 Recognizer = require('./Recognizer').Recognizer;
|
||||
var CommonTokenFactory = require('./CommonTokenFactory').CommonTokenFactory;
|
||||
var RecognitionException = require('./error/Errors').RecognitionException;
|
||||
var LexerNoViableAltException = require('./error/Errors').LexerNoViableAltException;
|
||||
|
||||
function TokenSource() {
|
||||
|
@ -150,9 +151,13 @@ Lexer.prototype.nextToken = function() {
|
|||
try {
|
||||
ttype = this._interp.match(this._input, this._mode);
|
||||
} catch (e) {
|
||||
console.log(e.stack);
|
||||
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;
|
||||
|
|
|
@ -64,13 +64,13 @@ function standardEqualsFunction(a, b) {
|
|||
return a.equals(b);
|
||||
}
|
||||
|
||||
function standardHashFunction(a) {
|
||||
function standardHashCodeFunction(a) {
|
||||
return a.hashCode();
|
||||
}
|
||||
|
||||
function Set(hashFunction, equalsFunction) {
|
||||
this.data = {};
|
||||
this.hashFunction = hashFunction || standardHashFunction;
|
||||
this.hashFunction = hashFunction || standardHashCodeFunction;
|
||||
this.equalsFunction = equalsFunction || standardEqualsFunction;
|
||||
return this;
|
||||
}
|
||||
|
@ -91,9 +91,8 @@ Set.prototype.add = function (value) {
|
|||
var hash = this.hashFunction(value);
|
||||
var key = "hash_" + hash;
|
||||
if (key in this.data) {
|
||||
var i;
|
||||
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])) {
|
||||
return values[i];
|
||||
}
|
||||
|
@ -114,9 +113,8 @@ Set.prototype.get = function (value) {
|
|||
var hash = this.hashFunction(value);
|
||||
var key = "hash_" + hash;
|
||||
if (key in this.data) {
|
||||
var i;
|
||||
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])) {
|
||||
return values[i];
|
||||
}
|
||||
|
@ -194,11 +192,110 @@ BitSet.prototype.toString = function () {
|
|||
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() {
|
||||
this.data = {};
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
AltDict.prototype.get = function (key) {
|
||||
key = "k-" + key;
|
||||
if (key in this.data) {
|
||||
|
@ -248,8 +345,12 @@ Hash.prototype.update = function () {
|
|||
case 'boolean':
|
||||
k = value;
|
||||
break;
|
||||
default:
|
||||
case 'string':
|
||||
k = value.hashCode();
|
||||
break;
|
||||
default:
|
||||
value.updateHashCode(this);
|
||||
continue;
|
||||
}
|
||||
k = k * 0xCC9E2D51;
|
||||
k = (k << 15) | (k >>> (32 - 15));
|
||||
|
@ -273,7 +374,7 @@ Hash.prototype.finish = function () {
|
|||
return hash;
|
||||
}
|
||||
|
||||
exports.hashStuff = function() {
|
||||
function hashStuff() {
|
||||
var hash = new Hash();
|
||||
hash.update.apply(arguments);
|
||||
return hash.finish();
|
||||
|
@ -304,13 +405,13 @@ function escapeWhitespace(s, escapeSpaces) {
|
|||
return s;
|
||||
}
|
||||
|
||||
exports.titleCase = function (str) {
|
||||
function titleCase(str) {
|
||||
return str.replace(/\w\S*/g, function (txt) {
|
||||
return txt.charAt(0).toUpperCase() + txt.substr(1);
|
||||
});
|
||||
};
|
||||
|
||||
exports.equalArrays = function(a, b)
|
||||
function equalArrays(a, b)
|
||||
{
|
||||
if (!Array.isArray(a) || !Array.isArray(b))
|
||||
return false;
|
||||
|
@ -327,10 +428,14 @@ exports.equalArrays = function(a, b)
|
|||
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.Hash = Hash;
|
||||
exports.titleCase = titleCase;
|
||||
exports.equalArrays = equalArrays;
|
|
@ -198,21 +198,25 @@ ATNConfigSet.prototype.equals = function(other) {
|
|||
};
|
||||
|
||||
ATNConfigSet.prototype.hashCode = function() {
|
||||
var hash = new Hash();
|
||||
this.updateHashCode(hash);
|
||||
return hash.finish();
|
||||
};
|
||||
|
||||
|
||||
ATNConfigSet.prototype.updateHashCode = function(hash) {
|
||||
if (this.readOnly) {
|
||||
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 {
|
||||
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", {
|
||||
get : function() {
|
||||
|
|
|
@ -162,6 +162,11 @@ 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;
|
||||
|
|
|
@ -1703,8 +1703,7 @@ ParserATNSimulator.prototype.addDFAState = function(dfa, D) {
|
|||
if (D == ATNSimulator.ERROR) {
|
||||
return D;
|
||||
}
|
||||
var hash = "key_" + D.hashCode();
|
||||
var existing = dfa.states[hash] || null;
|
||||
var existing = dfa.states.get(D);
|
||||
if(existing!==null) {
|
||||
return existing;
|
||||
}
|
||||
|
@ -1713,7 +1712,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;
|
||||
|
@ -42,6 +43,8 @@ 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;
|
||||
|
@ -516,33 +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 hash = new Hash();
|
||||
hash.update(c.state.stateNumber);
|
||||
if(!c.context.updateHashCode)
|
||||
c;
|
||||
c.context.updateHashCode(hash);
|
||||
var hashed = hash.finish()
|
||||
var key = "key_" + hashed;
|
||||
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();
|
||||
};
|
||||
|
||||
//
|
||||
|
|
Loading…
Reference in New Issue