program = { statement | func_define | type_define} ;
statement = var_decl ";"
| expr_stmt ";"
| ret_stmt ";"
| block_stmt
| if_stmt
| while_stmt
| include_stmt ";" ;
ret_stmt = "return" [expression];
include_stmt = "include" "(" string ")"
if_stmt = "if" "(" expression ")" block_stmt ["else" (if_stmt | block)]
while_stmt = "while" "(" expression ")" block_stmt;
func_define = "func" string"("[params]")" "{" {statement} "}";
type_define = "typedef" string "{" {type_pair} "}" ;
type_pair = string ":" TYPE ";" ;
params = identifier {"," identifier} ;
var_decl = "var" identifier ["=" expression] ;
expr_stmt = expression ;
expression = assign_expr | new_expr;
new_expr = "new" identifier "{" {new_assigns} "}";
new_assigns = new_assign {, new_assigns};
new_assign = identifier "=" expression ;
# level 0
assign_expr = logic_or "=" assign_expr
# level 1
logic_or = logic_and { "||" logic_and };
# level 2
logic_and = equality { "&&" equality };
# level 3
equality = comparison [("==" | "!=") comparison];
# level 4
comparison = assignment [(">" | "<" | ">=" | "<=" ) assignment];
# level 5
assignment = term { ( "+" | "-" ) term } ;
# level 6
term = factor { ( "*" | "/" ) factor } ;
# level 7
factor = [ "!" | "-" ] obj_access ;
# level 8
obj_access = primary_call {"." primary_call}
# level 9
primary_call = primary { "(" [ arg_list ] ")" };
primary = number | string | bool |array_list | object_list | null | "(" expression ")" ;
arg_list = expression { "," expression } ;
array_lit = "[" [ expression { "," expression } ] "]" ;
object_lit = "{" [ kv_pair { "," kv_pair } ] "}" ;
kv_pair = string ":" expression ;