summaryrefslogtreecommitdiff
path: root/old-lib/javascript/gflib.js
diff options
context:
space:
mode:
Diffstat (limited to 'old-lib/javascript/gflib.js')
-rw-r--r--old-lib/javascript/gflib.js1128
1 files changed, 0 insertions, 1128 deletions
diff --git a/old-lib/javascript/gflib.js b/old-lib/javascript/gflib.js
deleted file mode 100644
index 728655469..000000000
--- a/old-lib/javascript/gflib.js
+++ /dev/null
@@ -1,1128 +0,0 @@
-
-function GFGrammar(abstract, concretes) {
- this.abstract = abstract;
- this.concretes = concretes;
-}
-
-/* Translates a string from any concrete syntax to all concrete syntaxes.
- Uses the start category of the grammar.
-*/
-GFGrammar.prototype.translate = function (input, fromLang, toLang) {
- var outputs = new Object();
- var fromConcs = this.concretes;
- if (fromLang) {
- fromConcs = new Object();
- fromConcs[fromLang] = this.concretes[fromLang];
- }
- var toConcs = this.concretes;
- if (toLang) {
- toConcs = new Object();
- toConcs[toLang] = this.concretes[toLang];
- }
- for (var c1 in fromConcs) {
- var p = this.concretes[c1].parser;
- if (p) {
- var trees = p.parseString(input, this.abstract.startcat);
- if (trees.length > 0) {
- outputs[c1] = new Array();
- for (var i in trees) {
- outputs[c1][i] = new Object();
- for (var c2 in toConcs) {
- outputs[c1][i][c2] = this.concretes[c2].linearize(trees[i]);
- }
- }
- }
- }
- }
- return outputs;
-}
-
-
-/* ------------------------------------------------------------------------- */
-/* ----------------------------- LINEARIZATION ----------------------------- */
-/* ------------------------------------------------------------------------- */
-
-/* Extension to the String object */
-
-String.prototype.tag = "";
-String.prototype.setTag = function (tag) { this.tag = tag; };
-
-/* Abstract syntax trees */
-function Fun(name) {
- this.name = name;
- this.args = copy_arguments(arguments, 1);
-}
-Fun.prototype.print = function () { return this.show(0); } ;
-Fun.prototype.show = function (prec) {
- if (this.isMeta()) {
- if (isUndefined(this.type)) {
- return '?';
- } else {
- var s = '?:' + this.type;
- if (prec > 0) {
- s = "(" + s + ")" ;
- }
- return s;
- }
- } else {
- var s = this.name;
- var cs = this.args;
- for (var i in cs) {
- s += " " + (isUndefined(cs[i]) ? "undefined" : cs[i].show(1));
- }
- if (prec > 0 && cs.length > 0) {
- s = "(" + s + ")" ;
- }
- return s;
- }
-};
-Fun.prototype.getArg = function (i) {
- return this.args[i];
-};
-Fun.prototype.setArg = function (i,c) {
- this.args[i] = c;
-};
-Fun.prototype.isMeta = function() {
- return this.name == '?';
-} ;
-Fun.prototype.isComplete = function() {
- if (this.isMeta()) {
- return false;
- } else {
- for (var i in this.args) {
- if (!this.args[i].isComplete()) {
- return false;
- }
- }
- return true;
- }
-} ;
-Fun.prototype.isLiteral = function() {
- return (/^[\"\d]/).test(this.name);
-} ;
-
-/* Concrete syntax terms */
-
-function Arr() { this.arr = copy_arguments(arguments, 0); }
-Arr.prototype.tokens = function() { return this.arr[0].tokens(); };
-Arr.prototype.sel = function(i) { return this.arr[i.toIndex()]; };
-Arr.prototype.setTag = function(tag) {
- for (var i = 0, j = this.arr.length; i < j; i++) {
- this.arr[i].setTag(tag);
- }
-};
-
-function Seq() { this.seq = copy_arguments(arguments, 0); }
-Seq.prototype.tokens = function() {
- var xs = new Array();
- for (var i in this.seq) {
- var ys = this.seq[i].tokens();
- for (var j in ys) {
- xs.push(ys[j]);
- }
- }
- return xs;
-};
-Seq.prototype.setTag = function(tag) {
- for (var i = 0, j = this.seq.length; i < j; i++) {
- this.seq[i].setTag(tag);
- }
-};
-
-function Variants() { this.variants = copy_arguments(arguments, 0); }
-Variants.prototype.tokens = function() { return this.variants[0].tokens(); };
-Variants.prototype.sel = function(i) { return this.variants[0].sel(i); };
-Variants.prototype.toIndex = function() { return this.variants[0].toIndex(); };
-Variants.prototype.setTag = function(tag) {
- for (var i = 0, j = this.variants.length; i < j; i++) {
- this.variants[i].setTag(tag);
- }
-};
-
-function Rp(index,value) { this.index = index; this.value = value; }
-Rp.prototype.tokens = function() { return new Array(this.index.tokens()); };
-Rp.prototype.sel = function(i) { return this.value.arr[i.toIndex()]; };
-Rp.prototype.toIndex = function() { return this.index.toIndex(); };
-Rp.prototype.setTag = function(tag) { this.index.setTag(tag) };
-
-function Suffix(prefix,suffix) {
- this.prefix = new String(prefix);
- if (prefix.tag) { this.prefix.tag = prefix.tag; }
- this.suffix = suffix;
-};
-Suffix.prototype.tokens = function() {
- var xs = this.suffix.tokens();
- for (var i in xs) {
- xs[i] = new String(this.prefix + xs[i]);
- xs[i].setTag(this.prefix.tag);
- }
- return xs;
-};
-Suffix.prototype.sel = function(i) { return new Suffix(this.prefix, this.suffix.sel(i)); };
-Suffix.prototype.setTag = function(tag) { if (!this.prefix.tag) { this.prefix.setTag(tag); } };
-
-function Meta() { }
-Meta.prototype.tokens = function() {
- var newString = new String("?");
- newString.setTag(this.tag);
- return new Array(newString);
-};
-Meta.prototype.toIndex = function() { return 0; };
-Meta.prototype.sel = function(i) { return this; };
-Meta.prototype.setTag = function(tag) { if (!this.tag) { this.tag = tag; } };
-
-function Str(value) { this.value = value; }
-Str.prototype.tokens = function() {
- var newString = new String(this.value);
- newString.setTag(this.tag);
- return new Array(newString);
-};
-Str.prototype.setTag = function(tag) { if (!this.tag) { this.tag = tag; } };
-
-function Int(value) { this.value = value; }
-Int.prototype.tokens = function() {
- var newString = new String(this.value.toString());
- newString.setTag(this.tag);
- return new Array(newString);
-};
-Int.prototype.toIndex = function() { return this.value; };
-Int.prototype.setTag = function(tag) { if (!this.tag) { this.tag = tag; } };
-
-/* Type annotation */
-
-function GFAbstract(startcat, types) {
- this.startcat = startcat;
- this.types = types;
-}
-GFAbstract.prototype.addType = function(fun, args, cat) {
- this.types[fun] = new Type(args, cat);
-} ;
-GFAbstract.prototype.getArgs = function(fun) {
- return this.types[fun].args;
-}
-GFAbstract.prototype.getCat = function(fun) {
- return this.types[fun].cat;
-};
-GFAbstract.prototype.annotate = function(tree, type) {
- if (tree.name == '?') {
- tree.type = type;
- } else {
- var typ = this.types[tree.name];
- for (var i in tree.args) {
- this.annotate(tree.args[i], typ.args[i]);
- }
- }
- return tree;
-} ;
-GFAbstract.prototype.handleLiterals = function(tree, type) {
- if (tree.name != '?') {
- if (type == "String" || type == "Int" || type == "Float") {
- tree.name = type + "_Literal_" + tree.name;
- } else {
- var typ = this.types[tree.name];
- for (var i in tree.args) {
- this.handleLiterals(tree.args[i], typ.args[i]);
- }
- }
- }
- return tree;
-} ;
-/* Hack to get around the fact that our SISR doesn't build real Fun objects. */
-GFAbstract.prototype.copyTree = function(x) {
- var t = new Fun(x.name);
- if (!isUndefined(x.type)) {
- t.type = x.type;
- }
- var cs = x.args;
- if (!isUndefined(cs)) {
- for (var i in cs) {
- t.setArg(i, this.copyTree(cs[i]));
- }
- }
- return t;
-} ;
-GFAbstract.prototype.parseTree = function(str, type) {
- return this.annotate(this.parseTree_(str.match(/[\w\'\.\"]+|\(|\)|\?|\:/g), 0), type);
-} ;
-GFAbstract.prototype.parseTree_ = function(tokens, prec) {
- if (tokens.length == 0 || tokens[0] == ")") { return null; }
- var t = tokens.shift();
- if (t == "(") {
- var tree = this.parseTree_(tokens, 0);
- tokens.shift();
- return tree;
- } else if (t == '?') {
- var tree = this.parseTree_(tokens, 0);
- return new Fun('?');
- } else {
- var tree = new Fun(t);
- if (prec == 0) {
- var c, i;
- for (i = 0; (c = this.parseTree_(tokens, 1)) !== null; i++) {
- tree.setArg(i,c);
- }
- }
- return tree;
- }
-} ;
-
-function Type(args, cat) {
- this.args = args;
- this.cat = cat;
-}
-
-/* Linearization */
-
-function GFConcrete(flags, rules, parser) {
- this.flags = flags;
- this.rules = rules;
- if (parser) {
- this.parser = parser;
- } else {
- this.parser = undefined;
- }
-}
-GFConcrete.prototype.rule = function (name, cs) {
- var r = this.rules[name];
- if (r) {
- return this.rules[name](cs);
- } else {
- window.alert("Missing rule " + name);
- }
-};
-GFConcrete.prototype.addRule = function (name, f) { this.rules[name] = f; };
-GFConcrete.prototype.lindef = function (cat, v) { return this.rules[cat]([new Str(v)]); } ;
-GFConcrete.prototype.linearize = function (tree) {
- return this.unlex(this.linearizeToTerm(tree).tokens());
-};
-GFConcrete.prototype.linearizeToTerm = function (tree) {
- if (tree.isMeta()) {
- if (isUndefined(tree.type)) {
- return new Meta();
- } else {
- return this.lindef(tree.type, tree.name);
- }
- } else {
- var cs = new Array();
- for (var i in tree.args) {
- cs.push(this.linearizeToTerm(tree.args[i]));
- }
- if (tree.isLiteral()) {
- return new Arr(new Str(tree.name));
- } else {
- return this.rule(tree.name, cs);
- }
- }
-};
-GFConcrete.prototype.unlex = function (ts) {
- if (ts.length == 0) {
- return "";
- }
-
- var noSpaceAfter = /^[\(\-\[]/;
- var noSpaceBefore = /^[\.\,\?\!\)\:\;\-\]]/;
-
- var s = "";
- for (var i = 0; i < ts.length; i++) {
- var t = ts[i];
- var after = i < ts.length-1 ? ts[i+1] : null;
- s += t;
- if (after != null && !t.match(noSpaceAfter)
- && !after.match(noSpaceBefore)) {
- s += " ";
- }
- }
- return s;
-};
-GFConcrete.prototype.tagAndLinearize = function (tree) {
- return this.tagAndLinearizeToTerm(tree, "0").tokens();
-};
-GFConcrete.prototype.tagAndLinearizeToTerm = function (tree, route) {
- if (tree.isMeta()) {
- if (isUndefined(tree.type)) {
- var newMeta = new Meta();
- newMeta.setTag(route);
- return newMeta;
- } else {
- var newTerm = this.lindef(tree.type, tree.name);
- newTerm.setTag(route);
- return newTerm;
- }
- } else {
- var cs = new Array();
- for (var i in tree.args) {
- cs.push(this.tagAndLinearizeToTerm(tree.args[i], route + "-" + i));
- }
- var newTerm = this.rule(tree.name, cs);
- newTerm.setTag(route);
- return newTerm;
- }
-};
-
-/* Utilities */
-
-/* from Remedial JavaScript by Douglas Crockford, http://javascript.crockford.com/remedial.html */
-function isString(a) { return typeof a == 'string'; }
-function isArray(a) { return a && typeof a == 'object' && a.constructor == Array; }
-function isUndefined(a) { return typeof a == 'undefined'; }
-function isBoolean(a) { return typeof a == 'boolean'; }
-function isNumber(a) { return typeof a == 'number' && isFinite(a); }
-function isFunction(a) { return typeof a == 'function'; }
-
-function dumpObject (obj) {
- if (isUndefined(obj)) {
- return "undefined";
- } else if (isString(obj)) {
- return '"' + obj.toString() + '"'; // FIXME: escape
- } else if (isBoolean(obj) || isNumber(obj)) {
- return obj.toString();
- } else if (isArray(obj)) {
- var x = "[";
- for (var i in obj) {
- x += dumpObject(obj[i]);
- if (i < obj.length-1) {
- x += ",";
- }
- }
- return x + "]";
- } else {
- var x = "{";
- for (var y in obj) {
- x += y + "=" + dumpObject(obj[y]) + ";" ;
- }
- return x + "}";
- }
-}
-
-
-function copy_arguments(args, start) {
- var arr = new Array();
- for (var i = 0; i < args.length - start; i++) {
- arr[i] = args[i + start];
- }
- return arr;
-}
-
-/* ------------------------------------------------------------------------- */
-/* -------------------------------- PARSING -------------------------------- */
-/* ------------------------------------------------------------------------- */
-
-
-function Parser(startcat, rules, cats) {
- this.startcat = startcat;
- this.rules = rules;
- this.cats = cats;
-}
-Parser.prototype.showRules = function () {
- var ruleStr = new Array();
- ruleStr.push("");
- for (i = 0, j = this.rules.length; i < j; i++) {
- ruleStr.push(this.rules[i].show());
- }
- return ruleStr.join("");
-};
-Parser.prototype.parseString = function (string, cat) {
- var tokens = string.split(" ");
- // remove empty tokens
- for (var i = tokens.length - 1; i >= 0; i--) {
- if (tokens[i] == "") { tokens.splice(i, 1); }
- }
- chart = new Chart(true);
- predict(this.rules, tokens);
- while (chart.updated) {
- chart.updated = false;
- completeAndConvert();
- scan();
- combine();
- }
- var catToParse = this.startcat;
- if (cat) { catToParse = cat; }
- var goalRange = new Range(0, tokens.length);
- if (tokens.length == 1 && tokens[0] == "") { goalRange = new EmptyRange(); }
- var activeEdges = filterActiveEdges();
- var trees = new Array();
- for (var i = 0, j = this.cats[catToParse].length; i < j; i++) {
- if (foundTarget(this.cats[catToParse][i], new Array(new Array(goalRange)))) {
- trees = trees.concat(extractTrees(this.cats[catToParse][i], new Array(new Array(goalRange)), activeEdges, ""));
- }
- }
- for (var i = trees.length - 1; i >= 0; i--) {
- if (trees[i] == undefined) { trees.splice(i, 1); }
- }
- return trees;
-};
-
-// Rule Object Definition
-
-function Rule(cat, profile, args, linRec) {
- this.cat = cat;
- this.profile = profile;
- this.args = args;
- this.linRec = linRec;
-}
-Rule.prototype.show = function () {
- var recStr = new Array();
- recStr.push(this.cat, " -> ", this.profile.show(), " [", this.args, "] = ", showLinRec(this.linRec, ""));
- return recStr.join("");
-};
-
-// Profile definitions
-
-// Function application
-// The function (name) is applied to its arguments (args)
-function FunApp(name, args) {
- this.id = "FunApp";
- this.name = name;
- this.args = args.slice(0);
-}
-FunApp.prototype.show = function () {
- var funAppStr = new Array();
- funAppStr.push("(", this.name);
- for (var i = 0, j = this.args.length; i < j; i++) {
- funAppStr.push(this.args[i].show());
- }
- funAppStr.push(")");
- return funAppStr.join(" ");
-};
-
-// Literal
-function Lit(name) {
- this.id = "Lit";
- this.name = name;
-}
-Lit.prototype.show = function () { return this.name; };
-
-// Metavariable
-function MetaVar() { this.id = "MetaVar"; }
-MetaVar.prototype.show = function () { return "?"; };
-
-// Argument
-function Arg(i) {
- this.id = "Arg";
- this.name = "_";
- this.i = i;
-}
-Arg.prototype.show = function () {
- var argStr = new Array();
- argStr.push(this.id, "(", this.i, ")");
- return argStr.join("");
-};
-
-// Unification
-// The arguments (args) must be unified
-function Unify(args){
- this.id = "Unify";
- this.args = args.slice(0);
-}
-Unify.prototype.show = function () {
- var unifyStr = new Array();
- unifyStr.push("(", this.id);
- for (var i = 0, j = this.args.length; i < j; i++) {
- unifyStr.push(this.args[i].show());
- }
- unifyStr.push(")");
- return unifyStr.join(" ");
-};
-
-// Definition of symbols present in linearization records
-
-// Object to represent argument projections in grammar rules
-function ArgProj(i, label) {
- this.id = "argProj";
- this.i = i;
- this.label = label;
-}
-ArgProj.prototype.getId = function () { return this.id; };
-ArgProj.prototype.getArgNum = function () { return this.i };
-ArgProj.prototype.show = function () {
- var argStr = new Array();
- argStr.push(this.i, this.label);
- return argStr.join(".");
-};
-ArgProj.prototype.isEqual = function (obj) {
- return (this.id == obj.id && this.i == obj.i && this.label == obj.label);
-}
-
-// Object to represent terminals in grammar rules
-function Terminal (str) {
- this.id = "terminal";
- this.str = str;
-}
-Terminal.prototype.getId = function () { return this.id; };
-Terminal.prototype.show = function () {
- var terminalStr = new Array();
- terminalStr.push('"', this.str, '"');
- return terminalStr.join("");
-};
-Terminal.prototype.isEqual = function (obj) {
- return (this.id == obj.id && this.str == obj.str);
-}
-
-// Object to represent ranges in grammar rules
-function Range (i, j) {
- this.id = "range";
- this.i = i;
- this.j = j;
-}
-Range.prototype.getId = function () { return this.id; };
-Range.prototype.show = function () {
- var terminalStr = new Array();
- terminalStr.push("(", this.i, ",", this.j, ")");
- return terminalStr.join("");
-};
-Range.prototype.isEqual = function (obj) {
- return (this.id == obj.id && this.i == obj.i && this.j == obj.j);
-}
-
-// Object to represent the empty range in grammar rules
-function EmptyRange () {
- this.id = "emptyRange";
-}
-EmptyRange.prototype.getId = function () { return this.id; };
-EmptyRange.prototype.show = function () { return "emptyRange" };
-EmptyRange.prototype.isEqual = function (obj) {
- return (this.id == obj.id);
-}
-
-// Chart Object Definition
-function Chart(updated) {
- this.passive = new Array();
- this.active = new Array();
- this.updated = updated;
-}
-Chart.prototype.show = function () {
- var chartStr = new Array();
- chartStr.push("(", this.showPassive(), ", ", this.showActive(), ")");
- return chartStr.join("");
-};
-Chart.prototype.addPassiveEdge = function (cat, linRec) {
- if (!this.passive[cat] || !this.passive[cat].length) {
- this.passive[cat] = new Array();
- }
- this.passive[cat].push(linRec);
-};
-Chart.prototype.isPassiveElem = function (cat, linRec) {
- if (this.passive[cat]) {
- for (var i = 0, j = this.passive[cat].length; i < j; i++) {
- if (linRecsAreEqual(this.passive[cat][i], linRec)) {
- return true;
- }
- }
- }
- return false;
-};
-Chart.prototype.showPassive = function () {
- var edgesStr = new Array();
- edgesStr.push("[ ");
- for (var cat in this.passive) {
- for (var i = 0, j = this.passive[cat].length; i < j; i++) {
- edgesStr.push("( ", cat, ", ", showLinRec(this.passive[cat][i], ""), ")");
- if (i != j - 1) { edgesStr.push(", "); };
- }
- edgesStr.push(", ");
- }
- edgesStr.push(" ]");
- return edgesStr.join("");
- return edgesStr.join("") + "<br />";
-};
-Chart.prototype.addActiveEdge = function (cat, edge) {
- if (!this.active[cat] || !this.active[cat].length) {
- this.active[cat] = new Array();
- }
- this.active[cat].push(edge);
-};
-Chart.prototype.isActiveElem = function (cat, edge) {
- if (this.active[cat]) {
- for (var i = 0, j = this.active[cat].length; i < j; i++) {
- var currentEdge = this.active[cat][i];
- if (currentEdge.name == edge.name && (areArgsEqual(currentEdge.args, edge.args)) &&
- currentEdge.currLabel == edge.currLabel && currentEdge.currLin.isEqual(edge.currLin) &&
- linRecsAreEqual(currentEdge.linFound, edge.linFound) && linRowsAreEqual(currentEdge.remLin, edge.remLin) &&
- linRecsAreEqual(currentEdge.remLinRows, edge.remLinRows) &&
- arraysOfLinRecsAreEqual(currentEdge.children, edge.children)) {
- return true;
- }
- }
- }
- return false;
-};
-Chart.prototype.showActive = function () {
- var edgesStr = new Array()
- edgesStr.push("[ ");
- for (var cat in this.active) {
- for (var i = 0, j = this.active[cat].length; i < j; i++) {
- edgesStr.push("( ", this.active[cat][i].show(), " )");
- if (i != j - 1) { edgesStr.push(", "); };
- }
- edgesStr.push(", ");
- }
- edgesStr.push(" ]");
- return edgesStr.join("");
-};
-
-// Object to represent the active edges in a chart
-function ActiveEdge(profile, cat, name, args, linFound, currLabel, currLin, remLin, remLinRows, children) {
- this.profile = profile;
- this.cat = cat;
- this.name = name;
- this.args = args;
- this.linFound = linFound;
- this.currLabel = currLabel;
- this.currLin = currLin;
- this.remLin = remLin;
- this.remLinRows = remLinRows;
- this.children = children.slice(0);
-}
-ActiveEdge.prototype.show = function () {
- var linRecStr = new Array();
- linRecStr.push(this.profile.show(), ", ", this.cat, ", ", this.name, ", [ ", this.args, " ], ", showLinRec(this.linFound, ""),
- ", ", this.currLabel, ", ", this.currLin.show(), ", ", showLinRow(this.remLin, " ++ "),
- ", ", showLinRec(this.remLinRows, ""), ", [ ");
- for (var i = 0, j = this.children.length; i < j; i++) {
- linRecStr.push(showLinRec(this.children[i], ""));
- if (i != j - 1) { linRecStr.push(", "); };
- }
- linRecStr.push(" ]");
- return linRecStr.join("");
-};
-
-function areArgsEqual(args1, args2) {
- if (args1.length == args1.length && args1.join() == args2.join()) {
- return true
- }
- return false;
-}
-
-// Functions to manipulate linearization records
-
-// Returns a string representation of a linearization row
-function showLinRow(linRow, separator) {
- var linRowStr = new Array();
- linRowStr.push(" [ ");
- for (var i = 0, j = linRow.length; i < j; i ++) {
- linRowStr.push(linRow[i].show());
- if (i != j - 1) { linRowStr.push(separator) };
- }
- linRowStr.push(" ] ");
- return linRowStr.join("");
-}
-
-// Returns a string representation of a linearization record
-function showLinRec(linRec, separator) {
- var linRecStr = new Array();
- linRecStr.push(" [ ");
- for (var i = 0, j = linRec.length; i < j; i ++) {
- linRecStr.push(showLinRow(linRec[i], " ++ "));
- if (i != j - 1) { linRecStr.push(separator); };
- }
- linRecStr.push(" ] ");
- return linRecStr.join("");
-}
-
-// Checks if two linearization rows are equal
-function linRowsAreEqual(linRow1, linRow2) {
- if (linRow1.length == linRow2.length) {
- for (var i = 0, j = linRow1.length; i < j; i++) {
- if (linRow1[i].id && linRow2[i].id && !linRow1[i].isEqual(linRow2[i])) {
- return false;
- }
- }
- return true;
- }
- return false;
-}
-
-// Checks if two linearization records are equal
-function linRecsAreEqual(linRec1, linRec2) {
- if (linRec1.length == linRec2.length) {
- for (var i = 0, j = linRec1.length; i < j; i++) {
- if (!linRowsAreEqual(linRec1[i], linRec2[i])) { return false; }
- }
- return true;
- }
- return false;
-}
-
-// Checks if two arrays of linearization records are equal
-function arraysOfLinRecsAreEqual(array1, array2) {
- if (array1.length == array2.length) {
- for (var i = 0, j = array1.length; i < j; i++) {
- if (!linRecsAreEqual(array1[i], array2[i])) { return false; }
- }
- return true;
- }
- return false;
-}
-
-// Functions to manipulate ranges (restriction and concatenation)
-
-// Concatenates two ranges
-function rangeConcatLin (lin1, lin2) {
- if (lin1.id == "range" && lin2.id == "range") {
- if (lin1.j == lin2.i) { return (new Range(lin1.i, lin2.j)) }
- } else if (lin1.id == "range" && lin2.id == "emptyRange") { return lin1; }
- else if (lin1.id == "emptyRange" && lin2.id == "range") { return lin2; }
- else if (lin1.id == "emptyRange" && lin2.id == "emptyRange") { return lin1; }
- return undefined;
-}
-
-// Performs range concatenation on a linearization row
-function rangeConcatLins (lins) {
- var newLins = new Array();
- newLins.push(lins.shift());
- while (lins.length > 0) {
- if (!newLins[newLins.length - 1]) { return new Array(); }
- if (newLins[newLins.length - 1].id == "range" && lins[0].id == "range") {
- var rangeConcat = rangeConcatLin(newLins.pop(), lins[0]);
- if (typeof rangeConcat == 'undefined') { return new Array(); }
- newLins.push(rangeConcat);
- lins.shift();
- } else {
- newLins.push(lins.shift());
- }
- }
- return newLins;
-}
-
-// Performs range restriction on an element of a linearization row
-// while keeping track of the tokens that have been used
-function rangeRestLinTerm(tokens, lin, rangesNotConsumed) {
- if (lin.id == "argProj") { return new Array(lin); }
- else if (lin.id == "terminal") {
- var ranges = new Array();
- for (var i = 0, j = tokens.length; i < j; i++) {
- if (tokens[i] == lin.str) {
- ranges.push(new Range(i, i + 1));
- rangesNotConsumed[i] = undefined;
- }
- }
- if (ranges.length == 0) {
- return undefined;
- } else {
- return ranges;
- }
- }
- else { return new Array(); }
-}
-
-// Performs range restriction on a linearization record
-// while keeping track of the tokens that have been used
-function rangeRestRecTerm(linRec, tokens, rangesNotConsumed) {
- var ranges = new Array();
- for (var i = 0, j = linRec.length; i < j; i++) {
- var rangeRestLins = new Array();
- for (var k = 0, l = linRec[i].length; k < l; k++) {
- rangeRestLins.push(rangeRestLinTerm(tokens, linRec[i][k], rangesNotConsumed));
- }
- var combinedLins = combineLins(rangeRestLins);
- if (typeof combinedLins != 'undefined') {
- var filteredLins = new Array();
- if (combinedLins.length == 0) {
- filteredLins.push(new Array());
- } else {
- for (var m = 0, n = combinedLins.length; m < n; m++) {
- var temp = rangeConcatLins(combinedLins[m]);
- if (temp.length != 0) {
- filteredLins.push(temp);
- }
- }
- }
- ranges.push(filteredLins);
- } else { ranges.push(undefined); }
- }
- for (var k = 0, l = ranges.length; k < l; k++) {
- if (ranges[k] == undefined) { return undefined; }
- }
- return combineLins(ranges);
-}
-
-// Returns the combinations of the elements of an array of arrays
-function combineLins(linss) {
- if (linss.length > 0) {
- var combinedLins = new Array();
- var lins = linss.shift();
- if (lins) {
- if (lins.length != 0) {
- var tail = combineLins(linss);
- if (typeof tail == 'undefined') { return undefined; }
- for (var i = 0, j = lins.length; i < j; i++) {
- var head = new Array();
- head.push(lins[i]);
- if (tail.length == 0) { combinedLins.push(head); }
- else {
- for (var k = 0, l = tail.length; k < l; k++) {
- combinedLins.push(head.concat(tail[k]));
- }
- }
- }
- } else { return new Array(); }
- } else { return undefined; }
- return combinedLins;
- } else { return new Array(); }
-}
-
-// Inference Rules
-
-function predict(rules, tokens) {
- var rangesNotConsumed = genRanges(tokens.length);
- for (var i = 0, j = rules.length; i < j; i++) {
- var currentRule = rules[i];
- var linRec = rangeRestRecTerm(currentRule.linRec, tokens, rangesNotConsumed);
- if (linRec) {
- for (var k = 0, l = linRec.length; k < l; k++) {
- var currentRow = linRec[k].shift();
- var remlinRows = linRec[k];
- var children = new Array();
- for (var m = 0, n = currentRule.args.length; m < n; m++) {
- children.push(new Array());
- }
- var newActive = new ActiveEdge(currentRule.profile, currentRule.cat, currentRule.profile.name, currentRule.args, new Array(), 0, new EmptyRange(), currentRow, remlinRows, children);
- if (!chart.isActiveElem(currentRule.cat, newActive)) {
- chart.addActiveEdge(currentRule.cat, newActive);
- chart.updated = true;
- }
- }
- }
- }
- for (var i = 0, j = rangesNotConsumed.length; i < j; i++) {
- if (rangesNotConsumed[i] != undefined) {
- var cat = undefined;
- if (isNaN(tokens[i])) {
- cat = "-1";
- } else if (tokens[i].lastIndexOf(".") == -1) {
- cat = "-2";
- } else {
- cat = "-3";
- }
- var lit = undefined;
- if (cat == "-1") {
- lit = "\"" + tokens[i] + "\"";
- } else {
- lit = tokens[i];
- }
- var newActive = new ActiveEdge(new Lit(lit), cat, tokens[i], new Array(), new Array(), 0, new Range(i, i + 1), new Array(), new Array(), new Array());
- if (!chart.isActiveElem(cat, newActive)) {
- chart.addActiveEdge(cat, newActive);
- chart.updated = true;
- }
- }
- }
-}
-
-function genRanges(inputLength) {
- var ranges = new Array();
- for (var i = 0; i < inputLength; i++) {
- ranges.push(i);
- }
- return ranges;
-}
-
-function completeAndConvert() {
- for (var cat in chart.active) {
- var currentEdge = chart.active[cat];
- for (var i = 0, j = currentEdge.length; i < j; i++) {
- if (currentEdge[i].remLin.length == 0) {
- if (currentEdge[i].remLinRows.length == 0) {
- var linFound = currentEdge[i].linFound.slice(0);
- linFound.push(new Array(currentEdge[i].currLin));
- if (!chart.isPassiveElem(cat, linFound)) {
- chart.addPassiveEdge(cat, linFound);
- chart.updated = true;
- }
- } else {
- var linFound = currentEdge[i].linFound.slice(0);
- linFound.push(new Array(currentEdge[i].currLin));
- var remLinRows = currentEdge[i].remLinRows.slice(0);
- var currentRow = remLinRows.shift();
- var newActive = new ActiveEdge(currentEdge[i].profile, cat, currentEdge[i].name, currentEdge[i].args, linFound, linFound.length, new EmptyRange(), currentRow, remLinRows, currentEdge[i].children);
- if (!chart.isActiveElem(cat, newActive)) {
- chart.active[cat].push(newActive);
- chart.updated = true;
- }
- }
- }
- }
- }
-}
-
-function scan() {
- for (var cat in chart.active) {
- var currentEdge = chart.active[cat];
- for (var i = 0, j = currentEdge.length; i < j; i++) {
- if (currentEdge[i].remLin.length > 0 && currentEdge[i].remLin[0].id == "range") {
- var newRange = rangeConcatLin(currentEdge[i].currLin, currentEdge[i].remLin[0]);
- if (typeof newRange != 'undefined') {
- var remLin = currentEdge[i].remLin.slice(0);
- remLin.shift();
- var newActive = new ActiveEdge(currentEdge[i].profile, cat, currentEdge[i].name, currentEdge[i].args, currentEdge[i].linFound, currentEdge[i].currLabel, newRange, remLin, currentEdge[i].remLinRows, currentEdge[i].children);
- if (!chart.isActiveElem(cat, newActive)) {
- chart.active[cat].push(newActive);
- chart.updated = true;
- }
- }
- }
- }
- }
-}
-
-function combine() {
- for (var cat in chart.active) {
- for (var i = 0; i < chart.active[cat].length; i++) {
- var currentEdge = chart.active[cat][i];
- if (currentEdge.remLin.length && currentEdge.remLin[0].id == "argProj") {
- var argNumber = currentEdge.remLin[0].i;
- var catToCombine = currentEdge.args[argNumber];
- if (chart.passive[catToCombine]) {
- for (var k = 0, l = chart.passive[catToCombine].length; k < l; k++) {
- var currentPassive = chart.passive[catToCombine][k];
- var remLin = currentEdge.remLin.slice(0);
- var linRow = currentPassive[remLin[0].label];
- if (typeof linRow != 'undefined') {
- var newLinRow = linRow.slice(0);
- if (currentEdge.children[argNumber].length == 0) {
- var newRange = rangeConcatLin(currentEdge.currLin, newLinRow.shift());
- if (typeof newRange != 'undefined') {
- remLin.shift();
- var children = currentEdge.children.slice(0);
- children[argNumber] = currentPassive.slice(0);
- var newActive = new ActiveEdge(currentEdge.profile, currentEdge.cat, currentEdge.name, currentEdge.args, currentEdge.linFound, currentEdge.currLabel, newRange, remLin, currentEdge.remLinRows, children);
- if (!chart.isActiveElem(cat, newActive)) {
- chart.active[cat].push(newActive);
- chart.updated = true;
- }
- }
- } else {
- var child = currentEdge.children[argNumber];
- if (linRecsAreEqual(currentPassive, child)) {
- var newRange = rangeConcatLin(currentEdge.currLin, newLinRow.shift());
- if (typeof newRange != 'undefined') {
- remLin.shift();
- var children = currentEdge.children.slice(0);
- children[argNumber] = currentPassive.slice(0);
- var newActive = new ActiveEdge(currentEdge.profile, currentEdge.cat, currentEdge.name, currentEdge.args, currentEdge.linFound, currentEdge.currLabel, newRange, remLin, currentEdge.remLinRows, children);
- if (!chart.isActiveElem(cat, newActive)) {
- chart.active[cat].push(newActive);
- chart.updated = true;
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
-}
-
-// Checks if the parsing goal is in the chart
-function foundTarget(cat, linRec) {
- if (chart.passive[cat]) {
- for (var i = 0, j = chart.passive[cat].length; i < j; i++) {
- if (linRecsAreEqual(linRec, chart.passive[cat][i])) {
- return true;
- }
- }
- }
- return false;
-}
-
-// Filters the active edges that are relevant for tree extraction
-function filterActiveEdges() {
- var activeEdges = new Array();
- for (var cat in chart.active) {
- activeEdges[cat] = new Array();
- for (var i = 0, j = chart.active[cat].length; i < j; i++) {
- var currentEdge = chart.active[cat][i];
- if (currentEdge.remLin.length == 0 && currentEdge.remLinRows.length == 0) {
- var linFound = currentEdge.linFound.slice(0);
- linFound.push(new Array(currentEdge.currLin));
- var newActive = new ActiveEdge(currentEdge.profile, currentEdge.cat, currentEdge.name, currentEdge.args, linFound, "", "", "", "", currentEdge.children);
- activeEdges[cat].push(newActive);
- }
- }
- }
- return activeEdges;
-}
-
-// Extracts the parse trees from the chart
-function extractTrees(cat, linRec, activeEdges, currentTree) {
- var trees = new Array();
- for (var i = 0, j = activeEdges[cat].length; i < j; i++) {
- var currentEdge = activeEdges[cat][i];
- var currentNode = "(" + cat + "-" + i + ")";
- if (currentTree.indexOf(currentNode) == -1 && cat == currentEdge.cat && linRecsAreEqual(linRec, currentEdge.linFound)) {
- var subTrees = new Array();
- for (var k = 0, l = currentEdge.children.length; k < l; k++) {
- subTrees.push(extractTrees(currentEdge.args[k], currentEdge.children[k].slice(0), activeEdges, currentTree + currentNode));
- }
- var combinedSubTrees = combineLins(subTrees);
- if (combinedSubTrees) {
- if (currentEdge.children.length == 0) { combinedSubTrees.push(new Array()); }
- for (var m = 0, n = combinedSubTrees.length; m < n; m++) {
- var tree = buildTree(currentEdge.profile, combinedSubTrees[m]);
- if (tree) {
- trees.push(tree);
- }
- }
- }
- }
- }
- if (trees.length == 0) {
- return undefined;
- } else {
- return trees;
- }
-}
-
-// Builds a tree according to the profile
-function buildTree(profile, args) {
- switch(profile.id)
- {
- case "FunApp":
- var tree = new Fun(profile.name);
- for (var i = 0, j = profile.args.length; i < j; i++) {
- var subTree = buildTree(profile.args[i], args);
- if (subTree) {
- tree.setArg(i, subTree);
- } else {
- return undefined;
- }
- }
- return tree;
- case "Lit":
- return new Fun(profile.name);
- case "MetaVar":
- return new Fun("?");
- case "Arg":
- return args[profile.i];
- case "Unify":
- var subTrees = new Array();
- for (var i = 0, j = profile.args.length; i < j; i++) {
- subTrees.push(buildTree(profile.args[i], args))
- }
- return unifySubTrees(subTrees);
- }
-}
-
-// Tree unification functions
-function unifySubTrees(subTrees) {
- var t = subTrees[0];
- for (var i = 1, j = subTrees.length; i < j; i++) {
- t = unify(t, subTrees[i]);
- if (!t) { return undefined; }
- }
- return t;
-}
-
-function unify(a, b) {
- if (a.isMeta()) { return b };
- if (b.isMeta()) { return a };
- if (a.name == b.name && a.args.length == b.args.length) {
- for (var i = 0, j = a.args.length; i < j; i++) {
- if (!unify(a.args[i], b.args[i])) { return undefined; }
- }
- return a
- };
- return undefined;
-}