Expression Language (EL)
Issuer: openEHR Specification Program | |
---|---|
Release: BASE Release-1.0.4 |
Status: TRIAL |
Revision: [latest_issue] |
Date: [latest_issue_date] |
Keywords: openehr, expressions, rules |
© 2016 - 2022 The openEHR Foundation | |
---|---|
The openEHR Foundation is an independent, non-profit foundation, facilitating the sharing of health records by consumers and clinicians via open specifications, clinical models and open platform implementations. |
|
Licence |
Creative Commons Attribution-NoDerivs 3.0 Unported. https://creativecommons.org/licenses/by-nd/3.0/ |
Support |
Issues: Problem Reports |
Amendment Record
Issue | Details | Raiser, Implementer | Completed |
---|---|---|---|
R E L E A S E 1.0.4 |
|||
1.1.5 |
SPECBASE-33. Retrospectively release interim form of Expression Language. |
T Beale, |
|
1.1.0 |
SPECPUB-6. Correct UML package nesting and paths in documents; insert |
T Beale |
27 Nov 2017 |
1.0.1 |
Correct type of |
C Nanjo |
31 May 2016 |
1.0.0 |
Initial writing. Taken from AOM2 2.0.6. |
T Beale, |
15 Feb 2016 |
1. Preface
1.1. Purpose
This document specifies the openEHR Expression Model (EOM) and an abstract syntax, denoted the openEHR Expression Language (oEL). The EOM defines the semantics of a first order predicate style logic that can be used to express assertions (for example in archetypes) and rulesfor example in decision support situations.
The intended audience includes:
-
Standards bodies producing health informatics standards;
-
Academic groups using openEHR;
-
Solution vendors;
-
Medical informaticians and clinicians interested in health information.
1.2. Related Documents
Prerequisite documents for reading this document include:
Releated documents include:
1.3. Status
The contents of this specification were separated out from the AOM2 specification in order to provide a common model of expressions and rules structures for AOM, GDL and other specifications requiring it.
This specification is in the TRIAL state. The development version of this document can be found at https://specifications.openehr.org/releases/LANG/latest/expression_language.html.
Known omissions or questions are indicated in the text with a 'to be determined' paragraph, as follows:
TBD: (example To Be Determined paragraph)
1.4. Feedback
Feedback may be provided on the openEHR languages specifications forum.
Issues may be raised on the specifications Problem Report tracker.
To see changes made due to previously reported issues, see the BASE component Change Request tracker.
1.5. Conformance
Conformance of a data or software artifact to an openEHR specification is determined by a formal test of that artifact against the relevant openEHR Implementation Technology Specification(s) (ITSs), such as an IDL interface or an XML-schema. Since ITSs are formal derivations from underlying models, ITS conformance indicates model conformance.
2. Overview
The openEHR Expression Object Model (EOM) defines the semantics of all of the elements of computable expressions that are used in openEHR, and are likely to be used in healthcare and life sciences computing where rules and expressions are needed. The model is designed as an extensible core formalism suitable for use and extension in other formalisms (such as the openEHR Archetype formalism).
The openEHR Expression Language (EL) specified here is an abstract syntax counterpart to the Expression Object Model, and may be considered a 'default syntax'. Other syntaxes or syntax variants are certainly possible, and other serialisation methods are possible, such as object graph serialisation into XML, JSON, YAML etc. The EL is provided firstly as a way of specifying and explaining the semantics of the EOM, and secondly, as one way of actually authoring expressions and rules in textual form. This approach is the same as with any programming language, where the usual form for learning and programming is the abstract language form, while the computational form is an abstract syntax tree (AST) or similar.
Accordingly, the EOM should be considered the normative definition of the openEHR Expression formalism, and indeed not all implementations need support the language: they might for example only serialse in JSON or use purely graphical visualisation.
The formalism as defined here requires extensions for use, at a minimum to provide concrete value referencing. Extensions would also typically provide more operators, functions, leaf types and other features that are needed in specific circumstances.
Key features of the formalism include:
-
variable declarations, assignments and expressions;
-
strong typing;
-
standard logical operators including universal and existential quantification, as well as user-defined operators;
-
standard arithmetic and relational comparison operators, enabling the use of numerics;
-
parentheses for overridding operator precedence;
-
functions, including built-ins like
current_date
, standard functions such asmax()
defined on primitive types, as well as the ability to use external functions.
For reasons of comprehensibility and explanation, the Expression Language is defined first in this specification.
2.1. Design Background
The openEHR Expression Language is based on a limited first-order predicate logic language. It has similarities with OMG’s OCL (Object Constraint Language), and to the assertion syntax used in the Object-Z language (Smith, 2000). See Sowa (2000), Hein (2002), Kilov & Ross (1994) for an explanation of predicate logic in information modelling. It also draws on the semantics and some of the syntax (particularly agent-related) of the Eiffel Language (ECMA-367). It is not exactly the same as any of these languages because:
-
it has a different target meta-model, namely the BMM
expression
model; -
the syntax is designed to be comprehensible to developers familiar with modern mainstream object-oriented and functional languages such as Java, C#, Python, TypeScript etc.
Modern syntaxes that provide a more generic and minimal inspiration for the expression syntax described here include the Xpath syntax.
The semantic requirements are for expressions including arithmetic, boolean, and relational operators, functions, quantifier operators, operator precedence, parentheses, constant values, and certain kinds of variables. However, there is no support in the core specification for procedural semantics or most of the other complexities of full-blown programming languages.
2.2. Execution Model
The assumed execution model of the Expression language is that an EL text is evaluated by an evaluator against a data context, which determines the truth values of the expression(s). The data context typically includes data services such as the EHR, patient demographics, laboratory systems and so on - anything that is available computationally via some service. The text may contain symbols representing internal variables and bound variables, the latter of which map to entities in the data context.
No assumption is made about whether the data context used is complete or faithful to reality. Consequently, the expression universe is technically speaking an 'open world' in the sense of the open-world assumption. However, higher-level applications or components (or users) may have sufficient knowledge about the data as to be able to treat it in a closed world fashion, for example to treat absence of X as negation of X.
2.3. General Structure
The Expression Language may be used to write single Boolean-valued expressions within another computational context, and in future, a multi-section self-standing EL text
with a similar structure to an archetype. Expressions may be declarations, assignments or assertions. These are made up of expressions containing symbols which represent typed variables and constants. Variables are either bound or local, and are defined using $
names, e.g. $heart_rate
as used in shell script and some other programming languages. A bound variable is mapped to a field in the data context. In the current version of the language, this is achieved by assignment statements that either assign a path in the data context to a symbolic variable (reading) or the reverse (writing back). In this sense, 'assignment' can be understood as associating a data context path with a named variable.
3. The Expression Language
3.1. Overview
This section describes the openEHR Expression Language. In the various contexts where openEHR expressions are used, the syntax provides a foundation for concrete syntaxes supporting specific value-referencing mechanisms, as well as other types of rules, operands etc. The key features of the language are: variable declarations, assignments and expressions. Most of the semantics are in the expression part, which is based on first-order predicate logic with the addition of arithmetic and relational operators to enable the use of numeric elements. Expressions may contain constants, variable references, value references and functions.
3.2. Syntax style
The syntax style used here is generally so-called 'snake_case' rather than so-called 'CamelCase', in common with other openEHR specifications, but either may be used in real applications.
3.3. Typing
The Expression language is fully typed. The type system is the same as that used in other openEHR components, and supports the same set of basic types as described in the openEHR Foundation Types Specification, namely:
-
primitive types;
-
container types:
-
List<T>
, i.e. an ordered list of elements of primitive type T; -
Set<T>
, i.e. a set of elements of primitive type T; -
Hash<K:Ordered,V>
, i.e. a Hash table or dictionary;
-
-
an interval type:
-
Interval<T: Ordered>
where T is any ordered primitive type.
-
3.4. Literals
3.4.1. Primitive Types
The primitive types are shown below, along with typical literal values, which are expressed in the ODIN syntax.
Name | Literal value | Description |
---|---|---|
|
|
Boolean value |
|
|
Integer value |
|
|
Real value |
|
|
ISO8601-format date |
|
|
ISO8601-format date/time |
|
|
ISO8601-format time |
|
|
ISO8601-format duration |
|
|
String |
|
Uri in RFC3986 format |
|
|
|
Terminology code reference |
Automatic type promotion from Integer
to Real
applies to all integer and real values and expressions, in the same fashion as most programming languages.
TBD: do we need Integer64
and Real64
?
3.4.2. Container Types
The same container types as defined in the Foundation Types specification are supported in EL, as follows.
Name | Literal value | Description |
---|---|---|
|
|
Linear list of items of any primitive type, allowing order and repeated membership' |
|
|
Set of items of any primitive type; no order, unique membership; |
|
|
Indexed linear container; |
The above types each have an assumed interface consisting of functions and procedures that apply to all members of the container, consistent with the semantics of the container. These include the following methods that may be accessed in EL via the syntactic operators for_all
and there_exists
described below.
for_all (test(v: T): Boolean): Boolean -- True if for every v in container, test (v) is True there_exists (test(v: T): Boolean): Boolean -- True if there is any v in container for which test (v) is True
3.4.3. Interval Type
The same Interval
type as defined in the Foundation Types specification is supported in EL, as follows. Literal interval values take the same form as in ODIN.
Name | Literal value | Description |
---|---|---|
|
Interval of any ordered primitive |
|
|
the two-sided interval N >= x <= M |
|
|
the two-sided interval N > x <= M |
|
|
the two-sided interval N >= x < M |
|
|
the one-sided interval x < N |
|
|
the one-sided interval x > N |
|
|
the one-sided interval x <= N |
|
|
the one-sided interval x >= N |
|
|
the two-sided interval of N ±M |
|
|
the two-sided interval of N ±M |
Automatic type promotion from Interval<Integer>
to Interval<Real>
applies to all integer and real values and expressions, in the same fashion as most programming languages.
3.5. Statements
An EL text consists of statements, each of which may be a declaration, an assignment or an assertion.
3.5.1. Declarations
Variables are declared with a formal type. Bound variables additionally include an assignment to a path within an assumed data context, which may be understood as performing the binding. Local variable declaratoins may include an assignment to an expression result, in the manner of common programming languages.
-- local variable, primitive type $date_of_birth: Date -- local variable, container type $heart_rate_history: List<Real> -- local variable with assignment $age_in_years: Integer := current_date() - $date_of_birth -- a bound variable $weight: Quantity := /data[id3]/events[id4]/data[id2]/items[id5]/value
Variables are referenced within assignments and expressions using the same syntax, i.e. var_name
and $var_name
.
3.5.2. Constants
Constants are defined via the use of the equality operator =
in a declaration and a literal value, as follows.
Mph_to_kmh_factor: Real = 1.6 Pounds_to_kg: Real = 0.4536 Systolic_normal_range: Interval<Integer> = |105..135|
3.5.3. Assignment
An assignment to a writable variable is expressed using the :=
operator. An assignment may be made in a declaration in the same way as in many programming languages. The right hand side of an assignment is any value-returning expression. Typical assignments are illustrated below.
$speed_kmh: Real -- declaration $speed_mph: Real := 35.0 -- assignment in a declaration (not a constant) $speed_kmh := $speed_mph * Mph_to_kmh_factor -- assignment
3.6. Bound Variables, Evaluation and Validity
Variables that are bound to entities in the data context function differently from local variables, since their availability is predicated on the existence of the relevant entities. For example, the variable $body_weight
may be bound to a call that retrieves a patient heart rate from the EHR, via an appropriate API call. There is no guarantee that the value is available, so $body_weight
may therefore be undefined in a sense not applicable to local variables. In a programming language, if a variable is not explicitly set, it has either the default value of the type (e.g. 0
for Integer
) or a random value of the correct type. This behaviour is appropriate for local variables, but for bound variables that cannot be evaluated because the external entity does not exist, we want something like an exception to occur.
The approach used for EL is to allow bound variables to be used freely, as for local variables, but if a bound variable cannot be evaluated from the data context, an 'undefined value'
exception should be generated, indicating which variable could not be evaluated. To impose more control, the predicate exists ()
can be used within an expression or assertion to ensure that one or more variables can be populated before proceeding with logic that depends on them, as follows:
Check_vs_vars: exists $heart_rate and exists $blood_pressure
To assert that a certain part of a larger data structure exists, the following assertion can be used.
Smoker_details_recorded: $is_smoker implies exists $smoking_details
3.7. Expressions
Expressions constitute the main part of the Expressions language, and consist of a familiar typed, operator-based syntax common to many programming languages and logics. Formally, an expression is one of the following:
-
terminal entities;
-
non-terminal entities;
-
operators;
-
functions.
-
3.7.1. Terminal Entities
Terminal entities in EL are any of the following:
-
literals
-
variable
-
variable with sub-path
-
constant
-
function call
-
raw path
Use of variables, constants and function calls is the same as in common languages, using the following syntax.
-- expression containing a variable and function call current_date() - $date_of_birth -- expression containing a variable and a constant $speed_mph * Mph_to_kmh_factor
Variables that are bound to paths may be used to generate a reference to a sub-element, using an Xpath-like approach, as follows:
$event: List<Event> := /data[id2]/events[id3] Check_field_vals: $event/data[id4]/items[id7]/value/magnitude = $event/data[id4]/items[id5]/value/magnitude - $event/data[id4]/items[id6]/value/magnitude
In the above, the construction $event/data[id4]/items[id7]/value/magnitude
references an element in the data context whose location is given by the path to which $event is bound, i.e. /data[id2]/events[id3]
, concatenated with the subordinate path, giving a resulting path of /data[id2]/events[id3]/data[id4]/items[id7]/value/magnitude
.
Finally, in the current version of EL, raw paths may be used directly as variables. This is primarily to allow UI expression building tools that work based on the path map of a data context (e.g. an openEHR archetype) to generate expressions directly using paths rather than introducing variables.
3.7.1.1. Functions
Functions are considered leaf entities in the Expression language, and can be of a built-in type or external (user-defined) type. A simple example is:
$date_of_birth: Date $age: Duration $age := current_date() - $date_of_birth
This uses the built-in function current_date()
to compute a person’s age in the standard way. The typing is based on the operator -
(subtract) in the type Date
having the following signature, as defined in the openEHR Foundation Types Specification:
class Date infix '-' alias subtract (Date): Duration
The built-in functions are formally defined in the openEHR Base Types Specification. Some common ones are listed below.
Name | Textual Rendering | Signature | Meaning |
---|---|---|---|
Degree 0 functions (no arguments) |
|||
current_date |
|
:Date |
Current date |
current_time |
|
:Time |
Current time |
current_date_time |
|
:Date_time |
Curent date time |
current_time_zone |
|
:Time_zone |
Curent time zone |
Degree N functions (N arguments) |
|||
sum |
|
<Real, …>: Real |
Equivalent to x + y + … |
mean |
|
<Real, …>: Real |
The mean (average) value of x, y, … |
max |
|
<Real, …>: Real |
The maximum value among x, y, … |
min |
|
<Real, …>: Real |
The minimum value among x, y, … |
Any other functions that are used need to be mapped by the EL engine to implementations with matching signatures.
3.7.2. Operators
Expressions can include arithmetic, relational and boolean operators, plus the existential and universal quantifiers. The full operator set is shown below, along with textual and symbolic renderings. The latter are just standard Unicode symbols. Expression parsers should ideally support these symbols as operator equivalents in addition to the textual form, since it allows expressions to be expressed in a more compact and less language-independent way.
Identifier | Textual Rendering |
Symbolic Rendering |
Meaning |
---|---|---|---|
Arithmetic Operators - Numeric result; descending precendence order |
|||
exp |
^ |
^ |
Expontentiation |
times |
* |
* |
Multiplication |
divide |
/ |
/ |
Division |
mod |
% |
% |
Modulo (whole number) division |
plus |
+ |
+ |
Addition |
minus |
- |
- |
Subtraction |
Relational Operators - Boolean result; equal precedence |
|||
eq |
= |
= |
Equality relation between numerics |
ne |
!= |
≠ |
Inequality relation between numerics |
lt |
< |
< |
Less than relation between numerics |
le |
<= |
≤ |
Less than or equal relation between numerics |
gt |
> |
> |
Greater than relation between numerics |
ge |
>= |
≥ |
Greater than or equal relation between numerics |
Logical Operators - Boolean result; descending precendence order |
|||
not |
not, ~ |
∼ |
Negation, "not p" |
and |
and |
∧ |
Logical conjunction, "p and q" |
or |
or |
∨ |
Logical disjunction, "p or q" |
xor |
xor |
⊻ |
Exclusive or, "only one of p or q" |
implies |
implies |
⇒ |
Material implication, "p implies q", or "if p then q" |
Operator semantics that require further explanation are described below.
3.7.2.1. Logical Negation
All Boolean operators take Boolean operands and generate a Boolean result. The not
operator can be applied as a prefix operator to all operators returning a Boolean result as well as a parenthesised Boolean expression.
3.7.2.2. Precedence and Parentheses
The precendence of operators follows the order shown in the operator tables above. To change precedence, parentheses can be used in the fashion typical of most programming languages, as shown below.
$at_risk := $weight > 120 and ($is_smoker or $is_hypertensive)
3.7.2.3. Container Operators
The two standard quantification operators from predicate logic there exists
(∃ operator) and for all
(∀ operator) are defined in EL for the container types found in the openEHR Foundation Types.
The textual syntax of there exists
is as follows:
there_exists v : container_var | <Boolean expression mentioning v>
Here, the |
symbol is usually read in English as 'such that'. The symbolic equivalent may also be used:
∃ v : container_var | <Boolean expression mentioning v>
The for_all
operator has similar textual syntax:
for_all v : container_var | <Boolean expression mentioning v>
Here, the |
symbol is normally read in English as as 'it holds that'. The symbolic equivalent may also be used:
∀ v : container_var | <Boolean expression mentioning v>
For both operators, the :
symbol may be replaced by the keyword in
.
4. The Expression Object Model
4.1. Overview
The expression
package defines the Expression Object Model (EOM), a model of 'statements' and 'expressions' that can be used in various contexts in openEHR, including inside archetypes and in GDL guidelines. If the Expression Language or other syntax-based artefact is used, the model described here defines the parser output in the form of an expression tree. Other openEHR models designed for a particular purpose may reuse the expression
package and further specialise some of its types specifically intended for extension.
The package structure of the expression
package is shown below.
4.2. Core Package
The main expression
packages core
and extension
are illustrated below.
A group of statements to be used together is formally defined as one or more STATEMENTs
in a STATEMENT_SET
. There are three types of statements corresponding to the classes ASSERTION
, VARIABLE_DECLARATION
and ASSIGNMENT
. Assertions consist of an expression tree structure that evaluates to a Boolean
value. The root of the tree is a descendant of the class EXPR_ITEM
that represents a Boolean-returning operator or value. An Assertion has an optional tag, enabling it to be named.
A VARIABLE_DECLARATION
enables a named variable to be declared with a type, which must be one of the descendants of EXPR_DEF_TYPE
.
The ASSIGNMENT
class defines the usual operation of assigning a value (the source
i.e. the notional right-hand side) to a variable, (the target
, i.e. left-hand side). The source of an assignment can be any Expression or an EXTERNAL_QUERY
, which are sub-types of EXPR_VALUE
.
4.2.1. Expressions
Expressions are fully described statement values that may be evaluated internally (as compared to an external query) and are defined by the EXPR_XXX
classes. The Expression classes model a typical evaluation tree each of whose nodes is either a leaf or an operator node. The semantics of Expressions are described in the Expressions sub-section in the Language section.
In this model, function calls are treated as leaf nodes rather than tree nodes, which would be more typical of a functional language meta-model. The leaf node approach used here treats function calls as black boxes requiring an evaluation method, enabling the main expression tree to be evaluated by use of a standard set of operators whose semantics can be safely built in.
Operator semantics are defined by the class OPERATOR_DEF
, which includes the two attributes name
and symbols
which define the name of the operator and its allowable symbols respectively.
4.2.3. Class Descriptions
4.2.3.1. STATEMENT_SET Class
Class |
STATEMENT_SET |
|
---|---|---|
Description |
A container for a specific set of statements intended to be used together. |
|
Attributes |
Signature |
Meaning |
0..1 |
The member statements of this statement set. |
|
0..1 |
name: |
Optional name of this rule set. |
Functions |
Signature |
Meaning |
1..1 |
execution_result (): |
Execution result of the whole rule set. Determined by the and-ing of result values of Assertions in the rule set. |
4.2.3.2. STATEMENT Class
Class |
STATEMENT (abstract) |
|
---|---|---|
Description |
Meta-type for the notion of statement, which is a non-value-returning entity. |
4.2.3.3. ASSERTION Class
Class |
ASSERTION |
|
---|---|---|
Description |
Meta-type for a first order predicate logic expression with a Boolean result. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
0..1 |
tag: |
Expression tag, used for differentiating multiple assertions. |
0..1 |
string_expression: |
String form of expression, in case an expression evaluator taking String expressions is used for evaluation. |
1..1 |
expression: |
Root of expression tree. |
4.2.3.4. VARIABLE_DECLARATION Class
Class |
VARIABLE_DECLARATION |
|
---|---|---|
Description |
Meta-type for the declaration of a named variable that can be used in an expression. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
name: |
Name of the variable. |
1..1 |
type: |
Primitive type of the variable, enabling its use to be type-checked in expressions. |
4.2.3.5. ASSIGNMENT Class
Class |
ASSIGNMENT |
|
---|---|---|
Description |
Meta-type representing the assignment statement, which associates a named variable with an expression, and produces no value. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
target: |
The target variable on the notional left-hand side of this assignment. |
1..1 |
source: |
Source right hand side) of the assignment. |
4.2.3.6. EXPR_VALUE Class
Class |
EXPR_VALUE (abstract) |
|
---|---|---|
Description |
Any kind of statement element that can be evaluated. The type will either be supplied in descendant types or else will be inferred by an assignment statement linked to a typed variable. |
|
Functions |
Signature |
Meaning |
1..1 |
value (): |
The computed value of this node as a result of the nodes below it, for operator nodes, or else statically set or otherwise derived values. |
4.2.3.7. EXTERNAL_QUERY Class
Class |
EXTERNAL_QUERY |
|
---|---|---|
Description |
Definition of a variable whose value is derived from a query run on a data context in the operational environment. Typical uses of this kind of variable are to obtain values like the patient date of birth, sex, weight, and so on. It could also be used to obtain items from a knowledge context, such as a drug database. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
context: |
Optional name of context. This allows a basic separation of query types to be done in more sophisticated environments. Possible values might be “patient”, “medications” and so on. Not yet standardised. |
1..1 |
query_id: |
Identifier of query in the external context, e.g. “date_of_birth”. Not yet standardised. |
0..1 |
Optional arguments to query. Not yet standardised. |
4.2.3.8. EXPRESSION Class
Class |
EXPRESSION (abstract) |
|
---|---|---|
Description |
Abstract parent of all expression meta-types. |
|
Inherit |
||
Functions |
Signature |
Meaning |
1..1 |
type (): |
The primitive type of this node, which must be determined by redefinitions in concrete classes. |
4.2.3.9. EXPR_OPERATOR Class
Class |
EXPR_OPERATOR (abstract) |
|
---|---|---|
Description |
Abstract parent of operator types. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
0..1 |
precedence_overridden: |
True if the natural precedence of operators is overridden in the expression represented by this node of the expression tree. If True, parentheses should be introduced around the totality of the syntax expression corresponding to this operator node and its operands. |
1..1 |
operator_def: |
Operator definition. |
0..1 |
symbol: |
The symbol actually used in the rule, or intended to be used for serialisation. Must be a member of |
4.2.3.10. EXPR_UNARY_OPERATOR Class
Class |
EXPR_UNARY_OPERATOR |
|
---|---|---|
Description |
Unary operator expression node. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
operand: |
Operand node. |
4.2.3.11. EXPR_BINARY_OPERATOR Class
Class |
EXPR_BINARY_OPERATOR |
|
---|---|---|
Description |
Binary operator expression node. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
left_operand: |
Left operand node. |
1..1 |
right_operand: |
Right operand node. |
4.2.3.12. EXPR_FOR_ALL Class
Class |
EXPR_FOR_ALL |
|
---|---|---|
Description |
Universal quantification operator, usually known as |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
condition: |
Boolean condition that returns True or False when applied to a member of the operand of a |
1..1 |
operand: |
Reference to collection / container object to which the |
4.2.3.13. OPERATOR_DEF Class
Class |
OPERATOR_DEF |
|
---|---|---|
Description |
Abstract definition of an operator for use in the Rules evaluator. |
|
Attributes |
Signature |
Meaning |
1..1 |
identifier: |
Unique identifier of this operator within the rules system. |
0..1 |
4.2.3.14. EXPR_LEAF Class
Class |
EXPR_LEAF (abstract) |
|
---|---|---|
Description |
Meta-type representing one of:
|
|
Inherit |
||
Attributes |
Signature |
Meaning |
0..1 |
item: |
The reference item from which the value of this node can be computed. |
4.2.3.15. EXPR_LITERAL Class
Class |
EXPR_LITERAL |
|
---|---|---|
Description |
Literal value expression tree leaf item. This can represent a literal value of any primitive type included in the |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
item: |
A statically set constant value of a primitive type. |
4.2.3.16. EXPR_VARIABLE_REF Class
Class |
EXPR_VARIABLE_REF |
|
---|---|---|
Description |
Expression tree leaf item representing a reference to a declared variable. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
item: |
The variable referred to. |
4.2.3.17. EXPR_FUNCTION_CALL Class
Class |
EXPR_FUNCTION_CALL |
|
---|---|---|
Description |
Node representing a function call with 0 or more arguments. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
0..1 |
arguments: |
Arguments of this function, which can be from 0 to any number. Functions with no arguments are typically used to represent real world varying values like 'current time' and so on. |
4.3. Typing
The expressions.types
package is shown below.
The type system of the Expression formalism is defined via the type EXPR_TYPE_DEF
and its descendants. All types have a type_name
and a type_anchor
, which is a variable of the coresponding primtive type from within the openEHR base_types
package, i.e. Integer
, Real
, String
, etc. The type anchor can be used for testing assignments within the implementation. A special type TYPE_DEF_OBJECT
is included to enable a value reference (descendant of EXPR_VALUE_REF
) to refer to a complex object, to which some expression operators can be applied, including equality and existence. The types system is extensible, as described below.
4.3.1. Class Descriptions
4.3.1.1. EXPR_TYPE_DEF Class
Class |
EXPR_TYPE_DEF (abstract) |
|
---|---|---|
Description |
Ancestor class for type definitions known in the openEHR Expression formalism. |
|
Attributes |
Signature |
Meaning |
1..1 |
type_name: |
Natural language type name of this type as used in abstract rules syntax variable declarations. |
1..1 |
type_anchor: |
Attribute of the openEHR primitive type (or Any) corresponding to this type definition meta-type. |
4.3.1.2. TYPE_DEF_BOOLEAN Class
Class |
TYPE_DEF_BOOLEAN |
|
---|---|---|
Description |
Rules meta-type representing the primitive type Boolean. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
type_name: |
|
1..1 |
type_anchor: |
4.3.1.3. TYPE_DEF_INTEGER Class
Class |
TYPE_DEF_INTEGER |
|
---|---|---|
Description |
Rules meta-type representing the primitive type Integer. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
type_name: |
|
1..1 |
type_anchor: |
4.3.1.4. TYPE_DEF_REAL Class
Class |
TYPE_DEF_REAL |
|
---|---|---|
Description |
Rules meta-type representing the primitive type Real. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
type_name: |
|
1..1 |
type_anchor: |
4.3.1.5. TYPE_DEF_DATE Class
Class |
TYPE_DEF_DATE |
|
---|---|---|
Description |
Rules meta-type representing the primitive type Date. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
type_name: |
|
1..1 |
type_anchor: |
4.3.1.6. TYPE_DEF_DATE_TIME Class
Class |
TYPE_DEF_DATE_TIME |
|
---|---|---|
Description |
Rules meta-type representing the primitive type Date_time. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
type_name: |
|
1..1 |
type_anchor: |
4.3.1.7. TYPE_DEF_TIME Class
Class |
TYPE_DEF_TIME |
|
---|---|---|
Description |
Rules meta-type representing the primitive type Time. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
type_name: |
|
1..1 |
type_anchor: |
4.3.1.8. TYPE_DEF_DURATION Class
Class |
TYPE_DEF_DURATION |
|
---|---|---|
Description |
Rules meta-type representing the primitive type Duration. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
type_name: |
|
1..1 |
type_anchor: |
4.3.1.9. TYPE_DEF_STRING Class
Class |
TYPE_DEF_STRING |
|
---|---|---|
Description |
Rules meta-type representing the primitive type String. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
type_name: |
|
1..1 |
type_anchor: |
4.3.1.10. TYPE_DEF_URI Class
Class |
TYPE_DEF_URI |
|
---|---|---|
Description |
Rules meta-type representing the primitive type Uri. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
type_name: |
|
1..1 |
type_anchor: |
4.3.1.11. TYPE_DEF_TERMINOLOGY_CODE Class
Class |
TYPE_DEF_TERMINOLOGY_CODE |
|
---|---|---|
Description |
Rules meta-type representing the primitive type Terminology_code. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
type_name: |
|
1..1 |
type_anchor: |
4.3.1.12. TYPE_DEF_OBJECT_REF Class
Class |
TYPE_DEF_OBJECT_REF |
|
---|---|---|
Description |
Rules meta-type representing the type Object_ref, which is assumed to by the type of any non-primitive reference target within a rule. |
|
Inherit |
||
Attributes |
Signature |
Meaning |
1..1 |
type_name: |
Appendix A: Syntax Specification
The grammar and lexical specification for the standard Expression syntax is shown below in ANTLR4 form.
//
// description: Antlr4 grammar for openEHR Rules core syntax.
// author: Thomas Beale <thomas.beale@openehr.org>
// contributors:Pieter Bos <pieter.bos@nedap.com>
// support: openEHR Specifications PR tracker <https://openehr.atlassian.net/projects/SPECPR/issues>
// copyright: Copyright (c) 2016- openEHR Foundation <http://www.openEHR.org>
// license: Apache 2.0 License <http://www.apache.org/licenses/LICENSE-2.0.html>
//
grammar base_expressions;
import cadl2_primitives, odin_values;
//
// ======================= Top-level _objects ========================
//
statement_block: statement+ ;
// ------------------------- statements ---------------------------
statement: declaration | assignment | assertion;
declaration:
variable_declaration
| constant_declaration
;
variable_declaration: local_variable ':' type_id ( SYM_ASSIGNMENT expression )? ;
constant_declaration: constant_name ':' type_id ( SYM_EQ primitive_object )? ;
assignment:
binding
| local_assignment
;
//
// The following is the means of binding a data context path to a local variable
// TODO: remove this rule when proper external bindings are supported
binding: local_variable SYM_ASSIGNMENT bound_path ;
local_assignment: local_variable SYM_ASSIGNMENT expression ;
assertion: ( ( ALPHA_LC_ID | ALPHA_UC_ID ) ':' )? boolean_expr ;
//
// -------------------------- _expressions --------------------------
//
expression:
boolean_expr
| arithmetic_expr
;
//
// _expressions evaluating to boolean values, using standard precedence
// The equality_binop ones are not strictly necessary, but allow the use
// of boolean_leaf = true, which some people like
//
boolean_expr:
SYM_NOT boolean_expr
| boolean_expr SYM_AND boolean_expr
| boolean_expr SYM_XOR boolean_expr
| boolean_expr SYM_OR boolean_expr
| boolean_expr SYM_IMPLIES boolean_expr
| boolean_leaf equality_binop boolean_leaf
| boolean_leaf
;
//
// Atomic Boolean-valued expression elements
// TODO: SYM_EXISTS alternative to be replaced by defined() predicate
boolean_leaf:
boolean_literal
| for_all_expr
| there_exists_expr
| SYM_EXISTS ( bound_path | sub_path_local_variable )
| '(' boolean_expr ')'
| relational_expr
| equality_expr
| constraint_expr
| value_ref
;
boolean_literal:
SYM_TRUE
| SYM_FALSE
;
//
// Universal and existential quantifier
// TODO: 'in' probably isn't needed in the long term
for_all_expr: SYM_FOR_ALL VARIABLE_ID ( ':' | 'in' ) value_ref '|'? boolean_expr ;
there_exists_expr: SYM_THERE_EXISTS VARIABLE_ID ( ':' | 'in' ) value_ref '|'? boolean_expr ;
// Constraint expressions
// This provides a way of using one operator (matches) to compare a
// value (LHS) with a value range (RHS). As per ADL, the value range
// for ordered types like Integer, Date etc may be a single value,
// a list of values, or a list of intervals, and in future, potentially
// other comparators, including functions (e.g. divisible_by_N).
//
// For non-ordered types like String and Terminology_code, the RHS
// is in other forms, e.g. regex for Strings.
//
// The matches operator can be used to generate a Boolean value that
// may be used within an expression like any other Boolean (hence it
// is a booleanLeaf).
// TODO: non-primitive objects might be supported on the RHS in future.
constraint_expr: ( arithmetic_expr | value_ref ) SYM_MATCHES ( '{' c_inline_primitive_object '}' | CONTAINED_REGEXP );
//
// _expressions evaluating to arithmetic values, using standard precedence
//
arithmetic_expr:
<assoc=right> arithmetic_expr '^' arithmetic_expr
| arithmetic_expr ( '/' | '*' | '%' ) arithmetic_expr
| arithmetic_expr ( '+' | '-' ) arithmetic_expr
| arithmetic_leaf
;
arithmetic_leaf:
integer_value
| real_value
| date_value
| date_time_value
| time_value
| duration_value
| value_ref
| '(' arithmetic_expr ')'
;
//
// Equality expression between any arithmetic value; precedence is
// lowest, so only needed between leaves, since () will be needed for
// larger expressions anyway
//
equality_expr: arithmetic_expr equality_binop arithmetic_expr ;
equality_binop:
SYM_EQ
| SYM_NE
;
//
// Relational expressions of arithmetic operands generating Boolean values
//
relational_expr: arithmetic_expr relational_binop arithmetic_expr ;
relational_binop:
SYM_GT
| SYM_LT
| SYM_LE
| SYM_GE
;
//
// instances references: data references, variables, and function calls.
// TODO: Remove bound_path from this rule when external binding supported
//
value_ref:
function_call
| bound_path
| sub_path_local_variable
| local_variable
| constant_name
;
local_variable: VARIABLE_ID ;
// TODO: change to [] form, e.g. book_list [{title.contains("Quixote")}]
sub_path_local_variable: VARIABLE_WITH_PATH;
// TODO: Remove this rule when external binding supported
bound_path: ADL_PATH ;
constant_name: ALPHA_UC_ID ;
function_call: ALPHA_LC_ID '(' function_args? ')' ;
function_args: expression ( ',' expression )* ;
type_id: ALPHA_UC_ID ( '<' type_id ( ',' type_id )* '>' )? ;
References
Smith, G. (2000). The Object Z Specification Language. Kluwer Academic Publishers. Retrieved from http://www.itee.uq.edu.au/ smith/objectz.html