Other advanced features

The com.singularsys.jep.misc and com.singularsys.jep.walkers packages contain various other optional advanced features.

Bitwise and java operators

The BitwiseOperatorTable adds a set of bitwise operators: bitwise AND a & b, bitwise OR a | b, 1's complement ~a, XOR a ^ b, Left shift a >> b, Right shift a << b Right shift with zero extension: a <<< b

The JavaOperatorTable adds the bitwise operators and the full set of java operators x?y:z, ++x, --x, x++, x--, x+=y, x-=y, x*=y, x/=y, x%=y, x&=y, x|=y, x^=y, x<<=y, x>>=y, x<<<=y.

Line Numbering

The com.singularsys.jep.misc.lineNumbering package adds to add line and column number information to nodes which can be used for error detection. It can be set up with:

Jep jep = new Jep(
  new StandardConfigurableParser(),
  new LineNumberingNodeFactory(),
  new LineNumberingShuntingYard.LineNumberGrammarParserFactory());

The line and column number of each node can be found with

int line = (Integer) node.getHook(LineNumberingNodeFactory.Numbering.LINENUMBER);
int col = (Integer) node.getHook(LineNumberingNodeFactory.Numbering.COLUMNNUMBER);

Null Wrapped Functions

The com.singularsys.jep.misc.nullwrapper package allows functions to handle null in the same way as SQL's NULL. null will be treated as unknown and most operations involving null will return null. So sin(null) returns null and null + 5 returns null. The logical and and or operations follow slightly different rules with null || true giving true and null && false giving false.

The package works by using the Decorator pattern which takes and existing PostfixMathCommand and wraps it in another class which handles null correctly. The NullWrappedFunctionTable and NullWrappedOperatorTable take existing FunctionTable and OperatorTable and wrap each function and operator in them.

To set up this functionality use

jep.setComponent(new NullWrappedOperatorTable((OperatorTable2) jep.getOperatorTable(),true));
jep.setComponent(new NullWrappedFunctionTable(jep.getFunctionTable()));
jep.setComponent(new StandardConfigurableParser());
((FastEvaluator) jep.getEvaluator()).setTrapNullValues(false);

This also adds a null-safe equals operator <=> for which null<=>null is true. If you do not need this operator you can use the standard parser and omit thirds line setting the parser.

Tree traversal

Various methods for tree traversal provides by the com.singularsys.jep.walkers package are discussed in the manipulating expressions page. These include: the TreeAnalyzer which can calculate statistics about an expression, and the SubstitutionVisitor which can substitute one expression into another.

Functions

The com.singularsys.jep.misc.functions packages contain various other functions, see Optional functions for details.

Bound variables

The com.singularsys.jep.misc.boundvariable packages allows a direct binding between Jep variables and java objects so that when the jep variable is changed the corresponding object field also changed and vice versa.

The simplest way to use this is to use the FieldVariableBinding to bind a jep variable to a specific field of an object using the reflection mechanism. First set up an object with publically accessable fields.

public class MyObj {
    public Double a;
    public double b;
}

Then set up Jep using the BoundVariableFactory

// Create Jep with a variable factory which allows bound variables
Jep jep = new Jep(new BoundVariableFactory());
// Create an object, with a Double field a and a double field b
MyObj obj = new MyObj();
obj.a = new Double(3.0);
obj.b = 5.0;
// Create binding objects for the two fields
FieldVariableBinding bindA = new FieldVariableBinding(obj,"a");
FieldVariableBinding bindB = new FieldVariableBinding(obj,"b");
// Create variables bound to these fields
jep.addVariable("a", bindA);
jep.addVariable("a", bindB);

These variables can then be used as normal in Jep, and changes will affect the field values.

// Parse an equation using these values
Node n = jep.parse("b=4*a");
Object res = jep.evaluate(n);
System.out.println("Result is "+res+" value of field b is "+obj.b);

// setting the value of objects field alters the jep value
obj.a = 7.0;
res = jep.evaluate(n);
System.out.println("Result is "+res+" value of field b is "+obj.b);

The MutableDouble provides a simple class with a single Double value which can be bound to a Jep variable.

Other way of mapping Jep variables to java objects can be created by implementing the VariableBinding interface and the VariableBindingMapper interface allows variable names to be translated to specific variables. For instance the ChainedObjectVariableBindingMapper creates VariableBinding objects by translating the variable name into a chain of object references so "foo.a.b" might be translated into a reference to field "b" of the object at field "a" of an object.