//Variable and Constant definitions
var expColImg = new Array(2);
expColImg[0] = new Image(12,12);
expColImg[0].src = "minus.png";
expColImg[1] = new Image(12,12);
expColImg[1].src = "plus.png";
var selectedNode = "";
var collapseBuffer = new Array();
var abstractTree = new Fun ("?");
var navigationControlString = new Array();
var undoArray = new Array();
var redoArray = new Array();
var clipBoard;
var refPageCounter = 0;
var stringAbstractTree = undefined;
var myTree = treeFromAbstract(myAbstract.annotate(abstractTree, myAbstract.startcat), "0");
var keys = new Array();
keys ["Z"] = function() { clickUndo('actUndo'); }
keys ["Y"] = function() { clickRedo('actRedo'); }
keys ["R"] = function() { clickRefine('actRefine'); };
keys ["V"] = function() { clickPaste('actPaste'); };
keys ["X"] = function() { clickCut('actCut'); };
keys ["C"] = function() { clickCopy('actCopy'); };
keys ["D"] = function() { clickDelete('actDelete'); };
keys ["E"] = function() { clickReplace('actReplace'); };
keys ["W"] = function() { clickWrap('actWrap'); };
keys ["N"] = function() { clickRandomNode('actRandomNode'); };
keys ["T"] = function() { clickRandomTree('actRandomTree'); };
keys ["%"] = function() { leftArrowKey(); };
keys ["&"] = function() { upDownArrowKey(-1); };
keys ["'"] = function() { rightArrowKey(); };
keys ["("] = function() { upDownArrowKey( 1); };
keys ["27"] = function() { clickEsc(); };
function state(selectedNode, tree, collapseBuffer) {
this.selectedNode = selectedNode;
this.tree = myAbstract.copyTree(tree);
this.collapseBuffer = collapseBuffer;
return this;
}
function treeNode(name, caption) {
this.name = name;
this.caption = caption;
this.cat = "";
this.children = new Array();
this.collapsed = false;
return this;
}
treeNode.prototype.addChild = function (i, c) {
this.children[i] = c;
}
treeNode.prototype.hasChildren = function() {
return this.children.length;
}
// Generates a tree from the abstract tree contained in the element "stringTree"
function parseStringTree(elementToParse) {
stringAbstractTree = elementToParse;
abstractTree = myAbstract.parseTree(document.getElementById(elementToParse).value, myAbstract.startcat);
myTree = treeFromAbstract(myAbstract.annotate(abstractTree, myAbstract.startcat), "0");
nodeClick("0");
}
// If a key is pressed and a function assigned to that key, calls the function
function hotKeys(event) {
event = (event) ? event : ((window.event) ? event : null);
if (event) {
var charCode = (event.charCode) ? event.charCode : ((event.which) ? event.which : event.keyCode);
if (keys[String.fromCharCode(charCode).toUpperCase()] &&
!event.ctrlKey && !event.altKey && !event.shiftKey && !event.metaKey) {
keys[String.fromCharCode(charCode).toUpperCase()]();
}
else if (keys["" + charCode] &&
!event.ctrlKey && !event.altKey && !event.shiftKey && !event.metaKey) {
keys["" + charCode]();
}
else if (charCode >= "96" && charCode <= "105" &&
!event.ctrlKey && !event.altKey && !event.shiftKey && !event.metaKey) {
keys["" + (charCode - 96)]();
}
}
}
// Clears "numeric" hotkeys
function clearHotKeys() {
for (var key in keys) {
if ((parseInt(key) + 1) && (key != "27")) { keys[key] = function() { }; }
}
}
// Action to be performed when the up/down arrow key is pressed
function upDownArrowKey(pos) {
var nodePos = getNavPos(selectedNode);
if ((nodePos > 0 && pos < 0) || (nodePos < navigationControlString.length - 1 && pos > 0)) {
nodeClick(navigationControlString[nodePos + pos]);
}
}
// Gets the position of a given node in the navigationControlString
function getNavPos(nodeName) {
for (var i = 0, j = navigationControlString.length; i < j; i++) {
if (navigationControlString[i] == nodeName) { return i; };
}
return undefined;
}
// Given a name and a tree, gets the node in the tree with that name
function getNode(nodeName, node) {
if (nodeName == node.name) {
return node;
}
else {
for (var i = 0, j = node.children.length; i < j; i++) {
var found = getNode(nodeName, node.children[i]);
if (found) { return found; }
}
}
}
// Action to be performed when the left arrow key is pressed
function leftArrowKey() {
var node = getNode(selectedNode, myTree);
if (!node.collapsed && node.hasChildren()) {
signClick(node.name, node.caption);
}
else {
var parentNode = getParent(node.name, myTree);
if (parentNode) { nodeClick(parentNode.name); }
}
}
// Gets the parent of the selected node
function getParent(nodeName, node) {
if (node.name == nodeName) {
return undefined;
}
else {
for (var i = 0, j = node.children.length; i < j; i++) {
if (node.children[i].name == nodeName) { return node; }
}
for (var i = 0, j = node.children.length; i < j; i++) {
var found = getParent(nodeName, node.children[i]);
if (found) { return found; }
}
}
}
// Action to be performed when the right arrow key is pressed
function rightArrowKey() {
var node = getNode(selectedNode, myTree);
if (node.collapsed) {
signClick(node.name, node.caption);
}
else {
var firstDescendant = getfirstDescendant(node);
if (firstDescendant) {
nodeClick(firstDescendant.name);
}
}
}
// Gets the first descendant child of a node
function getfirstDescendant(node) {
if (node.hasChildren() && !node.collapsed) { return node.children[0]; }
return undefined;
}
// Produces and displays an HTML representation of the tree
function drawTree() {
var frame = document.getElementById("absFrame");
navigationControlString = new Array();
frame.innerHTML = "
" + getTree(myTree, 0) + "
";
document.getElementById("link" + selectedNode).scrollIntoView(false);
}
// Produces an HTML representation of the tree
function getTree(tree, level) {
navigationControlString[navigationControlString.length] = tree.name;
var htmlTree = "";
htmlTree += "";
if (tree.hasChildren()) {
htmlTree += "";
}
else {
htmlTree += "";
}
htmlTree += "" + overl(tree.caption) +
" : " + tree.cat + "";
if (tree.hasChildren() && !tree.collapsed) {
for (var i = 0, j = tree.children.length; i < j; i++) {
htmlTree += getTree(tree.children[i], level + 1);
}
}
htmlTree += "
";
return htmlTree;
}
// Linearizes and displays the abstract tree
function drawLinearizedFrame() {
var frame = document.getElementById("conFrame");
frame.innerHTML = getLinearizedFrame();
}
// Linearizes the abstract tree and returns it in HTML form
function getLinearizedFrame() {
var linearizedFrame = "";
for (var i = 0; i < myConcrete.length; i++) {
// linearizedFrame += "" + myConcrete[i].concreteSyntaxName + "
";
linearizedFrame += "";
var tokens = myConcrete[i].concreteSyntax.tagAndLinearize(abstractTree);
for (var j = 0, k = tokens.length; j < k; j++) {
linearizedFrame += createLinearized(tokens[j]);
}
linearizedFrame += "
";
}
linearizedFrame += abstractTree.printOverl();
return linearizedFrame;
}
// Creates an HTML representation of a linearization of an abstract tree
function createLinearized(token) {
var node = getNode(token.tag, myTree);
var linearized = ""; }
else { linearized += " onclick='nodeClick(\"" + node.name + "\");'> " + token + " "; }
return linearized;
}
// Expands/Collapses node
function signClick(name, caption) {
myTree = expandCollapse(myTree, name);
nodeClick(name);
}
// Sets the "collapsed" property of a given node
function expandCollapse(node, name) {
if (node.name == name) {
if (wasCollapsed(node.name)) { removeFromCollapseBuffer(node.name); }
else { collapseBuffer[collapseBuffer.length] = node.name; }
node.collapsed ^= true;
}
else {
for (var i = 0, j = node.children.length; i < j; i++) {
expandCollapse(node.children[i], name);
}
}
return node;
}
// Checks if a node was collapsed on the previous cycle
function wasCollapsed(nodeName) {
for (var i = 0, j = collapseBuffer.length; i < j; i++) {
if (nodeName == collapseBuffer[i]) {
return true;
}
}
return false;
}
// Removes a node from the collapseBuffer array
function removeFromCollapseBuffer(nodeName) {
var newBuffer = new Array();
for (var i = 0, j = collapseBuffer.length; i < j; i++) {
if (nodeName != collapseBuffer[i]) {
newBuffer[newBuffer.length] = collapseBuffer[i];
}
}
collapseBuffer = newBuffer;
}
// Selects a node
function nodeClick(name) {
if ((document.getElementById("actRefine") && document.getElementById("actRefine").className == "selected") ||
(document.getElementById("actReplace") && document.getElementById("actReplace").className == "selected") ||
(document.getElementById("actWrap") && document.getElementById("actWrap").className == "selected")) {
return; }
selectedNode = name;
if (stringAbstractTree) {
document.getElementById(stringAbstractTree).value = abstractTree.show();
}
document.getElementById("actFrame").innerHTML = showActions();
document.getElementById("refFrame").innerHTML = "";
drawTree();
drawLinearizedFrame();
}
// Shows the available actions for a node
function showActions(caption) {
var node = getNode(selectedNode, myTree);
var abstractNode = getNodeFromAbstract(abstractTree, node.name, "0");
var actions = "";
if (undoArray.length) {
actions += createAction("Undo", "action", "Undo", "Z"); }
else { actions += createAction("Undo", "unavailable", "Undo", "Z"); };
if (redoArray.length) {
actions += createAction("Redo", "action", "Redo", "Y"); }
else { actions += createAction("Redo", "unavailable", "Redo", "Y"); }
if (node.caption == "?") {
actions += createAction("Cut", "unavailable", "Cut", "X");
actions += createAction("Copy", "unavailable", "Copy", "C");
var AbsNodeType = abstractNode.type;
if (clipBoard && (AbsNodeType == myAbstract.getCat(clipBoard.name))) {
actions += createAction("Paste", "action", "Paste", "V");
}
else { actions += createAction("Paste", "unavailable", "Paste", "V"); }
actions += createAction("Delete", "unavailable", "Delete", "D");
actions += createAction("Refine", "action", "Refine", "R");
actions += createAction("Replace", "unavailable", "Replace", "E");
actions += createAction("Wrap", "unavailable", "Wrap", "W")
}
else if (node.caption) {
actions += createAction("Cut", "action", "Cut", "X");
actions += createAction("Copy", "action", "Copy", "C");
actions += createAction("Paste", "unavailable", "Paste", "V");
actions += createAction("Delete", "action", "Delete", "D");
actions += createAction("Refine", "unavailable", "Refine", "R");
actions += createAction("Replace", "action", "Replace", "E");
actions += createAction("Wrap", "action", "Wrap", "W")
}
if (node && !abstractNode.isComplete()) {
actions += createAction("RandomNode", "action", "Fill out the node at random", "N");
}
else {
actions += createAction("RandomNode", "unavailable", "Fill out the node at random", "N");
}
if (!abstractTree.isComplete()) {
actions += createAction("RandomTree", "action", "Fill out the tree at random", "T");
}
else {
actions += createAction("RandomTree", "unavailable", "Fill out the tree at random", "T");
}
actions += "
";
return actions;
}
// Gets a node from the abstract tree
function getNodeFromAbstract(absNode, route, currRoute) {
if (route == currRoute) {
return absNode;
}
else {
for (var i = 0, j = absNode.args.length; i < j; i++) {
var found = getNodeFromAbstract(absNode.args[i], route, currRoute + "-" + i);
if (found) { return found }
}
}
}
// Creates an action
function createAction(actionName, className, caption, hotKey) {
return "| " + caption +
" | (" + hotKey + ") |
";
}
// When the "Refine" action is selected, gets the appropriate refinements for a node
function clickRefine(actName) {
if (document.getElementById(actName).className == "action") {
highlightSelectedAction(actName);
pushUndoClearRedo();
if (selectedNode) {
refPageCounter = 0;
var node = getNodeFromAbstract(abstractTree, selectedNode, "0");
if (node.type == "String") {
var newType = prompt('Enter a String','String');
if (!newType) { newType = "AutoString" }
myAbstract.addType(newType,[], "String");
for (var i = 0, j = myConcrete.length; i < j; i++) {
myConcrete[i].concreteSyntax.addRule(newType, function(cs){ return new Arr(new Str(newType));});
}
node.name = newType;
abstractTree = insertNode(abstractTree, selectedNode, "0", node);
document.getElementById("actFrame").innerHTML = showActions();
document.getElementById("refFrame").innerHTML = "";
clearHotKeys();
concludeAction();
}
else {
document.getElementById("refFrame").innerHTML = showRefinements(selectedNode);
}
}
}
}
// Sets the className of actName to "selected" and grays out the other selections
function highlightSelectedAction(actName) {
graySelections(actName);
document.getElementById(actName).className = "selected";
drawTree();
}
// Grays out all actions except one
function graySelections(except) {
var refs = document.getElementById("actFrame").getElementsByTagName("tr");
for (var i = 0, j = refs.length; i < j; i++) {
if (refs[i].id != except) { refs[i].className = "closed"; }
}
}
// Pushes the abstract tree into the undo array and clears the redo array
function pushUndoClearRedo() {
undoArray.push(new state(selectedNode, abstractTree, collapseBuffer));
redoArray.length = 0;
}
// Gets the refinements to display
function showRefinements(nodeName) {
var refs = getAvailableRefinements(nodeName);
var pages = 0;
if (refs.length > 9) { pages = Math.floor(refs.length / 9); }
var upperLimit;
if (pages != refPageCounter) { upperLimit = (9 * refPageCounter) + 9; }
else { upperLimit = refs.length; }
var refinements = "";
var keyPos = 0;
refinements += ref_wrapToHtml("ref", "genRefRandom", "refinement", "", keyPos, "Choose at random");
keys["" + keyPos] = mkRefHotKey("genRefRandom");
keyPos++;
for (var i = (9 * refPageCounter), j = upperLimit; i < j; i++) {
refinements += ref_wrapToHtml("ref", refs[i], "refinement", "", keyPos, "");
keys["" + keyPos] = mkRefHotKey(refs[i]);
keyPos++;
}
if (pages > refPageCounter) {
refinements += ref_wrapNextRefsToHtml("nextRefs", "Next", "refinement", "+", "Next Refinements");
keys["107"] = mkRefNextRefsHotKey("Next");
}
if (0 < refPageCounter) {
refinements += ref_wrapNextRefsToHtml("nextRefs", "Previous", "refinement", "-", "Previous Refinements");
keys["109"] = mkRefNextRefsHotKey("Previous");
}
refinements += "
";
return refinements;
}
// Gets the available refinements for a node
function getAvailableRefinements(nodeName) {
var node = getNodeFromAbstract(abstractTree, nodeName, "0");
var metaType = node.type;
var refinements = new Array();
for (var fun in myAbstract.types) {
if (myAbstract.types[fun].cat == metaType) {
refinements[refinements.length] = fun;
}
}
return refinements;
}
// Creates an HTML representation of a Refinement/Wrap
function ref_wrapToHtml(funct, name, className, arg, hotKeyPos, caption) {
var ref_wrapHtml = "| ";
if (caption) { ref_wrapHtml += caption; }
else { ref_wrapHtml += overl(name) + " : " + refArgsToHtml(name) + myAbstract.getCat(name); }
ref_wrapHtml += " | (" + hotKeyPos + ") |
";
return ref_wrapHtml
}
// Creates the function to be used by a "numeric" hot key
function mkRefHotKey(refName) {
return function() { if (document.getElementById("ref" + refName)) { refClick(refName); } }
}
// Creates an HTML representation of a Refinement/Wrap
function ref_wrapNextRefsToHtml(funct, name, className, hotKeyPos, caption) {
var ref_wrapHtml = "| ";
ref_wrapHtml += caption;
ref_wrapHtml += " | (" + hotKeyPos + ") |
";
return ref_wrapHtml
}
// Creates the function to be used by a "+" hot key
function mkRefNextRefsHotKey(refName) {
return function() { if (document.getElementById("nextRefs" + refName)) { nextRefsClick(refName); } }
}
// Creates a string representation of the arguments of a refinement
function refArgsToHtml(fun) {
var args = "";
for (var i = 0, j = myAbstract.types[fun].args.length; i < j; i++) {
args += myAbstract.types[fun].args[i] + " -> ";
}
return args;
}
// Gets the type of a meta variable
function getMetaType(absNode, route, currRoute) {
if (route == currRoute && absNode.isMeta()) {
return absNode.type;
}
else {
for (var i = 0, j = absNode.args.length; i < j; i++) {
var found = getMetaType(absNode.args[i], route, currRoute + "-" + i);
if (found) { return found };
}
}
}
// When the "Undo" action is selected, undoes the last action
function clickUndo(actName) {
if (document.getElementById(actName).className == "action" && undoArray.length) {
highlightSelectedAction(actName);
redoArray.push(new state(selectedNode, abstractTree, collapseBuffer));
var prevState = undoArray.pop();
selectedNode = prevState.selectedNode;
abstractTree = myAbstract.copyTree(prevState.tree);
collapseBuffer = prevState.collapseBuffer;
if (abstractTree.isComplete()) { selectedNode = "0"; }
abstractTree = myAbstract.annotate(abstractTree, myAbstract.startcat);
myTree = treeFromAbstract(abstractTree, "0");
nodeClick(selectedNode);
}
}
// When the "Redo" action is selected, redoes the last action
function clickRedo(actName) {
if (document.getElementById(actName).className == "action" && redoArray.length) {
highlightSelectedAction(actName);
undoArray.push(new state(selectedNode, abstractTree, collapseBuffer));
var nextState = redoArray.pop();
selectedNode = nextState.selectedNode;
abstractTree = myAbstract.copyTree(nextState.tree);
collapseBuffer = nextState.collapseBuffer;
abstractTree = myAbstract.annotate(abstractTree, myAbstract.startcat);
myTree = treeFromAbstract(abstractTree, "0");
nodeClick(selectedNode);
}
}
// When the "Copy" action is selected, copies the selected node to the clipboard
function clickCopy(actName) {
if (document.getElementById(actName).className == "action") {
highlightSelectedAction(actName);
if (selectedNode) {
clipBoard = myAbstract.copyTree(getNodeFromAbstract(abstractTree, selectedNode, "0"));
document.getElementById("clipboardFrame").innerHTML = clipBoard.name + " : " +
myAbstract.getCat(clipBoard.name);
nodeClick(selectedNode);
}
}
}
// When the "Cut" action is selected, deletes the selected node and copies it to the clipboard
function clickCut(actName) {
if (document.getElementById(actName).className == "action") {
highlightSelectedAction(actName);
pushUndoClearRedo();
if (selectedNode) {
clipBoard = myAbstract.copyTree(getNodeFromAbstract(abstractTree, selectedNode, "0"));
document.getElementById("clipboardFrame").innerHTML = clipBoard.name + " : " +
myAbstract.getCat(clipBoard.name);
abstractTree = deleteNode(abstractTree, selectedNode, "0");
concludeAction();
}
}
}
// Annotates the abstract tree, creates a tree from the abstract tree and selects the next meta variable
function concludeAction() {
abstractTree = myAbstract.annotate(abstractTree, myAbstract.startcat);
myTree = treeFromAbstract(abstractTree, "0");
selectNextMeta();
}
// Selects the next meta variable available
function selectNextMeta() {
nodeClick(selectedNode);
if (!abstractTree.isComplete()) {
var pathToNextMeta = "";
var nodePos = getNavPos(selectedNode);
while (1) {
if (nodePos == navigationControlString.length) { nodePos = 0; }
var node = getNode(navigationControlString[nodePos], myTree);
if (node.caption == "?") { pathToNextMeta = node.name; break; }
nodePos++;
}
expandAscendants(pathToNextMeta);
nodeClick(pathToNextMeta);
}
}
// Gets the first meta variable from an abstract tree
function getNextMetaFromAbstract(node, route) {
if (node.isMeta()) { return route; }
for (var i = 0, j = node.args.length; i < j; i++) {
var found = getNextMetaFromAbstract(node.args[i], route + "-" + i);
if (found) { return found; }
}
}
// Expands the ascendants of a given node
function expandAscendants(nodeName) {
var nodePath = nodeName.split("-");
var currAscendant = nodePath.shift();
while (nodePath.length > 0) {
var node = getNode(currAscendant, myTree);
if (node.collapsed) {
myTree = expandCollapse(myTree, currAscendant);
}
currAscendant += "-" + nodePath.shift();
}
}
// When the "Paste" action is selected, pastes the contents of the clipboard into the selected node
function clickPaste(actName) {
if (document.getElementById(actName).className == "action") {
highlightSelectedAction(actName);
pushUndoClearRedo();
if (selectedNode) {
abstractTree = insertNode(abstractTree, selectedNode, "0", myAbstract.copyTree(clipBoard));
concludeAction();
}
}
}
// Inserts a node into a tree
function insertNode(absNode, route, currRoute, node) {
if (route == currRoute) {
return node;
}
else {
for (var i = 0, j = absNode.args.length; i < j; i++) {
absNode.setArg(i, insertNode(absNode.args[i], route, currRoute + "-" + i, node));
}
return absNode;
}
}
// When the "Delete" action is selected, deletes the selected node
function clickDelete(actName) {
if (document.getElementById(actName).className == "action") {
highlightSelectedAction(actName);
pushUndoClearRedo();
if (selectedNode) {
abstractTree = deleteNode(abstractTree, selectedNode, "0");
abstractTree = myAbstract.annotate(abstractTree, myAbstract.startcat);
myTree = treeFromAbstract(abstractTree, "0");
nodeClick(selectedNode);
}
}
}
// Deletes a node from a tree
function deleteNode(absNode, route, currRoute) {
if (route == currRoute) {
return new Fun("?");
}
else {
for (var i = 0, j = absNode.args.length; i < j; i++) {
absNode.setArg(i, deleteNode(absNode.args[i], route, currRoute + "-" + i));
}
return absNode;
}
}
// When the "Replace" action is selected, replaces the selected node with another refinement
function clickReplace(actName) {
if (document.getElementById(actName).className == "action") {
highlightSelectedAction(actName);
pushUndoClearRedo();
if (selectedNode) {
abstractTree = deleteNode(abstractTree, selectedNode, "0");
abstractTree = myAbstract.annotate(abstractTree, myAbstract.startcat);
myTree = treeFromAbstract(abstractTree, "0");
drawTree();
document.getElementById("refFrame").innerHTML = showRefinements(selectedNode);
}
}
}
// When the "Wrap" action is selected, wraps around the selected node with another refinement
function clickWrap(actName) {
if (document.getElementById(actName).className == "action") {
highlightSelectedAction(actName);
pushUndoClearRedo();
var node = getNode(selectedNode, myTree);
if (selectedNode) {
refPageCounter = 0;
var wrappers = getWrappers(node.caption);
document.getElementById("refFrame").innerHTML = wrappers;
if (wrappers.length <= 31) {
alert("No wrappers available");
document.getElementById("actFrame").innerHTML = showActions();
nodeClick(selectedNode);
}
}
}
}
// Gets the wrappers to display
function getWrappers(nodeCaption) {
var nodeType = myAbstract.types[nodeCaption].cat;
var availWrappers = getAvailableWrappers(nodeType);
var pages = Math.floor(availWrappers.length / 9);
var upperLimit;
if (pages != refPageCounter) { upperLimit = (9 * refPageCounter) + 9; }
else { upperLimit = availWrappers.length - (9 * refPageCounter); }
var wrappers = "";
var keyPos = 0;
for (var i = (9 * refPageCounter), j = (9 * refPageCounter) + upperLimit; i < j; i++) {
wrappers += ref_wrapToHtml("wrap", availWrappers[i][0], "wrapper", ", " + availWrappers[i][1], keyPos, "");
keys["" + keyPos] = mkWrapHotKey(availWrappers[i][0], availWrappers[i][1]);
keyPos++;
}
if (pages > (9 * refPageCounter)) {
refinements += ref_wrapNextRefsToHtml("nextWraps", "Next", "wrapper", "+", "Next Wrappers");
keys["107"] = mkWrapNextRefsHotKey("Next");
}
if (0 < (9 * refPageCounter)) {
refinements += ref_wrapNextRefsToHtml("nextWraps", "Previous", "wrapper", "-", "Previous Wrappers");
keys["109"] = mkWrapNextRefsHotKey("Previous");
}
wrappers += "
";
return wrappers;
}
// Gets the available wrappers for a node
function getAvailableWrappers(nodeType) {
var wrappers = new Array();
for (var fun in myAbstract.types) {
for (var i = 0, j = myAbstract.types[fun].args.length; i < j; i++) {
if (myAbstract.types[fun].args[i] == nodeType && myAbstract.types[fun].cat == nodeType) {
wrappers[wrappers.length] = new Array(fun, i);
break;
}
}
}
return wrappers;
}
// Creates the function to be used by a "numeric" hot key
function mkWrapHotKey(refName, argPos) {
return function() { if (document.getElementById("wrap" + refName)) { wrapClick(refName, argPos); } }
}
// Creates the function to be used by a "-" hot key
function mkWrapNextRefsHotKey(refName) {
return function() { if (document.getElementById("nextWraps" + refName)) { nextRefsClick(refName); } }
}
// When the "RandomNode" action is selected, refines the node at random
function clickRandomNode(actName) {
if (document.getElementById(actName).className == "action") {
highlightSelectedAction(actName);
pushUndoClearRedo();
if (selectedNode) {
var tempTree = myAbstract.copyTree(abstractTree);
abstractTree = myAbstract.copyTree(getNodeFromAbstract(abstractTree, selectedNode, "0"));
fillSubTree()
abstractTree = insertNode(tempTree, selectedNode, "0", myAbstract.copyTree(abstractTree));
concludeAction();
}
}
}
// Refines the sub tree
function fillSubTree() {
while (!abstractTree.isComplete()) {
var nodeToRefine = getNextMetaFromAbstract(abstractTree, "0");
if (nodeToRefine) {
var refs = getAvailableRefinements(nodeToRefine);
// FIX THIS ASAP!!!!
if (refs.length == 0) {
var node = getNodeFromAbstract(abstractTree, nodeToRefine, "0");
if (node.type == "String") {
var newType = "AutoString";
myAbstract.addType(newType,[], "String");
for (var i = 0, j = myConcrete.length; i < j; i++) {
myConcrete[i].concreteSyntax.addRule(newType, function(cs){ return new Arr(new Str(newType));});
}
node.name = newType;
abstractTree = insertNode(abstractTree, nodeToRefine, "0", node);
abstractTree = myAbstract.annotate(abstractTree, myAbstract.startcat);
}
}
else {
var selectedRef = refs[Math.floor(refs.length * Math.random())];
abstractTree = refineAbstractTree(abstractTree, nodeToRefine, "0", selectedRef);
abstractTree = myAbstract.annotate(abstractTree, myAbstract.startcat);
}
/*
var selectedRef = refs[Math.floor(refs.length * Math.random())];
abstractTree = refineAbstractTree(abstractTree, nodeToRefine, "0", selectedRef);
abstractTree = myAbstract.annotate(abstractTree, myAbstract.startcat);
*/
}
}
}
// When the "RandomTree" action is selected, refines the tree at random
function clickRandomTree(actName) {
if (document.getElementById(actName).className == "action") {
highlightSelectedAction(actName);
pushUndoClearRedo();
fillSubTree();
concludeAction();
}
}
// If a node is selected and is of type meta, it refines the node with a type refName
function refClick(refName) {
if (selectedNode) {
if (refName == "genRefRandom") {
var refs = getAvailableRefinements(selectedNode);
refName = refs[Math.floor(refs.length * Math.random())];
}
abstractTree = refineAbstractTree(abstractTree, selectedNode, "0", refName);
document.getElementById("actFrame").innerHTML = showActions();
document.getElementById("refFrame").innerHTML = "";
clearHotKeys();
concludeAction();
}
}
// If a refinement is selected, a node has the property "selected" set and the node is a meta variable,
// it refines node. Returns the refined abstract tree
function refineAbstractTree(absNode, route, currRoute, refName) {
if (route == currRoute && absNode.isMeta()) {
return createRefinement(refName);
}
else {
for (var i = 0, j = absNode.args.length; i < j; i++) {
absNode.setArg(i, refineAbstractTree(absNode.args[i], route, currRoute + "-" + i, refName));
}
return absNode;
}
}
// Creates a Fun of type refName object with the appropriate number of meta arguments
function createRefinement(refName) {
var newRef = new Fun(refName);
for (var i = 0, j = myAbstract.types[refName].args.length; i < j; i++) {
newRef.setArg(i, new Fun("?"));
}
return newRef;
}
// Creates a tree from an abstract tree
function treeFromAbstract(abstractNode, name) {
var node = new treeNode(name, abstractNode.name);
if (node.caption == "?") {
node.cat = abstractNode.type; }
else { node.cat = myAbstract.getCat(node.caption); }
if (wasCollapsed(node.name)) { node.collapsed = true; }
for (var i = 0, j = abstractNode.args.length; i < j; i++) {
node.addChild(i, treeFromAbstract(abstractNode.args[i], name + "-" + i));
}
return node
}
// Wraps a refinement around a node
function wrapClick(refName, argPos) {
if (selectedNode) {
var tempNode = createRefinement(refName);
tempNode.setArg(argPos, myAbstract.copyTree(getNodeFromAbstract(abstractTree, selectedNode, "0")));
abstractTree = insertNode(abstractTree, selectedNode, "0", tempNode);
document.getElementById("actFrame").innerHTML = showActions();
document.getElementById("refFrame").innerHTML = "";
clearHotKeys();
concludeAction();
}
}
// Handler for the escape key
function clickEsc() {
if ((document.getElementById("actRefine").className == "selected" ||
document.getElementById("actReplace").className == "selected" ||
document.getElementById("actWrap").className == "selected") && undoArray.length) {
var prevState = undoArray.pop();
selectedNode = prevState.selectedNode;
abstractTree = myAbstract.copyTree(prevState.tree);
collapseBuffer = prevState.collapseBuffer;
abstractTree = myAbstract.annotate(abstractTree, myAbstract.startcat);
myTree = treeFromAbstract(abstractTree, "0");
document.getElementById("actFrame").innerHTML = showActions();
if (selectedNode) { nodeClick(selectedNode) }
}
}
// If there are over ten refinements available shows only the selected nine
function nextRefsClick(refName) {
if (refName == "Next") { refPageCounter++; } else { refPageCounter--; }
clearHotKeys();
document.getElementById("refFrame").innerHTML = showRefinements(selectedNode);
}
// show overloaded name: ignore prefix ovr*_
function overl(name){
var nam = "";
if (name[0] + name[1] + name[2]=="ovr") {
i = 5 ;
while (name[i] != '_') {++i}
for (j = i+1 ; j != name.length ; ++j){ nam += name[j] ;}
}
else nam = name ;
return nam;
}
Fun.prototype.printOverl = function () { return this.showOverl(0); } ;
Fun.prototype.showOverl = function (prec) {
if (this.isMeta()) {
return '?';
} else {
var s = overl(this.name);
var cs = this.args;
for (var i in cs) {
s += " " + cs[i].showOverl(1);
}
if (prec > 0 && cs.length > 0) {
s = "(" + s + ")" ;
}
return s;
}
};