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); }