EBNF

Grammar:            QueryStatement EOF
QueryStatement:     UsingClause? FromResourceClause? SearchClause? FilterClauses WithClause?

UsingClause:        'using' UsingIdentifier UsingScopeClause?
UsingScopeClause:   'with' UsingScope
UsingIdentifier:    identifier StringValue
UsingScope:         'no'? 'dependencies'

FromResourceClause: 'from' FromSource
FromSource:         EntityName | FhirPathVariable

FilterClauses:      FilterClause+
FilterClause:       WhereClause | SelectClause | ForQuery | Orderby-clause | GroupByClause | SkipClause | TakeClause | DistinctClause

SearchClause:       'search' SearchExpression RangeClause?
SearchExpression:   SearchEquation ( SearchLogicalOp SearchEquation )*
SearchLogicalOp:    'and' | 'or'
SearchEquation:     FieldName SearchEqualityOp StringValue
SearchEqualityOp:   '=' | '!=' | '<' | '>' 


SelectClause:       'select' SelectBlock
Orderby-clause:     'order' 'by' order-field-list
order-field-list:   order-field
order-field:        fieldname ('desc | 'descending')?

GroupByClause:      'group', 'by', GroupByFieldList
DistinctClause:     'distinct'
GroupByFieldList:   FhirPathExpression (',' FhirPathExpression)* 
FieldNameList:      FieldName ( ',' FieldName )*
Query:              SelectClause | ForQuery


SelectBlock:        Group | FieldList
Group:              '{' FieldList  '}'
FieldList:          Field (','  Field)* 
Field:              Fetch-declaration | JoinQuery | GroupDereference | ForQuery | Projection | FhirPathFieldPath | Wildcard

fetch-declaration:  FhirPathExpression 'fetch', FetchDereference
JoinQuery:          JoinType? 'join'  Field
JoinType:           'left' | 'inner' | 'right' | 'outer'
GroupDereference:   FhirPathSelection Group
ForQuery:           ForClause WhereClause? SelectClause
ForClause:          'for'  FhirPathSelection
FetchDereference:   Field | Group


Value:              ForQuery | Group | FhirPathExpression | JoinQuery
Projection:         FieldName  ':'  Value



WhereClause:        'where' WhereList
WhereList:          FhirPathExpression ( 'and' FhirPathExpression )*


TakeClause:         'take' NumberValue
SkipClause:         'skip' NumberValue
RangeClause:        SkipClause? TakeClause?


WithClause:         'with' WithProperties
WithProperties:      WithProperty ( ',' WithProperty )
WithProperty:        'no'? identifier



FhirPathComparison: FhirPathSelection FhirPathCompareOperator FhirPathExpression
FhirPathExpression: FhirPathOperation | FhirPathComparison | FhirPathSelection
FhirPathOperation:  FhirPathSelection  FhirPathOperator  FhirPathExpression
FhirPathSelection:  FhirPathFieldPath | FhirPathConst | FhirPathBrackets
FhirPathBrackets:   '(' FhirPathExpression ')'
FhirPathOperator:   '*' | '/' | 'div' | 'mod' | '+' | '-' | '&' | 'is' | 'as' | '|' | 'and' | 'or' | 'xor' 
FhirPathVariable:   '%' identifier
FhirPathFieldPath:  FhirPathSegment ( '.' FhirPathSegment)* 
FhirPathSegment:    FhirPathIndexedSegment | FhirPathFunction | FhirPathFieldName | FhirPathVariable
FhirPathFieldName:  identifier
FhirPathIndexedSegment: identifier '[' integer ']' 
FhirPathFunction:   identifier '(' FhirPathParameterList ')'
FhirPathParameterList: FhirPathExpression ( ',' FhirPathExpression)*
FhirPathCompareOperator ( '=' | '!=' | '!~' | '~' | '<=' | '<' | '>=' | '>' | 'is' | 'in' | 'contains' | 'implies'