{"id":26154520,"url":"https://github.com/datacanvasio/expretau","last_synced_at":"2026-04-19T08:32:09.625Z","repository":{"id":57732925,"uuid":"315254627","full_name":"DataCanvasIO/expretau","owner":"DataCanvasIO","description":"ExpreTau is a simple expression engine written in Java, of which the runtime codes are splitted from parsing and compiling codes.","archived":false,"fork":false,"pushed_at":"2021-02-26T10:46:45.000Z","size":179,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2023-09-21T03:31:55.205Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DataCanvasIO.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-11-23T08:55:19.000Z","updated_at":"2021-06-04T13:40:33.000Z","dependencies_parsed_at":"2022-09-26T22:11:12.379Z","dependency_job_id":null,"html_url":"https://github.com/DataCanvasIO/expretau","commit_stats":null,"previous_names":[],"tags_count":2,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DataCanvasIO%2Fexpretau","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DataCanvasIO%2Fexpretau/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DataCanvasIO%2Fexpretau/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DataCanvasIO%2Fexpretau/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DataCanvasIO","download_url":"https://codeload.github.com/DataCanvasIO/expretau/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243000151,"owners_count":20219627,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-11T08:30:04.560Z","updated_at":"2026-04-19T08:32:09.582Z","avatar_url":"https://github.com/DataCanvasIO.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ExpreTau\n\n![Build with Maven](https://github.com/DataCanvasIO/expretau/workflows/Build%20with%20Maven/badge.svg)\n\nExpreTau is a simple expression engine written in Java, of which the runtime codes are split from parsing and compiling\ncodes. The classes in runtime are serializable so that they are suitable for runtime of distributed computing system,\nlike [Apache Flink](https://flink.apache.org/).\n\nExpreTau is just \"Expression\" and \"TAU\". The idea of \"TAU\" is coming\nfrom [The Tau Manifesto](https://tauday.com/tau-manifesto).\n\n## Getting Started\n\n```java\npublic class MyClass {\n    public Object calc() {\n        // The original expression string.\n        String exprString = \"(1 + 2) * (5 - (3 + 4))\";\n        // parse it into an Expr object.\n        Expr expr = ExpretauCompiler.INS.parse(exprString);\n        // Compile in a CompileContext (can be null without variables in the expression) and get an RtExpr object.\n        RtExpr rtExpr = expr.compileIn(null);\n        // Evaluate it in an EvalContext (can be null without variables in the expression).\n        return rtExpr.eval(null);\n    }\n}\n```\n\nThe `RtExpr` object can do `eval` multiple times in different `EvalContext` after generated by `compileIn`.\n\nModule `expretau_console` can be simply used as a command line calculator, which is based on ExpreTau.\n\n## Dependencies\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003cdependencies\u003e\n    \u003c!-- Required if you want to do parsing and compiling --\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eio.github.datacanvasio.expretau\u003c/groupId\u003e\n        \u003cartifactId\u003eexpretau-parser\u003c/artifactId\u003e\n        \u003cversion\u003e1.0.0\u003c/version\u003e\n    \u003c/dependency\u003e\n\n    \u003c!-- Required if you want to do evaluating --\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eio.github.datacanvasio.expretau\u003c/groupId\u003e\n        \u003cartifactId\u003eexpretau-runtime\u003c/artifactId\u003e\n        \u003cversion\u003e1.0.0\u003c/version\u003e\n    \u003c/dependency\u003e\n\u003c/dependencies\u003e\n```\n\n## Variables and Context\n\nVariables can be used in expressions, but a `CompileContext` must be provided to define the types of variables.\n\nA [JSON Schema](http://json-schema.org/) definition can be used as a source of `CompileContext`. For example (in YAML\nformat for simplicity, but you can surely use JSON format)\n\n```yaml\ntype: object\nproperties:\n    a:\n        type: integer\n    b:\n        type: number\n    c:\n        type: boolean\n    d:\n        type: string\nadditionalProperties: false\n```\n\nwhere variables `a`, `b`, `c`, `d` are defined with specified types. The a `RtExpr` can be compiled as following,\n\n```java\npublic class MyClass {\n    public RtExpr compile(String jsonSchemaInYamlFormat) {\n        // jsonSchemaInYamlFormat can be a String/InputStream contains the JSON Schema definition.\n        RtSchemaRoot schemaRoot = SchemaParser.YAML.parse(jsonSchemaInYamlFormat);\n        Expr expr = ExpretauCompiler.INS.parse(\"a + b\");\n        return expr.compileIn(schemaRoot.getSchema());\n    }\n}\n```\n\nYou can also create a parser with the `RtSchemaRoot` object to parse a JSON/YAML source into a `EvalContext` object.\n\n```java\npublic class MyClass {\n    public Object calc(RtSchemaRoot schemaRoot, RtExpr rtExpr) {\n        DataParser parser = DataParser.yaml().schema(schemaRoot);\n        // RtData implements EvalContext\n        RtData data = parser.parse(\"{a: 2, b: 3.0, c: true, d: foo}\");\n        // The result should be a Double 5.0\n        return rtExpr.eval(data);\n    }\n}\n```\n\n## Nested Context\n\nIn a JSON Schema definition, objects and arrays can be nested into each other, for example,\n\n```yaml\ntype: object\nproperties:\n    a:\n        type: object\n        properties:\n            b:\n                type: number\n            c:\n                type: boolean\n        additionalProperties: false\n    d:\n        type: array\n        items:\n            - type: integer\n            - type: string\n        additionalItems: false\nadditionalProperties: false\n```\n\nIn this context, you can use `a.b` and `a.c` to access the `number` and the `boolean` variables. The syntax looks the\nsame as map index, but they are really separate variables. On the contrary, `a` is not an existing variable. Also, you\ncan use `d[0]` and `d[1]` to access the `integer` and the `string` variables and `d` is not an existing variable.\n\nThe `additionalProperties` and `additionalItems` are crucial. If they are set to `true` (which is default in JSON Schema\nSpecification), `a` becomes a variable of `Map` type and `d` of `List` type, which can be accessed by the same syntax,\nbut the operating is a runtime indexing, not a var identifying in compiling time.\n\nThe special variable `$` can be used to access the whole context, so `$.a` is the same as `a`. `$` is useful for a\ncontext with an array as root. The parser also looks on `a.b` as `a['b']`, so the syntax to access variables is much\nlike JSONPath.\n\n## Operators\n\n| Category       | Operator   | Associativity |\n| :------------- | :--------- | :------------ |\n| Parenthesis    | `( )`      |               |\n| Function Call  | `( )`      | Left to right |\n| Name Index     | `.`        | Left to right |\n| Array Index    | `[ ]`      | Left to right |\n| Unary          | `+` `-`    | Right to left |\n| Multiplicative | `*` `/`    | Left to right |\n| Additive       | `+` `-`    | Left to right |\n| Relational     | `\u003c` `\u003c=` `\u003e` `\u003e=` `==` `=` `!=` `\u003c\u003e` | Left to right |\n| String         | `startsWith` `endsWith` `contains` `matches` | Left to right |\n| Logical NOT    | `!` `not`  | Left to right |\n| Logical AND    | `\u0026\u0026` `and` | Left to right |\n| Logical OR     | \u003ccode\u003e\u0026#x7c;\u0026#x7c;\u003c/code\u003e `or` | Left to right |\n\n## Data Types\n\n| Type Name    | JSON Schema Type | Hosting Java Type      | Literal in Expression |\n| :----------- | :--------------- | :--------------------- | :-------------------- |\n| Integer      |                  | java.lang.Integer      |                       |\n| Long         | integer          | java.lang.Long         | `0` `20` `-375`       |\n| Double       | number           | java.lang.Double       | `2.0` `-6.28` `3e-4`  |\n| Boolean      | boolean          | java.lang.Boolean      | `true` `false`        |\n| String       | string           | java.lang.String       | `\"hello\"` `'world'`   |\n| Decimal      |                  | java.math.BigDecimal   |\n| Time         |                  | java.util.Date         |\n| IntegerArray |                  | java.lang.Integer[]    |\n| LongArray    | array            | java.lang.Long[]       |\n| DoubleArray  | array            | java.lang.Double[]     |\n| BooleanArray | array            | java.lang.Boolean[]    |\n| StringArray  | array            | java.lang.String[]     |\n| DecimalArray |                  | java.math.BigDecimal[] |\n| ObjectArray  | array            | java.lang.Object[]     |\n| List         | array            | java.util.List         |\n| Map          | object           | java.util.Map          |\n| Object       | object           | java.lang.Object       |\n\nFor JSON Schema of type `array`, the final type is determined as in the following table.\n\n| Value of `additionalItems` | Value of `items.type` | Type Name            |\n| :------------------------- | :-------------------- | :------------------- |\n| `false`                    |                       | split into variables |\n| `true`                     | integer               | LongArray            |\n| `true`                     | number                | DoubleArray          |\n| `true`                     | boolean               | BooleanArray         |\n| `true`                     | string                | StringArray          |\n| `true`                     | object                | ObjectArray          |\n| `true`                     |                       | List                 |\n\nFor JSON Schema of type `object`, the final type is determined as in the following table.\n\n| Value of `additionalProperties` | Value of `properties` | Type Name            |\n| :------------------------------ | :-------------------- | :------------------- |\n| `false`                         |                       | split into variables |\n| `true`                          | not null              | Map                  |\n| `true`                          | null                  | Object               |\n\n**NOTE**: Some types cannot be written literally in expressions, but they do exist in the engine. They can be got by\npre-defined constants, variables or intermediate results.\n\n## Constants\n\n| Name | Value                   |\n| :--- | ----------------------: |\n| TAU  | 6.283185307179586476925 |\n| E    | 2.7182818284590452354   |\n\nThere is not \"3.14159265\" but \"TAU\". :smile:\n\n## Functions\n\n### Mathematical\n\nSee [Math (Java Platform SE 8)](https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html).\n\n| Function  | Java function based on | Description |\n| :-------- | :--------------------- | :---------- |\n| `abs(x)`  | `java.lang.Math.abs`   |             |\n| `sin(x)`  | `java.lang.Math.sin`   |             |\n| `cos(x)`  | `java.lang.Math.cos`   |             |\n| `tan(x)`  | `java.lang.Math.tan`   |             |\n| `asin(x)` | `java.lang.Math.asin`  |             |\n| `acos(x)` | `java.lang.Math.acos`  |             |\n| `atan(x)` | `java.lang.Math.atan`  |             |\n| `cosh(x)` | `java.lang.Math.cosh`  |             |\n| `sinh(x)` | `java.lang.Math.sinh`  |             |\n| `tanh(x)` | `java.lang.Math.tanh`  |             |\n| `log(x)`  | `java.lang.Math.log`   |             |\n| `exp(x)`  | `java.lang.Math.exp`   |             |\n\n### Type conversion\n\n| Function         | Java function based on | Description            |\n| :--------------- | :--------------------- | :--------------------- |\n| `int(x)`         |                        | Convert `x` to Integer |\n| `long(x)`        |                        | Convert `x` to Long    |\n| `double(x)`      |                        | Convert `x` to Double  |\n| `decimal(x)`     |                        | Convert `x` to Decimal |\n| `string(x)`      |                        | Convert `x` to String  |\n| `string(x, fmt)` |                        | Convert `x` to String, `x` is a Time  |\n| `time(x)`        |                        | Convert `x` to Time    |\n| `time(x, fmt)`   |                        | Convert `x` to Time, `x` is a String    |\n\n### String\n\nSee [String (Java Platform SE 8)](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html).\n\n| Function             | Java function based on | Description |\n| :------------------- | :--------------------- | :---------- |\n| `toLowerCase(x)`     | `String::toLowerCase`  |             |\n| `toUpperCase(x)`     | `String::toUpperCase`  |             |\n| `trim(x)`            | `String::trim`         |             |\n| `replace(x, a, b)`   | `String::replace`      |             |\n| `substring(x, s)`    | `String::substring`    |             |\n| `substring(x, s, e)` | `String::substring`    |             |\n\n## User defined functions\n\nIt is simple to add an user defined function to ExpreTau.\n\nFirst, define a class like\n\n```java\npublic class HelloOp extends RtFun {\n    private static final long serialVersionUID = -8060697833705004059L;\n\n    protected HelloOp(@Nonnull RtExpr[] paras) {\n        super(paras);\n    }\n\n    @Override\n    protected Object fun(@Nonnull Object[] values) {\n        return \"Hello \" + values[0];\n    }\n\n    @Override\n    public int typeCode() {\n        return TypeCode.STRING;\n    }\n}\n```\n\nThen register it to the `FunFactory`\n\n```java\npublic class TestUdf() {\n    @Test\n    public void test() {\n        FunFactory.INS.registerUdf(\"hello\", HelloOp::new);\n        // Now you can use the `hello` function\n        Expr expr = ExpretauCompiler.INS.parse(\"hello('world')\");\n        RtExpr rtExpr = expr.compileIn(null);\n        System.out.println(rtExpr.eval(null));\n    }\n}\n```\n\n## Modules\n\n| Module | Description | Documentation |\n| :----- | :---------- | :------------ |\n| `expretau_annotations` | An annotation processor to help generating some runtime code. This module is not required to using ExpreTau library. | [![javadoc](https://javadoc.io/badge2/io.github.datacanvasio.expretau/expretau-annotations/javadoc.svg)](https://javadoc.io/doc/io.github.datacanvasio.expretau/expretau-annotations) |\n| `expretau_console` | An command line application to parse and evaluate expressions inputted from console. | [![javadoc](https://javadoc.io/badge2/io.github.datacanvasio.expretau/expretau-console/javadoc.svg)](https://javadoc.io/doc/io.github.datacanvasio.expretau/expretau-console) |\n| `expretau_parser` | The ExpreTau parser, required to parse expression string. | [![javadoc](https://javadoc.io/badge2/io.github.datacanvasio.expretau/expretau-parser/javadoc.svg)](https://javadoc.io/doc/io.github.datacanvasio.expretau/expretau-parser) |\n| `expretau_runtime` | The ExpreTau runtime, required to evaluate the compiled runtime object. | [![javadoc](https://javadoc.io/badge2/io.github.datacanvasio.expretau/expretau-runtime/javadoc.svg)](https://javadoc.io/doc/io.github.datacanvasio.expretau/expretau-runtime) |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatacanvasio%2Fexpretau","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdatacanvasio%2Fexpretau","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatacanvasio%2Fexpretau/lists"}