WHITESPACE = _{ " " | "\t" }
NEWLINE = _{ "\n" | "\r\n" }
COMMENT = _{ ("//" ~ (!NEWLINE ~ ANY)*) | ("/*" ~ (!"*/" ~ ANY)* ~ "*/") }
boolean_literal = @{ "true" | "false" }
number_literal = @{ "-"? ~ ASCII_DIGIT+ ~ ("." ~ ASCII_DIGIT+)? }
string_literal = @{ "\"" ~ ("\\\"" | (!"\"" ~ ANY))* ~ "\"" }
format_string = @{ "$\"" ~ ("\\\"" | (!("{" | "\"" | NEWLINE) ~ ANY))* ~ "\"" }
format_string_part1 = @{ "$\"" ~ ("\\\"" | (!("{" | NEWLINE) ~ ANY))* ~ "{" }
format_string_part2 = @{ "}" ~ ("\\\"" | (!("{" | NEWLINE) ~ ANY))* ~ "{" }
format_string_part3 = @{ "}" ~ ("\\\"" | (!("\"" | NEWLINE) ~ ANY))* ~ "\"" }
format_string_literal = { format_string | (format_string_part1 ~ expr ~ (format_string_part2 ~ expr)* ~ format_string_part3) }
literal = { boolean_literal | number_literal | string_literal | format_string_literal }
id = { (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* }
ids = { id ~ ("." ~ id)* }
anno_if = { "@if" ~ expr ~ NEWLINE+ }
op2 = { "**" | "||" | "&&" | "<<" | ">>" | "<=" | ">=" | "==" | "!=" | "+" | "-" | "*" | "/" | "%" | "|" | "&" | "^" | "<" | ">" }
inner_sp = _{ (NEWLINE*) ~ "," ~ (NEWLINE*) }
base_expr = { literal | ids }
exprs = { (expr ~ (inner_sp ~ expr)*)? }
array_expr = { "[" ~ exprs ~ "]" }
map_expr = { "{" ~ NEWLINE* ~ (map_assign_pair ~ (inner_sp ~ map_assign_pair)*)* ~ NEWLINE* ~ "}" }
strong_expr = { base_expr | array_expr | map_expr }
expr_prefix = { "++" | "--" | "!" | "-" | "~" }
num_unit = {
"nanoseconds"
| "microseconds"
| "milliseconds"
| "seconds"
| "mins"
| "hours"
| "days"
| "weeks"
| "months"
| "years"
| "nanometers"
| "micrometers"
| "millimeters"
| "meters"
| "kilometers"
| "megameters"
| "KB"
| "MB"
| "GB"
| "TB"
}
expr_suffix = { ("(" ~ exprs ~ ")") | ("[" ~ expr ~ "]") | "++" | "--" | num_unit }
middle_expr = { expr_prefix* ~ strong_expr ~ expr_suffix* }
weak_expr = { middle_expr ~ (op2 ~ middle_expr)* }
op3_expr = { weak_expr ~ "?" ~ middle_expr ~ ":" ~ middle_expr }
expr = { op3_expr | weak_expr }
assign_pair = { anno_if? ~ ids ~ "=" ~ expr ~ NEWLINE+ }
map_assign_pair = { ids ~ ":" ~ expr ~ NEWLINE* }
group_head = { "[" ~ ids ~ "]" ~ NEWLINE+ }
group_array_head = { "[[" ~ ids ~ "]]" ~ NEWLINE+ }
group_block = { anno_if? ~ (group_head | group_array_head) ~ assign_pair* }
faml = { SOI ~ NEWLINE* ~ (group_block)* ~ EOI }