Jep can print textual representation of equations using the
PrintVisitor class. The Jep class
has a number of methods to enable printing:
void print()
Print the last parsed expression to System.out.
void print(Node node)
Print an expression to System.out.
void print(Node node, PrintStream out)
Print an expression to a given stream.
void println()
Print the last parsed expression to System.out with a new line.
void println(Node node)
Print an expression to System.out with a new line.
void println(Node node, PrintStream out)
Print an expression to a given stream with a newline.
String toString(Node node)
Returns a string representation of an expression.
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.
The PrintVisitor offers a number of methods to customise the output.
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);
(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).
(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.
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.
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}
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.