ALPHA = "A".."Z" | "a".."z" ;
DIGIT = "0".."9" ;
DQUOTE = '"' ;
SP = " " ;
TAB = ? U+0009 ? ;
CR = ? U+000D ? ;
LF = ? U+000A ? ;
WSP = SP | TAB ;
line_end = (CR , LF) | LF ;
blank = WSP | line_end ;
comment = "#" , { ? U+0009 | U+0020-U+007E ? } , line_end ;
ws = { blank | comment } ;
mws = (blank | comment) , { blank | comment } ;
document = ws , "{" , ws , { field } , ws , "}" , ws ;
identifier = identifier_begin , { identifier_contents } ;
identifier_begin = ALPHA | "_" ;
identifier_contents = ALPHA | DIGIT | "_" | "-" | "'" ;
field =
identifier
, ws
, "="
, ws
, element
, ws
, ";"
, ws ;
element =
string
| multiline_string
| list
| map
| number
| boolean
| null ;
map = "{" , ws , { field } , ws , "}" ;
list =
"["
, ws
, [ list_items ]
, ws
, "]" ;
list_items = element , { mws , element } ;
string = DQUOTE , { chars } , DQUOTE ;
chars = string_escape | string_literal ;
string_escape = "\" , ( DQUOTE | "\" ) ;
string_literal =
? U+0009 | U+000A | U+000D
| U+0020–U+0021
| U+0023–U+005B
| U+005D–U+007E
| U+0080–U+10FFFF ? ;
multiline_string = "''" , { multiline_chars } , "''" ;
multiline_chars = multiline_escape | multiline_literal ;
multiline_literal =
? U+0009 | U+000A | U+000D
| U+0020-U+007E
| U+0080-U+10FFFF ? ;
UTF8_char =
? U+0009
| U+000A
| U+000D
| U+0020–U+007E ?
| ? 2-byte UTF-8 sequence ?
| ? 3-byte UTF-8 sequence (excluding surrogates) ?
| ? 4-byte UTF-8 sequence up to U+10FFFF ? ;
number = [ "-" ] , ( decimal | integer ) ;
integer = "0" | ( non_zero , { DIGIT } ) ;
decimal = [ integer ] , "." , DIGIT , { DIGIT } ;
non_zero = "1".."9" ;
boolean = "true" | "false" ;
null = "null" ;