WHITESPACE = _{ " " | "\t" }
COMMENT = _{ "#" ~ (!NEWLINE ~ ANY)* }

sep = _{ "," | NEWLINE }

plus = { "+" }
minus = { "-" }
times = { "*" }
divide = { "/" }
intdiv = { "\\" }
modulus = { "%" }
power = { "^" }
quote = _{ "\"" }
infix = _{ WHITESPACE+ ~ (plus | minus | times | divide | intdiv | modulus | power) ~ WHITESPACE+ }

backslash = _{"\\" }
oct = _{ ASCII_OCT_DIGIT }
hex = _{ ASCII_HEX_DIGIT }
esc = @{
    "\\" ~ ("n" | "r" | "t" | "\\" | "\'" | "\"")
  | "\\0" ~ oct ~ oct
  | "\\x" ~ hex ~ hex
  | "\\U" ~ hex{8}
  | "\\u" ~ hex{4}
}

quoted_chars = @{ (!quote ~ !backslash ~ ANY)+ }
quoted_string = ${ (esc | quoted_chars)* }

special = { "{" | "}" | "(" | ")" | "[" | "]" | " " | "," | "$" | "#" }
special_esc = @{ "\\" ~ special }

bare_chars = @{ (!quote ~ !backslash ~ !special ~ !COMMENT ~ !NEWLINE ~ ANY)+ }
bare_string = ${ (special_esc | esc | bare_chars)+ }

dollar = { "$" }
function = ${ (bare_string ~ "(" ~ list ~ ")" | dollar ~ bare_string) }
value = !{
    function
  | bare_string
  | quote ~ quoted_string ~ quote
  | "(" ~ expression ~ ")"
  | "{" ~ table ~ "}"
  | "[" ~ list ~ "]"
}
template = { "let(" ~ sep* ~ (bare_string | quoted_string) ~ sep* ~ expression ~ sep* ~ ")" }
expression = ${ value ~ (infix ~ value)* }
exp_list = _{ ((template | expression) ~ sep ~ exp_list | sep ~ exp_list | (template | expression))? }
key_value = { expression{2,} }
kv_list = _{((template | key_value) ~ sep ~ kv_list | sep ~ kv_list | (template | key_value))? }
list = !{ exp_list }
table = !{ kv_list }
root = _{ table ~ EOI }
