/*
* Copyright (C) 2011 Alasdair C. Hamilton
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package ket.math.convert;
import java.util.*;
// TODO: Remove this dependency either by calling clipboard in
// this method's caller or by specializing clipboard
// functionality.
import ket.Edit;
import ket.MathCollection;
import ket.Selection;
import ket.math.*;
import ket.math.Highlight;
import ket.math.convert.Like;
import ket.math.purpose.*;
import ketUI.Clipboard;
import ketUI.DocumentManager;
import ketUI.Ket;
/**
* This class provides various specialized functionality to transform a given
* list of tokens into a meaningful argument.
*/
public class Interpretation {
Branch tokenList;
public String debug() {
//- return tokenList.toString();
return tokenList.toPrefixNotation();
}
/**
* Parse a given equation into a nested series of branches and
* arguments that represent each function or operand. These can then
* be processed and accessed with other class methods.
*
* @param tokenList A series of tokens to be interpreted in terms of an argument.
*/
public Interpretation(Branch tokenList) {
this.tokenList = tokenList;
}
public void recognizeSymbolicFunctions(KnownArguments knownArguments) {
Vector<SymbolicFunction> sortedFunctions = knownArguments.getSortedSymbolicFunctions();
boolean changed;
do {
changed = recognizeSymbolicFunctions(sortedFunctions);
} while (changed);
clean();
clean(); // This is needed because otherwise "a_b(x)" generates: compoundState(a, null) which is illegal: investigate further.
clean();
}
/**
* Recognize one of the various functions, replacing the tokens with a
* branch of the recognized function and returning after finding the
* first instance with the highest precedence.
* @return The success in recognizing and replacing any known function.
*/
public boolean recognizeSymbolicFunctions(Vector<SymbolicFunction> sortedSymbolicFunctions) {
for (SymbolicFunction symbolicFunction : sortedSymbolicFunctions) {
for (Branch child : getBranchVector(true)) {
if (symbolicFunction.split(child)) {
return true;
}
}
}
return false;
}
// &name -> name()
// TODO: As you never use &name notation, eliminate it and use &word for other purposes.
public void recognizeAmpersandFunctions(KnownArguments knownArguments) {
// BUG: While &f:x works, &f(x) does not.
for (Branch branch : getBranchVector(true, Function.AMPERSAND)) {
Argument child = Like.singleChild(branch);
if (child==null) continue;
State state = child.getState();
Function function = knownArguments.stateToFunction(state);
if (function==null) continue;
branch.setFunction(function);
branch.empty();
}
clean();
}
/**
* Recursively select all branches within a given function that are of
* type 'function' and return them in a depth-first vector.
*/
public Vector<Branch> getBranchVector(boolean includeRoot, Function function) {
Vector<Branch> branchVector = getBranchVector(includeRoot);
Vector<Branch> selectiveBranchVector = new Vector<Branch>();
for (Branch branch : branchVector) {
if (branch.getFunction()==function) {
selectiveBranchVector.add(branch);
}
}
return selectiveBranchVector;
}
public Vector<Branch> getBranchVector(boolean includeRoot) {
int settings = ArgumentVector.BRANCHES_ONLY;
settings |= includeRoot ? ArgumentVector.INCLUDE_ROOT : 0;
ArgumentVector argumentVector = new ArgumentVector(tokenList, settings);
return argumentVector.toBranchVector();
}
public Vector<Token> getTokenVector(boolean includeRoot) {
int settings = includeRoot ? ArgumentVector.INCLUDE_ROOT : 0;
Vector<Argument> argumentVector = new ArgumentVector(tokenList, settings);
Vector<Token> tokenVector = new Vector<Token>();
for (Argument argument : argumentVector) {
if (argument instanceof Token) {
tokenVector.add((Token) argument);
}
}
return tokenVector;
}
/**
* Functions may be written explicitly by converting
* branch'null'[Token[(Word)], Argument]
* into
* branch'Word'[Argument]
* for null branches with two arguments starting with a string value.
*/
public void makeImplicitFunctionsExplicit(KnownArguments knownArguments) {
// TODO: Ampersand is parsed as: branch'&'[branch'func'[x]] not (branch[branch'&'[func], x].
for (Branch branch : getBranchVector(true)) {
String functionName = Like.getImplicitFunctionName(branch);
if (functionName==null) continue;
Function function = knownArguments.recordUniqueFunction(functionName);
Branch bracketedArgument = (Branch) branch.lastChild();
Argument organizedFunction = tokenListToFunction(function, bracketedArgument);
branch.empty();
branch.append(organizedFunction);
}
clean();
}
/**
* Create a branch with the given function and either a single argument
* or a 'COMMA' branch of arguments.
*
* @param function The function of the new parent branch.
* @param argument Either an argument or a bracket branch containing a
* single comma branch, each argument of which is a separate argument
* to the new parent branch.
* @return A new parent branch with the given function type.
*/
public Branch tokenListToFunction(Function function, Argument argument) {
Branch parent = new Branch(function);
parent.append(argument);
if (argument instanceof Branch) {
Branch branch = (Branch) argument;
if (branch.size()>0) {
Argument first = branch.firstChild();
if (first.getFunction()==Function.COMMA) {
((Branch) first).removeIntermediate();
}
}
if (branch.getFunction()==Function.BRACKET) {
branch.removeIntermediate();
}
}
return parent;
}
public void recognizeSubscripts() {
for (Branch branch : getBranchVector(true, Function.SUBSCRIPT)) {
if (Like.functionOfTwoNonNullStates(branch)) {
CompoundState compoundState = new CompoundState(
branch.getChildren(),
CompoundState.SUBSCRIPT);
branch.replace(new Token(compoundState));
}
}
}
public void recognizeBold() {
for (Branch branch : getBranchVector(false, Function.BOLD)) {
if (branch.size()==1) {
branch.firstChild().setBold(true);
branch.removeIntermediate();
}
}
}
public void recognizeNull() {
for (Branch branch : getBranchVector(false, Function.NULL)) {
if (branch.size()==1) {
branch.removeIntermediate();
}
}
}
public void recursiveSubstitute(MathCollection mathCollection) { // CLARIFY
Vector<Branch> branchVector = getBranchVector(false, Function.WITH);
Edit e = new Edit(tokenList);
Collections.reverse(branchVector);
for (Branch branch : branchVector) {
Argument first = branch.firstChild();
if (first==null) return;
for (int i=1; i<branch.size(); i++) {
e.setCurrent(first);
e.substitute(branch.getChild(i));
}
e.replace(branch, first);
}
}
public void recognizeJoins() {
for (Branch branch : getBranchVector(true, Function.JOIN)) {
// TODO: Check all elements of this sublist are legal varaiables
// (before they were changed from wordTokens and symbolicTokens).
Vector<Argument> args = branch.getChildren();
if (branch.size()>=2 && areTokens(args)) {
CompoundState compoundState = new CompoundState(args, CompoundState.JOIN);
branch.replace(new Token(compoundState));
}
}
clean();
}
private static boolean areTokens(Vector<Argument> args) {
for (Argument argument : args) {
if (argument instanceof Branch) {
return false;
}
}
return true;
}
/**
* Use ~<address> to refer to the previous argument's addresses.
*/
public void substituteFromPreviousEquation(Highlight highlight) {
if (highlight.isFirstEquation()) {
// No previous equation exists.
return;
}
for (Branch branch : getBranchVector(false, Function.TILDE)) {
Integer path = Like.singleChildInteger(branch);
if (path==null) { // TODO: Negative value?
continue;
}
Argument previousRoot = highlight.getFirstSelectedEquation().getPreviousEquation().getRoot(); //> Simplify
Address address = new Address(path.intValue());
Argument relative = previousRoot.relativeAddress(address);
if (relative!=null) {
Argument replacement = Argument.cloneArgument(relative);
branch.replace(replacement);
}
}
}
/**
* Use \<address> to refer to an address within the current selection.
*/
public void substituteFromCurrentSelection(Highlight highlight) {
for (Branch branch : getBranchVector(false, Function.BACKSLASH)) {
Integer path = Like.singleChildInteger(branch);
if (path==null) {
continue;
}
Address address = new Address(path);
Argument relative = highlight.relativeAddress(address);
if (relative!=null) {
Argument replacement = Argument.cloneArgument(relative);
branch.replace(replacement);
}
}
clean();
}
/**
* Recognize implicit symbols in the list of tokens and convert them
* from a backslash symbol followed by a String word token into
* backslash branch with the word token as its only argument. This is
* required to recognize functions whose functions can only be
* specified implicitly, such as: a \in b.
*/
public void findImplicitSymbols(KnownArguments knownArguments) {
// x = sin \ alpha -> x, =, sin, \alpha
Set<Symbol> operandSymbolSet = knownArguments.getOperandSymbolSet();
for (int i=0; i<tokenList.size()-1; i++) {
Argument backslashToken = tokenList.getChild(i);
Argument wordVariableToken = tokenList.getChild(i+1);
boolean hasBackslash = backslashToken.getState()==Symbol.BACKSLASH;
boolean hasWord = wordVariableToken.getState() instanceof Word;
if (!hasBackslash || !hasWord) {
continue;
}
String name = wordVariableToken.getState().getName();
for (Symbol symbol : operandSymbolSet) {
// Look for known tokens
// TODO: Remove the second test, \* etc is messy.
if (symbol.getWord().equals(name) || symbol.getName().equals(name)) {
backslashToken.remove();
Token replacement = new Token(symbol);
wordVariableToken.replace(replacement); // BUG: wordVariableToken has no parent: why?
break;
}
}
}
}
/*-?
private void TEST__showParentChildren() {
for (int i=0; i<tokenList.size(); i++) {
Ket.out.println(" *** " + (tokenList.getChild(i).getParent()!=null));
}
}
*/
private void clean() {
tokenList.removeIntermdiateNullChildBranches();
tokenList.removeNullChildren();
}
/**
* Return the single (correctly parsed) argument in branch, or
* handle parsing errors meaningfully.
*/
public Argument getArgument() {
// TODO: Move this to a better place.
if (tokenList.getFunction()==null) {
tokenList.setFunction(Function.TIMES);
}
switch (tokenList.size()) {
case 0:
//- System.out.println("[zero] tokenList = " + tokenList);
//-return null;
return new Branch(Function.MATRIX); // can this be caused from anything other than parsing "()"?
case 1:
// 'tokenList' must be a branch so the real result is stored as a
// single argument inside it. Clean up the resulting argument.
Argument argument = tokenList.getChild(0);
argument.remove(); // TODO: This step invalidates the token list.
assert argument.getParent()==null : "Parsed expression has a non-null parent.";
return argument;
default:
// TODO: What default interpretations of multiple arguments are their?
return tokenList;
}
}
public void unknownsToProducts() {
for (Branch b : getBranchVector(false, null)) {
b.setFunction(Function.TIMES);
}
}
//////////////////
// LONG METHODS //
//////////////////
public void convertTokensToVariables(KnownArguments knownArguments) {
// TODO: This is unclear, re-work it for clarity of purpose.
for (Token token : getTokenVector(false)) {
State state = token.getState();
if (token instanceof VariableToken) {
knownArguments.recordVariable(state);
} else if (state instanceof VariableState) {
if (Symbol.CONSTANT_SYMBOLS.contains(state)) {
continue;
}
VariableToken replacement = new VariableToken((VariableState) state);
token.replace(replacement);
knownArguments.recordVariable(state);
}
}
}
/**
* Replace any functions of the form branch'hash'[Token((int) n)] with the n'th equation.
*/
public void substituteEquation(Highlight highlight) {
for (Branch branch : getBranchVector(false, Function.REFERENCE)) {
Argument match = matchReferenceBranch(branch, highlight);
if (match!=null) {
Argument clone = Argument.cloneArgument(match);
branch.replace(clone);
}
}
}
private Argument matchReferenceBranch(Branch branch, Highlight highlight) {
switch (branch.size()) {
case 1:
// #[<equation-name>|<equation-label>]
Purpose location = getFirstChildPurpose(branch);
return getRootByPurpose(location, highlight);
case 2:
// [<equation-name>|<equation-label>]#[address]
Purpose rootLocation = getFirstChildPurpose(branch);
Argument root = getRootByPurpose(rootLocation, highlight);
if (root==null) {
return null;
}
Integer path = Like.getInteger(branch.lastChild());
if (path==null) {
return null;
}
Address address = new Address(path.intValue());
return root.relativeAddress(address);
default:
return null;
}
}
/**
* Return the clone of an equation root by an instanceof purpose:
* either a word label or an integer equation number.
*/
private Argument getRootByPurpose(Purpose purpose, Highlight highlight) {
if (purpose instanceof IntegerValue) {
// Find the equation with the given number.
int equationNumber = ((IntegerValue) purpose).getInt();
return getRootByNumber(equationNumber, highlight);
} else if (purpose instanceof Word) {
// Find an equation with the given label.
Word word = (Word) purpose;
String value = word.getValue();
return getRootByLabel(value, highlight);
} else {
return null;
}
}
/**
* Replace any functions of the form branch'hash'[arg] with the value
* stored in clipboard(arg).
*/
public void substituteClipboard(Clipboard clipboard) {
if (clipboard==null) {
return;
}
for (Branch branch : getBranchVector(false, Function.CLIPBOARD)) {
Argument clone = matchClipboardBranch(branch, clipboard);
if (clone!=null) {
branch.replace(clone);
}
}
}
private Argument matchClipboardBranch(Branch branch, Clipboard clipboard) {
switch (branch.size()) {
case 0:
return clipboard.getArgument();
case 1: // Given a one letter word, return a clone of the content of the associated clipboard register.
return getClipboardRoot(branch, clipboard);
case 2: // Given 'a%13', return register 'a' of clipboard's first argument's third argument.
Argument root = getClipboardRoot(branch, clipboard);
if (root==null) {
return null;
}
Integer path = Like.getInteger(branch.lastChild());
if (path==null) {
return null;
}
Address address = new Address(path.intValue());
return root.relativeAddress(address);
default:
return null;
}
}
// TODO: Move to Like.
private Purpose getFirstChildPurpose(Branch branch) {
if (branch.size()>0) {
return branch.firstChild().getPurpose();
} else {
return null;
}
}
// TODO: Move to Like.
private Argument getClipboardRoot(Branch branch, Clipboard clipboard) {
Purpose purpose = getFirstChildPurpose(branch);
return clipboard.getArgument(purpose);
}
private Argument getRootByLabel(String label, Highlight highlight) {
EquationList equationList = highlight.getEquationList();
Equation match = equationList.getEquation(label);
if (match!=null) {
return match.getVisibleRoot();
} else {
return null;
}
}
/**
* Return the (cloned) visible root of the given equation that
* corresponds to the given equation number or null if not found.
*/
private Argument getRootByNumber(int equationNumber, Highlight highlight) {
Ket.out.println(" --- get root by number --- ");
Ket.out.println("\tnumber = " + equationNumber);
EquationList el = highlight.getEquationList();
for (Equation equation : el.getEquations()) {
if (equationNumber==equation.getEquationNumber()) {
return equation.getVisibleRoot();
}
}
return null;
}
public void recognizeFunctions(SymbolicFunction...functions) {
boolean changed = false;
do {
changed = false;
Vector<Branch> branchVector = getBranchVector(true);
Collections.reverse(branchVector);
for (Branch child : branchVector) {
if (Function.BRACKET.split(child)) {
changed = true;
for (Branch branch : getBranchVector(true, Function.BRACKET)) {
if (branch.size()==1) {
branch.removeIntermediate();
}
}
for (Branch branch : getBranchVector(false)) {
if (branch.getFunction()==null && branch.size()<=1) {
branch.removeIntermediate();
}
}
break;
}
}
} while (changed);
//?+ clean();
}
public int size() {
return tokenList.size();
}
public void addNullRoot() {
tokenList = new Branch(null, tokenList);
}
public void apply(KnownArguments knownArguments) {
Vector<Branch> branchVector = getBranchVector(true);
for (Branch child : branchVector) {
if (child.size()==0) {
Ket.out.println("[empty]");
continue;
}
Argument first = child.firstChild();
Ket.out.println("first: " + first);
Purpose purpose = first.getPurpose();
if (purpose==null) {
Ket.out.println("[null purpose]");
continue;
}
Ket.out.println("purpose: " + purpose);
Ket.out.println(purpose.getClass());
if (purpose instanceof Word) {
child.removeChild(0);
Function function = knownArguments.stateToFunction((State) purpose);
child.setFunction(function);
} else if (purpose instanceof Symbol) {
Function function = null;
System.out.println("BUG");
System.out.println("child = " + child);
if (true) throw new RuntimeException("Bug");
//?:
if (purpose==Symbol.ADD) {
function = Function.ADD;
} else if (purpose==Symbol.MINUS) {
function = Function.MINUS;
} else if (purpose==Symbol.SLASH) {
function = Function.FRACTION;
} else if (purpose==Symbol.TIMES) {
function = Function.TIMES;
} else if (purpose==Symbol.DOUBLE_SLASH) {
function = Function.DIVIDE;
} else if (purpose==Symbol.CARET) {
function = Function.POWER;
} else if (purpose==Symbol.TO) {
function = Function.TO;
} else if (purpose==Symbol.LESS_EQUALS) {
function = Function.LESS_EQUALS;
} else if (purpose==Symbol.LESS_THAN) {
function = Function.LESS_THAN;
} else if (purpose==Symbol.GREATER_EQUALS) {
function = Function.GREATER_EQUALS;
} else if (purpose==Symbol.GREATER_THAN) {
function = Function.GREATER_THAN;
} else if (purpose==Symbol.EQUALS) {
function = Function.EQUALS;
}
if (function!=null) {
child.removeChild(0);
child.setFunction(function);
}
}
}
}
/**
* A depth-first number of arguments within a tree structure of unknown tokens.
*/
public Branch asTree(Branch branch) {
if (branch.size()!=1) return null;
Vector<Integer> digits = Like.getPositiveDigits(branch.firstChild());
if (digits==null) return null;
Ket.out.println("[digits: " + digits + "]");
Branch root = new Branch(Function.VECTOR);
int i=0;
for (int d : digits) {
ArgumentVector v = new ArgumentVector(root, ArgumentVector.INCLUDE_ROOT); //+ .toBranchVector()
if (d==0) { // move back up the tree
i += 1;
} else { // append d new nodes to the i'th tree node.
if (i<0 || v.size()<=i) {
Ket.out.println("i=" + i + "/" + v.size());
return null;
}
Branch next = (Branch) v.get(i);
for (int j=0; j<d; j++) {
Branch b = new Branch(Function.VECTOR);
next.append(b);
}
i += 1;
}
}
ArgumentVector v = new ArgumentVector(root, ArgumentVector.INCLUDE_ROOT);
for (Argument a : v) {
if (a.asBranch().size()==0) {
a.replace(new Token(Symbol.UNKNOWN));
}
}
return root;
}
/**
* A branch of an equation will be read as
* <I>branch':'[(wordToken)sin, x]</I> but the sought format is
* <I>branch'sin'[x]</I>. This method recursively converts the second
* last argument of Function.COMPOSITION branches into a new branch with
* the last argument as its argument. Existing functions and functions
* are recognized while new functions are created. Matching is
* by name and then by alternative matching methods.
*/
public void expandFunctionPrefixNotation(KnownArguments knownArguments) {
for (Branch branch : getBranchVector(true, Function.COMPOSITION)) {
// branch[':'](Token'StrinValue', Token'StrinValue', Argument)
Branch tree = asTree(branch);
if (tree!=null) {
branch.replace(tree);
} else {
Argument argument = compositionToBranch(branch, knownArguments);
if (argument!=null) {
branch.replace(argument);
}
}
}
clean();
}
public void breakApart(KnownArguments knownArguments) {
//- Ket.out.println(" --- break apart --- ");
for (Branch branch : getBranchVector(true, Function.BREAK)) {
//- Ket.out.println("\t" + branch);
// a+b $ ^c -> (a+b) ^ c ; a+b $ b+c -> a*(b+c)
Branch result = new Branch(Function.UNKNOWN);
for (Argument child : branch.getChildren()) {
//- Ket.out.println("\t\t" + child);
Interpretation part = new Interpretation(new Branch(Function.UNKNOWN, Argument.cloneArgument(child)));
part.expandFunctionPrefixNotation(knownArguments);
part.makeImplicitFunctionsExplicit(knownArguments);
part.recognizeAmpersandFunctions(knownArguments);
part.convertTokensToVariables(knownArguments);
part.removeIntermediateBrackets();
result.append(part.getArgument());
//- Ket.out.println("\t\t\t" + child);
}
for (int q=0; q<1000 && result.size()>1; q++) { // For and not while so as to avoid an obvious infinite loop.
// Repeatedly find the lowest precidence operator and prepend or append it to its neighbour.
int min = precidence(result.firstChild());
int index = 0;
for (int i=1; i<result.size(); i++) { // Find the lowest precidence.
int p = precidence(result.getChild(i));
if (p<=min) {
index = i;
min = p;
}
}
int left = index>0 ? precidence(result.getChild(index-1)) : Integer.MAX_VALUE;
int right = index+1<result.size() ? precidence(result.getChild(index+1)) : Integer.MAX_VALUE;
if (left < right) {
result.getChildBranch(left).append( result.getChild(index) );
} else {
result.getChildBranch(right).prepend( result.getChild(index) );
}
}
branch.replace(result.firstChild()); // May contain multiple in which case return (TIMES ...).
}
}
private int precidence(Argument a) { // TODO: Move to individual.
Function function = a.getFunction();
if (function!=null) {
return function.getPrecedence();
} else {
return Integer.MIN_VALUE;
}
}
/**
* Given a composition of one or more arguments, convert them into nested branches.
*/
private Argument compositionToBranch(Branch branch, KnownArguments knownArguments) {
Argument argument = branch.lastChild();
for (int i=branch.size()-2; i>=0; i--) {
State state = Like.stateRepresentationOfFunctionLike(branch.getChild(i));
if (state!=null) {
Function function = knownArguments.stateToFunction(state);
argument = tokenListToFunction(function, argument);
} else {
Ket.out.println(" !!! Ampersand has too many arguments to denote a function !!! ");
Ket.out.println("The expected form would be\n\t&f (x)");
Ket.out.println("while the actual form is\n\t" + branch + "\n");
return null;
}
}
return argument;
}
/**
* Remove all instances of branch'bracket'[args...] while retaining
* child arguments.
*/
public void removeIntermediateBrackets() {
// TODO: Special case: If the root is a single bracket (which
// is never needed), read it as lisp notation?
Vector<Branch> brackets = getBranchVector(false, Function.BRACKET);
for (Branch branch : brackets) {
if (branch.size()<2) {
branch.removeIntermediate();
} else {
branch.setFunction(Function.MATRIX);
}
}
}
public String toString() {
return tokenList.firstChild().toString();
}
public void removeCommas() {
System.out.println("pre:" + getArgument().toPrefixNotation());
int settings = ArgumentVector.INCLUDE_ROOT; //?
ArgumentVector argumentVector = new ArgumentVector(tokenList, settings);
for (Argument a : argumentVector) {
if (a.getState()==Symbol.COMMA) {
a.remove();
}
}
System.out.println("post:" + getArgument().toPrefixNotation());
}
/**
* When recognizing functions like vectors, you are left with an inner
* branch with the rest of the arguments. But this appears as another
* bracket and would then be interpreted as a prefix function. To
* avoid this, the intermediate bracket is removed.
*/
public void ignoreSuccessiveArgs(KnownArguments knownArguments) {
System.out.println(" --- ignoreSuccessiveArgs --- ");
Vector<Branch> brackets = getBranchVector(true);
for (Branch branch : brackets) { // (f x y) -> f(x,y)
System.out.println();
Branch parent = branch.getParentBranch();
boolean test = false;
//- test |= parent!=null && parent.getFunction()==Function.VECTOR;
//- test |= parent!=null && parent.getFunction()==Function.CLJ_VECTOR;
if (parent==null) continue;
if (parent.getFunction()==null) continue;
Vector<SymbolicFunction> s = knownArguments.getSortedSymbolicFunctions();
if ( ! parent.getFunction().isIn(s) ) continue;
test = parent!=null && parent.getFunction().isIn(knownArguments.getSortedSymbolicFunctions());
if (test) { //-
//+ if (parent!=null && parent.getFunction().isIn(knownArguments.getSortedSymbolicFunctions())) { // HACK
System.out.println("[flattening '"+branch+"']");
branch.removeIntermediate();
}
}
}
public void recognizeCljFunctions(KnownArguments knownArguments) {
System.out.println(" --- recognizeCljFunctions --- ");
Vector<Branch> brackets = getBranchVector(true);
for (Branch branch : brackets) { // (f x y) -> f(x,y)
System.out.println();
/*-
Branch parent = branch.getParentBranch();
if (parent!=null && parent.getFunction()==Function.VECTOR) {
System.out.println("[Already parsed]");
continue;
}
*/
//- System.out.println("next = " + branch + ", PARENT=" + (parent!=null?parent.getFunction()==Function.VECTOR:"."); // TODO: Generalize.
if (branch.size()==0) continue;
System.out.println("[valid size]");
if (branch.getFunction()==null) {
System.out.println("[null]");
} else if (branch.getFunction()==Function.BRACKET) {
System.out.println("[bracket]");
} else if (branch.getFunction()==Function.COMMA) {
System.out.println("[comma]");
} else {
System.out.println("skip: " + branch.getFunction());
continue;
}
State state = branch.firstChild().getState();
if (state==null) {
continue;
} else if (state instanceof Word) {
System.out.println("[found a state! '"+state+"']");
} else {
System.out.println("[ignoring non word state '"+state+"']");
continue;
}
Function function = knownArguments.stateToFunction(state);
if (function==null) {
System.out.println("[ignore function]");
continue;
}
branch.setFunction(function);
branch.removeChild(0);
}
}
}