WHITESPACE = _{ " " }
identifier = @{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC | "_")* }
int = { ('0'..'9')+ }
number = @{
int ~ ("." ~ int?)?
}
plus = { "+" }
minus = { "-" }
neq = { "≠" }
eq = { "=" }
gt = { ">" }
lt = { "<" }
gte = { "≥" }
lte = { "≤" }
modop = { "MOD" }
not = { "NOT" }
mult = { "*" }
div = { "/" }
assign = { "←" | "🠐" }
comma = _{ "," }
lparen = _{ "(" }
rparen = _{ ")" }
lbrack = _{ "[" }
rbrack = _{ "]" }
boolean = { "true" | "false" }
exp = { ^"e" ~ (plus | minus)? ~ int }
string = ${ "\"" ~ inner ~ "\"" }
inner = @{ char* }
char = {
!("\"" | "\\") ~ ANY
| "\\" ~ ("\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t")
| "\\" ~ ("u" ~ ASCII_HEX_DIGIT{4})
}
nl = _{ "\n"+ }
program = _{ SOI ~ nl? ~ (instruction ~ nl)* ~ instruction? ~ EOI }
instruction = _{
selection_block |
iteration_block |
procedure_def |
display |
assignment |
expression
}
// returns a value
value = {
prefix_op? ~ number |
string |
prefix_op? ~ boolean |
prefix_op? ~ procedure_call |
prefix_op? ~ index |
prefix_op? ~ identifier |
prefix_op? ~ lparen ~ expression ~ rparen |
list
}
list = {
lbrack ~ (expression ~ comma)* ~ expression? ~ rbrack
}
operator = { (neq|eq|gt|lt|gte|lte|mult|div|plus|minus|modop) }
expression = { value ~ (operator ~ value)* }
prefix_op = { minus | not }
term = _{ value | lparen ~ expression ~ rparen }
display = { "DISPLAY" ~ lparen ~ expression ~ rparen }
assignment = {
identifier ~ assign ~ expression |
index ~ assign ~ expression
}
index = { identifier ~ lbrack ~ expression ~ rbrack }
procedure_call = { identifier ~ lparen ~ arglist? ~ rparen }
arglist = {
(expression ~ ("," ~ expression)*)
}
selection_block = {
if_else_expr |
if_expr
}
if_expr = { "IF" ~ expression ~ block }
if_else_expr = { "IF" ~ expression ~ block ~ "ELSE" ~ block }
block = {
"{" ~ nl ~ (block_instruction ~ nl )* ~ "}"
}
block_instruction = {
selection_block |
iteration_block |
return_statement |
display |
assignment
}
proc_instruction = {
return_statement |
selection_block |
iteration_block |
display |
assignment
}
return_statement = {
"RETURN" ~ expression
}
iteration_block = {
repeat_until |
repeat_times |
for_each
}
repeat_until = { "REPEAT" ~ "UNTIL" ~ expression ~ block }
repeat_times = { "REPEAT" ~ expression ~ "TIMES" ~ block }
for_each = { "FOR" ~ "EACH" ~ identifier ~ "IN" ~ expression ~ block }
procedure_def = {
"PROCEDURE" ~ identifier ~ lparen ~ paramlist ~ rparen ~ procedure_block
}
procedure_block = {
"{" ~ nl ~ (proc_instruction ~ nl )* ~ "}"
}
paramlist = {
(identifier ~ ("," ~ identifier)*)
}