Printing

Jep can print textual representation of equations using the PrintVisitor class. The Jep class has a number of methods to enable printing:

It can also create a string representation of an expression using

The com.singularsys.jep.PrintVisitor class is a Jep component that handles printing and conversion to strings. It has all the above methods plus a number of other methods to control the output.

Customisation

The PrintVisitor offers a number of methods to customise the output.

Number formatting
The setNumberFormat(NumberFormat) method sets the format for printing numbers. A useful format is a DecimalFormat with minimum fraction digits set to zero. This makes expressions like 3 x^2, print nicely without unnecessary decimal places.
DecimalFormat fmt = new DecimalFormat();
fmt.setMinimumFractionDigits(0);
fmt.setMaximumFractionDigits(15);
jep.getPrintVisitor().setNumberFormat(fmt);
Complex numbers
The default behaviour is to print complex numbers as (2.0, 0.25). If setMode(PrintVisitor.COMPLEX_I, true) is called then complex numbers are printed as 2.0+0.25 i. The exact format displayed can be set using the message properties see localization and Complex.toString(boolean,boolean).
Brackets
The default behaviour is to try to minimising the number of brackets used. With associative operators, like addition and multiplication, brackets are omitted, so (a+b)+c and a+(b+c) are both printed as a+b+c.

If setMode(PrintVisitor.FULL_BRACKET,true) is called then brackets are always printed around sub expressions, giving an unambiguous representation of the expression tree, so (a+b)+c is printed with brackets.

Brackets are also omitted around some non-associative operators like subtraction, (a-b)-c is printed as a-b-c. This behaviour is controlled by the Operator.BINDING_FOR_PRINT flag. This is set for subtraction but not division by default, so (a/b)/c is printed with brackets rather than the slightly ambiguous a/b/c.

The character used for brackets can be set using the setLBracket(String) and setRBracket(String) methods.

Function
The printing of functions can be customised using the setFunLBracket(String), setFunRBracket(String) and setFunArgSep(String) methods.
Operators
The symbol used to print operators can be set using the Operator.setPrintSymbol(String) method. The Operator.ASSOCIATIVE, Operator.LEFT, Operator.RIGHT flags can be used to control the placement of brackets.

Special rules

Special rules can be added to handle the printing of specific functions or operators. using the addSpecialRule(String,PrintRulesI) and addSpecialRule(Operator,PrintRulesI) methods for functions and operators respectively.

The PrintRulesI interface has a single method append(Node,PrintVisitor) that is called when a match for the function or operator is found. These can use the PrintVisitor.append(String) method to add text to the output and also call other PrintVisitor methods to print sub expressions.

The default printing of lists set using the PrintVisitor.StdListPrintRule PrintRulesI implementation

/** 
 * Prints a list of elements using '[' and ']' as delimiters 
 * and ',' as a separators.
 */
public static final class StdListPrintRule implements PrintRulesI {
    private static final long serialVersionUID = 300L;

    @Override
    public void append(Node node, PrintVisitor pv)
                                      throws JepException {
        pv.append("["); 
        for (int i = 0; i < node.jjtGetNumChildren(); ++i) {
            if (i > 0)
                pv.append(","); 
            pv.visit(node.jjtGetChild(i));
          }
          pv.append("]");
      }
  }

This first prints a [ then loops over the children printing each one using the visit(Node) method which uses the PrintVisitor to print that child. It finally prints a ].

The rule can be added using

pv.addSpecialRule(jep.getOperatorTable().getList(), new StdListPrintRule());

A similar rule, PrintVisitor.StdElePrintRule, is used to print array element access.

LaTeX

A print visitor can be configured to produce partial latex output. The following PrintVisitor prints, pi as \pi fractions as \frac{a}{b} and square roots as \sqrt{x}

. The setNumberFormat method is used to control the number format. Multiplication is printed with a space rather than a '*' using the Operator.setPrintSymbol(String) method.
Jep jep = new Jep();
PrintVisitor latex = new PrintVisitor();
DecimalFormat fmt = new DecimalFormat();
fmt.setMinimumFractionDigits(0);
fmt.setMaximumFractionDigits(15);
latex.setNumberFormat(fmt);
latex.addSpecialVarName("pi", "\\pi");
jep.getOperatorTable().getMultiply().setPrintSymbol(" ");
latex.addSpecialRule(jep.getOperatorTable().getDivide(), new PrintRulesI() {
	private static final long serialVersionUID = 1L;

	@Override
	public void append(Node node, PrintVisitor pv) throws JepException {
		pv.append("\\frac{");
		node.jjtGetChild(0).jjtAccept(pv, null);
		pv.append("}{");
		node.jjtGetChild(1).jjtAccept(pv, null);
		pv.append("}");
		
	}});
latex.addSpecialRule("sqrt", new PrintRulesI() {
	private static final long serialVersionUID = 1L;

	@Override
	public void append(Node node, PrintVisitor pv) throws JepException {
		pv.append("\\sqrt{");
		node.jjtGetChild(0).jjtAccept(pv, null);
		pv.append("}");
		
	}});
jep.reinitializeComponents();
latex.init(jep);

Further examples of build a LaTeX PrintVisitor can be found in the com.singularsys.jeptests.system.LatexTest class.

An alternative method for producing LaTex output is to use the MathML conversion extension and then convert the MathML to LaTeX using an external tool.

top

Examples