let parse_pred1 = dcg [ ?ctx; op = ctx#parse_pred1 -> op ]

let parse_func0 = dcg [ ?ctx; op = ctx#parse_func0 -> op ]

let parse_pred2 = dcg [ ?ctx; op = ctx#parse_pred2 -> op ]

-let parse_pred2_rel = dcg [ ?ctx; op = ctx#parse_pred2_rel -> op ]

let parse_func1 = dcg [ ?ctx; op = ctx#parse_func1 -> op ]

let parse_addop = dcg [ ?ctx; op = ctx#parse_addop -> op ]

let parse_mulop = dcg [ ?ctx; op = ctx#parse_mulop -> op ]

| _ = at_in; _ = ws; _ = kwd "which"; _ = ws; prep = parse_prep; rel_opt = parse_rel_opt; _ = ws; s = parse_s_for ->

rel_opt (Some (fun z -> prep z s))

- | p~~2~~ = parse_~~pred2_rel~~; _ = ws; op = parse_op -> init (fun x -> op (pred2 p~~2~~ x))

+ | comp = parse_comp_prefix; _ = ws; _ = parse_comp_suffix; _ = ws; op = parse_op -> init (fun x -> op (pred2 comp x))

| _ = kwd "between"; _ = ws; op1 = parse_op; _ = ws; _ = kwd "and"; _ = ws; op2 = parse_op ->

init (fun x -> bool0#and_ [op1 (pred2 pred2_geq x); op2 (pred2 pred2_leq x)]) ]

| np2 = parse_np2; rel_opt = parse_rel_opt ->

(fun x -> np2 x (rel_opt None))

| p2 = parse_p2; _ = ws; op = parse_op ->

- (fun x -> op (fun y -> p2 x y)) ]

+ (fun x -> op (fun y -> p2 x y))

+ | _ = a_the; _ = ws; comp = parse_comp_prefix; _ = ws; p2 = parse_p2; _ = ws; _ = parse_comp_suffix;

+ _ = ws; np = parse_np; y = new_var; y' = new_var ->

+ (fun x -> np (fun x' -> exists y (fun y -> exists y' (fun y' -> bool0#and_ [p2 x y; p2 x' y'; pred2 comp y y'])))) ]

+and parse_comp_prefix = dcg

+ [ _ = kwds ["same"; "equal"] -> pred2_eq

+ | _ = kwds ["other"; "different"] -> pred2_neq

+ | _ = kwds ["greater"; "higher"; "later"];

+ ( _ = ws; _ = kwd "or"; _ = ws; _ = kwd "equal" -> pred2_geq

+ | _ = kwds ["lesser"; "lower"; "earlier"];

+ ( _ = ws; _ = kwd "or"; _ = ws; _ = kwd "equal" -> pred2_leq

+and parse_comp_suffix = dcg

+ [ _ = kwds ["than"; "as"; "to"; "from"] -> () ]

[ det = parse_det; _ = ws; y, p2 = parse_ng2; _ = ws; _ = kwd "with"; _ = ws; np = parse_np ->

(fun x1 -> det y (p2 x1) (fun y -> np (fun x2 -> p2 x2 y)))