Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Grammar

This chapter presents Ion 1.1's domain grammar, by which we mean the grammar of the domain of values that drive Ion's encoding features.

We use a BNF-like notation for describing various syntactic parts of a document, including Ion data structures. In such cases, the BNF should be interpreted loosely to accommodate Ion-isms like commas, whitespace, and unconstrained ordering of struct fields.

For brevity, the following components are not explicitly defined in this grammar:

  • value - any Ion value literal
  • unannotated-identifier-symbol - an unannotated "identifier symbol" (as defined in the specification)
  • unannotated-uint - an unannotated integer greater than or equal to zero

Documents

document           ::= ivm segment*

ivm                ::= '$ion_1_1'

any-value-encoding ::= value | e-expression | tagless-element-list | tagless-element-sexp

segment            ::= any-value-encoding* directive?

directive          ::= ivm | encoding-directive

Directives

encoding-directive    ::= '(:$ion ' any-directive-content ')'

any-directive-content ::= set-symbols-content | add-symbols-content | set-macros-content | add-macros-content
                        | use-content | module-content | import-content | encoding-content

set-symbols-content   ::= 'set_symbols' symbol-text*
add-symbols-content   ::= 'add_symbols' symbol-text*
set-macros-content    ::= 'set_macros' macro-definition*
add-macros-content    ::= 'add_macros' macro-definition*
use-content           ::= 'use' catalog-key
module-content        ::= 'module' module-name macro-table? symbol-table?
import-content        ::= 'import' module-name catalog-key
encoding-content      ::= 'encoding' module-name*

Modules

catalog-key             ::= catalog-name catalog-version?

catalog-name            ::= string

catalog-version         ::= unannotated-uint

module-name             ::= unannotated-identifier-symbol

symbol-table            ::= '(symbols' symbol-table-entry* ')'

symbol-table-entry      ::= module-name | symbol-list

symbol-list             ::= '[' symbol-text* ']'

symbol-text             ::= symbol | string

macro-table             ::= '(macros' macro-table-entry* ')'

macro-table-entry       ::= macro-definition | module-name

Macro references

qualified-macro-ref     ::= module-name '::' macro-ref

macro-ref               ::= macro-name | macro-addr

macro-name              ::= unannotated-identifier-symbol

macro-addr              ::= unannotated-uint

any-macro-ref-encoding  ::= macro-ref | qualified-macro-ref

Macro definitions

no-argument                ::= '(:)'
macro-name-declaration     ::= macro-name | 'null'
macro-definition           ::= '(' macro-name-declaration value-with-placeholders ')' ; This prohibits "identity" macros

value-or-placeholder       ::= value-with-placeholders | placeholder
list-with-placeholders     ::= '[' value-or-placeholder* ']' ; Note: for brevity, this grammar avoids comma handling
sexp-with-placeholders     ::= '(' value-or-placeholder* ')'
field-value-or-placeholder ::= symbol-text ':' value-or-placeholder
struct-with-placeholders   ::= '{' field-value-or-placeholder* '}'
argument-or-placeholder    ::= value-with-placeholders | no-argument | placeholder
e-exp-with-placeholders    ::= '(:' any-macro-ref-encoding argument-or-placeholder* ')'
value-with-placeholders    ::= value | list-with-placeholders | sexp-with-placeholders
                             | struct-with-placeholders | e-exp-with-placeholders

primitive-encoding-type    ::= 'int' | 'int8' |  'int16' |  'int32' |  'int64'
                             | 'uint' | 'uint8' | 'uint16' | 'uint32' | 'uint64'
                             | 'float16' | 'float32' | 'float64'
                             | 'small_decimal'
                             | 'timestamp_day' | 'timestamp_min' | 'timestamp_s'
                             | 'timestamp_ms' | 'timestamp_us' | 'timestamp_ns'
                             | 'symbol'

primitive-type-marker      ::= '{#' primitive-encoding-type '}'
macro-type-marker          ::= '{:' any-macro-ref-encoding '}'
any-type-marker-encoding   ::= primitive-type-marker | macro-type-marker

placeholder                ::= tagged-placeholder | tagged-placeholder-default | tagless-placeholder
tagged-placeholder         ::= '(:?)'
tagged-placeholder-default ::= '(:? ' any-value-encoding ')'
tagless-placeholder        ::= '(:? ' primitive-type-marker ')'

tagless-element-list       ::= '[' any-type-marker-encoding value* ']'
tagless-element-sexp       ::= '(' any-type-marker-encoding value* ')'

E-expressions

argument            ::= any-value-encoding | no-argument
e-expression        ::= '(:' any-macro-ref-encoding argument* ')'