ROOT ::= EXPR* EXPR ::= | OR | ASSERT | VAR_DECL | CONST_DECL | ASSIGN | BLOCK | IF | return EXPR IF ::= if EXPR BLOCK (else (BLOCK | IF))? BLOCK ::= begin EXPR* end ASSIGN ::= ident assign EXPR VAR_DECL ::= var ident assign EXPR CONST_DECL ::= const ident assign EXPR ASSERT ::= assert EXPR eq EXPR OR ::= AND (or AND)* AND ::= EQ (and EQ)* EQ ::= CMP ((equal|not_equal) CMP)? CMP ::= TERM ((lt|gt|le|ge) TERM)? TERM ::= FACTOR ((add|sub) FACTOR)* FACTOR ::= USUB ((mul|div|mod) USUB)* USUB ::= sub* NOT NOT ::= not* POW POW ::= LITERAL (pow LITERAL)? LITERAL ::= | BUILTIN | opar EXPR cpar | ident | FUN | CALL CALL ::= ident opar ARGS cpar ARGS ::= (EXPR (comma EXPR)*)? FUN ::= fun opar PARAMS cpar EXPR* end PARAMS ::= (EXPR (comma EXPR)*)? BUILTIN ::= | int | bool | float | string