idl =
{ SOI ~ ws ~ control_section ~ metadata_section ~ shape_section ~ EOI }
ws =
_{ (sp | NEWLINE | (!("///") ~ line_comment | ",") )* }
sp =
_{ " " | "\t" }
br =
_{ ws ~ EOI? }
line_comment =
_{ "//" ~ ("\t" | '\u{20}'..'\u{10FFF}')* ~ NEWLINE }
documentation_comment =
_{ ws ~ "///" ~ documentation_text ~ NEWLINE }
documentation_text =
{ ("\t" | '\u{20}'..'\u{10FFF}')* }
control_section =
{ control_statement* }
control_statement =
{ "$" ~ ws ~ node_object_key ~ ws ~ ":" ~ ws ~ node_value ~ ws }
version_string =
{ ASCII_DIGIT+ ~ ( "." ~ ASCII_DIGIT+ )? }
shape_id =
@{ root_shape_id ~ shape_id_member? }
root_shape_id =
{ absolute_root_shape_id | identifier }
absolute_root_shape_id =
{ namespace ~ "#" ~ identifier }
namespace =
@{ identifier ~ ("." ~ identifier)* }
identifier =
@{ ( ASCII_ALPHA ~ (ASCII_ALPHA | ASCII_DIGIT | "_")* )
| ( "_" ~ ASCII_ALPHA ~ (ASCII_ALPHA | ASCII_DIGIT | "_")*) }
shape_id_member =
{ "$" ~ identifier }
node_value =
{ node_array | node_object | number | node_keywords | shape_id | text_block | quoted_text }
node_array =
{ "[" ~ ws ~ (node_value ~ ws)* ~ "]" }
// { empty_node_array | populated_node_array }
//
// empty_node_array =
// { "[" ~ ws ~ "]" }
//
// populated_node_array =
// { "[" ~ ws ~ node_value ~ ws ~ (comma ~ node_value ~ ws)* ~ trailing_comma ~ "]" }
trailing_comma =
_{ comma? }
comma =
_{ "," ~ ws }
node_object =
{ "{" ~ ws ~ (node_object_kvp ~ ws)* ~ "}" }
// _{ empty_node_object | populated_node_object }
//
// empty_node_object =
// { "{" ~ ws ~ "}" }
//
// populated_node_object =
// { "{" ~ ws ~ node_object_kvp ~ ws ~ (comma ~ node_object_kvp ~ ws)* ~ trailing_comma ~ "}" }
node_object_kvp =
{ node_object_key ~ ws ~ ":" ~ ws ~ node_value }
node_object_key =
_{ quoted_text | identifier }
number =
{ minus? ~ int ~ frac? ~ exp?}
decimal_point =
{ "."}
e =
{ "e" | "E" }
exp =
{ e ~ (minus | plus)? ~ ASCII_DIGIT+ }
frac =
{ decimal_point ~ ASCII_DIGIT+ }
int =
{ zero | (ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*) }
minus =
{ "-" }
plus =
{ "+" }
zero =
{ "0" }
node_keywords =
_{ kw_true | kw_false | kw_null }
kw_true = { "true" }
kw_false = { "false" }
kw_null = { "null" }
quoted_text =
{ DQUOTE ~ quoted_chars ~ DQUOTE }
quoted_chars =
@{ ('\u{20}'..'\u{21}' | '\u{23}'..'\u{5B}' | '\u{5D}'..'\u{10FFF}' | escaped_char | preserved_double)* }
escaped_char =
{escape ~ (escape | "'" | DQUOTE | "b" | "f" | "n" | "r" | "t" | "/" | unicode_escape) }
unicode_escape =
{ "u" ~ ASCII_HEX_DIGIT ~ ASCII_HEX_DIGIT ~ ASCII_HEX_DIGIT ~ ASCII_HEX_DIGIT }
preserved_double =
{ escape ~ ('\u{20}'..'\u{21}' | '\u{23}'..'\u{5B}' | '\u{5D}'..'\u{10FFF}') }
escape =
{ "\\" }
text_block =
{ DQUOTE{3} ~ br ~ block_quoted_chars ~ DQUOTE{3} }
// three_dquotes =
// _{ DQUOTE ~ DQUOTE ~ DQUOTE }
block_quoted_chars =
@{ ( !("\"\"\"") ~ DQUOTE | sp | NEWLINE | '\u{20}'..'\u{21}' | '\u{23}'..'\u{5B}' | '\u{5D}'..'\u{10FFF}' | escaped_char | preserved_double)* }
DQUOTE =
_{ "\"" }
shape_section =
{ ( namespace_statement ~ (use_section)? ~ (shape_statements)? )? }
namespace_statement =
{ "namespace" ~ ws ~ namespace ~ ws }
use_section =
{ use_statement+ }
use_statement =
{ "use" ~ ws ~ absolute_root_shape_id ~ ws }
shape_statements =
{ (shape_statement | apply_statement)+ }
shape_statement =
{ documentation_comment* ~ ws ~ trait_statements ~ shape_body ~ ws}
shape_body =
_{ simple_shape_statement | list_statement | set_statement | map_statement | structure_statement
| union_statement | service_statement | operation_statement | resource_statement }
simple_shape_statement =
{ simple_type_name ~ ws ~ identifier }
simple_type_name =
_{ type_blob | type_boolean | type_document | type_string | type_byte | type_short | type_integer | type_long
| type_float | type_double | type_big_integer | type_big_decimal | type_timestamp }
type_blob = { "blob" }
type_boolean = {"boolean"}
type_document = {"document"}
type_string = {"string"}
type_byte = {"byte"}
type_short = {"short"}
type_integer = {"integer"}
type_long = {"long"}
type_float = {"float"}
type_double = {"double"}
type_big_integer = {"bigInteger"}
type_big_decimal = {"bigDecimal"}
type_timestamp = {"timestamp"}
shape_members =
{ "{" ~ ws ~ (shape_member_kvp ~ ws)* ~ "}" }
// _{ empty_shape_members | populated_shape_members }
//
// empty_shape_members =
// { "{" ~ ws ~ "}" }
//
// populated_shape_members =
// { "{" ~ ws ~ shape_member_kvp ~ ws ~ (comma ~ shape_member_kvp ~ ws)* ~ trailing_comma ~ ws ~ "}" }
shape_member_kvp =
{ documentation_comment* ~ ws ~ trait_statements ~ identifier ~ ws ~ ":" ~ ws ~ shape_id }
list_statement =
{ "list" ~ ws ~ identifier ~ ws ~ shape_members }
set_statement =
{ "set" ~ ws ~ identifier ~ ws ~ shape_members }
map_statement =
{ "map" ~ ws ~ identifier ~ ws ~ shape_members }
structure_statement =
{ "structure" ~ ws ~ identifier ~ ws ~ shape_members }
union_statement =
{ "union" ~ ws ~ identifier ~ ws ~ shape_members }
service_statement =
{ "service" ~ ws ~ identifier ~ ws ~ node_object }
operation_statement =
{"operation" ~ ws ~ identifier ~ ws ~ node_object}
resource_statement =
{ "resource" ~ ws ~ identifier ~ ws ~ node_object }
apply_statement =
{ "apply" ~ ws ~ shape_id ~ ws ~ a_trait ~ ws}
trait_statements =
{ (ws ~ a_trait)* ~ ws }
a_trait =
{ "@" ~ shape_id ~ trait_body? }
trait_body =
// _{ empty_trait_body | populated_trait_body }
//
// empty_trait_body =
// _{ "(" ~ ws ~ ")" }
//
// populated_trait_body =
_{ "(" ~ ws ~ (trait_body_value ~ ws)* ~ ")" }
trait_body_value =
_{ trait_structure | node_value }
trait_structure =
_{ trait_structure_kvp ~ (ws ~ trait_structure_kvp)* }
trait_structure_kvp =
{ node_object_key ~ ws ~ ":" ~ ws ~ node_value }
metadata_section =
{ metadata_statement* }
metadata_statement =
{ "metadata" ~ ws ~ node_object_key ~ ws ~ "=" ~ ws ~ node_value ~ ws }