#keywords soft: name;
#keywords hard: fun not and or;
a = b;
b = a^;
binexpr = term binop +;
binop = '+' | '-' | '*' | '/' | '%' | '|' | '^' | '&' | '>>' | '<<';
block = {<expr ';'> <> *~};
chainop = reshape | tuple;
ct_args = [param_inferrable ',' *~];
delimited_expr = (expr);
expr = binexpr logicop +;
function_def = &{ kw: "fun"; name: name; ct_args: ct_args?; rt_args: rt_args?; return_type: <'->' expr>?; expr: <<'=' expr> | block>; };
leaf = &[ name: name; delimited_expr: delimited_expr; tuple: tuple; ];
logicop = "and" | "or";
name = @ident | <'@' "name" (expr)>;
param = name ':' expr;
param_inferrable = name <':' expr>?;
reshape = '.' <<name tuple> | name>;
rt_args = (param ',' *~);
term = <leaf | <unop term>> chainop <> *~;
tuple = (expr ',' *~);
unop = '-' | '~' | "not";