Commit 9d14a84a authored by Sebastian Pretscher's avatar Sebastian Pretscher

Added view to find conflicts

parent af9ab62a
......@@ -142,17 +142,24 @@ public class DocumentDidChangeJob extends Job {
e.printStackTrace();
}
errorReporter.pushToUIThread();
//errorReporter.pushToUIThread();
if (result != null) {
// System.out.println(result.toString());
ParserResultJob resultModelJob = new ParserResultJob(result,
revNumber);
resultModelJob.setSystem(true);
resultModelJob.schedule();
try {
resultModelJob.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
return Status.CANCEL_STATUS;
}
}
if (jobs.contains(JobsToDo.buildTable)) {
......@@ -168,6 +175,12 @@ public class DocumentDidChangeJob extends Job {
LaLrResultJob resultLaLrModelJob = new LaLrResultJob(lalrResult, revNumber, context);
resultLaLrModelJob.setSystem(true);
resultLaLrModelJob.schedule();
try {
resultLaLrModelJob.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
return Status.CANCEL_STATUS;
}
......
package de.tum.in.www2.cupplugin.editors;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Stack;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.draw2d.IFigure;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.zest.core.viewers.AbstractZoomableViewer;
import org.eclipse.zest.core.viewers.EntityConnectionData;
import org.eclipse.zest.core.viewers.GraphViewer;
import org.eclipse.zest.core.viewers.IEntityStyleProvider;
import org.eclipse.zest.core.viewers.IGraphEntityContentProvider;
import org.eclipse.zest.core.viewers.IZoomableWorkbenchPart;
import org.eclipse.zest.core.viewers.internal.ZoomManager;
import org.eclipse.zest.layouts.LayoutAlgorithm;
import org.eclipse.zest.layouts.LayoutStyles;
import org.eclipse.zest.layouts.algorithms.CompositeLayoutAlgorithm;
import org.eclipse.zest.layouts.algorithms.GridLayoutAlgorithm;
import org.eclipse.zest.layouts.algorithms.HorizontalShift;
import org.eclipse.zest.layouts.algorithms.SpringLayoutAlgorithm;
import de.in.tum.www2.cup.CupContext;
import de.in.tum.www2.cup.LALRResult;
import de.in.tum.www2.cup.internal.lalr_state;
import de.in.tum.www2.cup.internal.lalr_transition;
import de.tum.in.www2.cupplugin.editors.CupReduceGraphView.GraphNodeContentProvider;
import de.tum.in.www2.cupplugin.editors.CupReduceGraphView.ModelRebuildJob;
import de.tum.in.www2.cupplugin.editors.CupReduceGraphView.ParserNodeModelContentProvider;
import de.tum.in.www2.cupplugin.editors.CupReduceGraphView.ParserReduceConnection;
import de.tum.in.www2.cupplugin.editors.CupReduceGraphView.ParserReduceLabelProvider;
import de.tum.in.www2.cupplugin.editors.CupReduceGraphView.ParserReduceNode;
import de.tum.in.www2.cupplugin.model.CupParserLaLrChangeObserver;
import de.tum.in.www2.cupplugin.model.Model;
public class CupConflictGraphView implements CupParserLaLrChangeObserver,
IZoomableWorkbenchPart, CupEditorPageVisibility {
private static final int BUTTON_WIDTH = 120;
public GraphViewer graphViewer;
private Model parseModel;
private ParserConflictNodeModelContentProvider nodeModel;
private Composite graphComposite;
private Composite parentComposite;
private Label symbolLabel;
private ZoomManager zoomManager;
private Combo nodeSelection;
private Listener nodeSelectionListener;
private boolean isVisible = false;
private boolean shouldRebuildWhenVisible = false;
private HashMap<Integer, lalr_state> stateHashMap;
private Stack<DFSNode> searchStack;
private HashSet<lalr_state> visitedStates;
public CupConflictGraphView(Composite parent, IDocument doc) {
this.parseModel = Model.getInstanceForDocument(doc);
this.parseModel.registerModelObserver(this);
this.parentComposite = parent;
this.stateHashMap = new HashMap<Integer, lalr_state>();
this.searchStack = new Stack<CupConflictGraphView.DFSNode>();
this.visitedStates = new HashSet<lalr_state>();
GridLayout parentLayout = new GridLayout(5, false);
this.parentComposite.setLayout(parentLayout);
this.graphComposite = new Composite(parent, SWT.NONE);
this.graphComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL,
true, true, 5, 1));
this.graphComposite.setLayout(new FillLayout());
nodeModel = new ParserConflictNodeModelContentProvider();
graphViewer = new GraphViewer(this.graphComposite, SWT.NONE);
graphViewer.setContentProvider(new GraphConflictNodeContentProvider());
ParserConflictLabelProvider labelProvider = new ParserConflictLabelProvider(
nodeModel.getConnections());
graphViewer.setLabelProvider(labelProvider);
graphViewer.setInput(nodeModel.getNodes());
LayoutAlgorithm layout = new CompositeLayoutAlgorithm(
LayoutStyles.NO_LAYOUT_NODE_RESIZING, new LayoutAlgorithm[] {
new SpringLayoutAlgorithm(
LayoutStyles.NO_LAYOUT_NODE_RESIZING),
new HorizontalShift(
LayoutStyles.NO_LAYOUT_NODE_RESIZING),
new GridLayoutAlgorithm(
LayoutStyles.NO_LAYOUT_NODE_RESIZING) });
graphViewer.setLayoutAlgorithm(layout, true);
graphViewer.applyLayout();
// Setup search Result Label
symbolLabel = new Label(this.parentComposite, SWT.WRAP);
symbolLabel.setLayoutData(new GridData(SWT.LEFT, SWT.BOTTOM, true,
false, 5, 1));
// Setup Buttons to enable/disable some features
Button labelDisplayButton = new Button(this.parentComposite, SWT.CHECK);
labelDisplayButton.setText("Show labels");
labelDisplayButton.setLayoutData(new GridData(BUTTON_WIDTH, 20));
labelDisplayButton.setSelection(labelProvider.showTransitionLabels);
labelDisplayButton.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event event) {
switch (event.type) {
case SWT.Selection:
if (labelProvider.showTransitionLabels) {
labelProvider.showTransitionLabels = false;
} else {
labelProvider.showTransitionLabels = true;
}
graphViewer.refresh();
break;
}
}
});
Button colorEndStates = new Button(this.parentComposite, SWT.CHECK);
colorEndStates.setText("Mark final states");
colorEndStates.setLayoutData(new GridData(BUTTON_WIDTH, 20));
colorEndStates.setSelection(labelProvider.showColordEndStates);
colorEndStates.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event event) {
switch (event.type) {
case SWT.Selection:
if (labelProvider.showColordEndStates) {
labelProvider.showColordEndStates = false;
} else {
labelProvider.showColordEndStates = true;
}
graphViewer.refresh();
break;
}
}
});
Button colorStartState = new Button(this.parentComposite, SWT.CHECK);
colorStartState.setText("Mark start states");
colorStartState.setLayoutData(new GridData(BUTTON_WIDTH, 20));
colorStartState.setSelection(labelProvider.showColordStartState);
colorStartState.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event event) {
switch (event.type) {
case SWT.Selection:
if (labelProvider.showColordStartState) {
labelProvider.showColordStartState = false;
} else {
labelProvider.showColordStartState = true;
}
graphViewer.refresh();
break;
}
}
});
try {
Method protectedGetZoomMethod = AbstractZoomableViewer.class
.getDeclaredMethod("getZoomManager", null);
protectedGetZoomMethod.setAccessible(true);
zoomManager = (ZoomManager) protectedGetZoomMethod.invoke(
this.getZoomableViewer(), null);
} catch (NoSuchMethodException | SecurityException
| IllegalAccessException | IllegalArgumentException
| InvocationTargetException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (zoomManager != null) {
Combo combo = new Combo(this.parentComposite, SWT.READ_ONLY);
combo.setLayoutData(new GridData(BUTTON_WIDTH, 20));
String[] levels = zoomManager.getZoomLevelsAsText();
combo.setItems(levels);
combo.select(0);
combo.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event e) {
if (e.widget instanceof Combo) {
Combo c = (Combo) e.widget;
int idx = c.getSelectionIndex();
zoomManager.setZoomAsText(levels[idx]);
}
}
});
}
nodeSelection = new Combo(this.parentComposite, SWT.READ_ONLY);
}
public AbstractZoomableViewer getGraphViewer() {
return graphViewer;
}
@Override
public AbstractZoomableViewer getZoomableViewer() {
return getGraphViewer();
}
@Override
public void ModelChange(Model model) {
stateHashMap.clear();
CupContext lalrContext = model.getLaLrContext();
lalr_state.lalr_state_shared sharedState = lalr_state
.getShared(lalrContext);
Enumeration allEnum = sharedState.all();
while (allEnum.hasMoreElements()) {
Object o = allEnum.nextElement();
if (o instanceof lalr_state) {
stateHashMap.put(((lalr_state) o).index(), (lalr_state) o);
}
}
// TODO: This should only contain tainted states!!
List<String> stateNames = new ArrayList<String>();
for (lalr_state state : stateHashMap.values()) {
stateNames.add("State: " + state.index());
}
nodeSelection.setItems(stateNames.toArray(new String[0]));
if (nodeSelectionListener != null) {
nodeSelection.removeListener(SWT.Selection, nodeSelectionListener);
}
nodeSelectionListener = new Listener() {
@Override
public void handleEvent(Event event) {
// System.out.println(event.widget);
if (event.widget instanceof Combo) {
Combo c = (Combo) event.widget;
int idx = c.getSelectionIndex();
String[] parts = c.getItem(idx).split(" ");
setModelForDFSAfterState(stateHashMap.get(Integer.parseInt(parts[1])));
// System.out.println("Selected state: "+state.index());
}
}
};
nodeSelection.addListener(SWT.Selection, nodeSelectionListener);
}
private void setModelForDFSAfterState(lalr_state state) {
lalr_state first = stateHashMap.get(0);
searchStack.clear();
visitedStates.clear();
// first.transitions().on_symbol()
DFSNode firstState = new DFSNode(first, null, null);
searchStack.push(firstState);
boolean found = DFSSearch(firstState, state.index());
String resultString = "Way to state " + state.index() + ": ";
if (found) {
nodeModel.rebuildModel(searchStack);
LayoutAlgorithm layout = new CompositeLayoutAlgorithm(
LayoutStyles.NO_LAYOUT_NODE_RESIZING, new LayoutAlgorithm[] {
new SpringLayoutAlgorithm(
LayoutStyles.NO_LAYOUT_NODE_RESIZING),
new HorizontalShift(
LayoutStyles.NO_LAYOUT_NODE_RESIZING),
new GridLayoutAlgorithm(
LayoutStyles.NO_LAYOUT_NODE_RESIZING) });
graphViewer.setLayoutAlgorithm(layout, true);
graphViewer.applyLayout();
graphViewer.refresh();
for (DFSNode n : searchStack) {
if (n.predecessor != null) {
resultString += " with Transition: "
+ n.getPredTransition().on_symbol().toString()
+ " to state: " + n.getState().index();
} else {
resultString += "From state " + n.getState().index() + ":";
}
}
symbolLabel.setText(resultString);
// symbolLabel.redraw();
// parentComposite.layout();
symbolLabel.setLayoutData(new GridData(SWT.LEFT, SWT.BOTTOM, true,
false, 5, 1));
parentComposite.layout(true, true);
}
}
private boolean DFSSearch(DFSNode state, int searchIndex) {
if (state.getState().index() == searchIndex) {
return true;
}
visitedStates.add(state.getState());
lalr_transition trans = state.getState().transitions();
while (trans != null) {
if (visitedStates.contains(trans.to_state())
|| !trans.on_symbol().is_non_term()) {
trans = trans.next();
continue;
} else {
DFSNode node = new DFSNode(trans.to_state(), state.getState(),
trans);
searchStack.push(node);
if (DFSSearch(node, searchIndex)) {
return true;
}
searchStack.pop();
}
trans = trans.next();
}
trans = state.getState().transitions();
while (trans != null) {
if (visitedStates.contains(trans.to_state())
|| trans.on_symbol().is_non_term()) {
trans = trans.next();
continue;
} else {
DFSNode node = new DFSNode(trans.to_state(), state.getState(),
trans);
searchStack.push(node);
if (DFSSearch(node, searchIndex)) {
return true;
}
searchStack.pop();
}
trans = trans.next();
}
return false;
}
@Override
public void willBecomeVisible() {
// this.graphViewer.refresh();
}
@Override
public void becameHidden() {
// TODO Auto-generated method stub
}
static class DFSNode {
private lalr_state state;
private lalr_state predecessor;
private lalr_transition predTransition;
public DFSNode(lalr_state state, lalr_state predecessor,
lalr_transition predTransition) {
this.state = state;
this.predecessor = predecessor;
this.predTransition = predTransition;
}
public lalr_state getState() {
return state;
}
public void setState(lalr_state state) {
this.state = state;
}
public lalr_state getPredecessor() {
return predecessor;
}
public void setPredecessor(lalr_state predecessor) {
this.predecessor = predecessor;
}
public lalr_transition getPredTransition() {
return predTransition;
}
public void setPredTransition(lalr_transition predTransition) {
this.predTransition = predTransition;
}
}
static class ParserConflictNode {
private final int id;
private final String name;
private List<ParserConflictNode> connections;
private String description;
public ParserConflictNode(int id, String name) {
this.id = id;
this.name = name;
this.connections = new ArrayList<ParserConflictNode>();
this.description = "";
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public List<ParserConflictNode> getConnectedTo() {
return connections;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
static class ParserConflictConnection {
final String id;
final String label;
final ParserConflictNode source;
final ParserConflictNode destination;
public ParserConflictConnection(String id, String label,
ParserConflictNode source, ParserConflictNode destination) {
this.id = id;
this.label = label;
this.source = source;
this.destination = destination;
}
public String getLabel() {
return label;
}
public ParserConflictNode getSource() {
return source;
}
public ParserConflictNode getDestination() {
return destination;
}
}
static class ParserConflictNodeModelContentProvider {
private List<ParserConflictConnection> connections;
private List<ParserConflictNode> nodes;
private HashMap<Integer, ParserConflictNode> nodeMap;
LALRResult lalrResult;
CupContext lalrContext;
public ParserConflictNodeModelContentProvider() {
connections = new ArrayList<ParserConflictConnection>();
nodes = new ArrayList<ParserConflictNode>();
nodeMap = new HashMap<Integer, ParserConflictNode>();
}
public HashMap<Integer, ParserConflictNode> getNodeMap() {
return nodeMap;
}
public List<ParserConflictConnection> getConnections() {
return connections;
}
public void rebuildModel(Model model, LALRResult lalrResult,
CupContext lalrContext) {
this.lalrContext = lalrContext;
this.lalrResult = lalrResult;
}
public List<ParserConflictNode> getNodes() {
return nodes;
}
public void rebuildModel(Stack<DFSNode> foundNodes) {
connections.clear();
nodes.clear();
nodeMap.clear();
ParserConflictNode old = null;
int counter = 0;
for(DFSNode dfsNode : foundNodes) {
if(old == null) {
old = new ParserConflictNode(dfsNode.getState().index(), "State "+dfsNode.getState().index());
nodes.add(old);
continue;
}
ParserConflictNode n = new ParserConflictNode(dfsNode.getState().index(), "State "+dfsNode.getState().index());
nodes.add(n);
ParserConflictConnection con = new ParserConflictConnection(""+counter, dfsNode.getPredTransition().on_symbol().toString(), old, n);
old.getConnectedTo().add(n);
connections.add(con);
old = n;
}
}
}
static class GraphConflictNodeContentProvider extends ArrayContentProvider
implements IGraphEntityContentProvider {
@Override
public Object[] getConnectedTo(Object entity) {
if (entity instanceof ParserConflictNode) {
ParserConflictNode node = (ParserConflictNode) entity;
return node.getConnectedTo().toArray();
}
return null;
}
}
static class ParserConflictLabelProvider extends LabelProvider implements
IEntityStyleProvider {
private List<ParserConflictConnection> connections;
public boolean showTransitionLabels = true;
public boolean showColordEndStates = true;
public boolean showColordStartState = true;
public ParserConflictLabelProvider(