Page tree

Should you require any more information or have encountered a problem, please call the support helpdesk on (07) 5456 6000.

Skip to end of metadata
Go to start of metadata

Overview

Please note, this is a work in progress... The documents is being revised from an earlier version of GELLO.

GELLO Programs

A GELLO program is actually an expression (value) which is evaluated by the GELLO compiler.

 

The complete program must comply with a set of rules called a grammar, and must also also comply with another set of rules called the semantics. The combination of the grammar and the semantics defines the GELLO language. The grammar is defined formally by what is called a BNF grammar which is provided in the Appendices to this document. Many of the semantics are defined by the data type definitions (eg ISO 21090 data types) and the Virtual Medical Record (vMR) definition. The data types and vMR are defined by the GELLO class definition which has been successfully balloted by HL7 as a Draft Standard for trial use (DSTU) in September 2011.

 

GELLO programs are comprised of one or more lines of text which are further broken down into tokens and comments. The tokens are the items which have meaning to the compiler, while the comments are readable annotations for documenting the program and are ignored by the compiler.

 

Medical-Objects GELLO complies with the R2 release of the HL7/Ansi GELLO standard.

Why GELLO?

While GELLO has its roots in OCL 2.0, there are important distinctions between GELLO and OCL. You can read more about this here

Tokens

Tokens are the individual words which make up a GELLO program. Tokens can be identifiers, numbers, strings and symbols.

Identifiers

Identifiers are used in GELLO to represent variable names, type names, property names and method names.

 

Identifiers can be 1 or more characters in length, and must start with "A-Z", "a-z" or "_". Subsequent characters must be "A-Z", "a-z", "0-9", or "_".

 

In GELLO R2, identifiers are case sensitive, which means that identifiers with the same alphabetic letters but with a different case will be treated by the compiler as different names. There is no limit to the number of characters in an identifier.

 

Here are some examples of identifiers.

 

X
x
a1
A20
observation
Test_for_Creatinine
X201
_This_is_also_an_identifier


The BNF syntax for a GELLO variable is


<Identifier:        ["A"-"Z","a"-"z","_"](["A"-"Z","a"-"z","_","0"-"9"])* >

 

Numbers

Numbers are used in GELLO to represent Integer or Real values.

 

All numbers must start with a digit ("0-9") followed by digits ("0-9"), optionally a period ("."), more digits ("0-9") and an optional exponent.

 

An exponent is represented by the letter "E" or "e" followed by a signed integer. It means that the first part (the mantissa) is multiplied by 10 to the power of the exponent. i.e. 1.1e3 means 1.1 times 10 to the power 3 which is 1100

 

Integer numbers do not have a period or exponent (i.e. it is a string of digits only). In practice there is an upper and lower limit of what can be represented in computable form.

 

Here are some examples of Integer numbers.

0the value Zero
1the value one
15the value fifteen
2345the value two thousand, three hundred and forty five
812838482and so forth....

 


Real numbers are distinguished from Integer numbers by having a "." and an exponent. In practice there are limits to the size of the exponent and also the number of digits in the mantissa which can be represented in computable form.

 

Here are some examples of Real numbers.

0.0the value zero as a real number
1.0the value one as a real number
1.0e0the same value as above
0.15the value 15 divided by one hundred (or three twentieths)
20.201twenty plus two hundred and one thousands
3.141596254an approximation of Pi
1.0E2the value one hundred (one times ten to the power of two)
4.2E-304.2 divided by ten to the power of thirty
4.20.0e-32the same value as above

 

The BNF syntax for integer and Real numbers is as follows

 

<IntegerConstant:   (["0"-"9"])+ >
<RealConstant:      (["0"-"9"])+ "."(["0"-"9"])* (["E"|"e"](["+","-"])? (["0"-"9"])* )? >

 

Strings

Strings are used to represent textual values in GELLO expressions.

They are started with a quotation character (either " or ') and are terminated by the same character. Strings are not allowed to continue over omre than a line, and you can place any character in a string except for the surrounding quotation character. 

If you wish to add control character to a string, they can be embedded with the standard XML quoting practice using the form "&ssss;". The following escape symbols are recognised.

"&nl;"Add a new line (carriage return + line feed)
"""Add a double quote to the string ( " )
"'"Add a single quote to the sting ( ' )


Here are some examples of strings.

'this is a string'
"this is also a string"
"this is a string with some quotations marks. "GELLO" is the best language!!!"
"multi line string.&nl;another line.&nl;and another."


The syntax of strings is defined as follows.

<StringConstant:    ("\'"(~["\'",\n,\r])* "\'" | "\"" (~["\"","\n,\r])* "\"" ) >

Symbols

Symbols are characters or combinations of characters which had special meaning in GELLO. Here is a list of them.


+
-
*
/
=
.
..
(
)
[
]
{
}
,
;
:
::
<>
!=
<
>
<=
>=
->
|

Reserved Words


Reserved words are identifiers which are special in GELLO. They cannot be used as identifiers since they have special meaning within the grammar of GELLO. In GELLO R2, reserved words are case-sensitive, however some reserved words may have a capitalized variant.

 

Here is a list of them.

 

and or xor not div mod min max
iterate join
Let
If then else Endif
Context
Set Bag Sequence Tuple Enum
Integer String Real Boolean true false unknown null factory
Package EndPackage Class extends

Comments

Comments can be either single-line comments or multi-line comments. Comments are used to annotate the GELLO program without affecting how the program functions.

 

Single-line Comments[edit]
A single line comment starts with the "--" characters and can appear anywhere on a line, even on lines with GELLO source. All characters from the "--" up until the end of the line are treated as comments.

Some examples of single line comments are...

-- this is a single line comment.

 

 --                               All characters are ignored up to the end of the line.
 -- the following is a line of commented GELLO source.
--   let a:integer = 52
 -- the following is a comment after some GELLO source.
let b:string = 'some string'     -- our temporary variable "b" has the value "some string"

Multi-line Comments

A multi-line comment starts with the character sequence "/*" and finishes with the character sequence "*/". They can span more than one line or simple be embedded within an existing line.

Here are some examples of multi-line comments.

 /* this GELLO comment spans many lines.
 All the text here is commented and will be ignored by the GELLO compiler.
 We can put anything we like in here, including strings, numbers symbols and so forth as long 
 as it doesn't contain the multi-line comment end string.
 This comment will end after here */
 /*
 Another comment
 */
 /****** this too ********/
 let a: integer = /* an embedded comment */ 20
 /* we can put one here too */  if a = 20 then /* and here */ 50 else /* blah... */ endif


Values and Types

All expressions in GELLO have a Value and a Type. The Value is the actual representation of the Type. Types can be either Simple Types, Collection Types, Tuple Types or Model Types

Simple Types

Simple types represent the most fundamental pieces of data that a GELLO program can work with.

GELLO has several simple data types available. Integer, Real, String and Boolean

Integer Type

The Integer type represents values which are whole numbers. They can be positive or negative numbers and also include the value zero. MO-GELLO-R2 Integer values are stored as Extended precision real numbers (80 bits) with an exponent of Zero. This means they have at most 64 bits of precision (from -9,223,372,036,854,775,807 up to +9,223,372,036,854,775,807)

Real Type

The Real type represents values which are numbers which are not necessarily integers. Integers are a subset of Real numbers. MO-GELLO Real values are stored as Double precision real numbers (64 bits).

String Type

The String type represents values which are sequences of characters. Strings in MO-GELLO can have any length within the constraints of the available memory in the executing environment, and the characters are taken from the extended ASCII character set.

Boolean Type

The Boolean type is used to represent GELLO truth values. Values of this type can only be true, false or unknown.

Enumeration Types

Enumeration types are a specialization of the String type, however they are only permitted to have values that match the enumeration type. Any string value is permitted as an enumeration value.

For example a variable with enumeration type Colour could be defined as follows.

Let colour: Enum{"red", "blue", "yellow", "green", "violet") = "blue"


At the moment, the GELLO specification is incomplete with regard to using enumeration types, however if the underlying data model uses enumeration types, these may be imported by the GELLO program.

Collection Types

A collection is a list of data values, each with the same data type. The data values can be either of a simple type like integer or string, or can be complex data types like collections, tuples or classes. The components or items of a collection are formerly known as collection elements.

There are three kinds of collections, Sets, Bags and Sequences.

A Set is a list of items which are all distinct (i.e. there can be no identical items). They may be in any order, however the ordering is unimportant when comparing two sets.

A Bag is similar to a Set with the exception that more than one item of the same value is allowed, and ordering is unimportant when comparing two bags.

A Sequence is much the same as a bag, except that the order of the items is important.

Here are examples of Sets.

 

Set{ 1, 2, 3, 4, 5 } -- a set of the first 5 integers.
Set{ "apple", "orange", "pear" } -- a set of strings with values corresponding to the names of fruit

Here are examples of Bags.

 

Bag{ 1, 2, 2, 3, 4, 4, 4, 5 } -- a list of integer values 
-- (with duplicates)
Bag{ 1, 2, 3, 2, 4, 5, 4, 4 } -- same as above even though the ordering is different
Bag{ "apple", "orange", "pear", "apple" } -- a list of strings with values corresponding to the names of fruit

Here are examples of Sequences.

 

Sequence{ 1, 2, 2, 3, 4, 4, 4, 5 } -- a list of integer values (with duplicates)
Sequence{ 1, 2, 3, 2, 4, 5, 4, 4 } -- different to above since the ordering is important
Sequence{ "apple", "orange", "pear", "apple" } -- a list of strings with values corresponding to the names of fruit

Tuple Types

Tuple types are similar to Collections in that they represent a group of related data items. However, unlike collections where the collection elements must be all of the same type, in tuples they may be of different types. Each element of a tuple is accessed by its name, and has its own distinct element type.

Here is an example of a let statement with a tuple representing the contact details and of a patient. The tuple definition starts with "tuple(" and ends with ")". Tuple types may be nested within other complex types, and other types can be nested within a tuple type.

 

Let patient_contact: 
Tuple( surname: string,
givenname: string, 
streetnumber: integer,
streetname: string,
city: string,
zipcode: integer
country: string)
= Tuple{
surname = "Smith", 
givenname = "Fred",
streetnumber = 123,
streetname = "Lowdown St",
city = "MoTown",
zipcode = 998877,
country = "Republic of MoTownomia"}


The syntax of tuple type definitions is

 

TupleType ::= <Tuple> "(" TupleTypeList ")"
TupleTypeList ::= TupleTypeList "," TupleTypeElement
TupleTypeList ::= TupleTypeElement
TupleTypeElement ::= <Identifier> ":" Type

Class Types


Class types are similar to tuple types in that that have named elements which are called Attributes. Classes also have Operations which can be performed on the class. In general, the data model supplied to the GELLO program will have a number of classes which represent components of the data model.

Class Attributes

Enter topic text here.

Class Operations

Enter topic text here.

Expressions

Expressions form the foundation of GELLO programs and are made up of operands and operators. Generally an expression is written as a list of operands separated by operators. Operators have precedence, which means the order in which the operators will be applied when evaluating an expression with more than one operator. The precedence of operators may be overridden by the use of "(" and ")" to group sub-expressions.

conceptually in grammatical form

Expression ::= Expression Operator Operand
Expression ::= Operand


and

Operand ::= Literal
Operand ::= Variable
Operand ::= UnaryOperator Operand
Operand ::= "(" Expression ")"
Operand ::= ConditionalExpression

Operands

operands can be either literals, variable values, or the results of attributes, operations or queries.

Literals

Literal operands are operands which have fixed literal values, such as numbers, strings, or even complex literals like collection or tuple literals.

Integer Literals

Integer literals are values which are integer tokens. see Numbers

Real Literals

Real literals are values which are real tokens. see Numbers

String Literals

String literals are values which are string tokens. see Strings

Boolean Literals

Boolean literals are values which are boolean tokens. see Boolean Type

Collection Literals

the syntax of Collection Literals is as follows

 

CollectionLiteralExp ::= CollectionType "{" CollectionLiteralParts "}"
CollectionLiteralExp ::= CollectionType "{" "}"

CollectionLiteralParts ::= CollectionLiteralParts "," CollectionLiteralPart
CollectionLiteralParts ::= CollectionLiteralPart
CollectionLiteralPart ::= Expression
CollectionLiteralPart ::= CollectionRange
CollectionRange ::= Expression ".." Expression


Tuple Literals

the syntax of Tuple Literals is as follows

 

TupleLiteralExp ::= <Tuple> "{" TupleDefList "}"
TupleDefList ::= TupleDefList "," TupleDef
TupleDefList ::= TupleDef
TupleDef ::= <Identifier> ":" Type "=" Expression
TupleDef ::= <Identifier> "=" Expression

Variable values

A variable operand is represented by a variable name, and can be modified by any number of attributes or operations.

for example, in the program

Let a: Integer = 1
Let b: Integer = a + 25
b


there are variables a and b.

Whenever a variable is referred to, it is replaced in the expression by its value (in this example a has the value 1 and b has the value 26.

In this example,

Let sodiums = observations->select(code.name = "Sodium")
sodiums.value


there are several variable values.

observations code sodiums

Class Attribute Values

A class attribute value is specified by following an expression operand by a "." and an identifier representing the attribute name. The resulting operand can be used as operand. An attribute means the same as the property of a class in other object oriented languages.

for example, if a variable named obs of type Observation has the attributes name and age, these attributes can be written as

 

obs.name

 

and

 

obs.age


The operator "." may be repeatedly applied to the operand.

for example, one can write

obs.name.surname


to represent the surname attribute of the name attribute of the Observation obs

The syntax of a Class Attribute is

Variable ::= Variable . <Identifier>


Class Operation Values

Class Operation values are similar to attributes, but instead return the result of an operation applied to a variable operand. An operation means the same as a method of a class in other object oriented languages.

for example, if there is a variable patient of class Patient, and it has an operation

prescription_count_for_recent_years(num_years: Integer): Integer


to count the number of prescriptions in the last N years, one could get the number of prescriptions in the last year by writing...

patient.prescription_count_for_recent_years(1)


the syntax of a Class Operation is

Variable ::= Variable . <Identifier> "(" Params ")"


Operators

Expression Operators represent an operation which can be performed on one or two values or Operands of an expression. An operation on a single operand is called a Unary Operator and an operation on two operands is called a Binary Operator. Generally the form is either

UnaryOperator Operand


or

Operand1 BinaryOperator Operand2

Arithmetic operators

The following operators work on Reals and Integer types.

 

+ addition of two operands
- subtraction of two operands
* multiplication of two operands
/ division of two operands
- negation of a single operand


The following operators work on Integer types only

div integer division of two operands
mod integer modulo division (remainder after division) of two operands

Boolean operators

The following operators work on Boolean types. In GELLO, the Boolean operators also work for unknown values.

and the logical and of two operands
or the logical inclusive or of two operands
xor the logical exclusive or of two operands
not the logical inverse of one operand


Here is a table outlining the results of each Boolean operator

ABA and BA or BA xor BNot A
FalseFalseFalseFalseFalseTrue
FalseTrueFalseTrueTrueTrue
TrueFalseFalseTrueTrueFalse
TrueTrueTrueTrueFalseFalse
FalseUnknownFalseUnknownUnknownTrue
UnknownUnknownUnknownTrueUnknownFalse
UnknownFalseFalseUnknownUnknownUnknown
UnknownTrueUnknownTrueUnknownUnknown
UnknownUnknownUnknownUnknownUnknownUnknown

Class operators

There are several class operators available.

value.isUndefined() returns true if the value is null or undefined.

value.isDefined() returns true if the value is not null or undefined.

value.isTypeof(name) returns true if the class of value is name.

Collection Operators

A collection operator is an operator that operates on collection classes only. To understand how collection operators are used, see Using Collections.

It takes the form <collection> "->" <collection operator> "(" <parameters> ")"

Here is an example using a collection operator.

let sodiums = observations -> select(code.name = "Sodium")

This means select from the collection observations only observations which have the attribute code with a name of "Sodium".

Some collection operators may take one or more conditions as parameters, while others may take a number, and some no parameters at all.

There are many predefined collection operators in GELLO. Here is a list of them with some examples of usage.

Select Operator

 

select(BooleanExpression)
select(v | boolean-expression-with-v)
select(v:Type | boolean-expression-with-v)
observations->select(code.name = 'sodium')
observations->select(obs | obs.code.value > 20 or obs.code.name = 'Na')
observations->select(obs:EncodedObservation | obs.encoded.code.value > 20 or obs.code.name = 'Na')

Reject Operator

 

reject(BooleanExpression)
reject(v | boolean-expression-with-v)
reject(v:Type | boolean-expression-with-v)
observations->reject(code.name = 'sodium')
observations->reject(obs | obs.code.value > 20 or obs.code.name = 'Na')
observations->reject(obs:EncodedObservation | obs.encoded.code.value > 20 or obs.code.name = 'Na')

Collect Operator

 

collect(Expression)
collect(v | expression-with-v)
collect(v:Type | expression-with-v)
observations->collect(code.name)
observations->collect(obs | obs.code.value)
observations->collect(obs:EncodedObservation | obs.encoded.code.value)


ForAll Operator

 

forAll(BooleanExpression)
forAll(v | boolean-expression-with-v)
forAll(v:Type | boolean-expression-with-v)
observations->forAll(code.name = 'sodium')
observations->forAll(obs | obs.code.value > 20 or obs.code.name = 'Na')
observations->forAll(obs:EncodedObservation | obs.encoded.code.value > 20 or obs.code.name = 'Na')

Exists Operator

 

exists(BooleanExpression)
exists(v | boolean-expression-with-v)
exists(v:Type | boolean-expression-with-v)
observations->exists(code.name = 'sodium')
observations->exists(obs | obs.code.value > 20 or obs.code.name = 'Na')
observations->exists(obs:EncodedObservation | obs.encoded.code.value > 20 or obs.name = 'Na')

Iterate Operator

 

iterate(elem:Type; result:Type = expression | expression-with-elem-and-result)
observations->iterate( i:integer;
r:integer = 0 | 
if code.name = 'Na' then r + 1 else r endif
)

IncludesAll Operator

 

includesAll(CollectionExpression)
observations->collect(code.name)->includesAll('Na')

SortBy Operator

 

sortBy(ExpressionList)
observations->sortBy(code.name,date)

FirstN Operator

 

firstN(IntegerExpression)
observations->firstN(10)

 

LastN Operator

lastN(IntegerExpression)
observations->lastN(10)

 

ElemAt Operator

elemAt(IntegerExpression)observations->elemAt(5)

 

Size Operato

 
 size()observations->size() 
 

 

IsEmpty Operator

isEmpty()observations->isEmpty()

 

NotEmpty Operator

notEmpty()observations->notEmpty()

 

Sum Operator

sum()observations->collect(value)->sum()

 

Reverse Operator

reverse()observations->reverse()

 

Min Operator

min()observations->collect(value)->min()

 

Max Operator

max()observations->collect(value)->max()

 

Flatten Operator

flatten()observations->flatten()
First Operator[edit]
first()observations->first()

 

Last Operator

last()observations->last()

 

Average Operator

average()observations->collect(value)->average()stdev()observations->collect(value)->stdev()

 

Variance Operator

variance()observations->collect(value)->variance()count(object)observations->collect(code.name)->count('Na')

 

Includes Operator

includes(object)observations->collect(code.name)->includes('Na')

 

Including Operator

including(element)observations->collect(code.name)->including('Na')

 

Excluding Operator

excluding(element)observations->collect(code.name)->excluding('Na')

 

Intersection Operator

intersection(set)all_allergies->intersection(airborne_allergies)

 

Union Operator

union(set)new_allergies->intersection(old_allergies)

 

Join Operator

join(collections; joinedproperties; booleanExpression; orderbyExpression)

 

Conditional Expression

A Conditional Expression is an expression which is determined by a boolean value. If the expression between If and Then evaluates to true, the resulting expression is that between the Then and Else symbols, otherwise it is the expression between the Else and Endif symbols.. An important aspect of Conditional Expressions is that the two expressions alternatives are actually Expression Blocks which means one can have additional Let statements inside the Conditional Expression. It is important to remember that any variables defined in an expression block are only local to that block.

The syntax is as follows.

ConditionalExpression ::= <If> Expression <Then> ExpressionBlock <Else> ExpressionBlock <Endif>


Statements

A GELLO program typically consists of a number of statements one after the other. Usually a GELLO program contains a number of Let statements followed by a final Expression. It is completely valid to have a final Expression without any Let statements. The combination of statements and final expression is called an Expression Block. Expression Blocks can also appear inside Conditional Expressions.

There are several kinds of statements, Let Statements, Context Statements and Final Expression.

Statements are joined together into statement lists. Since GELLO is a declarative language, the order of statements should not affect the end result, however variables must be defined before they are used so any let statements defining them will need to be placed earlier in the statement lists before those variable are used.

The syntax of the statement section of a GELLO program is as follows

 

GELLO_Program ::= ExpressionBlock
ExpressionBlock ::= StatementList FinalExpression
StatementList ::= StatementList Statement
StatementList ::=
FinalExpression ::= Expression
FinalExpression ::=
Statement ::= LetStatement
Statement ::= ContextStatement

 

Let Statement

The Let Statement allows a GELLO expression to be assigned to a variable name. It is a very useful concept in that it allows GELLO expressions to be broken down into meaningful pieces, and also allows frequently used values to be reused within the GELLO program. A Let Statement can also be referred to as a Variable Declaration.

GELLO variables differ to those in typical computer languages in that they may only be assigned a value once which means that GELLO variables are effectively constant for their lifetime. The reason for this is that GELLO is derived from OCL which belongs to the family of functional languages.

If you are a programmer of commonly used programming languages like C or Pascal, it requires some rethinking to grasp the ways in which GELLO expressions are written. However, with a little practice complex GELLO programs can be effectively structured through the use of GELLO variables.

Some examples of Let Statements are...

 

Let a: Integer = 25
Let j = observation->select((code.code="2951-2") or (code.code = "2823-3"))
Let alt_ok: Boolean =
If alt_obs.isdefined() then
alt_obs.value < alt_obs.reference_range.upper_limit * 2
else
unknown
endif

 

In GELLO-R2, the reserved word "Let" is case-sensitive. Also, in MO-GELLO, the type of the variable is optional and may be omitted. The type of the variable can be inferred from the expression which is used to create it. If the type is specified, the assigned expression must be compatible with that type.

The syntax of Let statements is as follows.

 

LetStatement ::= <Let> <Identifier> OptionalType "=" Expression
OptionalType ::= ":" Type
OptionalType ::=


Final Expression

The Final Expression must be the last statement in a GELLO program. It is the result of executing the GELLO program. In MO-GELLO, this is currently optional, and when omitted, the GELLO program returns the null (or undefined) expression value.

In the following GELLO program

Let a: Integer = 50
Let b: Integer = (a*100 + 20) div 2
a + b


the final expression is the last line

a + b

In typical use, most GELLO programs will contain a Final Expression.

The syntax is

FinalExpression ::= Expression
FinalExpression ::=


Context Statement

The Context Statement is mainly used when GELLO is run as an query language within an existing class context. The <ClassName> parameter identifies the class context of the instance data for which GELLO query is being applied in an embedded GELLO environment. You can optionally assign a identifier to the class instance. If one is not given, the default name "self" is assigned.

For example, a messaging infrastructure might wish to execute a GELLO query on a message representing an instance from the data model. The instance root class should be the one specified in the Context statement (e.g. the SinglePatient class from the VMR model). Any Let statements or Final Expressions following the Context Statement can reference all the published attributes and operations of the underlying context class directly.

The syntax of a Context Statement is as follows.

ContextStatement ::= <Context> [ <Identifier> : ] <ClassName>


The Data Model


All GELLO program will have a predefined environment which is available to it. This environment will contain a list of predefined classes which can be used. When using the GELLO Interactive Debugging Environment (IDE) you can use the Class Explorer tab to explore the classes available with their properties and methods (attributes and operations).

Here is a list of some of the classes available....

NOTE - this only refers to the MO VMR model in MO-GELLO (GELLO R1)

AbsoluteTime
AbsoluteTimeInterval
Allergy
Allergies
Archetypes
Boolean
CodedValue
ConceptRelationShip
Duration
DurationInterval
Factory
GLIFDecisionResult
GTS
Integer
IntegerInterval
Lib
Medication
Medications
MLM
Model
Module
Modules
Observation
ObservationManager
Observations
ObservationSequence
Output
Patient
PhysicalQuantity
PhysicalQuantityInterval
Provider
Ratio
Real
RealInterval
Reports
SD
SnomedAttribute
SnomedAttributeGroup
String
StructuredNumeric


There are also a number of predefined variables defined. (Only available in older MO-GELLO R1)

Name
Class
observation
Observations
patient
Patient
model
Model


Using Collections

One of the most powerful features of GELLO is its ability to work with collections. Typically a data model has many different collections which can be queried with the collection operators.

It is important to remember that when a collection operator is used, the attributes of the element type of the collection become available automatically as variables inside the query. This can be seen with one of our demonstration examples.

context observations: Observations from Model.observations
let sodiums = observations->select(code.name = "Sodium")
sodiums.value


The collection observations from the supplied model has as its elements, values of class Observation. One of the attributes of an observation is code which of class CodedValue. Inside the select query, this attribute is made available in the same way as a variable and can be referred to directly. In this example, we compare the value of each element's attribute code and if its name matches the string "Sodium", that element is selected and placed into the new collection. The same principle applies to several collection operators.

Some of the frequently used ones are...

Select Operator

You can create a subset of a collection by using the select operator

collection -> select(boolean-expression)

This will create a new collection of the same type as collection, but only containing elements of the original collection which match the boolean expression or condition. In our example, the following is the collection operation select.

observations->select(code.name = "Sodium")


Collect Operator


You can create a new collection based on elements of the collection by using the collect operator.

collection -> collect(sub-expression)

This will create a new collection based on the original collection, but each new element will only be the value as determined by sub-expression. A short hand for a collect operation when sub-expression is a single attribute of the element type of the expression is

collection.sub-expression

In our example, the following expressions are identical

sodiums->collect(value)
sodiums.value


Using Physical Quantities

GELLO systems will use Health data types (Such as ISO21090 data types) in the Virtual Medical Record and generally the data types will include a special type of value called Physical Quantity (sometimes using the short name PQ). These are similar to the numeric Real type in that one can perform arithmetic on them (+, -, *, / and so forth), however they have the added property that each Physical Quantity has a units attached to it. This units property is fully managed by the GELLO framework when performing arithmetic on Physical Quantities. Many predefined units are included as standard, including most SI units. In the vEMR data model supplied by the Medical-Objects framework, Physical Quantities are used wherever possible in observations, medications and so forth.

It is important to remember the following rules when calculating with physical quantities. Units are compatible if their unit exponents are the same. For example, units of length (metres, feet, inches etc) are all compatible. As long as there is a conversion from one unit to another, units are also compatible. All units are formed from base SI units (e.g. metres, seconds, kilograms, etc)

If A and B are physical quantities:

Addition and Subtraction

Units of A and B must be compatible. If the units of A and B not identical, a units conversion operation will be made before the calculation. If they are not compatible, a GELLO exception (run time error) will be produced.

 

A + B Result.value = A.value + B.convert(A.unit).value, Result.unit = A.unit
A - B Result.value = A.value - B.convert(A.unit).value, Result.unit = A.unit


Multiplication

The unit indices of B are added to those of A. For example if A is in metres (m) and B is in square metres (m^2) then the result will be in cubic metres(m^3). If there are any conversion factors from the base units they will be multiplied together. The units do not need to be compatible - however this means that the result of the multiplication will need to be meaningful to what you are planning to do. If the units of A and B are not compatible, a derived unit will be formed with the combination of both units.

A * B Result.value = A.value * B.value, 
Result.unit.exponent = A.unit.exponent + B.unit.exponent, 
Result.unit.scale = A.unit.scale * B.unit.scale


Division

The unit indices of B are subtracted from those of A. For example if A is in cubic metres (m^3) and B is in metres (m) then the result will be in square metres(m^2). If there are any conversion factors from the base units they will be conversion(A) / conversion(B).

A / B Result.value = A.value / B.value, 
Result.unit.exponent = A.unit.exponent - B.unit.exponent, 
Result.unit.scale = A.unit.scale / B.unit.scale

Example of PQ use

An example of using physical quantities would be Body Mass Index. BMI = W / H^2

Let weight: PhysicalQuantity = factory.physicalquantity(55,'kg')
Let height: PhysicalQuantity = factory.physicalquantity(1.02,'m')
Let BMI: PhysicalQuantity = weight / (height * height)
"BMI=" + bmi.value.format(1,3) + ', units '+bmi.unit 


The results are...

WEIGHT: PhysicalQuantity = 55 kg
HEIGHT: PhysicalQuantity = 1.02 m
BMI: PhysicalQuantity = 52.8642829680892 kgm^-2
Result is BMI=52.864, units kgm^-2


Appendices

GELLO R2 EBNF

The following notational conventions are used throughout GELLO BNF syntax:

The root symbol of the syntax is GELLOExpression
Non-terminal symbols are denoted by plain identifiers, e.g. expression
Left-hand side terms in production rules are nonterminal
Tokens are represented with text strings enclosed in angle brackets, e.g. <atom>.
Reserved words are represented by text strings enclosed in double quotes.
The grammar below uses the following conventions:
(x)? denotes zero or one occurrences of x.
(x)* denotes zero or more occurrences of x.
(x)+ denotes one or more occurrences of x.
x | y means one of either x or y.

 

GELLOExpression::= OuterExpression
OuterExpression::= Declarative+ ( ExpressionNP? | <IN> Expression ) | Expression
Declarative::= LetStatement
| ContextNavigationStatement
InnerExpression::= LetStatement+ (ExpressionNP | <IN> Expression) | Expression
LetStatement::= <LET> <ID> ":" DataTypes <EQUAL> Expression
IfStatement::= <IF> Expression <THEN> InnerExpression <ELSE> InnerExpression <ENDIF>
ContextNavigationStatement::= ContextStatement
| PackageStatement
ContextStatement::= <CONTEXT> ContextClass ContextBlock?
| <CONTEXT> Alias ":" ContextClass ContextBlock?
ContextClass::= ClassName | CollectionType "(" ContextClass ")"
ContextBlock::= DefinitionBody+
DefinitionBody::= <DEF> ":" <ID> ":" DataTypes <EQUAL> InnerExpression
| <DEF> ":" <ID> "(" FormalParams? ")" ":" DataTypes <EQUAL> InnerExpression
FormalParams::= <ID> ":" DataTypes ("," FormalParams )?
Alias::= <ID>
PackageStatement::= <PACKAGE> PackageName
ContextStatement+
<ENDPACKAGE>
PackageName::= Name
Literal::= <STRING_LITERAL>
| <INTEGER_LITERAL>
| <REAL_LITERAL>
| <TRUE>
| <FALSE>
| <UNKNOWN>
| <NULL> 
| CollectionLiteral
| TupleLiteral
| "#" <ID>
CollectionLiteral::= CollectionType? "{" ( CollectionLiteralElement ( "," CollectionLiteralElement )* )? "}"
CollectionLiteralElement::= Expression ( ".." Expression )?
TupleLiteral::= <TUPLE> "{" TupleLiteralElement ( "," TupleLiteralElement )* "}"
TupleLiteralElement::= <ID> (":" DataTypes)? <EQUAL> Expression
DataTypes::= GELLOType
| ModelTypes
GELLOType::= BasicType 
| CollectionType ("(" DataTypes ")" )?
| TupleType 
| EnumerationType
BasicType::= <INTEGER> 
| <STRING>
| <REAL>
| <BOOLEAN>
ModelTypes::= ClassName
CollectionType::= <SET> 
| <BAG>
| <SEQUENCE>
TupleType::= <TUPLE> "(" TupleTypeElement ( "," TupleTypeElement )* ")"
TupleTypeElement::= <ID> ":" DataTypes
EnumerationType::= <ENUM> "(" <ID> ( "," <ID> )* ")"
ClassName::= NameWithPath
NameWithPath::= Name ( "::" Name )*
Name::= <ID> ("." <ID>)*
Expression::= ConditionalExpression
ConditionalExpression::= OrExpression
OrExpression::= ConditionalAndExpression (<OR> ConditionalAndExpression | 
<XOR> ConditionalAndExpression)*
ConditionalAndExpression::= ComparisonExpression (<AND> ComparisonExpression)*
ComparisonExpression::= AddExpression (<EQUAL> AddExpression | 
<NEQ> AddExpression | <LT> AddExpression | 
<LEQ> AddExpression | <GT> AddExpression | 
<GEQ> AddExpression)*
AddExpression::= MultiplyExpression (<MINUS> MultiplyExpression | 
<PLUS> MultiplyExpression)*
MultiplyExpression::= UnaryExpression (<TIMES> UnaryExpression | 
<DIVIDE> UnaryExpression | <MAX> UnaryExpression | 
<MIN> UnaryExpression | <INTDIV> UnaryExpression | 
<MOD> UnaryExpression )*
UnaryExpression::= PrimaryExpression 
| <NOT> UnaryExpression 
| <MINUS> UnaryExpression
| <PLUS> UnaryExpression
| PrimaryExpression
PrimaryExpression::= Literal
| Operand
| ReferenceToInstance
| IfStatement
| "(" Expression ")"
ExpressionNP::= ConditionalExpressionNP
ConditionalExpressionNP::= OrExpressionNP
OrExpressionNP::= ConditionalAndExpressionNP (<OR> ConditionalAndExpression |
<XOR> ConditionalAndExpression)*
ConditionalAndExpressionNP::= ComparisonExpressionNP (<AND> ComparisonExpression)*
ComparisonExpressionNP::= AddExpressionNP (<EQUAL> AddExpression |
<NEQ> AddExpression | <LT> AddExpression |
<LEQ> AddExpression | <GT> AddExpression |
<GEQ> AddExpression)*
AddExpressionNP::= MultiplyExpressionNP(<MINUS> MultiplyExpression |
<PLUS> MultiplyExpression)*
MultiplyExpressionNP::= UnaryExpressionNP (<TIMES> UnaryExpression |
<DIVIDE> UnaryExpression | <MAX> UnaryExpression |
<MIN> UnaryExpression | <INTDIV> UnaryExpression |
<MOD> UnaryExpression )*
UnaryExpressionNP::= PrimaryExpressionNP
| <NOT> UnaryExpression
PrimaryExpressionNP::= Literal
| Operand
| ReferenceToInstance
| IfStatement
Operand::= <ID>
| Operand "." <ID>
| Operand "." StringOperation
| Operand "." TupleOperation
| Operand "." StringOrTupleSize
| Operand "(" ParameterList ")"
| Operand "[" ExpressionList "]"
| Operand <ARROW> CollectionBody
| CollectionLiteral <ARROW> CollectionBody
| <SELF>
CollectionBody::= NonParamExp
| SelectionExp
| QuantifierExp
| SingleObjExp
| ListObjExp
| GetExp
| SetExp
| IterateExp
| JoinExp
SelectionExp::= <SELECT> "(" CExp ")"
| <REJECT> "(" CExp ")"
| <COLLECT> "(" CExp ")"
QuantifierExp::= <FORALL> "(" CExp ")"
| <EXISTS> "(" CExp ")"
CExp::= ConditionalExpression
| ConditionalExpressionWithIterator
| ConditionalExpressionWithIteratorType
ConditionalExpressionWithIterator::= <ID> "|" ConditionalExpression
ConditionalExpressionWithIteratorType::= <ID> ":" DataTypes "|" ConditionalExpression
NonParamExp::= <SIZE> "(" ")"
| <ISEMPTY> "(" ")"
| <NOTEMPTY> "(" ")"
| <SUM> "(" ")"
| <REVERSE> "(" ")"
| <MIN> "(" ")"
| <MAX> "(" ")"
| <FLATTEN> "(" ")"
| <AVERAGE> "(" ")"
| <MEAN> "(" ")"
| <MEDIAN> "(" ")"
| <MODE> "(" ")"
| <STDEV> "(" ")"
| <VARIANCE> "(" ")"
| <DISTINCT> "(" ")"
SingleObjExp::= <COUNT> "(" Object ")"
| <INCLUDES> "(" Object ")"
| <INCLUDING> "(" Object ")"
| <EXCLUDING> "(" Object ")"
ListObjExp::= <INCLUDESALL> "(" ObjectList ")"
| <SORTBY> "(" PropertyList ")"
GetExp::= <FIRSTN> "(" Expression ")"
| <LASTN> "(" Expression ")"
| <ELEMAT> "(" Expression ")"
| <LIKE> "(" Expression ")"
| <NOTLIKE> "(" Expression ")"
| <BETWEEN> "(" Expression "," Expression ")"
SetExp::= <INTERSECTION> "(" Expression ")"
| <UNION> "(" Expression ")"
IterateExp::= <ITERATE> "(" IterateParameterList ")"
JoinExp::= <JOIN> "(" ParameterList ";" ParameterList ";"
ConditionalExpression ";" ParameterList ")"
StringOperation::= StrConcat
| StrToUpper
| StrToLower
| Substring
StringOrTupleSize::= <SIZE> "(" ")"
StrConcat::= <CONCAT> "(" Expression ")"
StrToUpper::= <TOUPPER> "(" ")"
StrToLower::= <TOLOWER> "(" ")"
Substring::= <SUBSTRING> "(" Expression "," Expression ")"
TupleOperation::= TupleGetValue
| TupleGetElemName
| TupleGetElemType
TupleGetValue::= <GETVALUE> "(" TupleElemName ")"
TupleGetElemName::= <GETELEMNAME> "(" Expression ")"
TupleGetElemType::= <GETELEMTYPE> "(" Expression ")"
IterateParameterList::= <ID> (":" DataTypes)? ";" <ID> ":" DataTypes
<EQUAL> Expression "|" Expression
ParameterList::= ExpressionList?
ExpressionList::= Expression ("," Expression)*
ObjectList::= Object ("," Object)*
Object::= Expression
PropertyList::= Property ("," Property)*
Property::= Name
TupleElemName::= Name
ReferenceToInstance::= <FACTORY>.ClassName(ParameterList )

<#DECIMAL_LITERAL: (["0"-"9"])+ >
<#EXPONENT: ["e", "E"] (["+","-"])? (["0"-"9"])+>
<INTEGER_LITERAL: <DECIMAL_LITERAL>>
<REAL_LITERAL: <DECIMAL_LITERAL> "." (["0"-"9"])* (<EXPONENT>)? | "." (["0"-"9"])+ (<EXPONENT>)? >
<STRING_LITERAL: ('\"' (~[ '\"' , "\n", "\r"])* '\"' | "\'" (~[ "\'" , "\n", "\r"])* "\'" ) >
<ID: ["a"-"z","A"-"Z"] (["a"-"z","A"-"Z","0"-"9"] | "_"(["a"-"z","A"-"Z","0"-"9"])+)* >
<BAG: "Bag">
<BOOLEAN: "Boolean">
<ENUM: "Enum">
<INTEGER: "Integer">
<NULL: "null">
<REAL: "Real">
<SEQUENCE: "Sequence">
<SET: "Set">
<STRING: "String">
<SELF: "Self">
<TUPLE: "Tuple" >
<UNKNOWN: "unknown" | "Unknown" >
<AND: "&" | "and" >
<ARROW: "->" | "?" >
<AVERAGE: "average" >
<BETWEEN: "between" >
<COLLECT: "collect" >
<CONCAT: "concat" >
<COUNT: "count" >
<DEF: "Def" | "def" >
<DISTINCT: "distinct" >
<DIVIDE: "/" >
<ELEMAT: "elemat" >
<EXCLUDING: "excluding" >
<EXISTS: "exists" >
<FACTORY: "factory">
<FALSE: "false" | "False" >
<FIRSTN: "firstN" >
<FLATTEN: "flatten" >
<FORALL: "forAll" >
<EQUAL: "=" >
<GEQ: ">=" >
<GETELEMNAME: "getElemName" >
<GETELEMTYPE: "getElemType" >
<GETVALUE: "getValue" >
<GT: ">" >
<INCLUDES: "includes" >
<INCLUDESALL: "includesAll" >
<INCLUDING: "including" >
<INTDIV: "div" >
<INTERSECTION: "intersection" >
<ISEMPTY: "isEmpty" >
<ITERATE: "iterate" >
<JOIN: "join" >
<LASTN: "lastN" >
<LEQ: "<=" >
<LIKE: "like" >
<LT: "<" >
<MAX: "max" >
<MEAN: "mean" >
<MEDIAN: "median" >
<MIN: "min" >
<MINUS: "-" >
<MOD: "mod" >
<MODE: "mode" >
<NEQ: "!=" | "<>" >
<NEW: "new" >
<NOT: "!" | "not" >
<NOTEMPTY: "notEmpty" >
<NOTLIKE: "notlike" >
<OR: "|" | |or" >
<PLUS: "+" >
<REJECT: "reject" >
<REVERSE: "reverse" >
<SELECT: "select" >
<SIZE: "size" >
<SORTBY: "sortBy" >
<SDEV: "stdev" >
<SUBSTRING: "substring" >
<SUM: "sum" >
<TIMES: "*" >
<TOLOWER: "toLower" >
<TOUPPER: "toUpper">
<TRUE: "true">
<UNION: "union" >
<VARIANCE: "variance" >
<XOR: "*|" | "xor" >
<CONTEXT: "context" | "Context">
<ELSE: "else" >
<ENDPACKAGE: "EndPackage" | "endPackage" | "endpackage" >
<ENDIF: "endif" >
<IF: "If" | "if" >
<IN: "in" >
<LET: "Let" | "let" >
<PACKAGE: "Package" | "package">
<THEN: "then" >




Values and Types[edit]All expressions in GELLO have a Value and a Type. The Value is the actual representation of the Type. Types can be either Simple Types, Collection Types, Tuple Types or Model Types
Simple Types[edit]Simple types represent the most fundamental pieces of data that a GELLO program can work with.
GELLO has several simple data types available. Integer, Real, String and Boolean
Integer Type[edit]The Integer type represents values which are whole numbers. They can be positive or negative numbers and also include the value zero. MO-GELLO-R2 Integer values are stored as Extended precision real numbers (80 bits) with an exponent of Zero. This means they have at most 64 bits of precision (from -9,223,372,036,854,775,807 up to +9,223,372,036,854,775,807)
Real Type[edit]The Real type represents values which are numbers which are not necessarily integers. Integers are a subset of Real numbers. MO-GELLO Real values are stored as Double precision real numbers (64 bits).
String Type[edit]The String type represents values which are sequences of characters. Strings in MO-GELLO can have any length within the constraints of the available memory in the executing environment, and the characters are taken from the extended ASCII character set.
Boolean Type[edit]The Boolean type is used to represent GELLO truth values. Values of this type can only be true, false or unknown.
Enumeration Types[edit]Enumeration types are a specialization of the String type, however they are only permitted to have values that match the enumeration type. Any string value is permitted as an enumeration value.
For example a variable with enumeration type Colour could be defined as follows.
 Let colour: Enum{"red", "blue", "yellow", "green", "violet") = "blue"At the moment, the GELLO specification is incomplete with regard to using enumeration types, however if the underlying data model uses enumeration types, these may be imported by the GELLO program.
Collection Types[edit]A collection is a list of data values, each with the same data type. The data values can be either of a simple type like integer or string, or can be complex data types like collections, tuples or classes. The components or items of a collection are formerly known as collection elements.
There are three kinds of collections, Sets, Bags and Sequences.
A Set is a list of items which are all distinct (i.e. there can be no identical items). They may be in any order, however the ordering is unimportant when comparing two sets.
A Bag is similar to a Set with the exception that more than one item of the same value is allowed, and ordering is unimportant when comparing two bags.
A Sequence is much the same as a bag, except that the order of the items is important.
Here are examples of Sets.

 Set{ 1, 2, 3, 4, 5 }              -- a set of the first 5 integers.Set{ "apple", "orange", "pear" }  -- a set of strings with values corresponding to the names of fruit
Here are examples of Bags.

 Bag{ 1, 2, 2, 3, 4, 4, 4, 5 }     -- a list of integer values                                   -- (with duplicates)Bag{ 1, 2, 3, 2, 4, 5, 4, 4 }     -- same as above even though the ordering is differentBag{ "apple", "orange", "pear", "apple" }  -- a list of strings with values corresponding to the names of fruit
Here are examples of Sequences.

 Sequence{ 1, 2, 2, 3, 4, 4, 4, 5 }   -- a list of integer values (with duplicates)Sequence{ 1, 2, 3, 2, 4, 5, 4, 4 }   -- different to above since the ordering is importantSequence{ "apple", "orange", "pear", "apple" } -- a list of strings with values corresponding to the names of fruit
Tuple Types[edit]Tuple types are similar to Collections in that they represent a group of related data items. However, unlike collections where the collection elements must be all of the same type, in tuples they may be of different types. Each element of a tuple is accessed by its name, and has its own distinct element type.
Here is an example of a let statement with a tuple representing the contact details and of a patient. The tuple definition starts with "tuple(" and ends with ")". Tuple types may be nested within other complex types, and other types can be nested within a tuple type.
Let patient_contact:     Tuple( surname: string,           givenname: string,            streetnumber: integer,           streetname: string,           city: string,           zipcode: integer           country: string)
    = Tuple{           surname = "Smith",            givenname = "Fred",           streetnumber = 123,           streetname = "Lowdown St",           city = "MoTown",           zipcode = 998877,           country = "Republic of MoTownomia"}	The syntax of tuple type definitions is
TupleType ::= <Tuple> "(" TupleTypeList ")"
TupleTypeList ::= TupleTypeList "," TupleTypeElementTupleTypeList ::= TupleTypeElement
TupleTypeElement ::= <Identifier> ":" TypeClass Types[edit]Class types are similar to tuple types in that that have named elements which are called Attributes. Classes also have Operations which can be performed on the class. In general, the data model supplied to the GELLO program will have a number of classes which represent components of the data model.
Class Attributes[edit]Enter topic text here.
Class Operations[edit]Enter topic text here.
Expressions[edit]Expressions form the foundation of GELLO programs and are made up of operands and operators. Generally an expression is written as a list of operands separated by operators. Operators have precedence, which means the order in which the operators will be applied when evaluating an expression with more than one operator. The precedence of operators may be overridden by the use of "(" and ")" to group sub-expressions.
conceptually in grammatical form
Expression ::= Expression Operator OperandExpression ::= Operandand
Operand ::= LiteralOperand ::= VariableOperand ::= UnaryOperator OperandOperand ::= "(" Expression ")"Operand ::= ConditionalExpressionOperands[edit]operands can be either literals, variable values, or the results of attributes, operations or queries.
Literals[edit]Literal operands are operands which have fixed literal values, such as numbers, strings, or even complex literals like collection or tuple literals.

Integer Literals[edit]Integer literals are values which are integer tokens. see Numbers
Real Literals[edit]Real literals are values which are real tokens. see Numbers
String Literals[edit]String literals are values which are string tokens. see Strings
Boolean Literals[edit]Boolean literals are values which are boolean tokens. see Boolean Type
Collection Literals[edit]the syntax of Collection Literals is as follows
CollectionLiteralExp ::= CollectionType "{" CollectionLiteralParts "}"CollectionLiteralExp ::= CollectionType "{" "}"

CollectionLiteralParts ::= CollectionLiteralParts "," CollectionLiteralPartCollectionLiteralParts ::= CollectionLiteralPart
CollectionLiteralPart ::= ExpressionCollectionLiteralPart ::= CollectionRange
CollectionRange ::= Expression ".." Expression
Tuple Literals[edit]the syntax of Tuple Literals is as follows
TupleLiteralExp ::= <Tuple> "{" TupleDefList "}"
TupleDefList ::= TupleDefList "," TupleDefTupleDefList ::= TupleDef
TupleDef ::= <Identifier> ":" Type "=" ExpressionTupleDef ::= <Identifier> "=" ExpressionVariable values[edit]A variable operand is represented by a variable name, and can be modified by any number of attributes or operations.
for example, in the program
Let a: Integer = 1Let b: Integer = a + 25bthere are variables a and b.
Whenever a variable is referred to, it is replaced in the expression by its value (in this example a has the value 1 and b has the value 26.
In this example,
Let sodiums = observations->select(code.name = "Sodium")sodiums.valuethere are several variable values.
observations code sodiums
Class Attribute Values[edit]A class attribute value is specified by following an expression operand by a "." and an identifier representing the attribute name. The resulting operand can be used as operand. An attribute means the same as the property of a class in other object oriented languages.
for example, if a variable named obs of type Observation has the attributes name and age, these attributes can be written as
obs.nameand
obs.ageThe operator "." may be repeatedly applied to the operand.
for example, one can write
 obs.name.surnameto represent the surname attribute of the name attribute of the Observation obs
The syntax of a Class Attribute is
Variable ::= Variable . <Identifier>Class Operation Values[edit]Class Operation values are similar to attributes, but instead return the result of an operation applied to a variable operand. An operation means the same as a method of a class in other object oriented languages.
for example, if there is a variable patient of class Patient, and it has an operation
 prescription_count_for_recent_years(num_years: Integer): Integerto count the number of prescriptions in the last N years, one could get the number of prescriptions in the last year by writing...
  patient.prescription_count_for_recent_years(1)the syntax of a Class Operation is
Variable ::= Variable . <Identifier> "(" Params ")"Operators[edit]Expression Operators represent an operation which can be performed on one or two values or Operands of an expression. An operation on a single operand is called a Unary Operator and an operation on two operands is called a Binary Operator. Generally the form is either
 UnaryOperator Operandor
 Operand1 BinaryOperator Operand2Arithmetic operators[edit]The following operators work on Reals and Integer types.
+	addition of two operands-	subtraction of two operands*	multiplication of two operands/	division of two operands
-	negation of a single operandThe following operators work on Integer types only
div	integer division of two operandsmod	integer modulo division (remainder after division) of two operands
Boolean operators[edit]The following operators work on Boolean types. In GELLO, the Boolean operators also work for unknown values.
and	the logical and of two operandsor	the logical inclusive or of two operandsxor	the logical exclusive or of two operandsnot	the logical inverse of one operandHere is a table outlining the results of each Boolean operator
A	B	A and B	A or B	A xor B	not Afalse	false	false	false	false	truefalse	true	false	true	true	truetrue	false	false	true	true	falsetrue	true	true	true	false	falsefalse	unknown	false	unknown	unknown	truetrue	unknown	unknown	true	unknown	falseunknown	false	false	unknown	unknown	unknownunknown	true	unknown	true	unknown	unknownunknown	unknown	unknown	unknown	unknown	unknownClass operators[edit]There are several class operators available.
value.isUndefined()	returns true if the value is null or undefined.
value.isDefined()	returns true if the value is not null or undefined.
value.isTypeof(name)	returns true if the class of value is name.
Collection Operators[edit]A collection operator is an operator that operates on collection classes only. To understand how collection operators are used, see Using Collections.
It takes the form <collection> "->" <collection operator> "(" <parameters> ")"
Here is an example using a collection operator.
let sodiums = observations -> select(code.name = "Sodium")
This means select from the collection observations only observations which have the attribute code with a name of "Sodium".
Some collection operators may take one or more conditions as parameters, while others may take a number, and some no parameters at all.
There are many predefined collection operators in GELLO. Here is a list of them with some examples of usage.
Select Operator[edit]select(BooleanExpression)select(v | boolean-expression-with-v)select(v:Type | boolean-expression-with-v)
observations->select(code.name = 'sodium')observations->select(obs | obs.code.value > 20 or obs.code.name = 'Na')observations->select(obs:EncodedObservation | obs.encoded.code.value > 20 or obs.code.name = 'Na')Reject Operator[edit]reject(BooleanExpression)reject(v | boolean-expression-with-v)reject(v:Type | boolean-expression-with-v)
observations->reject(code.name = 'sodium')observations->reject(obs | obs.code.value > 20 or obs.code.name = 'Na')observations->reject(obs:EncodedObservation | obs.encoded.code.value > 20 or obs.code.name = 'Na')Collect Operator[edit]collect(Expression)collect(v | expression-with-v)collect(v:Type | expression-with-v)
observations->collect(code.name)observations->collect(obs | obs.code.value)observations->collect(obs:EncodedObservation | obs.encoded.code.value)ForAll Operator[edit]forAll(BooleanExpression)forAll(v | boolean-expression-with-v)forAll(v:Type | boolean-expression-with-v)
observations->forAll(code.name = 'sodium')observations->forAll(obs | obs.code.value > 20 or obs.code.name = 'Na')observations->forAll(obs:EncodedObservation | obs.encoded.code.value > 20 or obs.code.name = 'Na')

Exists Operator[edit]exists(BooleanExpression)exists(v | boolean-expression-with-v)exists(v:Type | boolean-expression-with-v)
observations->exists(code.name = 'sodium')observations->exists(obs | obs.code.value > 20 or obs.code.name = 'Na')observations->exists(obs:EncodedObservation | obs.encoded.code.value > 20 or obs.name = 'Na')

Iterate Operator[edit]iterate(elem:Type; result:Type = expression | expression-with-elem-and-result)
observations->iterate(	i:integer;					r:integer = 0 | 					if code.name = 'Na' then r + 1 else r endif				)IncludesAll Operator[edit]includesAll(CollectionExpression)
observations->collect(code.name)->includesAll('Na')
SortBy Operator[edit]sortBy(ExpressionList)
observations->sortBy(code.name,date)
FirstN Operator[edit]firstN(IntegerExpression)
observations->firstN(10)
LastN Operator[edit]lastN(IntegerExpression)
observations->lastN(10)
ElemAt Operator[edit]elemAt(IntegerExpression)
observations->elemAt(5)
Size Operator[edit]size()
observations->size()
IsEmpty Operator[edit]isEmpty()
observations->isEmpty()
NotEmpty Operator[edit]notEmpty()
observations->notEmpty()
Sum Operator[edit]sum()
observations->collect(value)->sum()
Reverse Operator[edit]reverse()
observations->reverse()
Min Operator[edit]min()
observations->collect(value)->min()
Max Operator[edit]max()
observations->collect(value)->max()
Flatten Operator[edit]flatten()
observations->flatten()First Operator[edit]first()
observations->first()
Last Operator[edit]last()
observations->last()
Average Operator[edit]average()
observations->collect(value)->average()
stdev()
observations->collect(value)->stdev()
Variance Operator[edit]variance()
observations->collect(value)->variance()
count(object)
observations->collect(code.name)->count('Na')
Includes Operator[edit]includes(object)
observations->collect(code.name)->includes('Na')
Including Operator[edit]including(element)
observations->collect(code.name)->including('Na')
Excluding Operator[edit]excluding(element)
observations->collect(code.name)->excluding('Na')
Intersection Operator[edit]intersection(set)
all_allergies->intersection(airborne_allergies)
Union Operator[edit]union(set)
new_allergies->intersection(old_allergies)
Join Operator[edit]join(collections; joinedproperties; booleanExpression; orderbyExpression)Conditional Expression[edit]A Conditional Expression is an expression which is determined by a boolean value. If the expression between If and Then evaluates to true, the resulting expression is that between the Then and Else symbols, otherwise it is the expression between the Else and Endif symbols.. An important aspect of Conditional Expressions is that the two expressions alternatives are actually Expression Blocks which means one can have additional Let statements inside the Conditional Expression. It is important to remember that any variables defined in an expression block are only local to that block.
The syntax is as follows.
ConditionalExpression ::= <If> Expression <Then> ExpressionBlock <Else> ExpressionBlock <Endif>Statements[edit]A GELLO program typically consists of a number of statements one after the other. Usually a GELLO program contains a number of Let statements followed by a final Expression. It is completely valid to have a final Expression without any Let statements. The combination of statements and final expression is called an Expression Block. Expression Blocks can also appear inside Conditional Expressions.
There are several kinds of statements, Let Statements, Context Statements and Final Expression.
Statements are joined together into statement lists. Since GELLO is a declarative language, the order of statements should not affect the end result, however variables must be defined before they are used so any let statements defining them will need to be placed earlier in the statement lists before those variable are used.
The syntax of the statement section of a GELLO program is as follows
GELLO_Program ::= ExpressionBlock
ExpressionBlock ::= StatementList FinalExpression
StatementList ::= StatementList StatementStatementList ::=
FinalExpression ::= ExpressionFinalExpression ::=
Statement ::= LetStatementStatement ::= ContextStatement
Let Statement[edit]The Let Statement allows a GELLO expression to be assigned to a variable name. It is a very useful concept in that it allows GELLO expressions to be broken down into meaningful pieces, and also allows frequently used values to be reused within the GELLO program. A Let Statement can also be referred to as a Variable Declaration.
GELLO variables differ to those in typical computer languages in that they may only be assigned a value once which means that GELLO variables are effectively constant for their lifetime. The reason for this is that GELLO is derived from OCL which belongs to the family of functional languages.
If you are a programmer of commonly used programming languages like C or Pascal, it requires some rethinking to grasp the ways in which GELLO expressions are written. However, with a little practice complex GELLO programs can be effectively structured through the use of GELLO variables.
Some examples of Let Statements are...

Let a: Integer = 25
Let j = observation->select((code.code="2951-2") or (code.code = "2823-3"))
Let alt_ok: Boolean =  If alt_obs.isdefined() then    alt_obs.value < alt_obs.reference_range.upper_limit * 2  else    unknown  endif
In GELLO-R2, the reserved word "Let" is case-sensitive. Also, in MO-GELLO, the type of the variable is optional and may be omitted. The type of the variable can be inferred from the expression which is used to create it. If the type is specified, the assigned expression must be compatible with that type.
The syntax of Let statements is as follows.
LetStatement ::= <Let> <Identifier> OptionalType "=" Expression
OptionalType ::= ":" TypeOptionalType ::=Final Expression[edit]The Final Expression must be the last statement in a GELLO program. It is the result of executing the GELLO program. In MO-GELLO, this is currently optional, and when omitted, the GELLO program returns the null (or undefined) expression value.
In the following GELLO program
Let a: Integer = 50Let b: Integer = (a*100 + 20) div 2a + bthe final expression is the last line
a + b
In typical use, most GELLO programs will contain a Final Expression.
The syntax is
FinalExpression ::= ExpressionFinalExpression ::=Context Statement[edit]The Context Statement is mainly used when GELLO is run as an query language within an existing class context. The <ClassName> parameter identifies the class context of the instance data for which GELLO query is being applied in an embedded GELLO environment. You can optionally assign a identifier to the class instance. If one is not given, the default name "self" is assigned.
For example, a messaging infrastructure might wish to execute a GELLO query on a message representing an instance from the data model. The instance root class should be the one specified in the Context statement (e.g. the SinglePatient class from the VMR model). Any Let statements or Final Expressions following the Context Statement can reference all the published attributes and operations of the underlying context class directly.
The syntax of a Context Statement is as follows.
ContextStatement ::= <Context> [ <Identifier> : ] <ClassName>The Data Model[edit]All GELLO program will have a predefined environment which is available to it. This environment will contain a list of predefined classes which can be used. When using the GELLO Interactive Debugging Environment (IDE) you can use the Class Explorer tab to explore the classes available with their properties and methods (attributes and operations).
Here is a list of some of the classes available....
NOTE - this only refers to the MO VMR model in MO-GELLO (GELLO R1)
AbsoluteTimeAbsoluteTimeIntervalAllergyAllergiesArchetypesBooleanCodedValueConceptRelationShipDurationDurationIntervalFactoryGLIFDecisionResultGTSIntegerIntegerIntervalLibMedicationMedicationsMLMModelModuleModulesObservationObservationManagerObservationsObservationSequenceOutputPatientPhysicalQuantityPhysicalQuantityIntervalProviderRatioRealRealIntervalReportsSDSnomedAttributeSnomedAttributeGroupStringStructuredNumericThere are also a number of predefined variables defined. (Only available in older MO-GELLO R1)
NameClassobservationObservationspatientPatientmodelModelUsing Collections[edit]One of the most powerful features of GELLO is its ability to work with collections. Typically a data model has many different collections which can be queried with the collection operators.
It is important to remember that when a collection operator is used, the attributes of the element type of the collection become available automatically as variables inside the query. This can be seen with one of our demonstration examples.
context observations: Observations from Model.observationslet sodiums = observations->select(code.name = "Sodium")sodiums.valueThe collection observations from the supplied model has as its elements, values of class Observation. One of the attributes of an observation is code which of class CodedValue. Inside the select query, this attribute is made available in the same way as a variable and can be referred to directly. In this example, we compare the value of each element's attribute code and if its name matches the string "Sodium", that element is selected and placed into the new collection. The same principle applies to several collection operators.
Some of the frequently used ones are...
Select Operator[edit]You can create a subset of a collection by using the select operator
collection -> select(boolean-expression)
This will create a new collection of the same type as collection, but only containing elements of the original collection which match the boolean expression or condition. In our example, the following is the collection operation select.
observations->select(code.name = "Sodium")Collect Operator[edit]You can create a new collection based on elements of the collection by using the collect operator.
collection -> collect(sub-expression)
This will create a new collection based on the original collection, but each new element will only be the value as determined by sub-expression. A short hand for a collect operation when sub-expression is a single attribute of the element type of the expression is
collection.sub-expression
In our example, the following expressions are identical
sodiums->collect(value)sodiums.valueUsing Physical Quantities[edit]GELLO systems will use Health data types (Such as ISO21090 data types) in the Virtual Medical Record and generally the data types will include a special type of value called Physical Quantity (sometimes using the short name PQ). These are similar to the numeric Real type in that one can perform arithmetic on them (+, -, *, / and so forth), however they have the added property that each Physical Quantity has a units attached to it. This units property is fully managed by the GELLO framework when performing arithmetic on Physical Quantities. Many predefined units are included as standard, including most SI units. In the vEMR data model supplied by the Medical-Objects framework, Physical Quantities are used wherever possible in observations, medications and so forth.
It is important to remember the following rules when calculating with physical quantities. Units are compatible if their unit exponents are the same. For example, units of length (metres, feet, inches etc) are all compatible. As long as there is a conversion from one unit to another, units are also compatible. All units are formed from base SI units (e.g. metres, seconds, kilograms, etc)
If A and B are physical quantities:
Addition and Subtraction[edit]Units of A and B must be compatible. If the units of A and B not identical, a units conversion operation will be made before the calculation. If they are not compatible, a GELLO exception (run time error) will be produced.
A + B		Result.value = A.value + B.convert(A.unit).value,  Result.unit = A.unitA - B		Result.value = A.value - B.convert(A.unit).value,  Result.unit = A.unitMultiplication[edit]The unit indices of B are added to those of A. For example if A is in metres (m) and B is in square metres (m^2) then the result will be in cubic metres(m^3). If there are any conversion factors from the base units they will be multiplied together. The units do not need to be compatible - however this means that the result of the multiplication will need to be meaningful to what you are planning to do. If the units of A and B are not compatible, a derived unit will be formed with the combination of both units.
A * B		Result.value = A.value * B.value, 		Result.unit.exponent = A.unit.exponent + B.unit.exponent, 		Result.unit.scale = A.unit.scale * B.unit.scaleDivision[edit]The unit indices of B are subtracted from those of A. For example if A is in cubic metres (m^3) and B is in metres (m) then the result will be in square metres(m^2). If there are any conversion factors from the base units they will be conversion(A) / conversion(B).
A / B		Result.value = A.value / B.value, 		Result.unit.exponent = A.unit.exponent - B.unit.exponent, 		Result.unit.scale = A.unit.scale / B.unit.scaleExample of PQ use[edit]An example of using physical quantities would be Body Mass Index. BMI = W / H^2
Let weight: PhysicalQuantity = factory.physicalquantity(55,'kg')Let height: PhysicalQuantity = factory.physicalquantity(1.02,'m')Let BMI: PhysicalQuantity = weight / (height * height)"BMI=" + bmi.value.format(1,3) + ', units '+bmi.unit   The results are...
WEIGHT: PhysicalQuantity = 55 kgHEIGHT: PhysicalQuantity = 1.02 mBMI: PhysicalQuantity = 52.8642829680892 kgm^-2Result is BMI=52.864, units kgm^-2Appendices[edit]GELLO R2 EBNF[edit]The following notational conventions are used throughout GELLO BNF syntax:
The root symbol of the syntax is GELLOExpressionNon-terminal symbols are denoted by plain identifiers, e.g. expressionLeft-hand side terms in production rules are nonterminalTokens are represented with text strings enclosed in angle brackets, e.g. <atom>.Reserved words are represented by text strings enclosed in double quotes.The grammar below uses the following conventions:(x)? denotes zero or one occurrences of x.(x)* denotes zero or more occurrences of x.(x)+ denotes one or more occurrences of x.x | y means one of either x or y.
GELLOExpression::=      OuterExpression
OuterExpression::=      Declarative+ ( ExpressionNP? | <IN> Expression ) | Expression
Declarative::=          LetStatement                                |   ContextNavigationStatement
InnerExpression::=      LetStatement+ (ExpressionNP | <IN> Expression) | Expression
LetStatement::=     <LET> <ID> ":" DataTypes <EQUAL> Expression
IfStatement::=     <IF> Expression <THEN> InnerExpression <ELSE> InnerExpression <ENDIF>
ContextNavigationStatement::=     ContextStatement                                |   PackageStatement
ContextStatement::=     <CONTEXT>  ContextClass ContextBlock?                                | <CONTEXT>  Alias ":" ContextClass ContextBlock?
ContextClass::=        ClassName | CollectionType "(" ContextClass ")"
ContextBlock::=        DefinitionBody+
DefinitionBody::=     <DEF> ":" <ID> ":" DataTypes <EQUAL> InnerExpression                                | <DEF> ":" <ID> "(" FormalParams? ")" ":" DataTypes <EQUAL> InnerExpression
FormalParams::= <ID> ":" DataTypes ("," FormalParams )?
Alias::=     <ID>
PackageStatement::=     <PACKAGE> PackageName                                       ContextStatement+                                  <ENDPACKAGE>
PackageName::=     Name
Literal::=          <STRING_LITERAL>                                |   <INTEGER_LITERAL>                                |   <REAL_LITERAL>                                |   <TRUE>                                |   <FALSE>                                |   <UNKNOWN>                                |   <NULL>                                  |   CollectionLiteral                                |   TupleLiteral                                |   "#" <ID>
CollectionLiteral::=  CollectionType? "{" ( CollectionLiteralElement ( "," CollectionLiteralElement )* )? "}"
CollectionLiteralElement::= Expression ( ".." Expression )?
TupleLiteral::= <TUPLE> "{" TupleLiteralElement ( "," TupleLiteralElement )* "}"
TupleLiteralElement::= <ID> (":" DataTypes)? <EQUAL> Expression
DataTypes::=      GELLOType                                |   ModelTypes
GELLOType::=      BasicType                                 |   CollectionType ("(" DataTypes ")" )?                                |   TupleType                                 |   EnumerationType
BasicType::=         <INTEGER>                                 |   <STRING>                                |   <REAL>                                |   <BOOLEAN>
ModelTypes::=   ClassName
CollectionType::=   <SET>                                 |   <BAG>                                |   <SEQUENCE>
TupleType::=            <TUPLE> "(" TupleTypeElement ( "," TupleTypeElement )* ")"
TupleTypeElement::=      <ID> ":" DataTypes
EnumerationType::=      <ENUM> "(" <ID> ( "," <ID> )* ")"
ClassName::=            NameWithPath
NameWithPath::=	Name ( "::" Name )*
Name::=	<ID> ("." <ID>)*
Expression::=     ConditionalExpression
ConditionalExpression::=     OrExpression
OrExpression::=     ConditionalAndExpression (<OR> ConditionalAndExpression  |                                     <XOR> ConditionalAndExpression)*
ConditionalAndExpression::=     ComparisonExpression (<AND> ComparisonExpression)*
ComparisonExpression::=		AddExpression (<EQUAL> AddExpression |                                     <NEQ> AddExpression | <LT> AddExpression  |                                     <LEQ> AddExpression | <GT>  AddExpression  |                                     <GEQ> AddExpression)*
AddExpression::=     MultiplyExpression (<MINUS> MultiplyExpression |                                     <PLUS> MultiplyExpression)*
MultiplyExpression::=     UnaryExpression (<TIMES> UnaryExpression |                                     <DIVIDE> UnaryExpression | <MAX>  UnaryExpression |                                     <MIN> UnaryExpression | <INTDIV> UnaryExpression |                                     <MOD> UnaryExpression )*
UnaryExpression::=		PrimaryExpression	                                    |   <NOT> UnaryExpression                                 |   <MINUS> UnaryExpression                                |   <PLUS> UnaryExpression                                |   PrimaryExpression
PrimaryExpression::=     Literal                                |   Operand                                |   ReferenceToInstance                                |   IfStatement                                |   "(" Expression ")"
ExpressionNP::=     ConditionalExpressionNP
ConditionalExpressionNP::=     OrExpressionNP
OrExpressionNP::=     ConditionalAndExpressionNP (<OR> ConditionalAndExpression  |                                    <XOR> ConditionalAndExpression)*
ConditionalAndExpressionNP::=     ComparisonExpressionNP (<AND> ComparisonExpression)*
ComparisonExpressionNP::=		AddExpressionNP (<EQUAL> AddExpression |                                    <NEQ> AddExpression | <LT> AddExpression  |                                    <LEQ> AddExpression | <GT>  AddExpression  |                                    <GEQ> AddExpression)*
AddExpressionNP::=     MultiplyExpressionNP(<MINUS> MultiplyExpression |                                    <PLUS> MultiplyExpression)*
MultiplyExpressionNP::=     UnaryExpressionNP (<TIMES> UnaryExpression |                                    <DIVIDE> UnaryExpression | <MAX>  UnaryExpression |                                    <MIN> UnaryExpression | <INTDIV> UnaryExpression |                                    <MOD> UnaryExpression )*
UnaryExpressionNP::=       PrimaryExpressionNP                                |   <NOT> UnaryExpression
PrimaryExpressionNP::=    Literal                                |   Operand                                |   ReferenceToInstance                                |   IfStatement
Operand::=              <ID>                                | Operand "."  <ID>                                | Operand "." StringOperation                                | Operand "." TupleOperation                                | Operand "." StringOrTupleSize                                | Operand "(" ParameterList ")"                                | Operand "[" ExpressionList "]"                                | Operand <ARROW> CollectionBody                                | CollectionLiteral <ARROW> CollectionBody                                | <SELF>
CollectionBody::=     NonParamExp                                |   SelectionExp                                |   QuantifierExp                                |   SingleObjExp                                |   ListObjExp                                |   GetExp                                |   SetExp                                |   IterateExp                                |   JoinExp
SelectionExp::=     <SELECT> "(" CExp ")"                                |   <REJECT> "(" CExp ")"                                |   <COLLECT> "(" CExp ")"
QuantifierExp::=     <FORALL> "(" CExp ")"                                |   <EXISTS>  "(" CExp ")"
CExp::=     ConditionalExpression                                |   ConditionalExpressionWithIterator                                |   ConditionalExpressionWithIteratorType
ConditionalExpressionWithIterator::=     <ID> "|" ConditionalExpression
ConditionalExpressionWithIteratorType::=      <ID> ":" DataTypes "|" ConditionalExpression
NonParamExp::=     <SIZE> "(" ")"                                |   <ISEMPTY> "(" ")"                                |   <NOTEMPTY> "(" ")"                                |   <SUM> "(" ")"                                |   <REVERSE> "(" ")"                                |   <MIN> "(" ")"                                |   <MAX> "(" ")"                                |   <FLATTEN> "(" ")"                                |   <AVERAGE> "(" ")"                                |   <MEAN> "(" ")"                                |   <MEDIAN> "(" ")"                                |   <MODE>  "(" ")"                                |   <STDEV> "(" ")"                                |   <VARIANCE> "(" ")"                                |   <DISTINCT> "(" ")"
SingleObjExp::=	    <COUNT> "(" Object ")"                                |   <INCLUDES> "(" Object ")"                                |   <INCLUDING> "(" Object ")"                                |   <EXCLUDING> "(" Object ")"
ListObjExp::=     <INCLUDESALL> "(" ObjectList ")"                                |   <SORTBY> "(" PropertyList ")"
GetExp::=     <FIRSTN> "(" Expression ")"                                |   <LASTN> "(" Expression ")"                                |   <ELEMAT> "(" Expression ")"                                |   <LIKE> "(" Expression ")"                                |   <NOTLIKE> "(" Expression ")"                                |   <BETWEEN> "(" Expression "," Expression ")"
SetExp::=     <INTERSECTION> "(" Expression ")"                                |   <UNION> "(" Expression ")"
IterateExp::=     <ITERATE> "(" IterateParameterList ")"
JoinExp::=    <JOIN>  "(" ParameterList ";" ParameterList ";"                                    ConditionalExpression ";" ParameterList ")"
StringOperation::=     StrConcat                                |   StrToUpper                                |   StrToLower                                |   Substring
StringOrTupleSize::=          <SIZE> "(" ")"
StrConcat::=     <CONCAT> "(" Expression ")"
StrToUpper::=     <TOUPPER> "(" ")"
StrToLower::=     <TOLOWER> "(" ")"
Substring::=     <SUBSTRING> "(" Expression "," Expression ")"
TupleOperation::=     TupleGetValue                                |   TupleGetElemName                                |   TupleGetElemType
TupleGetValue::=     <GETVALUE> "(" TupleElemName ")"
TupleGetElemName::=     <GETELEMNAME> "(" Expression ")"
TupleGetElemType::=     <GETELEMTYPE> "(" Expression ")"
IterateParameterList::=     <ID> (":" DataTypes)? ";" <ID> ":" DataTypes                                    <EQUAL> Expression "|" Expression
ParameterList::=     ExpressionList?
ExpressionList::=     Expression ("," Expression)*
ObjectList::=    Object ("," Object)*
Object::=     Expression
PropertyList::=     Property ("," Property)*
Property::=     Name
TupleElemName::=     Name
ReferenceToInstance::=		<FACTORY>.ClassName(ParameterList )

<#DECIMAL_LITERAL: (["0"-"9"])+ >
<#EXPONENT: ["e", "E"] (["+","-"])? (["0"-"9"])+>
<INTEGER_LITERAL: <DECIMAL_LITERAL>>
<REAL_LITERAL: <DECIMAL_LITERAL> "." (["0"-"9"])* (<EXPONENT>)? | "." (["0"-"9"])+ (<EXPONENT>)? >
<STRING_LITERAL: ('\"' (~[ '\"' , "\n", "\r"])* '\"' | "\'" (~[ "\'" , "\n", "\r"])* "\'" ) >
<ID: ["a"-"z","A"-"Z"] (["a"-"z","A"-"Z","0"-"9"] | "_"(["a"-"z","A"-"Z","0"-"9"])+)* >
<BAG: "Bag">
<BOOLEAN: "Boolean">
<ENUM: "Enum">
<INTEGER: "Integer">
<NULL: "null">
<REAL: "Real">
<SEQUENCE: "Sequence">
<SET: "Set">
<STRING: "String">
<SELF: "Self">
<TUPLE: "Tuple" >
<UNKNOWN: "unknown" | "Unknown" >
<AND: "&" | "and" >
<ARROW: "->" | "?" >
<AVERAGE: "average" >
<BETWEEN: "between" >
<COLLECT: "collect" >
<CONCAT: "concat" >
<COUNT: "count" >
<DEF: "Def" | "def" >
<DISTINCT: "distinct" >
<DIVIDE: "/" >
<ELEMAT: "elemat" >
<EXCLUDING: "excluding" >
<EXISTS: "exists" >
<FACTORY: "factory">
<FALSE: "false" | "False" >
<FIRSTN: "firstN" >
<FLATTEN: "flatten" >
<FORALL: "forAll" >
<EQUAL: "=" >
<GEQ: ">=" >
<GETELEMNAME: "getElemName" >
<GETELEMTYPE: "getElemType" >
<GETVALUE: "getValue" >
<GT: ">" >
<INCLUDES: "includes" >
<INCLUDESALL: "includesAll" >
<INCLUDING: "including" >
<INTDIV: "div" >
<INTERSECTION: "intersection" >
<ISEMPTY: "isEmpty" >
<ITERATE: "iterate" >
<JOIN: "join" >
<LASTN: "lastN" >
<LEQ: "<=" >
<LIKE: "like" >
<LT: "<" >
<MAX: "max" >
<MEAN: "mean" >
<MEDIAN: "median" >
<MIN: "min" >
<MINUS: "-" >
<MOD: "mod" >
<MODE: "mode" >
<NEQ: "!=" | "<>" >
<NEW: "new" >
<NOT: "!" | "not" >
<NOTEMPTY: "notEmpty" >
<NOTLIKE: "notlike" >
<OR: "|" | |or" >
<PLUS: "+" >
<REJECT: "reject" >
<REVERSE: "reverse" >
<SELECT: "select" >
<SIZE: "size" >
<SORTBY: "sortBy" >
<SDEV: "stdev" >
<SUBSTRING: "substring" >
<SUM: "sum" >
<TIMES: "*" >
<TOLOWER: "toLower" >
<TOUPPER: "toUpper">
<TRUE: "true">
<UNION: "union" >
<VARIANCE: "variance" >
<XOR: "*|" | "xor" >
<CONTEXT: "context" | "Context">
<ELSE: "else" >
<ENDPACKAGE: "EndPackage" | "endPackage" | "endpackage" >
<ENDIF: "endif" >
<IF: "If" | "if" >
<IN: "in" >
<LET: "Let" | "let" >
<PACKAGE: "Package" | "package">
<THEN: "then" >

  • No labels