Commit 69166194 authored by Michael Schwarz's avatar Michael Schwarz

graph structure for reduce/reduce

parent 9b79d4cf
...@@ -3,10 +3,13 @@ import java.util.Collections; ...@@ -3,10 +3,13 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.Stack; import java.util.Stack;
import java.util.Map.Entry; import java.util.Map.Entry;
import de.in.tum.www2.cup.internal.terminal;
public class GraphHelper<X> { 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 // 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 // higher precedence / order in general than a
......
...@@ -22,6 +22,7 @@ class PrecedenceToInsert extends GraphHelper<terminal>{ ...@@ -22,6 +22,7 @@ class PrecedenceToInsert extends GraphHelper<terminal>{
private Pair<terminal,terminal> originalEdge; private Pair<terminal,terminal> originalEdge;
private LinkedList<Pair<terminal,Precedence.Type>> result; private LinkedList<Pair<terminal,Precedence.Type>> result;
// Exception can not be moved to GraphHelper as that is generic and because Java
class PrecedenceCyclicException extends Exception{ class PrecedenceCyclicException extends Exception{
/** /**
* Every Exception is expected to have one of those * Every Exception is expected to have one of those
......
package de.tum.in.www2.cupplugin.views; package de.tum.in.www2.cupplugin.views;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
import java.util.Map.Entry;
import de.in.tum.www2.cup.ast.Precedence;
import de.in.tum.www2.cup.internal.internal_error; 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.lalr_item;
import de.in.tum.www2.cup.internal.lr_item_core; import de.in.tum.www2.cup.internal.lr_item_core;
import de.in.tum.www2.cup.internal.terminal;
import de.tum.in.www2.cupplugin.Pair;
import de.tum.in.www2.cupplugin.views.GraphHelper.TarjanNodeInfo;
import de.tum.in.www2.cupplugin.views.PrecedenceToInsert.PrecedenceCyclicException;
public class ReordersToDo extends GraphHelper<lr_item_core>{ public class ReordersToDo extends GraphHelper<lr_item_core>{
private LinkedList<lr_item_core> result;
public ReordersToDo(){
edges = new HashMap<>();
}
class OrderCyclicException extends Exception{
/**
* Every Exception is expected to have one of those
*/
private static final long serialVersionUID = -3346362877376712162L;
private List<lr_item_core> cycle;
public OrderCyclicException(String s,List<lr_item_core> cycle){
super(s);
this.cycle = cycle;
}
public String cycleToString(){
//Works because the cycle is guaranteed to have at least 3 elements
StringBuilder sb = new StringBuilder();
sb.append(cycle.get(0).toString());
sb.append(" ->");
for(int i=1;i < cycle.size()-1;i++){
sb.append(" ");
sb.append(cycle.get(i).toString());
sb.append(" ->");
}
sb.append(" ");
sb.append(cycle.get(cycle.size()-1).toString());
return sb.toString();
}
}
// These crazy many overriden versions are necessary because otherwise the lalr_items will // 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 // be put into the set, and their equals checks the lookahead set but we don't want that
...@@ -49,11 +97,99 @@ public class ReordersToDo extends GraphHelper<lr_item_core>{ ...@@ -49,11 +97,99 @@ public class ReordersToDo extends GraphHelper<lr_item_core>{
} }
} }
private boolean isHigher(lr_item_core high,lr_item_core low){ public void insertOrder(lr_item_core higher,lr_item_core lower) throws OrderCyclicException{
boolean addedHigher = false,addedLower = false;
if(!edges.containsKey(higher)){
edges.put(higher, new HashSet<>());
addedHigher = true;
}
if(!edges.containsKey(lower)){
edges.put(lower, new HashSet<>());
addedLower = true;
}
edges.get(lower).add(higher);
if(!isAcyclic()){
//Do rollback
edges.get(lower).remove(higher);
if(addedHigher){
edges.remove(higher);
}
if(addedLower){
edges.remove(lower);
}
throw new OrderCyclicException("",cycle);
}
}
public void insertOrder(lalr_item higher,lalr_item lower) throws OrderCyclicException{
try {
insertOrder(new lr_item_core(higher.the_production(),higher.dot_pos()),
new lr_item_core(lower.the_production(),lower.dot_pos()));
} catch (internal_error e) {
return;
}
}
private boolean isHigher(lr_item_core high,lr_item_core low){
if(!edges.containsKey(high) || !edges.containsKey(low)){ if(!edges.containsKey(high) || !edges.containsKey(low)){
return false; return false;
} }
return isReachable(low, high); return isReachable(low, high);
} }
private void topSort(){
result = new LinkedList<>();
tarjanNodeInfos = new HashMap<>();
tarjanStack = new Stack<>();
for(lr_item_core t : edges.keySet()){
TarjanNodeInfo tni = new TarjanNodeInfo();
tni.onStack = false;
tni.index = -1;
tni.lowlink = -1;
tarjanNodeInfos.put(t, tni);
}
for(Entry<lr_item_core, TarjanNodeInfo> e : tarjanNodeInfos.entrySet()){
if(e.getValue().index == -1){
topSortVisit(e.getKey());
}
}
}
private void topSortVisit(lr_item_core t){
if(tarjanNodeInfos.get(t).onStack){
throw new IllegalStateException("Expected result to be acyclic.");
}
if(tarjanNodeInfos.get(t).index == -1){
tarjanNodeInfos.get(t).onStack = true;
for(lr_item_core succ : edges.get(t)){
topSortVisit(succ);
}
tarjanNodeInfos.get(t).index = 1;
tarjanNodeInfos.get(t).onStack = false;
result.addFirst(t);
}
}
public List<lr_item_core> getItemsOrdered() throws OrderCyclicException{
if(!isAcyclic()){
throw new OrderCyclicException("",cycle);
}
topSort();
return result;
}
} }
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