forked from jasder/antlr
use hashCode instead of hashString - Lexer seems to work but not Parser
This commit is contained in:
parent
d9f04b08ff
commit
e850b4d97f
|
@ -30,9 +30,7 @@
|
|||
|
||||
// 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;
|
||||
|
@ -152,6 +150,7 @@ Lexer.prototype.nextToken = function() {
|
|||
try {
|
||||
ttype = this._interp.match(this._input, this._mode);
|
||||
} catch (e) {
|
||||
console.log(e.stack);
|
||||
this.notifyListeners(e); // report error
|
||||
this.recover(e);
|
||||
}
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ function arrayToString(a) {
|
|||
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,
|
||||
|
@ -65,7 +65,7 @@ function standardEqualsFunction(a,b) {
|
|||
}
|
||||
|
||||
function standardHashFunction(a) {
|
||||
return a.hashString();
|
||||
return a.hashCode();
|
||||
}
|
||||
|
||||
function Set(hashFunction, equalsFunction) {
|
||||
|
@ -77,13 +77,19 @@ function Set(hashFunction, equalsFunction) {
|
|||
|
||||
Object.defineProperty(Set.prototype, "length", {
|
||||
get: function () {
|
||||
return this.values().length;
|
||||
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();
|
||||
var key = "hash_" + hash;
|
||||
if (key in this.data) {
|
||||
var i;
|
||||
var values = this.data[key];
|
||||
|
@ -101,18 +107,22 @@ Set.prototype.add = function(value) {
|
|||
};
|
||||
|
||||
Set.prototype.contains = function (value) {
|
||||
return this.get(value) != null;
|
||||
};
|
||||
|
||||
Set.prototype.get = function (value) {
|
||||
var hash = this.hashFunction(value);
|
||||
var key = hash.hashCode();
|
||||
var key = "hash_" + hash;
|
||||
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 values[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return null;
|
||||
};
|
||||
|
||||
Set.prototype.values = function () {
|
||||
|
@ -140,7 +150,9 @@ BitSet.prototype.add = function(value) {
|
|||
|
||||
BitSet.prototype.or = function (set) {
|
||||
var bits = this;
|
||||
Object.keys(set.data).map( function(alt) { bits.add(alt); });
|
||||
Object.keys(set.data).map(function (alt) {
|
||||
bits.add(alt);
|
||||
});
|
||||
};
|
||||
|
||||
BitSet.prototype.remove = function (value) {
|
||||
|
@ -159,15 +171,17 @@ 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();
|
||||
return this.hashCode() === other.hashCode();
|
||||
};
|
||||
|
||||
Object.defineProperty(BitSet.prototype, "length", {
|
||||
|
@ -211,6 +225,60 @@ function DoubleDict() {
|
|||
return this;
|
||||
}
|
||||
|
||||
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;
|
||||
default:
|
||||
k = value.hashCode();
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
exports.hashStuff = function() {
|
||||
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);
|
||||
|
@ -236,12 +304,27 @@ function escapeWhitespace(s, escapeSpaces) {
|
|||
return s;
|
||||
}
|
||||
|
||||
exports.isArray = function (entity) {
|
||||
return Object.prototype.toString.call( entity ) === '[object Array]'
|
||||
exports.titleCase = function (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);});
|
||||
exports.equalArrays = function(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.Set = Set;
|
||||
|
@ -250,3 +333,4 @@ exports.AltDict = AltDict;
|
|||
exports.DoubleDict = DoubleDict;
|
||||
exports.escapeWhitespace = escapeWhitespace;
|
||||
exports.arrayToString = arrayToString;
|
||||
exports.Hash = Hash;
|
|
@ -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,36 +187,31 @@ 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) &&
|
||||
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;
|
||||
this.dipsIntoOuterContext === other.dipsIntoOuterContext);
|
||||
};
|
||||
|
||||
ATNConfigSet.prototype.hashString = function() {
|
||||
ATNConfigSet.prototype.hashCode = function() {
|
||||
if (this.readOnly) {
|
||||
if (this.cachedHashString === "-1") {
|
||||
this.cachedHashString = this.hashConfigs();
|
||||
if (this.cachedHashCode === -1) {
|
||||
this.cachedHashCode = this.hashConfigs();
|
||||
}
|
||||
return this.cachedHashString;
|
||||
return this.cachedHashCode;
|
||||
} else {
|
||||
return this.hashConfigs();
|
||||
}
|
||||
};
|
||||
|
||||
ATNConfigSet.prototype.hashConfigs = function() {
|
||||
var s = "";
|
||||
this.configs.map(function(c) {
|
||||
s += c.toString();
|
||||
});
|
||||
return s;
|
||||
var hash = new Hash();
|
||||
hash.update(this.configs);
|
||||
return hash.finish();
|
||||
};
|
||||
|
||||
Object.defineProperty(ATNConfigSet.prototype, "length", {
|
||||
|
@ -247,7 +243,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,8 +158,8 @@ LexerActionExecutor.prototype.execute = function(lexer, input, startIndex) {
|
|||
}
|
||||
};
|
||||
|
||||
LexerActionExecutor.prototype.hashString = function() {
|
||||
return this._hashString;
|
||||
LexerActionExecutor.prototype.hashCode = function() {
|
||||
return this.cachedHashCode;
|
||||
};
|
||||
|
||||
LexerActionExecutor.prototype.equals = function(other) {
|
||||
|
@ -166,7 +167,7 @@ LexerActionExecutor.prototype.equals = function(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;
|
||||
|
|
|
@ -1276,6 +1276,9 @@ ParserATNSimulator.prototype.closureCheckingStopState = function(config, configs
|
|||
this.closure_(config, configs, closureBusy, collectPredicates, fullCtx, depth, treatEofAsEpsilon);
|
||||
};
|
||||
|
||||
var drops = [];
|
||||
var odds = 0;
|
||||
|
||||
// Do the actual work of walking epsilon edges//
|
||||
ParserATNSimulator.prototype.closure_ = function(config, configs, closureBusy, collectPredicates, fullCtx, depth, treatEofAsEpsilon) {
|
||||
var p = config.state;
|
||||
|
@ -1286,8 +1289,16 @@ ParserATNSimulator.prototype.closure_ = function(config, configs, closureBusy, c
|
|||
// both epsilon transitions and non-epsilon transitions.
|
||||
}
|
||||
for(var i = 0;i<p.transitions.length; i++) {
|
||||
if(i==0 && this.canDropLoopEntryEdgeInLeftRecursiveRule(config))
|
||||
if(i==0) {
|
||||
if(drops.length==100)
|
||||
drops = [];
|
||||
if (this.canDropLoopEntryEdgeInLeftRecursiveRule(config)) {
|
||||
drops.push(odds);
|
||||
odds = odds + 1;
|
||||
continue;
|
||||
} else
|
||||
odds = odds + 1;
|
||||
}
|
||||
|
||||
var t = p.transitions[i];
|
||||
var continueCollecting = collectPredicates && !(t instanceof ActionTransition);
|
||||
|
@ -1342,6 +1353,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;
|
||||
|
@ -1690,7 +1703,7 @@ ParserATNSimulator.prototype.addDFAState = function(dfa, D) {
|
|||
if (D == ATNSimulator.ERROR) {
|
||||
return D;
|
||||
}
|
||||
var hash = D.hashString();
|
||||
var hash = "key_" + D.hashCode();
|
||||
var existing = dfa.states[hash] || null;
|
||||
if(existing!==null) {
|
||||
return existing;
|
||||
|
|
|
@ -41,6 +41,7 @@ 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;
|
||||
|
||||
function PredictionMode() {
|
||||
return this;
|
||||
|
@ -520,7 +521,13 @@ 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 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;
|
||||
if (alts === null) {
|
||||
alts = new BitSet();
|
||||
|
|
|
@ -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