Package ket.math.convert

Source Code of ket.math.convert.Interpretation

/*
* 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 ~&lt;address&gt; 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 \&lt;address&gt; 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);
    }
  }


}

TOP

Related Classes of ket.math.convert.Interpretation

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.