%token Int %token Name %token Binop %token LP "(" RP ")" %token LC "{" RC "}" %token Eq "=" %token Dot "." %token Com "," %token Kw_true "true" %token Kw_false "false" %token Kw_nil "nil" %token Kw_val "val" %token Kw_fun "fun" %token Kw_obj "obj" %token Kw_if "if" %token Kw_else "else" %token EOF %start modl %{ open Ast let infix_base e0 = (e0, []) let infix_app (e0, ops) op e2 = (e0, (op, e2) :: ops) let resolve_fixity (e0, ops) = List.fold_right (fun (op, e2) e1 -> Binop (op, e1, e2)) ops e0 %} %% modl: | items = list(item); EOF { { items } } item: | e = exp { Item_exp e } | "val"; n = Name; "="; e = exp { Item_val (n, e) } | "fun"; n = Name; p = params; e = exp { Item_fun (n, p, e) } | "obj"; n = Name; b = block { Item_obj (n, b) } exp: | e = infixexp { resolve_fixity e } | "if"; "("; e1 = exp; ")"; e2 = exp; "else"; e3 = exp { If (e1, e2, e3) } | "fun"; p = params; e = exp { Fun (p, e) } | "obj"; b = block { Obj b } | b = block { Scope b } infixexp: | e0 = singleexp { infix_base e0 } | e1 = infixexp; op = Binop; e2 = singleexp { infix_app e1 op e2 } singleexp: | i = Int { Literal (Int i) } | p = path { Path p } | f = path; a = args { Call (f, a) } | "("; e = exp; ")" { e } path: | x = Name { Var x } | e = singleexp; "."; x = Name { Ele (e, x) } params: "("; list = trailing_list(Name); ")" { list } args: "("; list = trailing_list(exp); ")" { list } block: "{"; list = list(item); "}" { list } trailing_list(X): | { [] } | x = X { [x] } | x = X; ","; xs = trailing_list(X) { x :: xs }