MOD ::= EXPR* EXPR ::= | ASSERT | VARDECL | FUNDECL | RETURN | VARSET | SCOPE | IF | OR ASSERT ::= assert EXPR VARDECL ::= let ident assign EXPR FUNDECL ::= fun ident opar PARAMS cpar BLOCK end PARAMS ::= (ident (comma ident)*)? RETURN ::= return EXPR VARSET ::= ident assign EXPR BLOCK ::= EXPR* SCOPE ::= begin BLOCK end IF ::= if EXPR then BLOCK (else BLOCK | IF)? end OR ::= AND (or AND)* AND ::= EQNE (and EQNE)* EQNE ::= | CMP | CMP eq CMP | CMP ne CMP CMP ::= TERM ((lt | le | ge | gt) TERM)? TERM ::= FACTOR ((add | sub) FACTOR)* FACTOR ::= POWER ((mul | div | mod) POWER)* POWER ::= UNARY (pow UNARY)? UNARY ::= sub? GROUP | not? GROUP GROUP ::= LITERAL | opar EXPR cpar LITERAL ::= BUILTIN | FUNCALL FUNCALL ::= ident opar ARGS cpar ARGS ::= (EXPR (comma EXPR)*)? BUILTIN ::= num | bool | str | ident