A parser for the DHIS2 expression language.
The parser is implemented as a kotlin multiplatform project in order to yield a Java and JS library that can be used in client and server of DHIS2.
The parsing follows the PEG approach. Essentially this means for each building block there is a corresponding function implementing its parsing which has this shape:
// e.g. to deal with the 'expr' fragment of the grammar
fun expr(expr: Expr, ctx: ParseContext) {
// ...
}
Each such method accepts two arguments:
- the
Expr
representing the parsed input expression and the position in it - the
ParseContext
to emit AST nodes and lookup named fragments
The parsing is implemented on 4 levels (high to low):
ExpressionGrammar
: high level composition of named fragmentsExpr
: specific hard coded fragments (likeexpr
), operators and bracketsLiterals
: terminals of the language; string, number, date literals etc.Chars
: named character sets of the language as used byLiterals
For an equivalent of a (ANTLR) grammar definition look at ExpressionGrammar
.
The public API of the library is encapsulated by Expression
which refers to types
in the org.hisp.dhis.lib.expression.spi
package.
For JavaScript the main entry point to the API is called ExpressionJs
.
DHIS2 has several expression language, each supporting a different set of functions.
To select which expression is used the Expression
is parameterized with a Mode
.
VALIDATION_RULE_EXPRESSION
: Computes a number for a validation ruleVALIDATION_RULE_RESULT_TEST
: Computes a boolean for a validation rule resultPREDICTOR_GENERATOR_EXPRESSION
: Computes a number or string data value for a predictor expressionPREDICTOR_SKIP_TEST
: Computes a boolean to test if a data section should be skipped when evaluating predictor expressionsINDICATOR_EXPRESSION
: Computes a number for an indicator expression (ad-hoc aggregate data computation)PROGRAM_INDICATOR_EXPRESSION
: Computes a number for a program indicator expression (persisted aggregate data computation)RULE_ENGINE_CONDITION
: Computes a boolean to check if a rule appliesRULE_ENGINE_ACTION
: Computes a boolean, string, number or date from a rule
This library uses the Binary Compatibility Validator plugin, which verifies that there are no changes in the public API of the library.
The way of work is: there is a file generated by the plugin (api/expression-parser.api
) with the binary representation of the expected public API. The plugin has a task (apiCheck
) that verifies that the public API of the code matches the expected API in the file.
If there is an intentional change in the public API, this file must be updated to reflect the changes and included as part of the pull request. It can be updated running the task apiDump
. This task can be run in the command line (./gradlew apiDump
) or using Gradle window in Intellij.
Library version is defined in the file build.gradle.kts
. The version must be manually increased
and include the -SNAPSHOT
suffix. Please make sure the version is updated before opening the PR.
On merged pull request to main
:
- Production release to Maven.
- Production release to NPMJS.
On pull request creation/update:
- Snapshot release to Maven.
On demand:
- Beta releases to NPMJS can be triggered on demand by using the action "Publish NPM beta". Please make sure you select the right branch in the selector.
Publication can be skipped by adding [skip publish]
to the pull request title.