Appendix A – CQL Syntax Formal Specification
Clinical Quality Language Release 1 STU2 (w/ Errata) (1.2.1)
Clinical Decision Support Work GroupMaturity Level: 4Ballot Status: STU 2.1

Appendix A – CQL Syntax Formal Specification

The formal specification for the CQL syntax is defined using the ANTLR4 grammar framework. This framework is a general purpose cross-platform technology for describing computer languages. For more information on this framework, refer to the ANTLR website http://www.antlr.org/.

The material in this section is necessarily technical and assumes familiarity with language definition in general, and ANTLR4 grammars in particular. In addition, the g4 presented here is somewhat simplified for ease of reference and is provided for informative use only. For the complete, normative g4 definition, refer to the CQL.g4 file included with the specification package.

1. Declarations

The CQL grammar is defined in a single ANTLR4 grammar file, CQL.g4. The root production rule is library, which specifies the overall structure for a library file:

library

:

libraryDefinition?

usingDefinition*

includeDefinition*

codesystemDefinition*

valuesetDefinition*

codeDefinition*

conceptDefinition*

parameterDefinition*

statement*

;

Other than statement, these production rules define the declarations available for a library.

libraryDefinition

: 'library' identifier ('version' versionSpecifier)?

;

usingDefinition

: 'using' modelIdentifier ('version' versionSpecifier)?

;

includeDefinition

: 'include' identifier ('version' versionSpecifier)? ('called' localIdentifier)?

;

localIdentifier

: identifier

;

accessModifier

: 'public'

| 'private'

;

parameterDefinition

: accessModifier? 'parameter' identifier typeSpecifier? ('default' expression)?

;

codesystemDefinition

: accessModifier? 'codesystem' identifier ':' codesystemId
('version' versionSpecifier)?

;

valuesetDefinition

: accessModifier? 'valueset' identifier ':' valuesetId
('version' versionSpecifier)? codesystems?

;

codesystems

: 'codesystems' '\{' codesystemIdentifier (',' codesystemIdentifier)* '}'

;

codesystemIdentifier

: (libraryIdentifier '.')? identifier

;

libraryIdentifier

: identifier

;

codeDefinition

: accessModifier? 'code' identifier ':' codeId
'from' codesystemIdentifier displayClause?

;

conceptDefinition

: accessModifier? 'concept' identifier ':' '\{' codeIdentifier
(',' codeIdentifier)* '}' displayClause?

;

codeIdentifier

: (libraryIdentifier '.')? identifier

;

codesystemId

: STRING

;

valuesetId

: STRING

;

versionSpecifier

: STRING

;

codeId

: STRING

;

2. Type Specifiers

The typeSpecifier production rule defines all type specifiers available in the language.

typeSpecifier

: namedTypeSpecifier

| listTypeSpecifier

| intervalTypeSpecifier

| tupleTypeSpecifier

| choiceTypeSpecifier

;

namedTypeSpecifier

: (modelIdentifier '.')? identifier

;

modelIdentifier

: identifier

;

listTypeSpecifier

: 'List' '<' typeSpecifier '>'

;

intervalTypeSpecifier

: 'Interval' '<' typeSpecifier '>'

;

tupleTypeSpecifier

: 'Tuple' '\{' tupleElementDefinition (',' tupleElementDefinition)* '}'

;

tupleElementDefinition

: identifier typeSpecifier

;

choiceTypeSpecifier

: 'Choice' '<' typeSpecifier (',' typeSpecifier)* '>'

;

3. Statements

The main body of the library then consists of any number of statements, defined by the statement production rule:

statement

: expressionDefinition

| contextDefinition

| functionDefinition

;

expressionDefinition

: 'define' accessModifier? identifier ':' expression

;

contextDefinition

: 'context' identifier

;

functionDefinition

: 'define' accessModifier? 'function' identifier
'(' (operandDefinition (',' operandDefinition)*)? ')'

('returns' typeSpecifier)?

':' (functionBody | 'external')

;

operandDefinition

: identifier typeSpecifier

;

functionBody

: expression

;

4. Queries

The query production rule defines the syntax for queries within CQL:

querySource

: retrieve

| qualifiedIdentifier

| '(' expression ')'

;

aliasedQuerySource

: querySource alias

;

alias

: identifier

;

queryInclusionClause

: withClause

| withoutClause

;

withClause

: 'with' aliasedQuerySource 'such that' expression

;

withoutClause

: 'without' aliasedQuerySource 'such that' expression

;

retrieve

: '[' namedTypeSpecifier (':' (codePath 'in')? terminology)? ']'

;

codePath

: identifier

;

terminology

: qualifiedIdentifier

| expression

;

qualifier

: identifier

;

query

: sourceClause
letClause?
queryInclusionClause*
whereClause?
returnClause?
sortClause?

;

sourceClause

: singleSourceClause

| multipleSourceClause

;

singleSourceClause

: aliasedQuerySource

;

multipleSourceClause

: 'from' aliasedQuerySource (',' aliasedQuerySource)*

;

letClause

: 'let' letClauseItem (',' letClauseItem)*

;

letClauseItem

: identifier ':' expression

;

whereClause

: 'where' expression

;

returnClause

: 'return' ('all' | 'distinct')? expression

;

sortClause

: 'sort' ( sortDirection | ('by' sortByItem (',' sortByItem)*) )

;

sortDirection

: 'asc' | 'ascending'

| 'desc' | 'descending'

;

sortByItem

: expressionTerm sortDirection?

;

qualifiedIdentifier

: (qualifier '.')* identifier

;

5. Expressions

The expression production rule defines the syntax for all expressions within CQL:

expression

: expressionTerm

| retrieve

| query

| expression 'is' 'not'? ('null' | 'true' | 'false')

| expression ('is' | 'as') typeSpecifier

| 'cast' expression 'as' typeSpecifier

| 'not' expression

| 'exists' expression

| expression 'properly'? 'between' expressionTerm 'and' expressionTerm

| pluralDateTimePrecision 'between' expressionTerm 'and' expressionTerm

| 'difference' 'in'

pluralDateTimePrecision 'between' expressionTerm 'and' expressionTerm

| expression ('⇐' | '<' | '>' | '>=') expression

| expression intervalOperatorPhrase expression

| expression ('=' | '!=' | '!=' | '~' | '!~') expression

| expression ('in' | 'contains') dateTimePrecisionSpecifier? expression

| expression 'and' expression

| expression ('or' | 'xor') expression

| expression 'implies' expression

| expression ('|' | 'union' | 'intersect' | 'except') expression

;

dateTimePrecision

: 'year' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second' | 'millisecond'

;

dateTimeComponent

: dateTimePrecision

| 'date'

| 'time'

| 'timezone'

;

pluralDateTimePrecision

: 'years' | 'months' | 'weeks' | 'days'

| 'hours' | 'minutes' | 'seconds' | 'milliseconds'

;

expressionTerm

: term

| expressionTerm '.' invocation

| expressionTerm '[' expression ']'

| 'convert' expression 'to' typeSpecifier

| ('+' | '-') expressionTerm

| ('start' | 'end') 'of' expressionTerm

| dateTimeComponent 'from' expressionTerm

| 'duration' 'in' pluralDateTimePrecision 'of' expressionTerm

| 'width' 'of' expressionTerm

| 'successor' 'of' expressionTerm

| 'predecessor' 'of' expressionTerm

| 'singleton' 'from' expressionTerm

| 'point' 'from' expressionTerm

| ('minimum' | 'maximum') namedTypeSpecifier

| expressionTerm '^' expressionTerm

| expressionTerm ('*' | '/' | 'div' | 'mod') expressionTerm

| expressionTerm ('+' | '-' | '&') expressionTerm

| 'if' expression 'then' expression 'else' expression

| 'case' expression? caseExpressionItem+ 'else' expression 'end'

| ('distinct' | 'collapse' | 'flatten') expression

;

caseExpressionItem

: 'when' expression 'then' expression

;

dateTimePrecisionSpecifier

: dateTimePrecision 'of'

;

relativeQualifier

: 'or before'

| 'or after'

;

offsetRelativeQualifier

: 'or more'

| 'or less'

;

exclusiveRelativeQualifier

: 'more than'

| 'less than'

;

quantityOffset

: (quantityLiteral offsetRelativeQualifier? )

| (exclusiveRelativeQualifier quantityLiteral)

;

intervalOperatorPhrase

: ('starts' | 'ends' | 'occurs')? 'same' dateTimePrecision?

(relativeQualifier | 'as') ('start' | 'end')?

| 'properly'? 'includes' dateTimePrecisionSpecifier? ('start' | 'end')?

| ('starts' | 'ends' | 'occurs')? 'properly'? ('during' | 'included in')
dateTimePrecisionSpecifier?

| ('starts' | 'ends' | 'occurs')? quantityOffset? ('before' | 'after')

('start' | 'end')?

| ('starts' | 'ends' | 'occurs')? 'properly'? 'within' quantityLiteral 'of'

('start' | 'end')?

| 'meets' ('before' | 'after')? dateTimePrecisionSpecifier?

| 'overlaps' ('before' | 'after')? dateTimePrecisionSpecifier?

| 'starts' dateTimePrecisionSpecifier?

| 'ends' dateTimePrecisionSpecifier?

;

6. Terms

The term production rule defines the syntax for core expression terms within CQL:

term

: invocation

| literal

| externalConstant

| intervalSelector

| tupleSelector

| instanceSelector

| listSelector

| codeSelector

| conceptSelector

| '(' expression ')'

;

invocation

: identifier

| identifier '(' expression (',' expression)*')'

| '$this'

;

intervalSelector

'Interval' ('['|'(') expression ',' expression (']'|')')

;

tupleSelector

: 'Tuple'? '\{' (':' | (tupleElementSelector (',' tupleElementSelector)*)) '}'

;

tupleElementSelector

: identifier ':' expression

;

instanceSelector

: namedTypeSpecifier '\{' (':' | (instanceElementSelector
(',' instanceElementSelector)*)) '}'

;

instanceElementSelector

: identifier ':' expression

;

listSelector

: ('List' ('<' typeSpecifier '>')?)? '\{' expression? (',' expression)* '}'

;

displayClause

: 'display' stringLiteral

;

codeSelector

: 'Code' stringLiteral 'from' codesystemIdentifier displayClause?

;

conceptSelector

: 'Concept' '\{' codeSelector (',' codeSelector)* '}' displayClause?

;

literal

: nullLiteral

| booleanLiteral

| stringLiteral

| dateTimeLiteral

| timeLiteral

| quantityLiteral

;

nullLiteral

: 'null'

;

booleanLiteral

: 'true'

| 'false'

;

stringLiteral

: STRING

;

dateTimeLiteral

: DATETIME

;

timeLiteral

: TIME

;

quantityLiteral

: QUANTITY unit?

;

unit

: dateTimePrecision

| pluralDateTimePrecision

| STRING // UCUM syntax for units of measure

;

identifier

: IDENTIFIER | QUOTEDIDENTIFIER

| 'all'

| 'Code'

| 'Concept'

| 'contains'

| 'date'

| 'display'

| 'distinct'

| 'end'

| 'exists'

| 'not'

| 'start'

| 'time'

| 'timezone'

| 'version'

| 'where'

;

7. Lexer Rules

The lexer rules define the terminal production rules in the language:

IDENTIFIER

: ([A-Za-z] | '')([A-Za-z0-9] | '')*

;

QUANTITY

: ('.'[0-9])?

;

QUOTEDIDENTIFIER

: '"' (ESC | .)*? '"'

;

STRING

: ('\'') (ESC | .)*? ('\'')

;

WS

: (' ' | '\r' | '\t') channel(HIDDEN)

;

NEWLINE

: ('\n') channel(HIDDEN)

;

COMMENT

: '/' .? '/' *→ channel(HIDDEN)

;

LINE_COMMENT

: '//' ~[\r\n]* channel(HIDDEN)

;