Skip to main content

Syntax

This page describes the concrete syntax you type when writing a FLASH block.

FLASH has two “contexts” that matter when you read the syntax:

  • FHIR target context: where a rule writes in the output resource.
  • Input context: what expressions (on the right-hand side) evaluate against.

If you’re looking for how those contexts behave at runtime (fan-out, append vs override, type shaping), see Evaluation model.

Declarations

A FLASH block starts with declarations that establish the output resource type (and optionally its id).

InstanceOf: (required)

InstanceOf: declares the FHIR type or profile identifier for the block.

InstanceOf: Patient

InstanceOf: accepts a single identifier token, such as:

  • a base type name (for example: Patient, Encounter, Observation)
  • a profile identifier from your definition set (for example: observation-bp)
  • a canonical URL (for example: http://hl7.org/fhir/StructureDefinition/Patient)

If the identifier can’t be parsed as a single token, the block fails at parse-time. If it parses but can’t be resolved in the active definition set, evaluation fails at definition-resolution time (covered in Diagnostics).

Instance: (optional)

Instance: computes an instance id for the resource. When present, it behaves like writing an id rule before the rest of the rule list.

Instance: $uuid('ExampleCare-Patient-001')
InstanceOf: Patient
* active = true

Placement and ordering:

  • Instance: appears at most once.
  • When present, Instance: is the first line of the block and is immediately followed by InstanceOf: on the next line.
  • InstanceOf: appears exactly once.

Instance: is an expression. It can be a literal string, a function call, or a complete parenthesis block. The expression must evaluate to a string or a primitive value that can safely be converted to a string.

Rule forms

After declarations, the block contains a list of rule lines and (optionally) variable bindings.

Rule lines start with * (after any indentation).

Assignment rule

An assignment rule writes the result of an expression (right-hand side of the =) into a FHIR target path.

InstanceOf: Patient
* active = true
* birthDate = "1985-01-23"

Form:

* <path> = <expr>

Context rule (target nesting)

A context rule sets the FHIR target context for nested rules. Nested rules are indented beneath the parent.

InstanceOf: Patient
* name
* family = "ExampleCare"
* given = "Avery"

Form:

* <path>
* <child-path> = <expr>
* <child-path>
...

Empty rule

It’s also valid to write a context rule with no right-hand side and no nested rules:

InstanceOf: Observation
* code.coding[ExampleCarePanel]

This “empty rule” form is used to materialize/validate the target element (for example, to force creation/selection of a sliced entry) without directly assigning a value on that line.

Input-context rule (input focus for nested evaluation)

An input-context rule changes the input context used by nested expressions, while the FHIR target context is still defined by the rule’s path.

InstanceOf: Patient
* (phones).telecom
* system = "phone"
* value = $

Form:

* (<expr>).<path>
...nested rules...

The same shape can also be used as a single-line assignment:

InstanceOf: Patient
* (patientId).id = $

If the input-context expression evaluates to an array, the nested rule set is evaluated once per item. JSONata focus/index binding syntax (like @$value and #$index) can be used inside the parentheses to control what $ and bound variables refer to.

Variable bindings inside a block

Variable bindings use JSONata’s assignment operator and are allowed inside a FLASH block.

InstanceOf: Patient
$fullName := firstName & " " & lastName
* name.text = $fullName

Form:

$name := <expr>

Within a FLASH block, lines that are neither rules (* ...) nor variable bindings ($name := ...) are rejected.

Indentation and blocks

FLASH uses indentation to express nesting.

  • Nesting depth advances in 2-space increments.
  • A nested line has greater indentation than its parent line.
  • Decreasing indentation closes blocks.
  • Mixing indentation widths (for example, 1 space) produces parse-time indentation errors.

The stable convention is 2 spaces per level. Tabs are accepted as indentation, but they’re easy to misalign visually; 2 spaces avoids “looks aligned, parses misaligned” failures.

Example with two nesting levels:

InstanceOf: Patient
* name
* period
* start = "2020-01-01"

Example of “continue a long path” using blocks (instead of trying to split a path across lines):

InstanceOf: Patient
* identifier
* assigner
* reference = "Organization/examplecare"

Paths and slices

Rule paths target FHIR JSON element names.

Path segments

  • Paths are dot-separated segments: a.b.c.
  • Segments are simple name tokens (they are not expressions).
  • Paths cannot be split across lines.

Multi-step paths are allowed on one line:

InstanceOf: Patient
* name.family = "ExampleCare"

If you prefer, the same write can be expressed using a context rule:

InstanceOf: Patient
* name
* family = "ExampleCare"

Choice types

When a FHIR element is a choice type (like value[x]), rule paths use the concrete JSON name (for example: valueQuantity, valueString, valueCodeableConcept).

InstanceOf: Observation
* valueQuantity = 180

Slice selectors with brackets

Brackets in FLASH paths are used for slice/profile selection, not array indexing.

InstanceOf: Patient
* identifier[ExampleCareMrn]
* system = "urn:examplecare:mrn"
* value = mrn

Slice selectors behave like element[sliceId], where sliceId is a legal slice identifier (often a simple name; some slices can be targeted via canonical identifiers/URLs, depending on how your definitions are authored).

Invalid patterns for brackets include:

  • name[0] (indexing)
  • identifier[1+2] (expressions)
  • coding[slice with spaces] (non-token selectors)

Comments and whitespace

For the canonical comment rules, see Comments.

Inside FLASH blocks, comments can appear on their own line or after a rule.

InstanceOf: Patient
// ExampleCare demo mapping
* active = true /* inline note */

Blank lines are allowed.

FLASH-specific gotcha: when Instance: is present, InstanceOf: immediately follows it as the next non-comment line. Putting other content between them is treated as a parse error.

Common syntax errors

  • Missing InstanceOf:: a block with rules but no InstanceOf: does not parse.
  • Separated headers: when using Instance:, placing anything between Instance: and InstanceOf: causes a parse-time error.
  • Wrong assignment operator: := is for $variables; rule assignments use =.
  • Invalid indentation: indentation that isn’t a 2-space multiple (or that doesn’t line up with an open block) fails at parse-time.
  • Using $ in a FLASH rule target path: $ variables belong in expressions (right-hand side of the =), not in rule paths.
  • Trying to index with brackets: name[0] is not valid FLASH; brackets denote slice/profile selection by name, never by numeric indices.
  • Splitting a path across lines: use a context rule to continue on the next line.
  • Semicolons inside object literals: { "a": 1; "b": 2 } is not valid.