grammar = `
@top Instances { (statement? newline)* statement? }
@tokens {
OpenBrace[closedBy="CloseBrace"] { "{" }
CloseBrace[openedBy="OpenBrace"] { "}" }
OpenBracket[closedBy="CloseBracket"] { "[" }
CloseBracket[openedBy="OpenBracket"] { "]" }
RightArrow { "->" }
LeftArrow { "<-" }
newline { "\n" }
space { (" " | "\t")+ }
Comment { "#" ![\n]* }
identifier { std.asciiLetter (std.asciiLetter | std.digit)* }
Id { '0' | $[1-9] @digit* }
hexDig { $[0-9A-Fa-f] }
subDelims { $[!$&'()*+,;=] }
unreserved { $[A-Za-z0-9\-._~] }
pctEncoded { "%" hexDig hexDig }
decOctet { "25" $[0-5] | "2" $[0-4] std.digit | $[01]? std.digit std.digit? }
ipv4address { decOctet "." decOctet "." decOctet "." decOctet }
h16 { hexDig (hexDig (hexDig hexDig?)?)? }
ls32 { h16 ":" h16 | ipv4address }
ipv6address {
h16 ":" h16 ":" h16 ":" h16 ":" h16 ":" h16 ":" ls32
| "::" h16 ":" h16 ":" h16 ":" h16 ":" h16 ":" ls32
| h16? "::" h16 ":" h16 ":" h16 ":" h16 ":" ls32
| (h16 (":" h16)?)? "::" h16 ":" h16 ":" h16 ":" ls32
| (h16 (":" h16 (":" h16)?)?)? "::" h16 ":" h16 ":" ls32
| (h16 (":" h16 (":" h16 (":" h16)?)?)?)? "::" h16 ":" ls32
| (h16 (":" h16 (":" h16 (":" h16 (":" h16)?)?)?)?)? "::" ls32
| (h16 (":" h16 (":" h16 (":" h16 (":" h16 (":" h16)?)?)?)?)?)? "::" h16
| (h16 (":" h16 (":" h16 (":" h16 (":" h16 (":" h16 (":" h16)?)?)?)?)?)?)? "::"
}
ipvFuture { $[Vv] hexDig+ "." (unreserved | subDelims | ":")+ }
ipLiteral { "[" (ipv6address | ipvFuture) "]" }
regName { (unreserved | pctEncoded | subDelims)* }
host { ipLiteral | ipv4address | regName }
userinfo { (unreserved | pctEncoded | subDelims | ":")* }
authority { (userinfo "@")? host (":" std.digit+)? }
pchar { unreserved | pctEncoded | subDelims | ":" | "@" }
scheme { std.asciiLetter $[A-Za-z0-9+\-.]* }
uri { scheme ":" ("//" authority | "/"? pchar+) ("/" pchar*)* }
char { $[\\u{20}\\u{21}\\u{23}-\\u{5b}\\u{5d}-\\u{10ffff}] | "\\\\" esc }
esc { $["\\\/bfnrt] | "u" hex hex hex hex }
hex { $[0-9a-fA-F] }
unit { "()" } // the haskell way?
string { '"' char* '"' }
boolean { "true" | "false" }
// f32 { "" }
// f64 { "" }
// i64 { "" }
// i32 { "" }
// i16 { "" }
// i8 { "" }
// u64 { "" }
// u32 { "" }
// u16 { "" }
// u8 { "" }
// bytes { "" }
// JSON { "JSON" } // should we import the JSON grammar?
term { identifier ":" (pchar | "/" | "?")* pchar+ }
Namespace { uri $[/?#] }
@precedence { boolean, uri }
}
@skip { space | Comment }
delimited<element> { (newline element?)* newline }
Literal {
unit | string | boolean
// | f32 | f64 | i64 | i32 | i16 | i8 | u64 | u32 | u16 | u8
// | bytes
// | JSON
}
Key { term }
Element { Key "#" Value }
Value { uri | Literal | Product | Coproduct | Reference }
Product { OpenBrace delimited<Component>? CloseBrace }
Component { Key RightArrow Value }
Coproduct { OpenBracket delimited<Option>? CloseBracket }
Option { Key (LeftArrow Value)? }
Reference { "*" Key }
statement { NamespaceDefinition | ElementDeclaration }
NamespaceDefinition { @specialize[@name=namespace]<identifier, "namespace"> Prefix { identifier } Namespace }
ElementDeclaration { @specialize[@name=element]<identifier, "element"> Key Value }
`;