// C++-style whitespace and comments WHITESPACE = _{ " " | "\t" | NEWLINE } COMMENT = _{ "//" ~ (!"\n" ~ ANY)* } // C-style names name_char = { ASCII_ALPHA_LOWER | ASCII_ALPHA_UPPER | "_" | "$" } name = @{ name_char ~ (name_char | ASCII_DIGIT)* } // Numbers in the usual formats dec_number = @{ ASCII_NONZERO_DIGIT ~ ASCII_DIGIT* } hex_number = ${ "0x" ~ ASCII_HEX_DIGIT+ } bin_number = ${ "0b" ~ ASCII_BIN_DIGIT+ } oct_number = ${ "0o" ~ ASCII_OCT_DIGIT+ } dec_zero = @{ "0" } number = { dec_number | hex_number | bin_number | oct_number | dec_zero } // Quoted strings as per normal escape = @{ "\\" ~ ("t" | "r" | "n" | "0" | "\\" | "\"") } string_inner = ${ !("\"" | "\\") ~ ANY | escape } string = ${ "\"" ~ string_inner* ~ "\"" } assignment = { expr ~ "=" ~ expr } add = { "+" } sub = { "-" } mul = { "*" } div = { "/" } modulus = { "%" } log_and = { "&&" } log_or = { "||" } bit_and = { "&" } bit_or = { "|" } xor = { "^" } lt = { "<" } le = { "<=" } gt = { ">" } ge = { ">=" } eq = { "==" } ne = { "!=" } lshift = { "<<" } rshift = { ">>" } prefix = { "*" | "-" | "!" | "&" } operator = _{ add | sub | mul | div | modulus | log_and | log_or | bit_and | bit_or | xor | lshift | rshift | lt | le | gt | ge | eq | ne } expr = { prefix* ~ term ~ suffix* ~ (operator ~ prefix* ~ term ~ suffix*)* } term = _{ number | name | "(" ~ expr ~ ")" | string } suffix = _{ subscript | arglist } subscript = { "[" ~ expr ~ "]" } arglist = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" } statement = { asm | ((return_stmt | var_decl | assignment | expr) ~ ";") | conditional | while_loop | repeat_loop } asm = { "asm" ~ asm_args? ~ "{" ~ asm_body ~ "}" } asm_args = _{ "(" ~ expr ~ ("," ~ expr)* ~ ")" } asm_body = { (!"}" ~ ANY)* } block = { "{" ~ statement* ~ "}" } function = { "fn" ~ name ~ argnames ~ block } argnames = { "(" ~ (name ~ ("," ~ name)*)? ~ ")" } function_prototype = { "fn" ~ name ~ argnames ~ ";" } declaration = { function | function_prototype | global | const_decl } program = { (COMMENT | WHITESPACE)? ~ declaration* ~ EOI } return_stmt = { "return" ~ expr? } conditional = { "if" ~ "(" ~ expr ~ ")" ~ block ~ ("else" ~ block)? } while_loop = { "while" ~ "(" ~ expr ~ ")" ~ block } repeat_loop = { "repeat" ~ "(" ~ expr ~ ")" ~ name? ~ block } var_decl = { "var" ~ name ~ size? ~ ("=" ~ expr)? } global = { "global" ~ name ~ size? ~ ";" } size = { "[" ~ expr ~ "]" } const_decl = { "const" ~ name ~ "=" ~ (string | expr) ~ ";" }