Commit 9b79d4cf authored by Michael Schwarz's avatar Michael Schwarz

Common superclass for grpah stuff

parent 88e54b1b
package de.tum.in.www2.cupplugin.views;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import java.util.Stack;
import java.util.Map.Entry;
public class GraphHelper {
public static <X> boolean isReachable(HashMap<X,Set<X>> edges,X from,X to){
public class GraphHelper<X> {
// Edges are stored in reverse order (i.e. there is a edge from a to b iff b has a explicit
// higher precedence / order in general than a
protected HashMap<X,Set<X>> edges;
public class TarjanNodeInfo{
public int index;
public boolean onStack;
public int lowlink;
}
protected int tarjanIndex;
protected HashMap<X,TarjanNodeInfo> tarjanNodeInfos;
protected Stack<X> tarjanStack;
protected LinkedList<X> cycle;
protected boolean isReachable(X from,X to){
HashSet<X> toCheck = new HashSet<>();
if(edges.get(from).size() == 0){
// if the node has no outgoing node, than nothing is reachable
......@@ -30,4 +50,76 @@ public class GraphHelper {
return false;
}
protected boolean isAcyclic(){
tarjanIndex = 0;
tarjanNodeInfos = new HashMap<>();
tarjanStack = new Stack<>();
for(X t : edges.keySet()){
TarjanNodeInfo tni = new TarjanNodeInfo();
tni.onStack = false;
tni.index = -1;
tni.lowlink = -1;
tarjanNodeInfos.put(t, tni);
}
cycle = new LinkedList<>();
for(Entry<X, TarjanNodeInfo> e : tarjanNodeInfos.entrySet()){
if(e.getValue().index == -1){
if(strongConnect(e.getKey())){
return false;
}
}
}
return true;
}
private boolean strongConnect(X t){
TarjanNodeInfo node = tarjanNodeInfos.get(t);
node.index = tarjanIndex;
node.lowlink = tarjanIndex;
node.onStack = true;
tarjanIndex++;
tarjanStack.push(t);
for(X succ : edges.get(t)){
if(tarjanNodeInfos.get(succ).index == -1){
if(strongConnect(succ)){
return true;
}
node.lowlink = Math.min(node.lowlink,tarjanNodeInfos.get(succ).lowlink);
}
else if(tarjanNodeInfos.get(succ).onStack){
node.lowlink = Math.min(node.lowlink,tarjanNodeInfos.get(succ).index);
}
}
if(node.lowlink == node.index){
X w = tarjanStack.pop();
tarjanNodeInfos.get(w).onStack = false;
if(!w.equals(t)){
// Construct cycle
cycle.add(t);
cycle.add(w);
do {
w = tarjanStack.pop();
cycle.add(w);
}
while(!w.equals(t));
//Cycle is in reverse order of what we want -> Reverse it
Collections.reverse(cycle);
return true;
}
}
return false;
}
}
\ No newline at end of file
......@@ -10,30 +10,17 @@ import java.util.Stack;
import java.util.Map.Entry;
import de.in.tum.www2.cup.ast.Precedence;
import de.in.tum.www2.cup.ast.Precedence.Type;
import de.in.tum.www2.cup.internal.terminal;
import de.tum.in.www2.cupplugin.Pair;
import de.tum.in.www2.cupplugin.views.CupConflictsView.ShiftReduceDetails;
import de.tum.in.www2.cupplugin.views.GraphHelper.TarjanNodeInfo;
class PrecedenceToInsert {
class PrecedenceToInsert extends GraphHelper<terminal>{
private HashMap<terminal,Precedence.Type> precs = new HashMap<>();
// Edges are stored in reverse order (i.e. there is a edge from a to b iff b has a explicit
// higher precedence than a
private HashMap<terminal,Set<terminal>> edges = new HashMap<>();
// These need to be inserted whenever an edge that contains the key is to be inserted
private Pair<terminal,terminal> originalEdge;
private int tarjanIndex;
private HashMap<terminal,TarjanNodeInfo> tarjanNodeInfos;
private Stack<terminal> tarjanStack;
private class TarjanNodeInfo{
public int index;
public boolean onStack;
public int lowlink;
}
private LinkedList<Pair<terminal,Precedence.Type>> result;
class PrecedenceCyclicException extends Exception{
/**
......@@ -66,9 +53,9 @@ class PrecedenceToInsert {
}
}
private LinkedList<terminal> cycle;
private LinkedList<Pair<terminal,Precedence.Type>> result;
public PrecedenceToInsert(){
edges = new HashMap<>();
}
/**
* Returns true iff this conflict would be resolved in favor of Shift by those precs
......@@ -194,77 +181,6 @@ class PrecedenceToInsert {
}
}
private boolean isAcyclic(){
tarjanIndex = 0;
tarjanNodeInfos = new HashMap<>();
tarjanStack = new Stack<>();
for(terminal t : precs.keySet()){
TarjanNodeInfo tni = new TarjanNodeInfo();
tni.onStack = false;
tni.index = -1;
tni.lowlink = -1;
tarjanNodeInfos.put(t, tni);
}
cycle = new LinkedList<>();
for(Entry<terminal, TarjanNodeInfo> e : tarjanNodeInfos.entrySet()){
if(e.getValue().index == -1){
if(strongConnect(e.getKey())){
return false;
}
}
}
return true;
}
private boolean strongConnect(terminal t){
TarjanNodeInfo node = tarjanNodeInfos.get(t);
node.index = tarjanIndex;
node.lowlink = tarjanIndex;
node.onStack = true;
tarjanIndex++;
tarjanStack.push(t);
for(terminal succ : edges.get(t)){
if(tarjanNodeInfos.get(succ).index == -1){
if(strongConnect(succ)){
return true;
}
node.lowlink = Math.min(node.lowlink,tarjanNodeInfos.get(succ).lowlink);
}
else if(tarjanNodeInfos.get(succ).onStack){
node.lowlink = Math.min(node.lowlink,tarjanNodeInfos.get(succ).index);
}
}
if(node.lowlink == node.index){
terminal w = tarjanStack.pop();
tarjanNodeInfos.get(w).onStack = false;
if(!w.equals(t)){
// Construct cycle
cycle.add(t);
cycle.add(w);
do {
w = tarjanStack.pop();
cycle.add(w);
}
while(!w.equals(t));
//Cycle is in reverse order of what we want -> Reverse it
Collections.reverse(cycle);
return true;
}
}
return false;
}
private void topSort(){
result = new LinkedList<>();
tarjanNodeInfos = new HashMap<>();
......@@ -361,7 +277,7 @@ class PrecedenceToInsert {
// This works because we have guarantee that the graph is a DAG
// t reachable from over -> t has higher precedence
return GraphHelper.isReachable(edges, over, t);
return isReachable(over, t);
}
/**
......
package de.tum.in.www2.cupplugin.views;
import java.util.HashMap;
import java.util.Set;
import de.in.tum.www2.cup.internal.internal_error;
import de.in.tum.www2.cup.internal.lalr_item;
import de.in.tum.www2.cup.internal.lr_item_core;
public class ReordersToDo {
private HashMap<lr_item_core,Set<lr_item_core>> edges = new HashMap<>();
public class ReordersToDo extends GraphHelper<lr_item_core>{
// These crazy many overriden versions are necessary because otherwise the lalr_items will
// be put into the set, and their equals checks the lookahead set but we don't want that
......@@ -57,6 +54,6 @@ public class ReordersToDo {
return false;
}
return GraphHelper.isReachable(edges, low, high);
return isReachable(low, high);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment