- and rule_loop (t : Grammar2.n_symbol) states rank y0 y1 =
- incr rule_counter;
- if !rule_counter land (65535) == 0 then begin Gc.minor() end;
- let rhs = Grammar2.get_rule g t in
- let id1 = Grammar2.get_id1 rhs in
- let id2 = Grammar2.get_id2 rhs in
- let conf = Grammar2.get_conf rhs in
- if Grammar2.is_non_terminal g id1 then
- let id1 = Grammar2.non_terminal id1 in
- match conf with
- | Grammar2.C0 -> rule_loop id1 states 1 (Grammar2.Node0 id2) dummy_leaf
- | Grammar2.C1 -> rule_loop id1 states 1 (Grammar2.Node1(id2,y0)) dummy_leaf
- | Grammar2.C2 -> rule_loop id1 states 2 (Grammar2.Node0 id2) y0
- | Grammar2.C3 -> rule_loop id1 states 2 y0 (Grammar2.Node0 id2)
- | Grammar2.C4 -> rule_loop id1 states 1 (Grammar2.Node2(id2, y0, y1)) dummy_leaf
- | Grammar2.C5 -> rule_loop id1 states 2 (Grammar2.Node1(id2, y0)) y1
- | Grammar2.C6 -> rule_loop id1 states 2 y0 (Grammar2.Node1(id2, y1))
- else
- let id1 = Grammar2.terminal id1 in
- match conf with
- | Grammar2.C0 | Grammar2.C1 -> assert false
- | Grammar2.C2 -> terminal_loop id1 states (Grammar2.Node0 id2) y0
- | Grammar2.C3 -> terminal_loop id1 states y0 (Grammar2.Node0 id2)
- | Grammar2.C4 -> assert false
- | Grammar2.C5 -> terminal_loop id1 states (Grammar2.Node1(id2, y0)) y1
- | Grammar2.C6 -> terminal_loop id1 states y0 (Grammar2.Node1(id2, y1))
+ and rule_loop (t : Grammar2.n_symbol) states y0 y1 =
+ if t = Node.nil || states == dummy_set then nil_res else
+ let () = incr rule_counter in
+ if !rule_counter land 65535 == 0 then begin Gc.minor() end;
+ let k = (t, states) in
+ let pstates = DCache.find dcache k in
+ let notfound = DCache.notfound pstates in
+ let rhs = Grammar2.get_rule g t in
+ let id1 = Grammar2.get_id1 rhs in
+ let id2 = Grammar2.get_id2 rhs in
+ let conf = Grammar2.get_conf rhs in
+ if notfound then
+ let ny0 = dispatch_param0 conf id2 y0 y1 in
+ let ny1 = dispatch_param1 conf id2 y0 y1 in
+ let res = dispatch_loop id1 states ny0 ny1 in
+ pstates.(0) <- res.in0;
+ pstates.(1) <- res.in1;
+ res (*
+ UCache.add ucache (t, states, fst res.out0, fst res.out1)
+ res.main;
+ let h = Hashtbl.create 7 in
+ for i = 0 to res_len - 1 do
+ Hashtbl.add h (0, i) (snd res.out0).(i);
+ Hashtbl.add h (1, i) (snd res.out1).(i);
+ done;
+ { res with
+ main = ((fst res.main), (U.close h (snd res.main)));
+ } *)
+
+ else
+ let res0 = partial_loop y0 pstates.(0) in
+ let res1 = partial_loop y1 pstates.(1) in
+ let k2 = (t, states, fst res0.main, fst res1.main) in
+ let s, r =
+ try
+ UCache.find ucache k2
+ with
+ Not_found ->
+ let ores0 = { res0 with main = fst res0.main, U.var 0 (snd res0.main) }
+ and ores1 = { res1 with main = fst res1.main, U.var 1 (snd res1.main) }
+ in
+ let res = dispatch_loop id1 states (Grammar2.Cache (0,ores0)) (Grammar2.Cache (1, ores1)) in
+ UCache.add ucache k2 res.main;
+ res.main
+ in
+ let h = Hashtbl.create 7 in
+ for i = 0 to res_len - 1 do
+ Hashtbl.add h (0, i) (snd res0.main).(i);
+ Hashtbl.add h (1, i) (snd res1.main).(i);
+ done;
+ { in0 = pstates.(0);
+ in1 = pstates.(1);
+ out0 = res0.main;
+ out1 = res1.main;
+ main = s, U.close h r;
+ }
+
+ and dispatch_loop id1 states ny0 ny1 =
+ if Grammar2.is_non_terminal g id1 then
+ rule_loop (Grammar2.non_terminal id1) states ny0 ny1
+ else
+ terminal_loop (Grammar2.terminal id1) states ny0 ny1