diff options
| author | aarne <aarne@chalmers.se> | 2009-12-09 09:47:16 +0000 |
|---|---|---|
| committer | aarne <aarne@chalmers.se> | 2009-12-09 09:47:16 +0000 |
| commit | c8ceed08efcc0bdc1fcbd89bce643d9f52f0991b (patch) | |
| tree | 5f0b314341c129eba1bc67b8b887fb8a4486fad8 /old-lib/javascript/gflib.js | |
| parent | 101df06f6c8380328d4266adadac3ab6d1bac0b3 (diff) | |
moving a few things to deprecated
Diffstat (limited to 'old-lib/javascript/gflib.js')
| -rw-r--r-- | old-lib/javascript/gflib.js | 1128 |
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; -} |
