program ::= (statement ';'?)*; statement ::= definition | expression; definition ::= 'def' def-spec '=' expression; def-spec ::= IDENTIFIER arg-spec*; arg-spec ::= IDENTIFIER; expression ::= binary-expression | unary-expression; unary-expression ::= unop+ simple-expression; binary-expression ::= call-expression (binop call-expression)*; call-expression ::= simple-expression+; binop ::= '*' | '/' | '+' | '-' | '?=' | '/=' | '>' | '>=' | '<' | '<='; unop ::= '+' | '-' | '!'; simple-expression ::= '(' expression ')' | 'true' | 'false' | INTEGER | IDENTIFIER | STRING | array | if-else-expression | let-in-expression | fn-expression | do-expression; array ::= '(' ')' | '[' ']' | '[' expression (',' expression)* ','? ']'; if-else-expression ::= 'if' expression 'then' expression 'else' expression; let-in-expression ::= 'let' def-spec '=' expression ('and' def-spec '=' expression)* 'in' expression; fn-expression ::= 'fn' arg-spec+ '->' expression | 'fn' arg-spec+ do-expression; do-expression ::= 'do' expression (';' expression)* 'end';