Skip to content

Commit

Permalink
Adds Ion Schema 2.0 specification (#82)
Browse files Browse the repository at this point in the history
  • Loading branch information
popematt authored Sep 22, 2022
1 parent 951556f commit 8671e3b
Show file tree
Hide file tree
Showing 7 changed files with 992 additions and 2 deletions.
5 changes: 5 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -251,13 +251,18 @@ GEM
unf_ext
unf_ext (0.0.8.2)
unicode-display_width (1.8.0)
webrick (1.7.0)
zeitwerk (2.6.0)

PLATFORMS
ruby

DEPENDENCIES
github-pages
webrick (~> 1.7)

RUBY VERSION
ruby 2.6.8p205

BUNDLED WITH
1.17.2
2 changes: 1 addition & 1 deletion _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ baseurl: /ion-schema
markdown: kramdown
kramdown:
input: GFM
toc_levels: "2,3"
toc_levels: "1,2"
highlighter: rouge
defaults:
-
Expand Down
179 changes: 179 additions & 0 deletions _includes/grammar-2-0.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
<ISL_VERSION_MARKER> ::= $ion_schema_2_0

<SCHEMA> ::= <ISL_VERSION_MARKER> <NAMED_TYPE_DEFINITION>...
| <ISL_VERSION_MARKER> <HEADER> <NAMED_TYPE_DEFINITION>... <FOOTER>

<HEADER> ::= schema_header::{ <HEADER_FIELD>... }

<HEADER_FIELD> ::= <IMPORTS_DECLARATION>
| <USER_CONTENT_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_CONTENT_DECLARATION> ::= user_content: { <USER_CONTENT_DECLARATION_FIELD>... }

<USER_CONTENT_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_REFERENCE> ::= <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_REFERENCE> ::= { <OCCURS>, <CONSTRAINT>... }
| <TYPE_REFERENCE>

<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_REFERENCE>... ]

<ANNOTATIONS_MODIFIER> ::= required::
| closed::

<ANNOTATIONS> ::= annotations: <ANNOTATIONS_MODIFIER>... [ <SYMBOL>... ]
| annotations: <TYPE_REFERENCE>

<ANY_OF> ::= any_of: [ <TYPE_REFERENCE>... ]

<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_REFERENCE>
| element: distinct::<TYPE_REFERENCE>

<EXPONENT> ::= exponent: <INT>
| exponent: <RANGE_INT>

<FIELD> ::= <SYMBOL>: <VARIABLY_OCCURRING_TYPE_REFERENCE>

<FIELDS> ::= fields: { <FIELD>... }
| fields: closed::{ <FIELD>... }

<FIELD_NAMES> ::= field_names: <TYPE_REFERENCE>
| field_names: distinct::<TYPE_REFERENCE>

<IEEE754_FLOAT> ::= ieee754_float: binary16
| ieee754_float: binary32
| ieee754_float: binary64

<NOT> ::= not: <TYPE_REFERENCE>

<ONE_OF> ::= one_of: [ <TYPE_REFERENCE>... ]

<ORDERED_ELEMENTS> ::= ordered_elements: [ <VARIABLY_OCCURRING_TYPE_REFERENCE>... ]

<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_REFERENCE>

<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>
26 changes: 26 additions & 0 deletions _includes/grammar-element.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!--
Arguments:
productions: a comma separated list of production names. E.g. "TIMESTAMP_PRECISION,TIMESTAMP_PRECISION_VALUE"
TODO: When introducing ISL 2.1, make this accept an argument containing the ISL version number.
-->
{% assign productions = include.productions | upcase | split: "," %}
{% capture grammar %}
{% include grammar-2-0.txt %}
{% endcapture %}
{% assign grammar_lines = grammar | escape_once | newline_to_br | split: '<br />' %}

<div class="bs-callout bs-callout-grammar">
<pre>
{%- for production in productions -%}
{%- assign is_in_production = false -%}
{%- assign production_start = "&lt;PRODUCTION> ::=" | escape_once | replace: "PRODUCTION", production -%}
{%- for grammar_line in grammar_lines -%}
{%- assign grammar_line_stripped = grammar_line | strip -%}
{%- if grammar_line contains production_start -%}{%- assign is_in_production = true -%}{%- endif -%}
{%- if is_in_production -%}{{- grammar_line | escape_once -}}{%- endif -%}
{%- if is_in_production and grammar_line_stripped == "" -%}{%- break -%}{%- endif -%}
{%- endfor -%}
{%- endfor -%}
</pre>
</div>
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ redirect_from:

* [Ion Schema Language Versioning](isl-versioning)
* [Ion Schema 1.0 Specification](isl-1-0/spec)
* Ion Schema 2.0 Specification (Coming soon!)
* [Ion Schema 2.0 Specification](isl-2-0/spec)

### Cookbooks

Expand Down
13 changes: 13 additions & 0 deletions docs/isl-2-0/bnf-grammar.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
title: Ion Schema 2.0 BNF-Style Grammar
---
# {{page.title}}

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.

{% capture grammar %}{% include grammar-2-0.txt %}{% endcapture %}
<pre class="grammar">
{{ grammar | escape_once }}
</pre>
Loading

0 comments on commit 8671e3b

Please sign in to comment.