Package ket.math.convert

Source Code of ket.math.convert.ArgumentParser

/*
* 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/>
*/

/*
* TODO: You use #, ~ and \ with <number> and how could they be better coordinated?
*
* AMPERSAND
* BRACKET
* COMMA
* TIMES
*/

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 ketUI.Ket;
import ket.Edit;
import ket.math.*;
import ket.Selection;
import ketUI.Clipboard;
import ket.math.Highlight;
import ket.MathCollection;
import ketUI.DocumentManager;
import ket.math.purpose.Word;
import ket.math.purpose.Text;
import ket.math.purpose.IntegerValue;
import ket.math.purpose.VariableToken;
import ket.math.purpose.VariableState;
import ket.math.purpose.CompoundState;
import ket.math.convert.Interpretation;

/**
* This class parses a given string representation of functions, variables etc
* into an instance of Argument that represents part of an equation.
*/
public class ArgumentParser {

  /**
   * If set, print the token list as it is parsed to Ket.out.
   */
  static final boolean DEBUG = false;

  KnownArguments knownArguments;
  Clipboard clipboard;
  MathCollection mathCollection;
  Interpretation interpretation;


  /**
   * This method tokenizes and parses a given string into a mathematical expression.
   */
  public static Argument parseArgument(String argumentString, KnownArguments knownArguments, Clipboard clipboard, MathCollection mathCollection) {
    assert knownArguments==Ket.MATH_ARGUMENTS;
    Branch tokenList = Tokenization.tokenize(argumentString, knownArguments);
    if (tokenList==null) {
      Ket.out.println(" !!! Parsing argument::null token list when parsing !!! ");
      Ket.out.println("\tstring = '" + argumentString + "'");
      return null;
    }
    ArgumentParser equationParser = new ArgumentParser(tokenList, knownArguments, clipboard, mathCollection);
    equationParser.parseAsMath();
    return equationParser.getArgument();
  }

  public static Argument parseClj(String argumentString, Clipboard clipboard, MathCollection mathCollection) {
    System.out.println(" --- parse clj --- ");
    Branch tokenList = Tokenization.tokenize(argumentString, Ket.CLJ_ARGUMENTS);
    if (tokenList==null) {
      Ket.out.println(" !!! Parsing argument::null token list when parsing !!! ");
      Ket.out.println("\tstring = '" + argumentString + "'");
      return null;
    }
    ArgumentParser equationParser = new ArgumentParser(tokenList, Ket.CLJ_ARGUMENTS, clipboard, mathCollection);
    equationParser.parseAsClj();
    return equationParser.getArgument();
  }

  /**
   * Parse raw expressions to avoid hard-coding substitutes while allowing references to 'x' to be replaced with the corresponding variable, x.
   */
  public static Argument parseAs(String argumentString, Argument x) { // "sin(x)", token(q) -> sin(q)
    Argument a = ArgumentParser.parseArgument(argumentString, Ket.KNOWN_ARGUMENTS, null, null);
    if (a==null) return null;
    Edit e = new Edit(a);
    e.substitute(new Token(new Word("x")), x);
    return e.getCurrent();
  }

  /**
   * This method tokenizes and parses a given string into a mathematical expression.
   */
  public static Argument parsePrefix(String prefixString, KnownArguments knownArguments, Clipboard clipboard, MathCollection mathCollection) {
    Branch tokenList = Tokenization.tokenize(prefixString, knownArguments);
    if (tokenList==null) {
      Ket.out.println(" !!! Parsing prefix notation::null token list when parsing !!! ");
      Ket.out.println("\tstring = '" + prefixString + "'");
      return null;
    }
    int open = 0;
    int close = 0;
    for (Argument child : tokenList.getChildren()) {
      if (child.getPurpose()==Symbol.OPEN_BRACKET) {
        open += 1;
      } else if (child.getPurpose()==Symbol.CLOSE_BRACKET) {
        close += 1;
      }
    }
    if (open>close) {
      for (int i=0; i<open-close; i++) {
        tokenList.append(new Token(Symbol.CLOSE_BRACKET));
      }
    }
    ArgumentParser equationParser = new ArgumentParser(tokenList, knownArguments, clipboard, mathCollection);
    //+? try {
      equationParser.processTokenListAsPrefixNotation();
    /*} catch (Exception e) {
      Ket.out.println(" !!! Exception while parsing !!! ");
      //+? Ket.out.println("string= '" + prefixString + "'");
      e.printStackTrace();
      Ket.out.println();
    }*/
    return equationParser.getArgument();
  }

  /**
   * Parse a regular expression string that represents a pattern of arguments.
   */
  public static Argument parseRegex(String regex, KnownArguments knownArguments, Clipboard clipboard, MathCollection mathCollection) {
    // Note: Not yet used.
    Branch tokenList = Tokenization.tokenize(regex, knownArguments);
    if (tokenList==null) {
      Ket.out.println(" !!! Parsing argument regular expression::null token list when parsing !!! ");
      Ket.out.println("\tregex = '" + regex + "'");
      return null;
    }
    ArgumentParser equationParser = new ArgumentParser(tokenList, knownArguments, clipboard, mathCollection);
    equationParser.processRegex();
    return equationParser.getArgument();
  }



  /**
   * Given an argument, return a clone of it and process the clone.
   */
  public static Argument cloneArgument(Argument argument, KnownArguments knownArguments, Clipboard clipboard, MathCollection mathCollection) {
    Argument clone = Argument.cloneArgument(argument);
    Branch tokenList = new Branch(null, clone);
    ArgumentParser equationParser = new ArgumentParser(tokenList, knownArguments, clipboard, mathCollection);
    equationParser.parseAsMath();
    return equationParser.getArgument();
  }


  /**
   * 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.
   * @param knownArguments The known functions, symbols and variables used for reference when parsing.
   * @param clipboard A collection of replacement branches that can substitute for a given equation.
   */
  private ArgumentParser(Branch tokenList,
      KnownArguments knownArguments,
      Clipboard clipboard,
      MathCollection mathCollection) {

    this.knownArguments = knownArguments;
    this.clipboard = clipboard; // can be null
    this.mathCollection = mathCollection;
    this.interpretation = new Interpretation(tokenList);
  }


  private void debug(int x) {
    if (DEBUG) {
      Ket.out.println(" ("+x+"): " + interpretation.debug());
    }
  }

  private void processTokenListAsPrefixNotation() {
               if (DEBUG) Ket.out.println(" --- Process Token List --- ");
               debug(0);
    interpretation.findImplicitSymbols(knownArguments);
               debug(1);
    interpretation.recognizeFunctions(Function.BRACKET, Function.SUBSCRIPT, Function.JOIN);
               debug(2);
    interpretation.removeIntermediateBrackets();
               debug(3);
    interpretation.addNullRoot();
               debug(0);
    interpretation.apply(knownArguments);
               debug(4);
    interpretation.recognizeSubscripts();
               debug(5);
    interpretation.recognizeJoins();
               debug(6);
  }

  private void parseAsClj() {
    interpretation.removeCommas()// Commas are whitespace.
    interpretation.findImplicitSymbols(knownArguments);
    interpretation.recognizeSymbolicFunctions(knownArguments);
    interpretation.removeIntermediateBrackets()// BUG? (rand) -> rand
    interpretation.ignoreSuccessiveArgs(knownArguments); // Having found vectors etc., flatten the (rest args).
    interpretation.recognizeCljFunctions(knownArguments); // BUG: What about '(rand) etc.?
  }

  // Bug: a_b:x -> composition(subscript(a,b),x), but a_b(x) -> subscript(a,composition(b,x)).
  private void parseAsMath() {
    if (DEBUG) Ket.out.println(" --- Process Token List --- ");

    interpretation.findImplicitSymbols(knownArguments);
    //+? interpretation.recognizeFunctions(Function.BRACKET);
    interpretation.recognizeSymbolicFunctions(knownArguments)//( f '(' x ')' -> ?( f , x )
    interpretation.recognizeSubscripts();
    interpretation.recognizeJoins();

    interpretation.breakApart(knownArguments); // <-- new bit
    interpretation.expandFunctionPrefixNotation(knownArguments); //: f:x -> f(x)
    interpretation.makeImplicitFunctionsExplicit(knownArguments); //( ?(f,(x)) -> f(x)
    interpretation.recognizeAmpersandFunctions(knownArguments);
    interpretation.convertTokensToVariables(knownArguments);
    interpretation.removeIntermediateBrackets();

    // TODO: What is needed is an interface that ambiguously refers
    // to either cursor or argument range, and an object of that
    // type may be accessed from selection or mathCollection.
    Highlight highlight = null;
    if (mathCollection!=null) {
      highlight = mathCollection.getHighlight();
      interpretation.substituteFromPreviousEquation(highlight);
      interpretation.substituteFromCurrentSelection(highlight);
      interpretation.substituteClipboard(clipboard);
    }

    interpretation.substituteEquation(highlight);


    interpretation.unknownsToProducts();

    interpretation.recognizeBold();
    interpretation.recognizeNull();

    interpretation.recursiveSubstitute(mathCollection);


    if (DEBUG) Ket.out.println();

  }

  private void processRegex() {

    // TODO: Change to reflect differences between regular expressions and arguments.

    interpretation.findImplicitSymbols(knownArguments);
    interpretation.recognizeSymbolicFunctions(knownArguments);
    interpretation.recognizeSubscripts();
    interpretation.recognizeJoins();

    interpretation.expandFunctionPrefixNotation(knownArguments);
    interpretation.makeImplicitFunctionsExplicit(knownArguments);
    interpretation.recognizeAmpersandFunctions(knownArguments);
    interpretation.convertTokensToVariables(knownArguments);
    interpretation.removeIntermediateBrackets();

    // TODO: What is needed is an interface that ambiguously refers
    // to either cursor or argument range, and an object of that
    // type may be accessed from selection or mathCollection.
    Highlight highlight = null;
    if (mathCollection!=null) {
      highlight = mathCollection.getHighlight();
      interpretation.substituteFromPreviousEquation(highlight);
      interpretation.substituteFromCurrentSelection(highlight);
      interpretation.substituteClipboard(clipboard);
    }
    interpretation.substituteEquation(highlight);
  }

  public Argument getArgument() {
    return interpretation.getArgument();
  }

}
TOP

Related Classes of ket.math.convert.ArgumentParser

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.