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)]