Ion Schema 2.0 BNF-Style Grammar
This grammar is intended as a learning aid and is not authoritative.
Some limitations of this grammar are that it cannot accurately represent open content, that it excludes equivalent encodings of an Ion value (e.g. the symbol year
could also be 'year'
), that it does not describe a valid ISL regex string, and that it does not describe reserved words that cannot be used as a type name.
<ISL_VERSION_MARKER> ::= $ion_schema_2_0 <SCHEMA> ::= <ISL_VERSION_MARKER> [<HEADER>] <NAMED_TYPE_DEFINITION>... [<FOOTER>] <HEADER> ::= schema_header::{ <HEADER_FIELD>... } <HEADER_FIELD> ::= <IMPORTS_DECLARATION> | <USER_RESERVED_FIELDS_DECLARATION> <IMPORTS_DECLARATION> ::= imports: [ <IMPORT>... ], <IMPORT> ::= <IMPORT_SCHEMA> | <IMPORT_TYPE> | <IMPORT_TYPE_ALIAS> <IMPORT_SCHEMA> ::= { id: <SCHEMA_ID> } <IMPORT_TYPE> ::= { id: <SCHEMA_ID>, type: <TYPE_NAME> } <IMPORT_TYPE_ALIAS> ::= { id: <SCHEMA_ID>, type: <TYPE_NAME>, as: <TYPE_NAME> } <USER_RESERVED_FIELDS_DECLARATION> ::= user_reserved_fields: { <USER_RESERVED_FIELDS_DECLARATION_FIELD>... } <USER_RESERVED_FIELDS_DECLARATION_FIELD> ::= schema_header: [ <SYMBOL>... ], | type: [ <SYMBOL>... ], | schema_footer: [ <SYMBOL>... ], <FOOTER> ::= schema_footer::{ } <NAMED_TYPE_DEFINITION> ::= type::{ name: <TYPE_NAME>, <CONSTRAINT>... } <INLINE_TYPE_DEFINITION> ::= { <CONSTRAINT>... } <SCHEMA_ID> ::= <STRING> | <SYMBOL> <TYPE_NAME> ::= <SYMBOL> <TYPE_ARGUMENT> ::= <TYPE_NAME> | $null_or::<TYPE_NAME> | <INLINE_TYPE_DEFINITION> | $null_or::<INLINE_TYPE_DEFINITION> | <IMPORT_TYPE> | $null_or::<IMPORT_TYPE> <OCCURS> ::= occurs: <INT> | occurs: <RANGE_INT> | occurs: optional | occurs: required <VARIABLY_OCCURRING_TYPE_ARGUMENT> ::= { <OCCURS>, <CONSTRAINT>... } | <TYPE_ARGUMENT> <NUMBER> ::= <DECIMAL> | <FLOAT> | <INT> <EXCLUSIVITY> ::= exclusive:: | "" <RANGE_INT> ::= range::[ <EXCLUSIVITY><INT>, <EXCLUSIVITY><INT> ] | range::[ min, <EXCLUSIVITY><INT> ] | range::[ <EXCLUSIVITY><INT>, max ] <RANGE_NUMBER> ::= range::[ <EXCLUSIVITY><NUMBER>, <EXCLUSIVITY><NUMBER> ] | range::[ min, <EXCLUSIVITY><NUMBER> ] | range::[ <EXCLUSIVITY><NUMBER>, max ] <RANGE_TIMESTAMP> ::= range::[ <EXCLUSIVITY><TIMESTAMP>, <EXCLUSIVITY><TIMESTAMP> ] | range::[ min, <EXCLUSIVITY><TIMESTAMP> ] | range::[ <EXCLUSIVITY><TIMESTAMP>, max ] <RANGE_TIMESTAMP_PRECISION> ::= range::[ <EXCLUSIVITY><TIMESTAMP_PRECISION_VALUE>, <EXCLUSIVITY><TIMESTAMP_PRECISION_VALUE> ] | range::[ min, <EXCLUSIVITY><TIMESTAMP_PRECISION_VALUE> ] | range::[ <EXCLUSIVITY><TIMESTAMP_PRECISION_VALUE>, max ] <CONSTRAINT> ::= <ALL_OF> | <ANNOTATIONS> | <ANY_OF> | <BYTE_LENGTH> | <CODEPOINT_LENGTH> | <CONTAINER_LENGTH> | <CONTAINS> | <CONTENT> | <ELEMENT> | <EXPONENT> | <FIELDS> | <FIELD_NAMES> | <IEEE745_FLOAT> | <NOT> | <ONE_OF> | <ORDERED_ELEMENTS> | <PRECISION> | <REGEX> | <TIMESTAMP_OFFSET> | <TIMESTAMP_PRECISION> | <TYPE> | <VALID_VALUES> <ALL_OF> ::= all_of: [ <TYPE_ARGUMENT>... ] <ANNOTATIONS_MODIFIER> ::= required:: | closed:: <ANNOTATIONS> ::= annotations: <ANNOTATIONS_MODIFIER>... [ <SYMBOL>... ] | annotations: <TYPE_ARGUMENT> <ANY_OF> ::= any_of: [ <TYPE_ARGUMENT>... ] <BYTE_LENGTH> ::= byte_length: <INT> | byte_length: <RANGE_INT> <CODEPOINT_LENGTH> ::= codepoint_length: <INT> | codepoint_length: <RANGE_INT> <CONTAINER_LENGTH> ::= container_length: <INT> | container_length: <RANGE_INT> <CONTAINS> ::= contains: [ <VALUE>... ] <ELEMENT> ::= element: <TYPE_ARGUMENT> | element: distinct::<TYPE_ARGUMENT> <EXPONENT> ::= exponent: <INT> | exponent: <RANGE_INT> <FIELD> ::= <SYMBOL>: <VARIABLY_OCCURRING_TYPE_ARGUMENT> <FIELDS> ::= fields: { <FIELD>... } | fields: closed::{ <FIELD>... } <FIELD_NAMES> ::= field_names: <TYPE_ARGUMENT> | field_names: distinct::<TYPE_ARGUMENT> <IEEE754_FLOAT> ::= ieee754_float: binary16 | ieee754_float: binary32 | ieee754_float: binary64 <NOT> ::= not: <TYPE_ARGUMENT> <ONE_OF> ::= one_of: [ <TYPE_ARGUMENT>... ] <ORDERED_ELEMENTS> ::= ordered_elements: [ <VARIABLY_OCCURRING_TYPE_ARGUMENT>... ] <PRECISION> ::= precision: <INT> | precision: <RANGE_INT> <REGEX> ::= regex: <STRING> | regex: i::<STRING> | regex: m::<STRING> | regex: i::m::<STRING> <TIMESTAMP_OFFSET> ::= timestamp_offset: [ "[+|-]hh:mm"... ] <TIMESTAMP_PRECISION_VALUE> ::= year | month | day | minute | second | millisecond | microsecond | nanosecond <TIMESTAMP_PRECISION> ::= timestamp_precision: <TIMESTAMP_PRECISION_VALUE> | timestamp_precision: <RANGE_TIMESTAMP_PRECISION> <TYPE> ::= type: <TYPE_ARGUMENT> <UTF8_BYTE_LENGTH> ::= utf8_byte_length: <INT> | utf8_byte_length: <RANGE_INT> <VALID_VALUES> ::= valid_values: [ <VALUE_OR_RANGE>... ] | valid_values: <RANGE_NUMBER> | valid_values: <RANGE_TIMESTAMP> <VALUE_OR_RANGE> ::= <VALUE> | <RANGE_NUMBER> | <RANGE_TIMESTAMP>