WHITESPACE = _{ " " | "\t" | "\n" | "\r" } COMMENT = _{ "#" ~ (!("\n" | "\r") ~ ANY)* } uson_text = { SOI ~ expr* ~ EOI } expr = { value } // Values value = { typed | false_val | null_val | true_val | assign | object | array | number | string } false_val = { "false" } null_val = { "null" } true_val = { "true" } // Objects - support optional commas like arrays object = { "{" ~ (member ~ (","? ~ member)* ~ ","?)? ~ "}" } member = { string ~ ":" ~ value } // Arrays array = { "[" ~ (value ~ (","? ~ value)* ~ ","?)? ~ "]" } // Numbers - must not be followed by alphanumeric to avoid matching "1ab" as number number = @{ "-"? ~ int ~ ("." ~ ASCII_DIGIT+)? ~ (^"e" ~ ("+" | "-")? ~ ASCII_DIGIT+)? ~ !ASCII_ALPHANUMERIC } int = { "0" | (ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*) } // Strings string = { double_quoted_string | single_quoted_string | unquoted_string } double_quoted_string = @{ "\"" ~ (escape_sequence | (!("\"" | "\\") ~ ANY))* ~ "\"" } single_quoted_string = @{ "'" ~ (escape_sequence | (!("'" | "\\") ~ ANY))* ~ "'" } unquoted_string = @{ simple_char+ } simple_char = { !("\"" | "#" | "," | ":" | "[" | "\\" | "]" | "{" | "}" | WHITESPACE) ~ ANY } escape_sequence = @{ "\\" ~ ( "\"" | "'" | "\\" | "/" | "#" | "b" | "f" | "n" | "r" | "t" | ("u" ~ ASCII_HEX_DIGIT{4}) ) } // Assignments assign = { string ~ ":" ~ value } // Typed literals typed = { type_name ~ "!" ~ value } type_name = @{ (ASCII_ALPHA | ASCII_DIGIT | "_" | "-")+ }