use of org.antlr.works.visualization.fa.FAState in project antlrworks by antlr.
the class GFactory method buildGraphGroup.
private GGraphGroup buildGraphGroup(Grammar grammar, GrammarError error) {
// Create one GGraph for each error rules
List<GGraph> graphs = new ArrayList<GGraph>();
FAFactory factory = new FAFactory(grammar);
for (String rule : error.rules) {
NFAState startState = grammar.getRuleStartState(rule);
FAState state = factory.buildNFA(startState, optimize);
GGraph graph = renderer.render(state);
graph.setName(rule);
graphs.add(graph);
}
// Add only graphs that are referenced by at least one error path.
// For example, the statement rule of the java.g grammar produces
// states that do not exist in the graph (they are after the accepted state
// and are ignored by the FAFactory)
GGraphGroup gg = new GGraphGroup();
for (GGraph graph : graphs) {
if (graph.containsAtLeastOneState(error.states))
gg.add(graph);
}
// Attach all error paths to the GGraphGroup
for (int i = 0; i < error.paths.size(); i++) {
List states = error.paths.get(i);
Boolean disabled = error.pathsDisabled.get(i);
try {
gg.addPath(states, disabled, factory.getSkippedStatesMap());
} catch (Exception e) {
if (console == null)
e.printStackTrace();
else
console.println(e);
}
}
// Attach all unreacheable alts to the GGraphGroup
for (Object[] unreachableAlt : error.unreachableAlts) {
gg.addUnreachableAlt((NFAState) unreachableAlt[0], (Integer) unreachableAlt[1]);
}
if (error.paths.size() > 0)
gg.getPathGroup().setPathVisible(0, true);
return gg;
}
use of org.antlr.works.visualization.fa.FAState in project antlrworks by antlr.
the class GFactory method buildGraphsForRule.
public GGraph buildGraphsForRule(ANTLRGrammarEngine antlrEngineGrammar, String rule) throws Exception {
NFAState startState = antlrEngineGrammar.getRuleStartState(rule);
if (startState == null)
return null;
FAState state = new FAFactory(antlrEngineGrammar.getGrammarForRule(rule)).buildNFA(startState, optimize);
GGraph graph = renderer.render(state);
graph.setName(rule);
return graph;
}
use of org.antlr.works.visualization.fa.FAState in project antlrworks by antlr.
the class GRenderer method recursiveRenderPositionAlternative.
public FAState recursiveRenderPositionAlternative(FAState state, GPoint basePoint) {
FAState alternativeEndState = alternativeEndState(state);
// This point is used to position each transition
GPoint point = new GPoint(basePoint);
point.addX(GContext.NODE_WIDTH + GContext.EPSILON_WIDTH);
GDimension firstAlternativeDimension = null;
for (int t = 0; t < state.getNumberOfTransitions(); t++) {
FATransition transition = state.transition(t);
GLink link = getNode(state).getLink(transition);
if (t == 0) {
// We remember here the size of the first transition because if we find later
// a "loop" transition, we will have to offset this "loop" by the size of the first
// transition (because the "loop" is always drawed above the first transition).
firstAlternativeDimension = link.branchDim;
}
if (t > 0 && !transition.loop) {
// Offset the current point for each transition (except for a "loop" because it is
// displayed above the first transition)
point.addY(GContext.LINE_SPACE);
point.addY(link.branchDim.up);
}
if (transition.target == alternativeEndState) {
// The transition is simply a single transition (epsilon normally).
if (transition.loop) {
// If this is a "loop", draw it above the first transition
GPoint vp = new GPoint(basePoint);
vp.subY(firstAlternativeDimension.up);
vp.subY(link.branchDim.down);
// The "virtual position" is used by the link to know where to display itself
// when it has to "curve" (because both start and end point are on the same y-axis value)
getNode(state).getLink(transition).setVirtualPosition(vp);
} else {
getNode(state).getLink(transition).setVirtualPosition(point);
point.addY(link.branchDim.down);
}
} else {
// The transition is more than a single transition, continue recursively...
recursiveRenderPositionNode(transition.target, alternativeEndState, new GPoint(point));
point.addY(link.branchDim.down);
}
}
return alternativeEndState;
}
use of org.antlr.works.visualization.fa.FAState in project antlrworks by antlr.
the class GRenderer method alternativeEndState.
public FAState alternativeEndState(FAState alt) {
int counter = alt.getNumberOfTransitions() - 1;
FAState state = alt;
while (true) {
FATransition transition = state.getFirstTransition();
if (transition == null)
break;
state = transition.target;
// Note: a state can be both an end-of-alternative and an alternative itself ;-)
if (analysis.numberOfIncomingTransition(state) > 1) {
counter -= analysis.numberOfIncomingTransition(state) - 1;
if (counter <= 0)
break;
}
if (state.isAlternative()) {
counter += state.getNumberOfTransitions() - 1;
}
}
return state;
}
use of org.antlr.works.visualization.fa.FAState in project antlrworks by antlr.
the class GGraphGroup method addPath.
public void addPath(List path, boolean disabled, Map<Integer, FAState> skippedStates) {
List<GPathElement> elements = new ArrayList<GPathElement>();
/** path contains a list of NFAState states (from ANTLR): they represent
* all the states along the path. The graphical representation of the NFA/SD
* does not necessarily contains all the states of the path because the representation
* can be simplified to remove all unecessary states.
* The problem here is to use the information stored in the transition of the
* graphical representation to figure out exactly which graphical node corresponds
* to the path.
*/
NFAState state;
GNode node;
NFAState nextState = null;
GNode nextNode = null;
for (pathIndex = 0; getPathIndex() < path.size(); pathIndex = getPathIndex() + 1) {
if (getPathIndex() == 0) {
nextState = (NFAState) path.get(getPathIndex());
nextNode = findNodeForStateNumber(nextState.stateNumber);
if (nextNode == null) {
// A path can start from anywhere in the graph. It might happen
// that the starting state of the path has been skipped by
// the optimization in FAFactory. We use the skippedStates mapping
// to find out what is the parent state of the skipped state.
FAState parentState = skippedStates.get(nextState.stateNumber);
if (parentState == null) {
System.err.println("[GGraphGroup] Starting path state " + nextState.stateNumber + "[" + nextState.enclosingRule.name + "] cannot be found in the graph");
return;
} else {
nextNode = findNodeForStateNumber(parentState.stateNumber);
}
}
continue;
} else {
state = nextState;
node = nextNode;
}
nextState = (NFAState) path.get(getPathIndex());
nextNode = findNodeForStateNumber(nextState.stateNumber);
GNode externalNode = null;
if (nextNode == null) {
// The state has probably been skipped during the graphical rendering.
// Find the next non-skipped state.
FATransition t = getNodeTransitionToNextNonSkippedState(node, path);
if (t == null) {
// No transition found. Look in the skipped states mapping because
// it might be possible that the next state is in another rule but
// cannot be found because it has been skipped.
FAState parentState = skippedStates.get(nextState.stateNumber);
if (parentState == null) {
// OK. The node really does not exist. Continue by skipping it.
nextNode = node;
continue;
} else {
nextNode = findNodeForStateNumber(parentState.stateNumber);
}
} else {
// is incrementing it
if (getPathIndex() >= path.size()) {
nextNode = findNodeForStateNumber(t.target.stateNumber);
} else {
nextState = (NFAState) path.get(getPathIndex());
if (t.target.stateNumber == nextState.stateNumber) {
nextNode = findNodeForStateNumber(t.target.stateNumber);
} else {
// The only case that the target state of the transition if not
// the next state of the path is when the next state of the path
// is in another rule. In this case, the target state of the transition
// will contain a negative state number indicating an external rule reference:
// this external rule reference is added by AW during rendering and is not
// part of any ANTLR NFA.
// This node is the node representing the external rule reference
// before jumping outside of the rule
externalNode = findNodeForStateNumber(t.target.stateNumber);
// This node is the first node in the other rule
nextNode = findNodeForStateNumber(nextState.stateNumber);
}
}
}
}
if (state == null || node == null || nextNode == null)
continue;
if (state.enclosingRule.name.equals(nextState.enclosingRule.name))
addNextElementInSameRule(elements, node, nextNode);
else
addNextElementInOtherRule(elements, node, externalNode, nextNode, nextState);
}
if (nextNode != null)
elements.add(GPathElement.createElement(nextNode));
getPathGroup().addPath(new GPath(elements, disabled));
}
Aggregations