PROG ::= (INSTR (EOI+ INSTR)*)? INSTR ::= EXPR | assert EXPR | assert_static_fail INSTR | return EXPR | VARDECL | CONSTDECL | ASSIGN | IF VARDECL ::= let_mut ident assign EXPR CONSTDECL ::= let ident assign EXPR ASSIGN ::= ident assign EXPR IF ::= if EXPR THEN (else (IF | ELSE))? THEN ::= INSTR* ELSE ::= INSTR* EXPR ::= IMP IMP ::= OR (imp OR)? OR ::= AND (or AND)* AND ::= EQ (and EQ)* EQ ::= CMP ((eq | ne) CMP)? CMP ::= TERM ((lt | le | gt | ge) TERM)? TERM ::= FACTOR ((add | sub) FACTOR)* FACTOR ::= UNOP ((mul | div | mod) UNOP)* UNOP ::= (add | sub | not)? POW POW ::= GROUP (pow GROUP)? GROUP ::= BASE | opar EXPR cpar BASE ::= int | bool | ident | FUN | CALL CALL ::= obrace ident expr* cbrace ARGS ::= expr* FUN ::= fun opar PARAMS cpar RET BODY end PARAMS ::= (PARAM (comma PARAM))? PARAM ::= ident (as TYPE) RET ::= arrow TYPE | BODY ::= INSTR* TYPE ::= type | fun lt (type (arrow type)*)? gt