Skip to content

Korml v0 Grammar

This page defines the v0 grammar at the token level. v0 is the unversioned, YAML-compatible, single-document language. The node grammar is the same as v1; the stream/document-boundary wrapper is not present.

Status

Korml v0 is intended as the YAML-compatible minimal source format: one document, no version header, and no support for multiple documents.

Notation

Form Meaning
A ::= B A is defined as B.
A? zero or one occurrence of A.
A* zero or more occurrences of A.
A+ one or more occurrences of A.
A \| B either A or B.
TOKEN a lexer token.

Whitespace, comments, and blank lines are trivia from the point of view of the semantic document model. They are nevertheless retained by the concrete syntax tree.

Token classes

The v0 parser is defined over these token classes:

WHITESPACE
COMMENT
NEWLINE
EOF

INDENT
DEDENT

DASH_ITEM
COLON

FLOW_SEQUENCE_START
FLOW_SEQUENCE_END
FLOW_MAPPING_START
FLOW_MAPPING_END
FLOW_SEPARATOR

SQ_SCALAR
DQ_SCALAR
PLAIN_SCALAR
LITERAL_BLOCK_SCALAR
FOLDED_BLOCK_SCALAR

INDENT and DEDENT are abstract layout tokens. An implementation may either emit them explicitly or derive the same structure from retained whitespace tokens.

v0 does not use VERSION_DIRECTIVE, DOC_START, or DOC_END tokens. A source containing a version directive or document boundary marker is not a valid v0 source.

Source

A v0 source text represents exactly one implicit document. The document may be empty.

Source ::= Trivia* Node? Trivia* EOF

There is no version directive and no explicit document start marker. The version is implicit: a source parsed as v0 is a Korml v0 document.

Examples of complete v0 sources:

name: example
enabled: true
- alpha
- beta
- gamma

Nodes

Node ::= BlockNode
       | FlowNode
       | Scalar

BlockNode ::= BlockMapping
            | BlockSequence

FlowNode ::= FlowMapping
           | FlowSequence

A node is the syntactic form that represents a document-model value. The document model has only mappings, sequences, scalars, and the empty document. An empty document is a source with no node at all. There is no empty node anywhere else: every mapping entry, sequence entry and flow entry has a value.

Block mappings

BlockMapping ::= MappingEntry+

MappingEntry ::= SimpleKey COLON MappingValue

SimpleKey ::= Scalar

MappingValue ::= InlineValue
               | NestedBlockValue

InlineValue ::= Trivia* (FlowNode | Scalar)

NestedBlockValue ::= Trivia* NEWLINE INDENT BlockNode DEDENT

Only simple scalar keys are part of Korml v0. Complex keys are intentionally excluded.

Every mapping entry has a value: a key followed by nothing, as in key:, is not valid. An empty string is written "", an empty sequence [] and an empty mapping {}.

Example:

title: Example
count: 3
nested:
  enabled: true
  target: local

Block sequences

BlockSequence ::= SequenceEntry+

SequenceEntry ::= DASH_ITEM SequenceValue

SequenceValue ::= InlineValue
                | NestedBlockValue

Every sequence entry has a value: a dash followed by nothing is not valid.

Examples:

- alpha
- beta
- gamma
- name: first
  enabled: true
- name: second
  enabled: false

Flow mappings

FlowMapping ::= FLOW_MAPPING_START Trivia* FlowMappingEntries? Trivia* FLOW_MAPPING_END

FlowMappingEntries ::= FlowMappingEntry (Trivia* FLOW_SEPARATOR Trivia* FlowMappingEntry)*

FlowMappingEntry ::= SimpleKey Trivia* COLON Trivia* FlowValue

Example:

{ name: example, enabled: true }

Flow sequences

FlowSequence ::= FLOW_SEQUENCE_START Trivia* FlowSequenceEntries? Trivia* FLOW_SEQUENCE_END

FlowSequenceEntries ::= FlowValue (Trivia* FLOW_SEPARATOR Trivia* FlowValue)*

Example:

[alpha, beta, gamma]

Flow values

FlowValue ::= FlowMapping
            | FlowSequence
            | FlowScalar

FlowScalar ::= SQ_SCALAR
             | DQ_SCALAR
             | PLAIN_SCALAR

Block scalars are block constructs and are not flow scalar forms.

Every flow entry has a value, so { key: }, [alpha, , gamma] and a trailing separator as in [alpha, beta, ] are not valid. The empty collections [] and {} are values and remain valid.

Scalars

Scalar ::= SQ_SCALAR
         | DQ_SCALAR
         | PLAIN_SCALAR
         | LITERAL_BLOCK_SCALAR
         | FOLDED_BLOCK_SCALAR

Korml has no block-scalar chomping indicators: |-, |+, >- and >+ are not valid. How a block scalar's final line breaks belong to its value is fixed by the lexical structure.

At the language level, scalar values are text. Boolean, integer, floating-point, date, and application-specific interpretation belong to a schema or decoding layer, not to the core grammar.

Trivia

Trivia ::= WHITESPACE
         | COMMENT
         | NEWLINE

Trivia does not create document-model values. It is part of the concrete syntax and must be retained by round-trip preserving implementations.