ork.cql.3.16.0.source-code.cql.g4 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cql Show documentation
Show all versions of cql Show documentation
The cql library for the Clinical Quality Language Java reference implementation
grammar cql;
/*
* Clinical Quality Language Grammar Specification
* Version 1.5 - Mixed Normative/Trial-Use
*/
import fhirpath;
/*
* Parser Rules
*/
definition
: usingDefinition
| includeDefinition
| codesystemDefinition
| valuesetDefinition
| codeDefinition
| conceptDefinition
| parameterDefinition
;
library
:
libraryDefinition?
definition*
statement*
EOF
;
/*
* Definitions
*/
libraryDefinition
: 'library' qualifiedIdentifier ('version' versionSpecifier)?
;
usingDefinition
: 'using' qualifiedIdentifier ('version' versionSpecifier)? ('called' localIdentifier)?
;
includeDefinition
: 'include' qualifiedIdentifier ('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
;
/*
* Type Specifiers
*/
typeSpecifier
: namedTypeSpecifier
| listTypeSpecifier
| intervalTypeSpecifier
| tupleTypeSpecifier
| choiceTypeSpecifier
;
namedTypeSpecifier
: (qualifier '.')* referentialOrTypeNameIdentifier
;
modelIdentifier
: identifier
;
listTypeSpecifier
: 'List' '<' typeSpecifier '>'
;
intervalTypeSpecifier
: 'Interval' '<' typeSpecifier '>'
;
tupleTypeSpecifier
: 'Tuple' '{' tupleElementDefinition (',' tupleElementDefinition)* '}'
;
tupleElementDefinition
: referentialIdentifier typeSpecifier
;
choiceTypeSpecifier
: 'Choice' '<' typeSpecifier (',' typeSpecifier)* '>'
;
/*
* Statements
*/
statement
: expressionDefinition
| contextDefinition
| functionDefinition
;
expressionDefinition
: 'define' accessModifier? identifier ':' expression
;
contextDefinition
: 'context' (modelIdentifier '.')? identifier
;
fluentModifier
: 'fluent'
;
functionDefinition
: 'define' accessModifier? fluentModifier? 'function' identifierOrFunctionIdentifier '(' (operandDefinition (',' operandDefinition)*)? ')'
('returns' typeSpecifier)?
':' (functionBody | 'external')
;
operandDefinition
: referentialIdentifier typeSpecifier
;
functionBody
: expression
;
/*
* Expressions
*/
querySource
: retrieve
| qualifiedIdentifierExpression
| '(' expression ')'
;
aliasedQuerySource
: querySource alias
;
alias
: identifier
;
queryInclusionClause
: withClause
| withoutClause
;
withClause
: 'with' aliasedQuerySource 'such that' expression
;
withoutClause
: 'without' aliasedQuerySource 'such that' expression
;
retrieve
: '[' (contextIdentifier '->')? namedTypeSpecifier (':' (codePath codeComparator)? terminology)? ']'
;
contextIdentifier
: qualifiedIdentifierExpression
;
codePath
: simplePath
;
codeComparator
: 'in'
| '='
| '~'
;
terminology
: qualifiedIdentifierExpression
| expression
;
qualifier
: identifier
;
query
: sourceClause letClause? queryInclusionClause* whereClause? (aggregateClause | returnClause)? sortClause?
;
sourceClause
: 'from'? aliasedQuerySource (',' aliasedQuerySource)*
;
letClause
: 'let' letClauseItem (',' letClauseItem)*
;
letClauseItem
: identifier ':' expression
;
whereClause
: 'where' expression
;
returnClause
: 'return' ('all' | 'distinct')? expression
;
aggregateClause
: 'aggregate' ('all' | 'distinct')? identifier startingClause? ':' expression
;
startingClause
: 'starting' (simpleLiteral | quantity | ('(' expression ')'))
;
sortClause
: 'sort' ( sortDirection | ('by' sortByItem (',' sortByItem)*) )
;
sortDirection
: 'asc' | 'ascending'
| 'desc' | 'descending'
;
sortByItem
: expressionTerm sortDirection?
;
qualifiedIdentifier
: (qualifier '.')* identifier
;
qualifiedIdentifierExpression
: (qualifierExpression '.')* referentialIdentifier
;
qualifierExpression
: referentialIdentifier
;
simplePath
: referentialIdentifier #simplePathReferentialIdentifier
| simplePath '.' referentialIdentifier #simplePathQualifiedIdentifier
| simplePath '[' simpleLiteral ']' #simplePathIndexer
;
simpleLiteral
: STRING #simpleStringLiteral
| NUMBER #simpleNumberLiteral
;
expression
: expressionTerm #termExpression
| retrieve #retrieveExpression
| query #queryExpression
| expression 'is' 'not'? ('null' | 'true' | 'false') #booleanExpression
| expression ('is' | 'as') typeSpecifier #typeExpression
| 'cast' expression 'as' typeSpecifier #castExpression
| 'not' expression #notExpression
| 'exists' expression #existenceExpression
| expression 'properly'? 'between' expressionTerm 'and' expressionTerm #betweenExpression
| ('duration' 'in')? pluralDateTimePrecision 'between' expressionTerm 'and' expressionTerm #durationBetweenExpression
| 'difference' 'in' pluralDateTimePrecision 'between' expressionTerm 'and' expressionTerm #differenceBetweenExpression
| expression ('<=' | '<' | '>' | '>=') expression #inequalityExpression
| expression intervalOperatorPhrase expression #timingExpression
| expression ('=' | '!=' | '~' | '!~') expression #equalityExpression
| expression ('in' | 'contains') dateTimePrecisionSpecifier? expression #membershipExpression
| expression 'and' expression #andExpression
| expression ('or' | 'xor') expression #orExpression
| expression 'implies' expression #impliesExpression
| expression ('|' | 'union' | 'intersect' | 'except') expression #inFixSetExpression
;
dateTimePrecision
: 'year' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second' | 'millisecond'
;
dateTimeComponent
: dateTimePrecision
| 'date'
| 'time'
| 'timezone' // NOTE: 1.3 compatibility level only
| 'timezoneoffset'
;
pluralDateTimePrecision
: 'years' | 'months' | 'weeks' | 'days' | 'hours' | 'minutes' | 'seconds' | 'milliseconds'
;
expressionTerm
: term #termExpressionTerm
| expressionTerm '.' qualifiedInvocation #invocationExpressionTerm
| expressionTerm '[' expression ']' #indexedExpressionTerm
| 'convert' expression 'to' (typeSpecifier | unit) #conversionExpressionTerm
| ('+' | '-') expressionTerm #polarityExpressionTerm
| ('start' | 'end') 'of' expressionTerm #timeBoundaryExpressionTerm
| dateTimeComponent 'from' expressionTerm #timeUnitExpressionTerm
| 'duration' 'in' pluralDateTimePrecision 'of' expressionTerm #durationExpressionTerm
| 'difference' 'in' pluralDateTimePrecision 'of' expressionTerm #differenceExpressionTerm
| 'width' 'of' expressionTerm #widthExpressionTerm
| 'successor' 'of' expressionTerm #successorExpressionTerm
| 'predecessor' 'of' expressionTerm #predecessorExpressionTerm
| 'singleton' 'from' expressionTerm #elementExtractorExpressionTerm
| 'point' 'from' expressionTerm #pointExtractorExpressionTerm
| ('minimum' | 'maximum') namedTypeSpecifier #typeExtentExpressionTerm
| expressionTerm '^' expressionTerm #powerExpressionTerm
| expressionTerm ('*' | '/' | 'div' | 'mod') expressionTerm #multiplicationExpressionTerm
| expressionTerm ('+' | '-' | '&') expressionTerm #additionExpressionTerm
| 'if' expression 'then' expression 'else' expression #ifThenElseExpressionTerm
| 'case' expression? caseExpressionItem+ 'else' expression 'end' #caseExpressionTerm
| ('distinct' | 'flatten') expression #aggregateExpressionTerm
| ('expand' | 'collapse') expression ('per' (dateTimePrecision | expression))? #setAggregateExpressionTerm
;
caseExpressionItem
: 'when' expression 'then' expression
;
dateTimePrecisionSpecifier
: dateTimePrecision 'of'
;
relativeQualifier
: 'or before'
| 'or after'
;
offsetRelativeQualifier
: 'or more'
| 'or less'
;
exclusiveRelativeQualifier
: 'less than'
| 'more than'
;
quantityOffset
: (quantity offsetRelativeQualifier?)
| (exclusiveRelativeQualifier quantity)
;
temporalRelationship
: ('on or'? ('before' | 'after'))
| (('before' | 'after') 'or on'?)
;
intervalOperatorPhrase
: ('starts' | 'ends' | 'occurs')? 'same' dateTimePrecision? (relativeQualifier | 'as') ('start' | 'end')? #concurrentWithIntervalOperatorPhrase
| 'properly'? 'includes' dateTimePrecisionSpecifier? ('start' | 'end')? #includesIntervalOperatorPhrase
| ('starts' | 'ends' | 'occurs')? 'properly'? ('during' | 'included in') dateTimePrecisionSpecifier? #includedInIntervalOperatorPhrase
| ('starts' | 'ends' | 'occurs')? quantityOffset? temporalRelationship dateTimePrecisionSpecifier? ('start' | 'end')? #beforeOrAfterIntervalOperatorPhrase
| ('starts' | 'ends' | 'occurs')? 'properly'? 'within' quantity 'of' ('start' | 'end')? #withinIntervalOperatorPhrase
| 'meets' ('before' | 'after')? dateTimePrecisionSpecifier? #meetsIntervalOperatorPhrase
| 'overlaps' ('before' | 'after')? dateTimePrecisionSpecifier? #overlapsIntervalOperatorPhrase
| 'starts' dateTimePrecisionSpecifier? #startsIntervalOperatorPhrase
| 'ends' dateTimePrecisionSpecifier? #endsIntervalOperatorPhrase
;
term
: invocation #invocationTerm
| literal #literalTerm
| externalConstant #externalConstantTerm
| intervalSelector #intervalSelectorTerm
| tupleSelector #tupleSelectorTerm
| instanceSelector #instanceSelectorTerm
| listSelector #listSelectorTerm
| codeSelector #codeSelectorTerm
| conceptSelector #conceptSelectorTerm
| '(' expression ')' #parenthesizedTerm
;
qualifiedInvocation // Terms that can be used after the function/member invocation '.'
: referentialIdentifier #qualifiedMemberInvocation
| qualifiedFunction #qualifiedFunctionInvocation
;
qualifiedFunction
: identifierOrFunctionIdentifier '(' paramList? ')'
;
invocation
: referentialIdentifier #memberInvocation
| function #functionInvocation
| '$this' #thisInvocation
| '$index' #indexInvocation
| '$total' #totalInvocation
;
function
: referentialIdentifier '(' paramList? ')'
;
ratio
: quantity ':' quantity
;
literal
: ('true' | 'false') #booleanLiteral
| 'null' #nullLiteral
| STRING #stringLiteral
| NUMBER #numberLiteral
| LONGNUMBER #longNumberLiteral
| DATETIME #dateTimeLiteral
| DATE #dateLiteral
| TIME #timeLiteral
| quantity #quantityLiteral
| ratio #ratioLiteral
;
intervalSelector
: // TODO: Consider this as an alternative syntax for intervals... (would need to be moved up to expression to make it work)
//expression ( '..' | '*.' | '.*' | '**' ) expression;
'Interval' ('['|'(') expression ',' expression (']'|')')
;
tupleSelector
: 'Tuple'? '{' (':' | (tupleElementSelector (',' tupleElementSelector)*)) '}'
;
tupleElementSelector
: referentialIdentifier ':' expression
;
instanceSelector
: namedTypeSpecifier '{' (':' | (instanceElementSelector (',' instanceElementSelector)*)) '}'
;
instanceElementSelector
: referentialIdentifier ':' expression
;
listSelector
: ('List' ('<' typeSpecifier '>')?)? '{' (expression (',' expression)*)? '}'
;
displayClause
: 'display' STRING
;
codeSelector
: 'Code' STRING 'from' codesystemIdentifier displayClause?
;
conceptSelector
: 'Concept' '{' codeSelector (',' codeSelector)* '}' displayClause?
;
keyword
: 'after'
| 'aggregate'
| 'all'
| 'and'
| 'as'
| 'asc'
| 'ascending'
| 'before'
| 'between'
| 'by'
| 'called'
| 'case'
| 'cast'
| 'code'
| 'Code'
| 'codesystem'
| 'codesystems'
| 'collapse'
| 'concept'
| 'Concept'
| 'contains'
| 'context'
| 'convert'
| 'date'
| 'day'
| 'days'
| 'default'
| 'define'
| 'desc'
| 'descending'
| 'difference'
| 'display'
| 'distinct'
| 'div'
| 'duration'
| 'during'
| 'else'
| 'end'
| 'ends'
| 'except'
| 'exists'
| 'expand'
| 'false'
| 'flatten'
| 'fluent'
| 'from'
| 'function'
| 'hour'
| 'hours'
| 'if'
| 'implies'
| 'in'
| 'include'
| 'includes'
| 'included in'
| 'intersect'
| 'Interval'
| 'is'
| 'let'
| 'library'
| 'List'
| 'maximum'
| 'meets'
| 'millisecond'
| 'milliseconds'
| 'minimum'
| 'minute'
| 'minutes'
| 'mod'
| 'month'
| 'months'
| 'not'
| 'null'
| 'occurs'
| 'of'
| 'on or'
| 'or'
| 'or after'
| 'or before'
| 'or less'
| 'or more'
| 'or on'
| 'overlaps'
| 'parameter'
| 'per'
| 'point'
| 'predecessor'
| 'private'
| 'properly'
| 'public'
| 'return'
| 'same'
| 'second'
| 'seconds'
| 'singleton'
| 'start'
| 'starting'
| 'starts'
| 'sort'
| 'successor'
| 'such that'
| 'then'
| 'time'
| 'timezone' // NOTE: 1.3 Compatibility level only
| 'timezoneoffset'
| 'to'
| 'true'
| 'Tuple'
| 'union'
| 'using'
| 'valueset'
| 'version'
| 'week'
| 'weeks'
| 'where'
| 'when'
| 'width'
| 'with'
| 'within'
| 'without'
| 'xor'
| 'year'
| 'years'
;
// NOTE: Not used, this is the set of reserved words that may not appear as identifiers in ambiguous contexts
reservedWord
: 'aggregate'
| 'all'
| 'and'
| 'as'
| 'after'
| 'before'
| 'between'
| 'case'
| 'cast'
| 'Code'
| 'collapse'
| 'Concept'
| 'convert'
| 'day'
| 'days'
| 'difference'
| 'distinct'
| 'duration'
| 'during'
| 'else'
| 'exists'
| 'expand'
| 'false'
| 'flatten'
| 'from'
| 'if'
| 'in'
| 'included in'
| 'is'
| 'hour'
| 'hours'
| 'Interval'
| 'let'
| 'List'
| 'maximum'
| 'millisecond'
| 'milliseconds'
| 'minimum'
| 'minute'
| 'minutes'
| 'month'
| 'months'
| 'not'
| 'null'
| 'occurs'
| 'of'
| 'on or'
| 'or'
| 'or on'
| 'per'
| 'point'
| 'properly'
| 'return'
| 'same'
| 'second'
| 'seconds'
| 'singleton'
| 'sort'
| 'such that'
| 'then'
| 'to'
| 'true'
| 'Tuple'
| 'week'
| 'weeks'
| 'when'
| 'with'
| 'within'
| 'without'
| 'year'
| 'years'
;
// Keyword identifiers are keywords that may be used as identifiers in a referential context
// Effectively, keyword except reservedWord
keywordIdentifier
: 'asc'
| 'ascending'
| 'by'
| 'called'
| 'code'
| 'codesystem'
| 'codesystems'
| 'concept'
| 'contains'
| 'context'
| 'date'
| 'default'
| 'define'
| 'desc'
| 'descending'
| 'display'
| 'div'
| 'end'
| 'ends'
| 'except'
| 'fluent'
| 'function'
| 'implies'
| 'include'
| 'includes'
| 'intersect'
| 'library'
| 'meets'
| 'mod'
| 'or after'
| 'or before'
| 'or less'
| 'or more'
| 'overlaps'
| 'parameter'
| 'predecessor'
| 'private'
| 'public'
| 'start'
| 'starting'
| 'starts'
| 'successor'
| 'time'
| 'timezone' // NOTE: 1.3 Compatibility Level only
| 'timezoneoffset'
| 'union'
| 'using'
| 'valueset'
| 'version'
| 'where'
| 'width'
| 'xor'
;
// Obsolete identifiers are keywords that could be used as identifiers in CQL 1.3
// NOTE: Not currently used, this is the set of keywords that were defined as allowed identifiers as part of 1.3
// NOTE: Several keywords were commented out in this list (notably exists) because of an issue with the ANTLR tooling.
// In 4.5, having these keywords as identifiers results in unacceptable parsing performance. In 4.6+, having them as
// identifiers resulted in incorrect parsing. See Github issue [#343](https://github.com/cqframework/clinical_quality_language/issues/343) for more detail
// This should no longer be an issue with 1.4 due to the introduction of reserved words
obsoleteIdentifier
: 'all'
| 'Code'
| 'code'
| 'Concept'
| 'concept'
| 'contains'
| 'date'
| 'display'
| 'distinct'
| 'end'
| 'exists'
| 'not'
| 'start'
| 'time'
| 'timezone' // NOTE: 1.3 Compatibility level only
| 'timezoneoffset'
| 'version'
| 'where'
;
// Function identifiers are keywords that may be used as identifiers for functions
functionIdentifier
: 'after'
| 'aggregate'
| 'all'
| 'and'
| 'as'
| 'asc'
| 'ascending'
| 'before'
| 'between'
| 'by'
| 'called'
| 'case'
| 'cast'
| 'code'
| 'Code'
| 'codesystem'
| 'codesystems'
| 'collapse'
| 'concept'
| 'Concept'
| 'contains'
| 'context'
| 'convert'
| 'date'
| 'day'
| 'days'
| 'default'
| 'define'
| 'desc'
| 'descending'
| 'difference'
| 'display'
| 'distinct'
| 'div'
| 'duration'
| 'during'
| 'else'
| 'end'
| 'ends'
| 'except'
| 'exists'
| 'expand'
| 'false'
| 'flatten'
| 'fluent'
| 'from'
| 'function'
| 'hour'
| 'hours'
| 'if'
| 'implies'
| 'in'
| 'include'
| 'includes'
| 'included in'
| 'intersect'
| 'Interval'
| 'is'
| 'let'
| 'library'
| 'List'
| 'maximum'
| 'meets'
| 'millisecond'
| 'milliseconds'
| 'minimum'
| 'minute'
| 'minutes'
| 'mod'
| 'month'
| 'months'
| 'not'
| 'null'
| 'occurs'
| 'of'
| 'or'
| 'or after'
| 'or before'
| 'or less'
| 'or more'
| 'overlaps'
| 'parameter'
| 'per'
| 'point'
| 'predecessor'
| 'private'
| 'properly'
| 'public'
| 'return'
| 'same'
| 'singleton'
| 'second'
| 'seconds'
| 'start'
| 'starting'
| 'starts'
| 'sort'
| 'successor'
| 'such that'
| 'then'
| 'time'
| 'timezone' // NOTE: 1.3 Compatibility level only
| 'timezoneoffset'
| 'to'
| 'true'
| 'Tuple'
| 'union'
| 'using'
| 'valueset'
| 'version'
| 'week'
| 'weeks'
| 'where'
| 'when'
| 'width'
| 'with'
| 'within'
| 'without'
| 'xor'
| 'year'
| 'years'
;
// Reserved words that are also type names
typeNameIdentifier
: 'Code'
| 'Concept'
| 'date'
| 'time'
;
referentialIdentifier
: identifier
| keywordIdentifier
;
referentialOrTypeNameIdentifier
: referentialIdentifier
| typeNameIdentifier
;
identifierOrFunctionIdentifier
: identifier
| functionIdentifier
;
identifier
: IDENTIFIER
| DELIMITEDIDENTIFIER
| QUOTEDIDENTIFIER
;
QUOTEDIDENTIFIER
: '"' (ESC | .)*? '"'
;
DATETIME
: '@' DATEFORMAT 'T' TIMEFORMAT? TIMEZONEOFFSETFORMAT?
;
LONGNUMBER
: [0-9]+'L'
;
fragment ESC
: '\\' ([`'"\\/fnrt] | UNICODE) // allow \`, \', \", \\, \/, \f, etc. and \uXXX
;