statement   : if-expr
            : while-expr
            : for-expr
            : expr
            : val-expr
            : function-def

if-expr     : KEYWORD:if LPAREN val-expr RPAREN LCPAREN (statement)* RCPAREN
                (KEYWORD:elif LCPAREN (statement)* RCPAREN)*
                (KEYWORD:else LCPAREN (statement)* RCPAREN)?

while-expr  : KEYWORD:while LPAREN val-expr RPAREN LCPAREN (statement)* RCPAREN

for-expr    : KEYWORD:for TYPE IDENTIFIER KEYWORD:in LPAREN arith-expr COMMA arith-expr COMMA arith-expr RPAREN LCPAREN (statement)* RCPAREN

function-def: KEYWORD:fun TYPE? IDENTIFIER LPAREN (TYPE IDENTIFIER)? (COMMA TYPE IDENTIFIER)* RPAREN LCPAREN (statement)* (KEYWORD:return val-expr)? RCPAREN

expr        : KEYWORD:return val-expr

assignment  : TYPE IDENTIFIER EQ val-expr

val-expr    : comp-expr ((KEYWORD:AND|KEYWORD:OR) comp-expr)*

comp-expr   : NOT comp-expr
            : arith-expr ((EE|LT|GT|LTE|GTE) arith-expr)*

arith-expr  : term ((PLUS|MINUS) term)*

term        : factor ((MUL|DIV) factor)*

factor      : (PLUS|MINUS) factor
            : power

power       : call (POW factor)*

call        : atom (LPAREN val-expr? (COMMA val-expr)* RPAREN)?

value       : unit
            : list

list        : LSQUARE (val-expr (COMMA val-expr)*) RSQUARE

unit        : INT|FLOAT|STRING|IDENTIFIER (LSQUARE arith-expr RSQUARE)
            : LPAREN expr RPAREN
