GWTJep JavaScript mathematical expression parser/evaluator.
GWTInterop - Jep functions exposed to JavaScript
The GWTInterop module exposes a limited set of Jep functionality so that it can be called directly from JavaScript.
Basic functionality
To use the GWTInterop functionality include the following JavaScript
<script type="text/javascript">
var pageType = "Interop";
window.jepModuleLoaded = function() {
jep = new Jep();
}
</script>
<script type="text/javascript" src="gwtjep/gwtjep.nocache.js"></script>
The jepModuleLoaded function is called once the module is loaded,
which in turn creates a new Jep object jep.
Alternatively just include the line
<script type="text/javascript" src="gwtjep/gwtjep.nocache.js"></script>
and create a jep instance when needed, using
jep = new Jep();
To parse an expression use
try {
node1 = jep.parse("y = 2 x+3");
} catch(e) {
alert(e);
}
The value can be set with
try {
jep.setVariable("x",5)
} catch(e) {
alert(e);
}
Which can then be evaluated with
try {
result1 = jep.evaluate(node1);
alert(result1);
} catch(e) {
alert(e);
}
And the variable value retrieved with
result2 = jep.getVariableValue("y")
alert(result2);
Forms Example
In this example variable name and values can read from form elements.
First input an expressions and press parse, then set the variable and finally press evaluate.
| Expression | |||
| Result | |||
| Variable | Value | ||
The JavaScript code:
// ensures the jep object created
function checkJep() {
if(typeof jep == "undefined") {
jep = new Jep();
document.getElementById("errOut").value = "jep constructed"
}
else {
document.getElementById("errOut").value = ""
}
}
function reportError(str) {
document.getElementById("errOut").value = str
}
function parse() {
checkJep()
const expr = document.getElementById("expression").value
try {
node1 = jep.parse(expr)
} catch(e) {
reportError(e)
}
}
function eval1() {
checkJep()
try {
let res = jep.evaluate(node1)
document.getElementById("expVal").value = res
} catch(e) { reportError(e) }
}
function setVar1() {
checkJep()
try {
const name = document.getElementById("var1Name").value
const val = document.getElementById("var1Val").valueAsNumber
let res = jep.setVariable(name,val)
} catch(e) { reportError(e) }
}
function var1Changed() {
setVar1();
eval1();
}
function getVar1() {
checkJep()
try {
const name = document.getElementById("var1Name").value
let res = jep.getVariableValue(name)
document.getElementById("var1Val").value = res
} catch(e) { reportError(e) }
}
function setVar2() {
checkJep()
try {
const name = document.getElementById("var2Name").value
const val = document.getElementById("var2Val").value
let res = jep.setVariable(name,Number(val))
} catch(e) { reportError(e) }
}
function getVar2() {
checkJep()
try {
const name = document.getElementById("var2Name").value
let res = jep.getVariableValue(name)
document.getElementById("var2Val").value = res
} catch(e) { reportError(e) }
}
Note the code needs to catch exceptions. Alternative method that do not throw exceptions
are available: jep.parseNE(string), jep.evaluateNE(), jep.setVariableNE().
If these encounter an error the will return null and an internal variable with the message set.
The jep.getErrorMsg() command can be used to retrieve this message. For example
node = jep.parseNE("x-")
if(node == null) {
alert(jep.getErrorMsg())
}
Java source code
Currently only a limited portion of the jep functionality is exposed to JavaScript. This could be expanded
by copying or expanding the com.singularsys.client.GWTInterop class.
The class start with
@JsType(namespace = JsPackage.GLOBAL, name = "Jep")
public class GWTInterop implements EntryPoint {
Jep jep;
/**
* Creates a Jep instance using the StandardConfigurableParser
*/
@JsConstructor
public GWTInterop() {
jep = new Jep(new StandardConfigurableParser());
}
/**
* Standard GWT method called when the module is loaded.
* Calls the onModLoad() native method which in turn calls
* the JavaScript jepModuleLoaded() method.
*/
@Override
@JsIgnore
public void onModuleLoad() {
onModLoad();
}
/**
* Calls the JavaScript jepModuleLoaded() method.
*/
@JsIgnore
protected native void onModLoad() /*-{
$wnd.jepModuleLoaded();
}-*/;
Which sets the JavaScript name of the class, adds a constructor that is made viewable from JavaScript
with the @JsConstructor annotation. The onModuleLoad method is called by the GWT system
when the module is loaded, this calls a native JavaScript method onModLoad() which in turn
calls the JavaScript method jepModuleLoaded() discussed at the top of the page.
A couple of wrapper types tagged with @JsType are used for objects parsed to and from JavaScript
@JsType
public static class GWTNode {
Node node;
GWTNode(Node n) {
node = n;
}
}
@JsType
public static class GWTVariable {
Variable v;
GWTVariable(Variable n) {
v = n;
}
}
Methods visible to JavaScript are tagged with @JsMethod.
/**
* Parse an expression
* @param S expression
* @return root node of parse tree or null on ParseException
* @throws ParseException if an error in parsing
*/
@JsMethod
public GWTNode parse(String S) throws ParseException {
errorMsg="";
Node res = jep.parse(S);
return new GWTNode(res);
}