let concat (a : nfa)
(b : nfa)
(p1 : state hashset)
(p2 : state hashset) : ((state, state) Hashtbl.t *
(state, state) Hashtbl.t * nfa) =
let offset = a.next_q in
let convert x = x + offset in
let lhs = fmap p1 (fun x -> x) in
let rhs = fmap p2 convert in
let q = copy a.q in
let _ = iter (fun m2q -> add q (convert m2q)) b.q in
let delta = Hashtbl.create (Hashtbl.length a.delta + Hashtbl.length b.delta) in
let _ = copy_table a.delta delta (fun x -> x) in
let _ = copy_table b.delta delta convert in
let epsilon = Hashtbl.create (Hashtbl.length a.delta + Hashtbl.length b.delta) in
let _ = copy_table a.epsilon epsilon (fun x -> x) in
let _ = copy_table b.epsilon epsilon convert in
let result = { s = a.s; f = (convert b.f); delta = delta; epsilon = epsilon; q = q;
next_q = a.next_q + b.next_q } in
let curset = which_states epsilon a.f in
let _ = add curset (convert b.s) in
(lhs, rhs, result)