static void getBackwardReach(const NGHolder &g, ReportID report, u32 lag, map<s32, CharReach> &look) { ue2::flat_set<NFAVertex> curr, next; for (auto v : inv_adjacent_vertices_range(g.accept, g)) { if (contains(g[v].reports, report)) { curr.insert(v); } } for (u32 i = lag + 1; i <= MAX_BACK_LEN; i++) { if (curr.empty() || contains(curr, g.start) || contains(curr, g.startDs)) { break; } next.clear(); CharReach cr; for (auto v : curr) { assert(!is_special(v, g)); cr |= g[v].char_reach; insert(&next, inv_adjacent_vertices(v, g)); } assert(cr.any()); look[0 - i] |= cr; curr.swap(next); } }
static bool couldEndLiteral(const ue2_literal &s, NFAVertex initial, const NGHolder &h) { ue2::flat_set<NFAVertex> curr, next; curr.insert(initial); for (auto it = s.rbegin(), ite = s.rend(); it != ite; ++it) { const CharReach &cr_s = *it; bool matched = false; next.clear(); for (auto v : curr) { if (v == h.start) { // We can't see what we had before the start, so we must assume // the literal could overlap with it. return true; } const CharReach &cr_v = h[v].char_reach; if (overlaps(cr_v, cr_s)) { insert(&next, inv_adjacent_vertices(v, h)); matched = true; } } if (!matched) { return false; } curr.swap(next); } return true; }
static bool getTransientPrefixReach(const NGHolder &g, u32 lag, map<s32, CharReach> &look) { if (in_degree(g.accept, g) != 1) { DEBUG_PRINTF("more than one accept\n"); return false; } // Must be a floating chain wired to startDs. if (!hasSingleFloatingStart(g)) { DEBUG_PRINTF("not a single floating start\n"); return false; } NFAVertex v = *(inv_adjacent_vertices(g.accept, g).first); u32 i = lag + 1; while (v != g.startDs) { DEBUG_PRINTF("i=%u, v=%u\n", i, g[v].index); if (is_special(v, g)) { DEBUG_PRINTF("special\n"); return false; } look[0 - i] = g[v].char_reach; NFAVertex next = NGHolder::null_vertex(); for (auto u : inv_adjacent_vertices_range(v, g)) { if (u == g.start) { continue; // Benign, checked by hasSingleFloatingStart } if (next == NGHolder::null_vertex()) { next = u; continue; } DEBUG_PRINTF("branch\n"); return false; } if (next == NGHolder::null_vertex() || next == v) { DEBUG_PRINTF("no predecessor or only self-loop\n"); // This graph is malformed -- all vertices in a graph that makes it // to this analysis should have predecessors. assert(0); return false; } v = next; i++; } DEBUG_PRINTF("done\n"); return true; }
static void find_connected(TaskSystemType& task_system, const typename TaskSystemType::ClusterIdType& curr_clust_id, std::list<typename TaskSystemType::ClusterIdType>& connected_comps, int nr_of_connected) { typedef typename TaskSystemType::GraphType GraphType; typedef typename TaskSystemType::ClusterType ClusterType; typedef typename TaskSystemType::ClusterIdType ClusterIdType; typedef typename TaskSystemType::inv_adjacency_iterator inv_adjacency_iterator; typedef typename TaskSystemType::adjacency_iterator adjacency_iterator; GraphType& sys_graph = task_system.sys_graph; ClusterType& curr_clust = sys_graph[curr_clust_id]; if(!curr_clust.is_valid()) return; inv_adjacency_iterator parent_iter, parent_end; boost::tie(parent_iter, parent_end) = inv_adjacent_vertices(curr_clust_id, sys_graph); for ( ; parent_iter != parent_end; ++parent_iter) { const ClusterIdType& curr_parent_id = *parent_iter; // ClusterType& curr_parent = sys_graph[curr_parent_id]; find_connected(task_system, curr_parent_id, connected_comps, nr_of_connected); } if(curr_clust.group != 0) std::cout << "Already visited node " << curr_clust.index_list << std::endl; else { connected_comps.push_back(curr_clust_id); curr_clust.group = nr_of_connected; curr_clust.valid = false; } adjacency_iterator child_iter, child_end; boost::tie(child_iter, child_end) = adjacent_vertices(curr_clust_id, sys_graph); for ( ; child_iter != child_end; ++child_iter) { const ClusterIdType& curr_child_id = *child_iter; // ClusterType& curr_child = sys_graph[curr_child_id]; find_connected(task_system, curr_child_id, connected_comps, nr_of_connected); } }
static void apply(TaskSystemType& task_system) { typedef typename TaskSystemType::GraphType GraphType; typedef typename TaskSystemType::ClusterLevels ClusterLevels; typedef typename TaskSystemType::ClusterType ClusterType; typedef typename TaskSystemType::ClusterIdType ClusterIdType; typedef typename TaskSystemType::inv_adjacency_iterator inv_adjacency_iterator; typedef typename ClusterLevels::value_type SameLevelClusterIdsType; GraphType& sys_graph = task_system.sys_graph; ClusterLevels& clusters_by_level = task_system.clusters_by_level; if(task_system.levels_valid == false) task_system.update_node_levels(); typename ClusterLevels::iterator level_iter = clusters_by_level.begin(); /*! Skip the first level. Which contains only the root node and some invlaidated clusters.*/ ++level_iter; /*! Skip the second level as well. All nodes here have root as parent.*/ ++level_iter; int level_number = 2; for( ;level_iter != clusters_by_level.end(); ++level_iter, ++level_number) { SameLevelClusterIdsType& current_level = *level_iter; typename SameLevelClusterIdsType::iterator clustid_iter = current_level.begin(); for( ;clustid_iter != current_level.end(); ++clustid_iter) { ClusterIdType& curr_clust_id = *clustid_iter; ClusterType& curr_clust = sys_graph[curr_clust_id]; if(!curr_clust.is_valid()) { continue; } if(in_degree(curr_clust_id, sys_graph) == 1) { continue; } std::vector<ClusterIdType> parent_ids; inv_adjacency_iterator parent_iter, parent_end; boost::tie(parent_iter, parent_end) = inv_adjacent_vertices(curr_clust_id, sys_graph); const ClusterIdType& main_parent_id = *parent_iter; ClusterType& main_parent = sys_graph[main_parent_id]; /*! start from the second parent.*/ parent_iter++; for ( ; parent_iter != parent_end; ++parent_iter) { const ClusterIdType& other_parent_id = *parent_iter; ClusterType& other_parent = sys_graph[other_parent_id]; /*! Don't merge different level parents for now.*/ if(other_parent.level == main_parent.level) parent_ids.push_back(*parent_iter); } typename std::vector<ClusterIdType>::iterator id_iter; for(id_iter = parent_ids.begin(); id_iter != parent_ids.end(); ++id_iter) { task_system.concat_same_level_clusters(main_parent_id, *id_iter); } } } task_system.levels_valid = false; }
static void apply(TaskSystemType& task_system, const typename TaskSystemType::ClusterIdType& dest_id, const typename TaskSystemType::ClusterIdType& src_id) { typedef typename TaskSystemType::GraphType GraphType; typedef typename TaskSystemType::ClusterType ClusterType; typedef typename TaskSystemType::adjacency_iterator adjacency_iterator; typedef typename TaskSystemType::inv_adjacency_iterator inv_adjacency_iterator; GraphType& sys_graph = task_system.sys_graph; if(dest_id == src_id) return; ClusterType& dest = sys_graph[dest_id]; ClusterType& src = sys_graph[src_id]; if(dest.level > src.level) { std::cout << "trying to add edge : " << dest.level << " -> " << src.level << std::endl; } // std::cout << "Trying merege " << dest.index_list << " and " << src.index_list << std::endl; typename ClusterType::iterator task_iter; for(task_iter = src.begin(); task_iter != src.end(); ++task_iter) { dest.add_task(*task_iter); } adjacency_iterator src_child_iter, src_child_end, curr_src_child_iter; boost::tie(src_child_iter, src_child_end) = adjacent_vertices(src_id, sys_graph); while (src_child_iter != src_child_end) { /*! Increment before erase. Apparently erasing an edge invalidates the vertex iterators in VS. something is going on inside boost that I don't know yet. Or VS is just being VS as ususal. (the edge container is in fact a set, but that should matter only if we iterate over ages. well apparently not :) )*/ curr_src_child_iter = src_child_iter; ++src_child_iter; if(dest_id != *curr_src_child_iter) { boost::add_edge(dest_id, *curr_src_child_iter, sys_graph); } else { std::cout << "trying to add edge : " << sys_graph[dest_id].index_list << " -> " << sys_graph[*curr_src_child_iter].index_list << std::endl; } boost::remove_edge(src_id, *curr_src_child_iter, sys_graph); } inv_adjacency_iterator src_parent_iter, src_parent_end, curr_src_parent_iter; boost::tie(src_parent_iter, src_parent_end) = inv_adjacent_vertices(src_id, sys_graph); while (src_parent_iter != src_parent_end) { /*! Increment before erase. Apparently erasing an edge invalidates the vertex iterators in VS. something is going on inside boost that I don't know yet. Or VS is just being VS as ususal. (the edge container is in fact a set, but that should matter only if we iterate over ages. well apparently not :) )*/ curr_src_parent_iter = src_parent_iter; ++src_parent_iter; if(*curr_src_parent_iter != dest_id) { boost::add_edge(*curr_src_parent_iter, dest_id, sys_graph); } else { std::cout << "trying to add edge : " << sys_graph[*curr_src_parent_iter].index_list << " -> " << sys_graph[dest_id].index_list << std::endl; } boost::remove_edge(*curr_src_parent_iter, src_id, sys_graph); } // boost::clear_vertex(src_id, sys_graph); boost::remove_vertex(src_id, sys_graph); }