let gen_string (m : nfa) : string option =
  let visited = create (size m.q) in
  let visit q = add visited q in
  let visited q = mem visited q in

  let get_next (w : string) (q : state) =
    let res = ref [] in
    let epsset = eps_closure m q in
    let delta = all_delta ~create:false m.delta q in
    let handle_eps q2 =
      res := (w, q2)::!res 
    in
    let handle_rhs q2 charset =
      let handle_char c = 
        res := (w ^ (Charset.char_as_string c), q2)::!res in
      Charset.iter handle_char charset 
    in
      StateSet.iter handle_eps epsset;
      Hashtbl.iter handle_rhs delta;
      !res in

  let rec walk (queue: (string * state) list) : string option = match queue with
    | (w, q)::qs when q = m.f -> Some w
    | (w, q)::qs when not (visited q) -> visit q; walk (qs @ (get_next w q))
    | (w, q)::qs -> walk qs
    | [] -> None 
  in
    walk [("", m.s)]