Using the JEP package of classes in your project is simple. The following steps will get you started quickly.
org.nfunk.jep.JEP myParser = new org.nfunk.jep.JEP();
myParser.addStandardFunctions(); myParser.addStandardConstants();
myParser.addVariable("x", 0);
myParser.parseExpression(ExpressionString); result = myParser.getValue();
The code of the sample applets provide more extensive look at how the parser methods are used.
Three methods for evaluating an expression are available:
The first two methods call getValueAsObject()
internally, and perform the necessary conversions into either a double
value, or a Complex
object.
Errors can occur both while parsing an expression and while evaluating an
expression. The hasError()
method reports whether an error has occured during the most recent action
(either parsing or evaluation). If the result is true
, you can
then use getErrorInfo()
to obtain further information on the errors that have occured.
You can enable the implicit multiplication option with setImplicitMul(true). The default setting is false (no implicit multiplication).
Implicit multiplication allows expressions such as "2 x" to be interpreted as "2*x". Note that a space is required between two variables for them to be interpreted as being multiplied. The same holds for a variable followed by a number. For example "y 3" is interpreted as "y*3", but "y3" is interpreted as a single variable with the name y3. If a variable is preceded by a number, no space is required between them for implicit multiplication to come in effect.
To enable parsing of undeclared variables, use setAllowUndeclared(true). The default setting is false (undeclared variables are not allowed).
If you do not know what variable names may occur in the expression before
parsing it, you can use setAllowUndeclared(true)
. With this option
enabled, it is not necessary to add variables to the parser before parsing
an expression. If a new variable is found while parsing, it is automatically
added to the symbol table. See Obtaining a list
of variables to read about how to access these variables.
While parsing an expression with undeclared variables allowed, all A list of all the variables and constants that have been added to the parser, can be obtained with the getSymbolTable() method.
This method is most useful when the undeclared variables option is enabled.
After an expression has been parsed, a list of all variables occurring in
that expression can be obtained using the getSymbolTable()
method.
The return value is a SymbolTable object. Note that SymbolTable extends Hashtable.
If you want to use complex numbers in your expression, you can call addComplex() after creating the parser object. This will add the imaginary unit as constant i. Two parser functions re() and im() are also added and can be used to obtain the real and imaginary components of complex numbers. You will need to import the org.nfunk.jep.type.Complex class to be able to manipulate complex values from expressions.
By using the imaginary unit constant i, you can work with complex numbers in your expressions. A sample complex expression would be (1+2*i)^3. Currently the (re, im) notation is not supported.
To obtain a complex value from an expression, you must use the getComplexValue() function. It will evaluate the expression and return the result as a Complex object. Note that the class used internally for Complex numbers is also used for returning the value.
Adding a complex variable or constant to the parser before evaluating an expression can be done with addVariable(String name, double re, double im). It takes three parameters: the name of the variable as string, the real component, and the imaginary component.
Vectors are ordered sets of Double elements. A vector is a list of values, separated by commas, and enclosed by square brackets. An example expression involving a vector is:
[3, 4, 5]*2
It would be evaluated as [6, 8, 10] by JEP. To add a vector as variable, use the addVariable(String name, Object value) method. If the result of an expression is a vector, it can be obtained by calling the getValueAsObject() function.
Strings can be entered in an expression by using double quotes. They can be concatenated with the + operator and compared with the == and != relational operators. A sample expression involving the string type is "foo" + "bar" == "foobar", which would be evaluated by JEP as 1 (true).
To add a string as a variable, use the addVariable(String name, Object value) method. If the result of an expression is a string, it can be obtained by calling the getValueAsObject() function.
In most cases, you will only need to work with the few built in types that JEP supplies (Double, Complex, Vector, String). But suppose you want to evaluate expressions that involve other types. This is possible by using the addVariableAsObject(String name, Object value) method to add variables of any type. The only place where the type of a variable matters, is in the function classes.
When an expression is evaluated, values are operated on with the classes in the function package. These include the operators (such as Add and Subtract), as well as the functions (such as Sine and Cosine). Without making modifications to the source code, only the default types are handled with these classes. So, in order to be able to handle your own types, you will need to modify theses classes, or make your own function classes as described in the custom functions section.
The getTopNode() method can be used to get the expression tree after parsing an expression. This will be useful if you want to do more than just evaluate the expressions you parse. For example, you may want to determine the derivative of an expression. In order to be able to this, you will need direct access to the expression tree.
The expression tree consists of nodes. Each of the nodes in the parse tree is an object of one of the following types:
All of them extend the SimpleNode class (which implements the Node interface). Binary operators (+,-,*,/...) and functions are ASTFunNodes. The type of operator (the function class) is stored in the pfmc member, and as a string in the name member. Use the getPFMC() and getName() methods to access these members.
To traverse the expression tree you can use a visitor class (ParserDumpVisitor is an example class used to print out all the nodes). Look at the EvaluatorVisitor class to see how expressions are evaluated using the Visitor design pattern.
By default when an expression such as "1+2" is parsed, the constants "1" and "2" are created internally as Double objects. In most cases this is fine, but in some cases you may want to use custom classes for representing numbers.
This is made possible through creating a number class that implements the
NumberFactory
interface. It includes one method called createNumber(String
value), which should return an object initialized to the value of the
parameter. You can load your custom number factory with the JEP constructor
JEP(boolean traverse_in, Boolean allowUndeclared_in, Boolean implicitMul_in,
NumberFactory numberFactory_in)
.
The custom number objects need to be handled by custom functions which you can create by following the instructions on the Custom Functions page.