// Adapted from https://pest.rs/book/examples/json.html
WHITESPACE = _{ " " | "\t" | "\r" | "\n" | COMMENT }
COMMENT = { ("//" ~ (!NEWLINE ~ ANY)* ~ NEWLINE) | ("/*" ~ (!("*/") ~ ANY)* ~ "*/") }
ident = @{ (ASCII_ALPHA | "$" | "_") ~ (ASCII_ALPHANUMERIC | "$" | "_" | "-")* }
splat = { "..." ~ value }
parameters = { WHITESPACE* ~ value ~ ("," ~ WHITESPACE* ~ value)* }
fn_call = ${ ident ~ WHITESPACE* ~ "(" ~ WHITESPACE* ~ (splat | parameters)? ~ WHITESPACE* ~ ")" }
object = {
"{" ~ WHITESPACE* ~ "}"
| "{" ~ WHITESPACE* ~ pair ~ (WHITESPACE* ~ "," ~ WHITESPACE* ~ pair)* ~ WHITESPACE* ~ "}"
}
pair = { string ~ WHITESPACE* ~ ":" ~ WHITESPACE* ~ value }
array = {
"[" ~ WHITESPACE* ~ "]"
| "[" ~ WHITESPACE* ~ value ~ (WHITESPACE* ~ "," ~ WHITESPACE* ~ value)* ~ WHITESPACE* ~ "]"
}
string = ${ "\"" ~ inner ~ "\"" }
inner = @{ char* }
char = {
!("\"" | "\\") ~ ANY
| "\\" ~ ("\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t")
| "\\" ~ ("u" ~ ASCII_HEX_DIGIT{4})
}
boolean = { "true" | "false" }
null = { "null" }
number = @{
"-"? ~ ("0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*) ~ ("." ~ ASCII_DIGIT*)? ~ (^"e" ~ ("+" | "-")? ~ ASCII_DIGIT+)?
}
quote = { "'" ~ value }
value = _{ fn_call | boolean | null | ident | string | object | array | number | quote }
expr = _{ SOI ~ value ~ COMMENT? ~ EOI }