nodes := linespace* (node nodes?)? linespace* node := ('/-' node-space*)? type? identifier (node-space+ node-prop-or-arg)* (node-space* node-children ws*)? node-space* node-terminator node-prop-or-arg := ('/-' node-space*)? (prop | value) node-children := ('/-' node-space*)? '{' nodes '}' node-space := ws* escline ws* | ws+ node-terminator := single-line-comment | newline | ';' | eof identifier := string | bare-identifier bare-identifier := ((identifier-char - digit - sign) identifier-char* | sign ((identifier-char - digit) identifier-char*)?) - keyword identifier-char := unicode - linespace - [\/(){}<>;[]=,"] keyword := boolean | 'null' prop := identifier '=' value value := type? (string | number | keyword) type := '(' identifier ')' string := raw-string | escaped-string escaped-string := '"' character* '"' character := '\' escape | [^\"] escape := ["\\/bfnrt] | 'u{' hex-digit{1, 6} '}' hex-digit := [0-9a-fA-F] raw-string := 'r' raw-string-hash raw-string-hash := '#' raw-string-hash '#' | raw-string-quotes raw-string-quotes := '"' .* '"' number := decimal | hex | octal | binary decimal := sign? integer ('.' integer)? exponent? exponent := ('e' | 'E') sign? integer integer := digit (digit | '_')* digit := [0-9] sign := '+' | '-' hex := sign? '0x' hex-digit (hex-digit | '_')* octal := sign? '0o' [0-7] [0-7_]* binary := sign? '0b' ('0' | '1') ('0' | '1' | '_')* boolean := 'true' | 'false' escline := '\\' ws* (single-line-comment | newline) linespace := newline | ws | single-line-comment newline := See Table (All line-break white_space) ws := bom | unicode-space | multi-line-comment bom := '\u{FEFF}' unicode-space := See Table (All White_Space unicode characters which are not `newline`) single-line-comment := '//' ^newline+ (newline | eof) multi-line-comment := '/*' commented-block commented-block := '*/' | (multi-line-comment | '*' | '/' | [^*/]+) commented-block