program = statement* EOF ; statement = expr ";" | definition | block | "if" expr block ( "else" block )? | "for" ( expr? | IDENTIFIER "in" expr ) block | "return" "!?"? expr? ";" | "continue" ";" | "break" ";" | declaration ; definition = "def" IDENTIFIER struct_block | "def" IDENTIFIER "(" params? ")" TYPE? block params = param ( "," param )* ; param = IDENTIFIER TYPE ; block = "{" statement* "}" ; struct_block = "{" ( definitions | declaration )+ "}" ; expr = assignment ; declaration = "const" IDENTIFIER TYPE = expr_list ";" | "var" IDENTIFIER TYPE ( "=" expr_list )? ";" ; expr_list = expr | "[" expr ( "," expr )? "]" assignment = INDENTIFIER ( "[" expr "]" )* "=" expr | logic_or ; logic_or = logic_and ( "||" logic_and )* ; logic_and = equality ( "&&" equality )* ; equality = comparison ( ( "!=" | "==" ) comparison )* ; comparison = bitterm ( ( ">" | ">=" | "<" | "<=" ) bitterm )* ; bitterm = term ( ( "<<" | ">>" | "|" | "^" ) term )* ; term = bitfactor ( ( "-" | "+" ) bitfactor )* ; bitfactor = factor ( "&" factor )* ; factor = unary ( ( "/" | "*" | "%" ) unary )* ; unary = ( "?" | "!" | "-" | "~" ) unary | call ; call = primary ( "(" arguments? ")" | "." IDENTIFIER )* | primary ( "[" expr "]" )+ ; primary = NUMBER | STRING | FUNC | "true" | "false" | "(" expr ")" | IDENTIFIER ; arguments = expr ( "," expr )* ; NUMBER = ( "0x" HEX_DIGIT+ | "0b" BIN_DIGIT+ | DIGIT+ ) | "'" CHAR "'"; STRING = "\"" ( "\\\"" | )* "\"" ; FUNC = IDENTIFIER ; IDENTIFIER = ALPHA ( ALPHA | DIGIT )* ; TYPE = NON_ARRAY_TYPE | ARRAY_TYPE NON_ARRAY_TYPE = "number" | "bool" | "string" | FUNC_TYPE FUNC_TYPE = "func" "(" ( TYPE ( "," TYPE )* )? ")" TYPE? ARRAY_TYPE = "[" expr "]" NON_ARRAY_TYPE ALPHA = "a" ... "z" | "A" ... "Z" | "_" ; ALPHA_DIGIT = "0" ... "9" | "a" ... "f" | "A" ... "F" ; BIN_DIGIT = "0" | "1" ; DIGIT = "0" ... "9" ;