{"id":9,"date":"2014-02-01T14:16:53","date_gmt":"2014-02-01T12:16:53","guid":{"rendered":"http:\/\/dekarlab.de\/wp\/?p=9"},"modified":"2020-05-23T15:38:58","modified_gmt":"2020-05-23T13:38:58","slug":"simple-grammar-parser","status":"publish","type":"post","link":"https:\/\/dekarlab.de\/wp\/?p=9","title":{"rendered":"Simple Grammar Parser"},"content":{"rendered":"<p>Sometimes there is a need to add scripting to your java application. The Parser for Simple Grammar can help you to evaluate simple expressions, like: AND, OR, +, -, *, \/.<br \/>\n<!--more--><br \/>\nIt supports three common data types: String, Number, Boolean. Moreover, it is possible to add custom functions and variables to your expressions.<\/p>\n<p>The code for parser can be downloaded here:\u00a0<b><a href=\"https:\/\/github.com\/dekarlab\/simplegr\">GitHub Repository<\/a><\/b><\/p>\n<p>The common example is calculator, where we enter the expression, computer calculates it and returns the answer. We can start with simple expression:<\/p>\n<p><code><br \/>\nIF(Auto==\"Audi\" OR Auto==\"BMW\", \"German\", \"Unknown\")<br \/>\n<\/code><\/p>\n<p>If we evaluate this expression, we can recieve two answers &#8220;German&#8221; or &#8220;Unknown&#8221; depending on the value in Variable Auto. In this expression we have the following elements:<\/p>\n<p>Function: <b>IF<\/b><br \/>\nwith three parameters, which are separated by commas:<br \/>\n1. Auto==&#8221;Audi&#8221; OR Auto==&#8221;BMW&#8221;<br \/>\n2. &#8220;German&#8221;<br \/>\n3. &#8220;Unknown&#8221;<\/p>\n<p>The first parameter is a complex expression of type Boolean, since we can get the TRUE or FALSE.<\/p>\n<p>The second and the third parameters are String Literals.<\/p>\n<p>The java application, which parses this expression can be written as follows:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n\/\/The list of functions\r\nFunctionList functions = new FunctionList();\r\n\/\/The list of variables\r\nVariableList variables = new VariableList();\r\n\/\/Our expression as String\r\nString expr = &quot;IF(Auto==\\&quot;Audi\\&quot; OR Auto==\\&quot;BMW\\&quot;,\r\n    \\&quot;German\\&quot;, \\&quot;Unknown\\&quot;)&quot;;\r\n\/\/We create new parser and as an input parameter we add expression\r\nSimpleGrParser parser = new SimpleGrParser(new StringReader(expr));\r\n\/\/We parse expression\r\nparser.parse();\r\n\/\/We get the root of the expression tree\r\nExpression root = (Expression) parser.rootNode();\r\n\/\/We evaluate expression as String\r\nString output = root.evaluateAsString(variables, functions);\r\n\/\/Output of the result\r\nSystem.out.println(output);\r\n<\/pre>\n<p>Function List and Variable List contains our functions and variables. But what is the logic of our function (IF) and the value of our variable (Auto). We describe this directly in the new classes, which are shown below.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npublic class FunctionList implements FunctionHandler {\r\n@Override\r\npublic String getValueAsString(String name, Expression[] params,\r\nVariableValueHandler variables) throws Exception {\r\nif (name.equals(&quot;IF&quot;)) {\r\nif (params[0].evaluateAsBoolean(variables, this)) {\r\nreturn params[1].evaluateAsString(variables, this);\r\n} else {\r\nreturn params[2].evaluateAsString(variables, this);\r\n}\r\n}\r\nreturn null;\r\n}\r\n@Override\r\npublic Boolean getValueAsBoolean(String name, Expression[] params,\r\nVariableValueHandler variables) throws Exception {\r\nreturn null;\r\n}\r\n@Override\r\npublic Double getValueAsNumber(String name, Expression[] params,\r\nVariableValueHandler variables) throws Exception {\r\nreturn null;\r\n}\r\n@Override\r\npublic Class&amp;lt;?&amp;gt; getReturnType(String name) {\r\nif (name.equals(&quot;IF&quot;)) {\r\nreturn String.class;\r\n}\r\nreturn null;\r\n}\r\n}\r\npublic class VariableList implements VariableValueHandler {\r\n@Override\r\npublic String getValueAsString(String name) {\r\nif(name.equals(&quot;Auto&quot;)) {\r\nreturn &quot;Audi&quot;;\r\n}\r\nreturn null;\r\n}\r\n@Override\r\npublic Boolean getValueAsBoolean(String name) {\r\nreturn null;\r\n}\r\n@Override\r\npublic Double getValueAsNumber(String name) {\r\nreturn null;\r\n}\r\n@Override\r\npublic Class&amp;lt;?&amp;gt; getType(String name) {\r\nif(name.equals(&quot;Auto&quot;)) {\r\nreturn String.class;\r\n}\r\nreturn null;\r\n}\r\n}\r\n<\/pre>\n<p>The parser is written using JAVACC. This software helps to define own grammar, to parse it, and to construct the expression tree for further evaluation.<\/p>\n<p>For our simple expression we describe the grammar and using JAVACC we build the following expression tree of java objects:<\/p>\n<p><code><br \/>\nFuncExpr=\"IF\"<br \/>\nBoolOrExpr=\"OR\" (First Parameter in Function)<br \/>\nBoolEqualsExpr=\"==\"<br \/>\nVariable=\"Auto\"<br \/>\nStringLiteral=\"Audi\"<br \/>\nBoolEqualsExpr=\"==\"<br \/>\nVariable=\"Auto\"<br \/>\nStringLiteral=\"BMW\"<br \/>\nStringLiteral=\"German\" (Second Parameter in Function)<br \/>\nStringLiteral=\"Unknown\" (Third Parameter in Function)<br \/>\n<\/code><\/p>\n<p>On the next step we need to evaluate this tree. Every object contains functions:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nevaluateAsString();\r\nevaluateAsNumber();\r\nevaluateAsBoolean();\r\n<\/pre>\n<p>By calling of this functions by every object recurcively, starting from IF we receive the result.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Sometimes there is a need to add scripting to your java application. The Parser for Simple Grammar can help you to evaluate simple expressions, like: AND, OR, +, -, *, \/.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0},"categories":[2],"tags":[57,40],"_links":{"self":[{"href":"https:\/\/dekarlab.de\/wp\/index.php?rest_route=\/wp\/v2\/posts\/9"}],"collection":[{"href":"https:\/\/dekarlab.de\/wp\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dekarlab.de\/wp\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dekarlab.de\/wp\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dekarlab.de\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=9"}],"version-history":[{"count":13,"href":"https:\/\/dekarlab.de\/wp\/index.php?rest_route=\/wp\/v2\/posts\/9\/revisions"}],"predecessor-version":[{"id":61,"href":"https:\/\/dekarlab.de\/wp\/index.php?rest_route=\/wp\/v2\/posts\/9\/revisions\/61"}],"wp:attachment":[{"href":"https:\/\/dekarlab.de\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=9"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dekarlab.de\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=9"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dekarlab.de\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=9"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}