@a-s8h/liblevenshtein
Version:
Various utilities regarding Levenshtein transducers.
134 lines (115 loc) • 3.76 kB
JavaScript
// Generated by CoffeeScript 1.7.1
(function() {
var Dawg, DawgNode, global;
DawgNode = (function() {
DawgNode.next_id = 0;
function DawgNode() {
this.id = DawgNode.next_id;
DawgNode.next_id += 1;
this['is_final'] = false;
this['edges'] = {};
}
DawgNode.prototype.bisect_left = function(edges, edge, lower, upper) {
var i;
while (lower < upper) {
i = (lower + upper) >> 1;
if (edges[i] < edge) {
lower = i + 1;
} else {
upper = i;
}
}
return lower;
};
DawgNode.prototype['toString'] = function() {
var edge, edges, label, node, _ref;
edges = [];
_ref = this['edges'];
for (label in _ref) {
node = _ref[label];
edge = label + node.id.toString();
edges.splice(this.bisect_left(edges, edge, 0, edges.length), 0, edge);
}
return (+this['is_final']) + edges.join('');
};
return DawgNode;
})();
Dawg = (function() {
function Dawg(dictionary) {
var word, _i, _len;
if (!(dictionary && typeof dictionary.length === 'number')) {
throw new Error("Expected dictionary to be array-like");
}
this.previous_word = '';
this['root'] = new DawgNode();
this.unchecked_nodes = [];
this.minimized_nodes = {};
for (_i = 0, _len = dictionary.length; _i < _len; _i++) {
word = dictionary[_i];
this['insert'](word);
}
this.finish();
}
Dawg.prototype['insert'] = function(word) {
var character, i, next_node, node, previous_word, unchecked_nodes, upper_bound;
i = 0;
previous_word = this.previous_word;
upper_bound = word.length < previous_word.length ? word.length : previous_word.length;
while (i < upper_bound && word[i] === previous_word[i]) {
i += 1;
}
this.minimize(i);
unchecked_nodes = this.unchecked_nodes;
if (unchecked_nodes.length === 0) {
node = this['root'];
} else {
node = unchecked_nodes[unchecked_nodes.length - 1][2];
}
while ((character = word[i]) !== undefined) {
next_node = new DawgNode();
node['edges'][character] = next_node;
unchecked_nodes.push([node, character, next_node]);
node = next_node;
i += 1;
}
node['is_final'] = true;
this.previous_word = word;
};
Dawg.prototype.finish = function() {
this.minimize(0);
};
Dawg.prototype.minimize = function(lower_bound) {
var character, child, child_key, j, minimized_nodes, parent, unchecked_nodes, _ref;
minimized_nodes = this.minimized_nodes;
unchecked_nodes = this.unchecked_nodes;
j = unchecked_nodes.length;
while (j > lower_bound) {
_ref = unchecked_nodes.pop(), parent = _ref[0], character = _ref[1], child = _ref[2];
child_key = child.toString();
if (child_key in minimized_nodes) {
parent['edges'][character] = minimized_nodes[child_key];
} else {
minimized_nodes[child_key] = child;
}
j -= 1;
}
};
Dawg.prototype['accepts'] = function(word) {
var edge, node, _i, _len;
node = this['root'];
for (_i = 0, _len = word.length; _i < _len; _i++) {
edge = word[_i];
node = node['edges'][edge];
if (!node) {
return false;
}
}
return node['is_final'];
};
return Dawg;
})();
global = typeof exports === 'object' ? exports : typeof window === 'object' ? window : this;
global['levenshtein'] || (global['levenshtein'] = {});
global['levenshtein']['DawgNode'] = DawgNode;
global['levenshtein']['Dawg'] = Dawg;
}).call(this);