use of org.antlr.v4.runtime.atn.RuleStopState in project antlr4 by tunnelvisionlabs.
the class LexerATNSimulator method addDFAState.
/**
* Add a new DFA state if there isn't one with this set of
* configurations already. This method also detects the first
* configuration containing an ATN rule stop state. Later, when
* traversing the DFA, we will know which rule to accept.
*/
@NotNull
protected DFAState addDFAState(@NotNull ATNConfigSet configs) {
/* the lexer evaluates predicates on-the-fly; by this point configs
* should not contain any configurations with unevaluated predicates.
*/
assert !configs.hasSemanticContext();
DFAState proposed = new DFAState(atn.modeToDFA[mode], configs);
DFAState existing = atn.modeToDFA[mode].states.get(proposed);
if (existing != null)
return existing;
configs.optimizeConfigs(this);
DFAState newState = new DFAState(atn.modeToDFA[mode], configs.clone(true));
ATNConfig firstConfigWithRuleStopState = null;
for (ATNConfig c : configs) {
if (c.getState() instanceof RuleStopState) {
firstConfigWithRuleStopState = c;
break;
}
}
if (firstConfigWithRuleStopState != null) {
int prediction = atn.ruleToTokenType[firstConfigWithRuleStopState.getState().ruleIndex];
LexerActionExecutor lexerActionExecutor = firstConfigWithRuleStopState.getLexerActionExecutor();
newState.setAcceptState(new AcceptStateInfo(prediction, lexerActionExecutor));
}
return atn.modeToDFA[mode].addState(newState);
}
use of org.antlr.v4.runtime.atn.RuleStopState in project antlr4 by tunnelvisionlabs.
the class DOTGenerator method getDOT.
/**
* Return a String containing a DOT description that, when displayed,
* will show the incoming state machine visually. All nodes reachable
* from startState will be included.
*/
public String getDOT(ATNState startState, String[] ruleNames, boolean isLexer) {
if (startState == null)
return null;
// The output DOT graph for visualization
Set<ATNState> markedStates = new HashSet<ATNState>();
ST dot = stlib.getInstanceOf("atn");
dot.add("startState", startState.stateNumber);
dot.add("rankdir", rankdir);
List<ATNState> work = new LinkedList<ATNState>();
work.add(startState);
while (!work.isEmpty()) {
ATNState s = work.get(0);
if (markedStates.contains(s)) {
work.remove(0);
continue;
}
markedStates.add(s);
// don't go past end of rule node to the follow states
if (s instanceof RuleStopState)
continue;
// special case: if decision point, then line up the alt start states
// unless it's an end of block
// if ( s instanceof BlockStartState ) {
// ST rankST = stlib.getInstanceOf("decision-rank");
// DecisionState alt = (DecisionState)s;
// for (int i=0; i<alt.getNumberOfTransitions(); i++) {
// ATNState target = alt.transition(i).target;
// if ( target!=null ) {
// rankST.add("states", target.stateNumber);
// }
// }
// dot.add("decisionRanks", rankST);
// }
// make a DOT edge for each transition
ST edgeST;
for (int i = 0; i < s.getNumberOfTransitions(); i++) {
Transition edge = s.transition(i);
if (edge instanceof RuleTransition) {
RuleTransition rr = ((RuleTransition) edge);
// don't jump to other rules, but display edge to follow node
edgeST = stlib.getInstanceOf("edge");
String label = "<" + ruleNames[rr.ruleIndex];
if (((RuleStartState) rr.target).isPrecedenceRule) {
label += "[" + rr.precedence + "]";
}
label += ">";
edgeST.add("label", label);
edgeST.add("src", "s" + s.stateNumber);
edgeST.add("target", "s" + rr.followState.stateNumber);
edgeST.add("arrowhead", arrowhead);
dot.add("edges", edgeST);
work.add(rr.followState);
continue;
}
if (edge instanceof ActionTransition) {
edgeST = stlib.getInstanceOf("action-edge");
edgeST.add("label", getEdgeLabel(edge.toString()));
} else if (edge instanceof AbstractPredicateTransition) {
edgeST = stlib.getInstanceOf("edge");
edgeST.add("label", getEdgeLabel(edge.toString()));
} else if (edge.isEpsilon()) {
edgeST = stlib.getInstanceOf("epsilon-edge");
edgeST.add("label", getEdgeLabel(edge.toString()));
boolean loopback = false;
if (edge.target instanceof PlusBlockStartState) {
loopback = s.equals(((PlusBlockStartState) edge.target).loopBackState);
} else if (edge.target instanceof StarLoopEntryState) {
loopback = s.equals(((StarLoopEntryState) edge.target).loopBackState);
}
edgeST.add("loopback", loopback);
} else if (edge instanceof AtomTransition) {
edgeST = stlib.getInstanceOf("edge");
AtomTransition atom = (AtomTransition) edge;
String label = String.valueOf(atom.label);
if (isLexer)
label = "'" + getEdgeLabel(new StringBuilder().appendCodePoint(atom.label).toString()) + "'";
else if (grammar != null)
label = grammar.getTokenDisplayName(atom.label);
edgeST.add("label", getEdgeLabel(label));
} else if (edge instanceof SetTransition) {
edgeST = stlib.getInstanceOf("edge");
SetTransition set = (SetTransition) edge;
String label = set.label().toString();
if (isLexer)
label = set.label().toString(true);
else if (grammar != null)
label = set.label().toString(grammar.getVocabulary());
if (edge instanceof NotSetTransition)
label = "~" + label;
edgeST.add("label", getEdgeLabel(label));
} else if (edge instanceof RangeTransition) {
edgeST = stlib.getInstanceOf("edge");
RangeTransition range = (RangeTransition) edge;
String label = range.label().toString();
if (isLexer)
label = range.toString();
else if (grammar != null)
label = range.label().toString(grammar.getVocabulary());
edgeST.add("label", getEdgeLabel(label));
} else {
edgeST = stlib.getInstanceOf("edge");
edgeST.add("label", getEdgeLabel(edge.toString()));
}
edgeST.add("src", "s" + s.stateNumber);
edgeST.add("target", "s" + edge.target.stateNumber);
edgeST.add("arrowhead", arrowhead);
if (s.getNumberOfTransitions() > 1) {
edgeST.add("transitionIndex", i);
} else {
edgeST.add("transitionIndex", false);
}
dot.add("edges", edgeST);
work.add(edge.target);
}
}
// }
for (ATNState s : markedStates) {
if (!(s instanceof RuleStopState))
continue;
ST st = stlib.getInstanceOf("stopstate");
st.add("name", "s" + s.stateNumber);
st.add("label", getStateLabel(s));
dot.add("states", st);
}
for (ATNState s : markedStates) {
if (s instanceof RuleStopState)
continue;
ST st = stlib.getInstanceOf("state");
st.add("name", "s" + s.stateNumber);
st.add("label", getStateLabel(s));
st.add("transitions", s.getTransitions());
dot.add("states", st);
}
return dot.render();
}
use of org.antlr.v4.runtime.atn.RuleStopState in project antlr4 by tunnelvisionlabs.
the class ATNDeserializer method deserialize.
@SuppressWarnings("deprecation")
public ATN deserialize(@NotNull char[] data) {
data = data.clone();
// was implemented.
for (int i = 1; i < data.length; i++) {
data[i] = (char) (data[i] - 2);
}
int p = 0;
int version = toInt(data[p++]);
if (version != SERIALIZED_VERSION) {
String reason = String.format(Locale.getDefault(), "Could not deserialize ATN with version %d (expected %d).", version, SERIALIZED_VERSION);
throw new UnsupportedOperationException(new InvalidClassException(ATN.class.getName(), reason));
}
UUID uuid = toUUID(data, p);
p += 8;
if (!SUPPORTED_UUIDS.contains(uuid)) {
String reason = String.format(Locale.getDefault(), "Could not deserialize ATN with UUID %s (expected %s or a legacy UUID).", uuid, SERIALIZED_UUID);
throw new UnsupportedOperationException(new InvalidClassException(ATN.class.getName(), reason));
}
boolean supportsLexerActions = isFeatureSupported(ADDED_LEXER_ACTIONS, uuid);
ATNType grammarType = ATNType.values()[toInt(data[p++])];
int maxTokenType = toInt(data[p++]);
ATN atn = new ATN(grammarType, maxTokenType);
//
// STATES
//
List<Tuple2<LoopEndState, Integer>> loopBackStateNumbers = new ArrayList<Tuple2<LoopEndState, Integer>>();
List<Tuple2<BlockStartState, Integer>> endStateNumbers = new ArrayList<Tuple2<BlockStartState, Integer>>();
int nstates = toInt(data[p++]);
for (int i = 0; i < nstates; i++) {
int stype = toInt(data[p++]);
// ignore bad type of states
if (stype == ATNState.INVALID_TYPE) {
atn.addState(null);
continue;
}
int ruleIndex = toInt(data[p++]);
if (ruleIndex == Character.MAX_VALUE) {
ruleIndex = -1;
}
ATNState s = stateFactory(stype, ruleIndex);
if (stype == ATNState.LOOP_END) {
// special case
int loopBackStateNumber = toInt(data[p++]);
loopBackStateNumbers.add(Tuple.create((LoopEndState) s, loopBackStateNumber));
} else if (s instanceof BlockStartState) {
int endStateNumber = toInt(data[p++]);
endStateNumbers.add(Tuple.create((BlockStartState) s, endStateNumber));
}
atn.addState(s);
}
// delay the assignment of loop back and end states until we know all the state instances have been initialized
for (Tuple2<LoopEndState, Integer> pair : loopBackStateNumbers) {
pair.getItem1().loopBackState = atn.states.get(pair.getItem2());
}
for (Tuple2<BlockStartState, Integer> pair : endStateNumbers) {
pair.getItem1().endState = (BlockEndState) atn.states.get(pair.getItem2());
}
int numNonGreedyStates = toInt(data[p++]);
for (int i = 0; i < numNonGreedyStates; i++) {
int stateNumber = toInt(data[p++]);
((DecisionState) atn.states.get(stateNumber)).nonGreedy = true;
}
int numSllDecisions = toInt(data[p++]);
for (int i = 0; i < numSllDecisions; i++) {
int stateNumber = toInt(data[p++]);
((DecisionState) atn.states.get(stateNumber)).sll = true;
}
int numPrecedenceStates = toInt(data[p++]);
for (int i = 0; i < numPrecedenceStates; i++) {
int stateNumber = toInt(data[p++]);
((RuleStartState) atn.states.get(stateNumber)).isPrecedenceRule = true;
}
//
// RULES
//
int nrules = toInt(data[p++]);
if (atn.grammarType == ATNType.LEXER) {
atn.ruleToTokenType = new int[nrules];
}
atn.ruleToStartState = new RuleStartState[nrules];
for (int i = 0; i < nrules; i++) {
int s = toInt(data[p++]);
RuleStartState startState = (RuleStartState) atn.states.get(s);
startState.leftFactored = toInt(data[p++]) != 0;
atn.ruleToStartState[i] = startState;
if (atn.grammarType == ATNType.LEXER) {
int tokenType = toInt(data[p++]);
if (tokenType == 0xFFFF) {
tokenType = Token.EOF;
}
atn.ruleToTokenType[i] = tokenType;
if (!isFeatureSupported(ADDED_LEXER_ACTIONS, uuid)) {
// this piece of unused metadata was serialized prior to the
// addition of LexerAction
int actionIndexIgnored = toInt(data[p++]);
if (actionIndexIgnored == 0xFFFF) {
actionIndexIgnored = -1;
}
}
}
}
atn.ruleToStopState = new RuleStopState[nrules];
for (ATNState state : atn.states) {
if (!(state instanceof RuleStopState)) {
continue;
}
RuleStopState stopState = (RuleStopState) state;
atn.ruleToStopState[state.ruleIndex] = stopState;
atn.ruleToStartState[state.ruleIndex].stopState = stopState;
}
//
// MODES
//
int nmodes = toInt(data[p++]);
for (int i = 0; i < nmodes; i++) {
int s = toInt(data[p++]);
atn.modeToStartState.add((TokensStartState) atn.states.get(s));
}
atn.modeToDFA = new DFA[nmodes];
for (int i = 0; i < nmodes; i++) {
atn.modeToDFA[i] = new DFA(atn.modeToStartState.get(i));
}
//
// SETS
//
List<IntervalSet> sets = new ArrayList<IntervalSet>();
// First, read all sets with 16-bit Unicode code points <= U+FFFF.
p = deserializeSets(data, p, sets, getUnicodeDeserializer(UnicodeDeserializingMode.UNICODE_BMP));
// deserialize sets with 32-bit arguments <= U+10FFFF.
if (isFeatureSupported(ADDED_UNICODE_SMP, uuid)) {
int previousSetCount = sets.size();
p = deserializeSets(data, p, sets, getUnicodeDeserializer(UnicodeDeserializingMode.UNICODE_SMP));
atn.setHasUnicodeSMPTransitions(sets.size() > previousSetCount);
}
//
// EDGES
//
int nedges = toInt(data[p++]);
for (int i = 0; i < nedges; i++) {
int src = toInt(data[p]);
int trg = toInt(data[p + 1]);
int ttype = toInt(data[p + 2]);
int arg1 = toInt(data[p + 3]);
int arg2 = toInt(data[p + 4]);
int arg3 = toInt(data[p + 5]);
Transition trans = edgeFactory(atn, ttype, src, trg, arg1, arg2, arg3, sets);
// System.out.println("EDGE "+trans.getClass().getSimpleName()+" "+
// src+"->"+trg+
// " "+Transition.serializationNames[ttype]+
// " "+arg1+","+arg2+","+arg3);
ATNState srcState = atn.states.get(src);
srcState.addTransition(trans);
p += 6;
}
// edges for rule stop states can be derived, so they aren't serialized
// Map rule stop state -> return state -> outermost precedence return
Set<Tuple3<Integer, Integer, Integer>> returnTransitions = new LinkedHashSet<Tuple3<Integer, Integer, Integer>>();
for (ATNState state : atn.states) {
boolean returningToLeftFactored = state.ruleIndex >= 0 && atn.ruleToStartState[state.ruleIndex].leftFactored;
for (int i = 0; i < state.getNumberOfTransitions(); i++) {
Transition t = state.transition(i);
if (!(t instanceof RuleTransition)) {
continue;
}
RuleTransition ruleTransition = (RuleTransition) t;
boolean returningFromLeftFactored = atn.ruleToStartState[ruleTransition.target.ruleIndex].leftFactored;
if (!returningFromLeftFactored && returningToLeftFactored) {
continue;
}
int outermostPrecedenceReturn = -1;
if (atn.ruleToStartState[ruleTransition.target.ruleIndex].isPrecedenceRule) {
if (ruleTransition.precedence == 0) {
outermostPrecedenceReturn = ruleTransition.target.ruleIndex;
}
}
returnTransitions.add(Tuple.create(ruleTransition.target.ruleIndex, ruleTransition.followState.stateNumber, outermostPrecedenceReturn));
}
}
// Add all elements from returnTransitions to the ATN
for (Tuple3<Integer, Integer, Integer> returnTransition : returnTransitions) {
EpsilonTransition transition = new EpsilonTransition(atn.states.get(returnTransition.getItem2()), returnTransition.getItem3());
atn.ruleToStopState[returnTransition.getItem1()].addTransition(transition);
}
for (ATNState state : atn.states) {
if (state instanceof BlockStartState) {
// we need to know the end state to set its start state
if (((BlockStartState) state).endState == null) {
throw new IllegalStateException();
}
// block end states can only be associated to a single block start state
if (((BlockStartState) state).endState.startState != null) {
throw new IllegalStateException();
}
((BlockStartState) state).endState.startState = (BlockStartState) state;
}
if (state instanceof PlusLoopbackState) {
PlusLoopbackState loopbackState = (PlusLoopbackState) state;
for (int i = 0; i < loopbackState.getNumberOfTransitions(); i++) {
ATNState target = loopbackState.transition(i).target;
if (target instanceof PlusBlockStartState) {
((PlusBlockStartState) target).loopBackState = loopbackState;
}
}
} else if (state instanceof StarLoopbackState) {
StarLoopbackState loopbackState = (StarLoopbackState) state;
for (int i = 0; i < loopbackState.getNumberOfTransitions(); i++) {
ATNState target = loopbackState.transition(i).target;
if (target instanceof StarLoopEntryState) {
((StarLoopEntryState) target).loopBackState = loopbackState;
}
}
}
}
//
// DECISIONS
//
int ndecisions = toInt(data[p++]);
for (int i = 1; i <= ndecisions; i++) {
int s = toInt(data[p++]);
DecisionState decState = (DecisionState) atn.states.get(s);
atn.decisionToState.add(decState);
decState.decision = i - 1;
}
//
if (atn.grammarType == ATNType.LEXER) {
if (supportsLexerActions) {
atn.lexerActions = new LexerAction[toInt(data[p++])];
for (int i = 0; i < atn.lexerActions.length; i++) {
LexerActionType actionType = LexerActionType.values()[toInt(data[p++])];
int data1 = toInt(data[p++]);
if (data1 == 0xFFFF) {
data1 = -1;
}
int data2 = toInt(data[p++]);
if (data2 == 0xFFFF) {
data2 = -1;
}
LexerAction lexerAction = lexerActionFactory(actionType, data1, data2);
atn.lexerActions[i] = lexerAction;
}
} else {
// for compatibility with older serialized ATNs, convert the old
// serialized action index for action transitions to the new
// form, which is the index of a LexerCustomAction
List<LexerAction> legacyLexerActions = new ArrayList<LexerAction>();
for (ATNState state : atn.states) {
for (int i = 0; i < state.getNumberOfTransitions(); i++) {
Transition transition = state.transition(i);
if (!(transition instanceof ActionTransition)) {
continue;
}
int ruleIndex = ((ActionTransition) transition).ruleIndex;
int actionIndex = ((ActionTransition) transition).actionIndex;
LexerCustomAction lexerAction = new LexerCustomAction(ruleIndex, actionIndex);
state.setTransition(i, new ActionTransition(transition.target, ruleIndex, legacyLexerActions.size(), false));
legacyLexerActions.add(lexerAction);
}
}
atn.lexerActions = legacyLexerActions.toArray(new LexerAction[legacyLexerActions.size()]);
}
}
markPrecedenceDecisions(atn);
atn.decisionToDFA = new DFA[ndecisions];
for (int i = 0; i < ndecisions; i++) {
atn.decisionToDFA[i] = new DFA(atn.decisionToState.get(i), i);
}
if (deserializationOptions.isVerifyATN()) {
verifyATN(atn);
}
if (deserializationOptions.isGenerateRuleBypassTransitions() && atn.grammarType == ATNType.PARSER) {
atn.ruleToTokenType = new int[atn.ruleToStartState.length];
for (int i = 0; i < atn.ruleToStartState.length; i++) {
atn.ruleToTokenType[i] = atn.maxTokenType + i + 1;
}
for (int i = 0; i < atn.ruleToStartState.length; i++) {
BasicBlockStartState bypassStart = new BasicBlockStartState();
bypassStart.ruleIndex = i;
atn.addState(bypassStart);
BlockEndState bypassStop = new BlockEndState();
bypassStop.ruleIndex = i;
atn.addState(bypassStop);
bypassStart.endState = bypassStop;
atn.defineDecisionState(bypassStart);
bypassStop.startState = bypassStart;
ATNState endState;
Transition excludeTransition = null;
if (atn.ruleToStartState[i].isPrecedenceRule) {
// wrap from the beginning of the rule to the StarLoopEntryState
endState = null;
for (ATNState state : atn.states) {
if (state.ruleIndex != i) {
continue;
}
if (!(state instanceof StarLoopEntryState)) {
continue;
}
ATNState maybeLoopEndState = state.transition(state.getNumberOfTransitions() - 1).target;
if (!(maybeLoopEndState instanceof LoopEndState)) {
continue;
}
if (maybeLoopEndState.epsilonOnlyTransitions && maybeLoopEndState.transition(0).target instanceof RuleStopState) {
endState = state;
break;
}
}
if (endState == null) {
throw new UnsupportedOperationException("Couldn't identify final state of the precedence rule prefix section.");
}
excludeTransition = ((StarLoopEntryState) endState).loopBackState.transition(0);
} else {
endState = atn.ruleToStopState[i];
}
// all non-excluded transitions that currently target end state need to target blockEnd instead
for (ATNState state : atn.states) {
for (Transition transition : state.transitions) {
if (transition == excludeTransition) {
continue;
}
if (transition.target == endState) {
transition.target = bypassStop;
}
}
}
// all transitions leaving the rule start state need to leave blockStart instead
while (atn.ruleToStartState[i].getNumberOfTransitions() > 0) {
Transition transition = atn.ruleToStartState[i].removeTransition(atn.ruleToStartState[i].getNumberOfTransitions() - 1);
bypassStart.addTransition(transition);
}
// link the new states
atn.ruleToStartState[i].addTransition(new EpsilonTransition(bypassStart));
bypassStop.addTransition(new EpsilonTransition(endState));
ATNState matchState = new BasicState();
atn.addState(matchState);
matchState.addTransition(new AtomTransition(bypassStop, atn.ruleToTokenType[i]));
bypassStart.addTransition(new EpsilonTransition(matchState));
}
if (deserializationOptions.isVerifyATN()) {
// reverify after modification
verifyATN(atn);
}
}
if (deserializationOptions.isOptimize()) {
while (true) {
int optimizationCount = 0;
optimizationCount += inlineSetRules(atn);
optimizationCount += combineChainedEpsilons(atn);
boolean preserveOrder = atn.grammarType == ATNType.LEXER;
optimizationCount += optimizeSets(atn, preserveOrder);
if (optimizationCount == 0) {
break;
}
}
if (deserializationOptions.isVerifyATN()) {
// reverify after modification
verifyATN(atn);
}
}
identifyTailCalls(atn);
return atn;
}
use of org.antlr.v4.runtime.atn.RuleStopState in project antlr4 by tunnelvisionlabs.
the class ATN method getExpectedTokens.
/**
* Computes the set of input symbols which could follow ATN state number
* {@code stateNumber} in the specified full {@code context}. This method
* considers the complete parser context, but does not evaluate semantic
* predicates (i.e. all predicates encountered during the calculation are
* assumed true). If a path in the ATN exists from the starting state to the
* {@link RuleStopState} of the outermost context without matching any
* symbols, {@link Token#EOF} is added to the returned set.
*
* <p>If {@code context} is {@code null}, it is treated as
* {@link ParserRuleContext#EMPTY}.</p>
*
* <p>Note that this does NOT give you the set of all tokens that could
* appear at a given token position in the input phrase. In other words, it
* does not answer:</p>
*
* <quote>"Given a specific partial input phrase, return the set of all
* tokens that can follow the last token in the input phrase."</quote>
*
* <p>The big difference is that with just the input, the parser could land
* right in the middle of a lookahead decision. Getting all
* <em>possible</em> tokens given a partial input stream is a separate
* computation. See https://github.com/antlr/antlr4/issues/1428</p>
*
* <p>For this function, we are specifying an ATN state and call stack to
* compute what token(s) can come next and specifically: outside of a
* lookahead decision. That is what you want for error reporting and
* recovery upon parse error.</p>
*
* @param stateNumber the ATN state number
* @param context the full parse context
* @return The set of potentially valid input symbols which could follow the
* specified state in the specified context.
* @throws IllegalArgumentException if the ATN does not contain a state with
* number {@code stateNumber}
*/
@NotNull
public IntervalSet getExpectedTokens(int stateNumber, @Nullable RuleContext context) {
if (stateNumber < 0 || stateNumber >= states.size()) {
throw new IllegalArgumentException("Invalid state number.");
}
RuleContext ctx = context;
ATNState s = states.get(stateNumber);
IntervalSet following = nextTokens(s);
if (!following.contains(Token.EPSILON)) {
return following;
}
IntervalSet expected = new IntervalSet();
expected.addAll(following);
expected.remove(Token.EPSILON);
while (ctx != null && ctx.invokingState >= 0 && following.contains(Token.EPSILON)) {
ATNState invokingState = states.get(ctx.invokingState);
RuleTransition rt = (RuleTransition) invokingState.transition(0);
following = nextTokens(rt.followState);
expected.addAll(following);
expected.remove(Token.EPSILON);
ctx = ctx.parent;
}
if (following.contains(Token.EPSILON)) {
expected.add(Token.EOF);
}
return expected;
}
use of org.antlr.v4.runtime.atn.RuleStopState in project antlr4 by tunnelvisionlabs.
the class ATNPrinter method asString.
public String asString() {
if (start == null)
return null;
marked = new HashSet<ATNState>();
work = new ArrayList<ATNState>();
work.add(start);
StringBuilder buf = new StringBuilder();
ATNState s;
while (!work.isEmpty()) {
s = work.remove(0);
if (marked.contains(s))
continue;
int n = s.getNumberOfTransitions();
// System.out.println("visit "+s+"; edges="+n);
marked.add(s);
for (int i = 0; i < n; i++) {
Transition t = s.transition(i);
if (!(s instanceof RuleStopState)) {
// don't add follow states to work
if (t instanceof RuleTransition)
work.add(((RuleTransition) t).followState);
else
work.add(t.target);
}
buf.append(getStateString(s));
if (t instanceof EpsilonTransition) {
buf.append("->").append(getStateString(t.target)).append('\n');
} else if (t instanceof RuleTransition) {
buf.append("-").append(g.getRule(((RuleTransition) t).ruleIndex).name).append("->").append(getStateString(t.target)).append('\n');
} else if (t instanceof ActionTransition) {
ActionTransition a = (ActionTransition) t;
buf.append("-").append(a.toString()).append("->").append(getStateString(t.target)).append('\n');
} else if (t instanceof SetTransition) {
SetTransition st = (SetTransition) t;
boolean not = st instanceof NotSetTransition;
if (g.isLexer()) {
buf.append("-").append(not ? "~" : "").append(st.toString()).append("->").append(getStateString(t.target)).append('\n');
} else {
buf.append("-").append(not ? "~" : "").append(st.label().toString(g.getVocabulary())).append("->").append(getStateString(t.target)).append('\n');
}
} else if (t instanceof AtomTransition) {
AtomTransition a = (AtomTransition) t;
String label = g.getTokenDisplayName(a.label);
buf.append("-").append(label).append("->").append(getStateString(t.target)).append('\n');
} else {
buf.append("-").append(t.toString()).append("->").append(getStateString(t.target)).append('\n');
}
}
}
return buf.toString();
}
Aggregations