let create_graph (assgn : assignment)
(group : nodeid hashset)
(curgraph : graph) : graph =
let new_graph = copy_graph curgraph in
let visited = create (size group) in
let mem_visited x = mem visited (fst !(!x)) in
let add_visited x = add visited (fst !(!x)) in
let remove_epsilon nfa (lstate,rstate) =
let theset = which_states ~create:false nfa.epsilon lstate in
remove theset rstate in
let remove_epsilon_step id =
let id_node = find_node new_graph id in
let machine, trans = match id_node.lang with
| SuperMachine (m, trans) -> (m,trans)
| _ -> raise (IllegalLangOp "create_graph > remove_epsilon_step") in
let handle_constraint (lhs, id, rhs) =
if not (mem_visited lhs) then (
let (l, r) = get_assignment assgn lhs machine.s in
List.iter (remove_epsilon machine) (snd !(!lhs));
add_trans machine l Epsilon r;
add_visited lhs);
if not (mem_visited rhs) then (
let (l, r) = get_assignment assgn rhs machine.f in
List.iter (remove_epsilon machine) (snd !(!rhs));
add_trans machine l Epsilon r;
add_visited rhs)
in
id_node.lang <- Machine machine;
List.iter handle_constraint trans
in
let merge_overlap_step id =
let id_node = find_node new_graph id in
let constraints = match id_node.lang with
| SubMachine (_, c) -> c
| _ -> raise (IllegalLangOp "create_graph > merge_overlap_step")
in
if Hashtbl.length constraints > 1 then
id_node.lang <- (merge_subnfas new_graph assgn constraints)
else
let set_lang super (lhs, rhs) =
let super_node = find_node new_graph super in
let machine = match super_node.lang with
| Machine m -> m
| _ -> raise (IllegalLangOp "create_graph > merge_overlap_step") in
let s', s = get_assignment assgn lhs machine.s in
let f, f' = get_assignment assgn rhs machine.f in
id_node.lang <- Machine (extract_nfa machine s f)
in
Hashtbl.iter set_lang constraints in
let bottom_pred id =
let id_node = find_node new_graph id in
let edge_pred edge = match edge with
| OutConcatLeft _
| OutConcatRight _ -> true
| OutIsect target -> mem group target
in
not (exists edge_pred id_node.outb)
in
let supernodes, subnodes = split bottom_pred group in
List.iter remove_epsilon_step supernodes;
List.iter merge_overlap_step subnodes;
new_graph