lib/rley/gfg/grm_flow_graph.rb in rley-0.5.03 vs lib/rley/gfg/grm_flow_graph.rb in rley-0.5.04

- old
+ new

@@ -44,13 +44,14 @@ # then elimination of unreachable symbols def diagnose mark_unreachable_symbols end - Branching = Struct.new(:vertex, :to_visit, :visited) do - def initialize(aVertex) + Branching = Struct.new(:vertex, :in_edge, :to_visit, :visited) do + def initialize(aVertex, aCallEdge) super(aVertex) + self.in_edge = aCallEdge self.to_visit = aVertex.edges.dup self.visited = [] end def done? @@ -62,52 +63,71 @@ visited << next_one.successor unless next_one.nil? return next_one end end + + def print_vertex(aText, aVertex) + print aText + ' ' + if aVertex.kind_of?(NonTerminalVertex) + puts "#{aVertex.class} #{aVertex.non_terminal.name}" + else + p(aVertex.label) + end + end # Walk over all the vertices of the graph that are reachable from a given # start vertex. This is a depth-first graph traversal. # @param aStartVertex [StartVertex] the depth-first traversal begins # from here # @param _visitAction [Proc] block called when a new graph vertex is found def traverse_df(aStartVertex, &_visitAction) visited = Set.new stack = [] visitee = aStartVertex + curr_edge = nil begin + # print_vertex( 'Traversing', visitee) + first_time = !visited.include?(visitee) if first_time yield(visitee) visited << visitee - end - + end + case visitee when Rley::GFG::StartVertex if first_time - stack.push(Branching.new(visitee)) + stack.push(Branching.new(visitee, curr_edge)) curr_edge = stack.last.next_edge else - # Skip start and end vertices + # Skip both start and end vertices # Retrieve the corresponding return edge curr_edge = get_matching_return(curr_edge) end when Rley::GFG::EndVertex - stack.pop if stack.last.done? - break if stack.empty? - curr_edge = stack.last.next_edge + if stack.last.done? + popped = stack.pop + break if stack.empty? + # puts "Popped!" + return_key = popped.in_edge.key.sub(/^CALL/, 'RET') + curr_edge = visitee.edges.find { |e| e.key == return_key } + else + curr_edge = stack.last.next_edge + end else # All other vertex types have only one successor curr_edge = visitee.edges[0] end visitee = curr_edge.successor unless curr_edge.nil? end until stack.empty? # Now process the end vertex matching the initial start vertex - yield(end_vertex_for[aStartVertex.non_terminal]) + last_one = end_vertex_for[aStartVertex.non_terminal] + yield(last_one) unless visited.include?(last_one) end private def add_vertex(aVertex) @@ -286,14 +306,16 @@ # Mark all non-terminals as unreachable start_vertex_for.each_value do |a_vertex| a_vertex.non_terminal.unreachable = true end - # Now traverse graph from start vertex - # and make all visited non-terminals as reachable + # Now traverse graph from start vertex of graph + # and mark all visited non-terminals as reachable traverse_df(start_vertex) do |a_vertex| - next unless a_vertex.kind_of?(StartVertex) - a_vertex.non_terminal.unreachable = false + # print_vertex(' Visiting', a_vertex) + if a_vertex.kind_of?(StartVertex) + a_vertex.non_terminal.unreachable = false + end end end end # class end # module end # module