The com.singularsys.jep.misc and com.singularsys.jep.walkers packages contain various other optional advanced features.
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
.
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);
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.
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.
The com.singularsys.jep.misc.functions packages contain various other functions, see Optional functions for details.
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 publicly accessible 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.