WHITESPACE = _{ " " | "\t" | NEWLINE } 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 } op2 = { "+" | "-" | "*" | "/" | "**" | "%" | "|" | "&" | "||" | "&&" | "<<" | ">>" | "^" | "<" | "<=" | ">" | ">=" | "==" | "!=" } base_expr = { literal | ids | ("(" ~ expr ~ ")") } _exprs = { (expr ~ ("," ~ expr)*)? } array_expr = { "[" ~ _exprs ~ "]" } map_expr = { "{" ~ (map_assign_pair ~ ("," ~ map_assign_pair)*)* ~ "}" } strong_expr = { base_expr | array_expr | map_expr } expr_prefix = { "++" | "--" | "!" | "-" | "~" } expr_suffix = { ("." ~ id ~ ("(" ~ _exprs ~ ")")?) | "++" | "--" } middle_expr = { expr_prefix* ~ strong_expr ~ expr_suffix* } weak_expr = { middle_expr ~ (op2 ~ middle_expr)* } op3_expr = { middle_expr ~ "?" ~ middle_expr ~ ":" ~ middle_expr } expr = { weak_expr | op3_expr } assign_pair = { anno_if? ~ ids ~ "=" ~ expr } map_assign_pair = { ids ~ ":" ~ expr } group_head = { "[" ~ ids ~ "]" } group_array_head = { "[[" ~ ids ~ "]]" } group_block = { anno_if? ~ (group_head | group_array_head) ~ assign_pair* } oml = { SOI ~ (group_block)* ~ EOI }