2023-07-17 23:00:01 -05:00
|
|
|
// 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* ~ "\"" }
|
|
|
|
|
|
2023-08-14 00:26:02 -05:00
|
|
|
assignment = { expr ~ "=" ~ expr }
|
2023-07-17 23:00:01 -05:00
|
|
|
|
|
|
|
|
add = { "+" }
|
|
|
|
|
sub = { "-" }
|
|
|
|
|
mul = { "*" }
|
|
|
|
|
div = { "/" }
|
|
|
|
|
modulus = { "%" }
|
|
|
|
|
log_and = { "&&" }
|
|
|
|
|
log_or = { "||" }
|
|
|
|
|
bit_and = { "&" }
|
|
|
|
|
bit_or = { "|" }
|
|
|
|
|
xor = { "^" }
|
|
|
|
|
lt = { "<" }
|
|
|
|
|
le = { "<=" }
|
|
|
|
|
gt = { ">" }
|
|
|
|
|
ge = { ">=" }
|
|
|
|
|
eq = { "==" }
|
|
|
|
|
ne = { "!=" }
|
|
|
|
|
lshift = { "<<" }
|
|
|
|
|
rshift = { ">>" }
|
2023-08-13 23:55:49 -05:00
|
|
|
prefix = { "*" | "-" | "!" | "&" }
|
2023-07-17 23:00:01 -05:00
|
|
|
|
|
|
|
|
operator = _{
|
|
|
|
|
add
|
|
|
|
|
| sub
|
|
|
|
|
| mul
|
|
|
|
|
| div
|
|
|
|
|
| modulus
|
|
|
|
|
| log_and
|
|
|
|
|
| log_or
|
|
|
|
|
| bit_and
|
|
|
|
|
| bit_or
|
|
|
|
|
| xor
|
|
|
|
|
| lshift
|
|
|
|
|
| rshift
|
|
|
|
|
| lt
|
|
|
|
|
| le
|
|
|
|
|
| gt
|
|
|
|
|
| ge
|
|
|
|
|
| eq
|
|
|
|
|
| ne
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-04 17:27:28 -05:00
|
|
|
expr = { prefix* ~ term ~ suffix* ~ (operator ~ prefix* ~ term ~ suffix*)* }
|
2023-08-14 00:26:02 -05:00
|
|
|
term = _{ number | name | "(" ~ expr ~ ")" | string }
|
2023-07-17 23:00:01 -05:00
|
|
|
|
2023-08-15 00:39:53 -05:00
|
|
|
suffix = _{ subscript | arglist }
|
2023-07-17 23:00:01 -05:00
|
|
|
subscript = { "[" ~ expr ~ "]" }
|
2023-08-14 00:26:02 -05:00
|
|
|
arglist = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" }
|
2023-07-17 23:00:01 -05:00
|
|
|
|
2023-08-03 00:53:43 -05:00
|
|
|
statement = { asm | ((return_stmt | var_decl | assignment | expr) ~ ";") | conditional | while_loop | repeat_loop }
|
2023-07-17 23:00:01 -05:00
|
|
|
|
|
|
|
|
asm = { "asm" ~ asm_args? ~ "{" ~ asm_body ~ "}" }
|
2023-08-15 01:30:35 -05:00
|
|
|
asm_args = _{ "(" ~ expr ~ ("," ~ expr)* ~ ")" }
|
2023-07-17 23:00:01 -05:00
|
|
|
asm_body = { (!"}" ~ ANY)* }
|
|
|
|
|
|
|
|
|
|
block = { "{" ~ statement* ~ "}" }
|
|
|
|
|
|
|
|
|
|
function = { "fn" ~ name ~ argnames ~ block }
|
2023-08-15 00:39:53 -05:00
|
|
|
argnames = { "(" ~ (name ~ ("," ~ name)*)? ~ ")" }
|
2023-07-17 23:00:01 -05:00
|
|
|
|
2023-08-26 00:42:41 -05:00
|
|
|
function_prototype = { "fn" ~ name ~ argnames ~ ";" }
|
|
|
|
|
|
|
|
|
|
declaration = { function | function_prototype | global | const_decl }
|
2023-07-17 23:00:01 -05:00
|
|
|
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 }
|
2023-08-15 00:39:53 -05:00
|
|
|
var_decl = { "var" ~ name ~ size? ~ ("=" ~ expr)? }
|
|
|
|
|
global = { "global" ~ name ~ size? ~ ";" }
|
2023-07-17 23:00:01 -05:00
|
|
|
size = { "[" ~ expr ~ "]" }
|
2023-08-14 00:26:02 -05:00
|
|
|
const_decl = { "const" ~ name ~ "=" ~ (string | expr) ~ ";" }
|