PROG ::= INSTR* INSTR ::= | DIR | EXPR semicolon | FUNDECL | return EXPR semicolon | EXTERN semicolon EXTERN ::= extern fun ident opar PARAMS cpar RET FUNDECL ::= fun ident opar PARAMS cpar RET BLOCK PARAMS ::= (ident type? (comma ident type?)*) RET ::= type? BLOCK ::= obrace INSTR* cbrace DIR ::= hash ident EXPR (as ident)? EXPR ::= | OR OR ::= AND (or AND)* AND ::= EQNE (and EQNE)* EQNE ::= CMP ((eq|ne) CMP)? CMP ::= ADDSUB ((lt|le|gt|ge) ADDSUB)? ADDSUB ::= MULDIVMOD ((add|sub) MULDIVMOD)* MULDIVMOD ::= LITERAL ((mul|div|mod) LITERAL)* LITERAL ::= | ident | int | CALL | NS | not LITERAL CALL ::= ident opar ARGS cpar ARGS ::= (EXPR (comma EXPR)*)? NS ::= ident (dot (ident|CALL))+