protected String getStateLabel(ATNState s) { if ( s==null ) return "null"; String stateLabel = ""; if (s instanceof BlockStartState) { stateLabel += "→\\n"; } else if (s instanceof BlockEndState) { stateLabel += "←\\n"; } stateLabel += String.valueOf(s.stateNumber); if (s instanceof PlusBlockStartState || s instanceof PlusLoopbackState) { stateLabel += "+"; } else if (s instanceof StarBlockStartState || s instanceof StarLoopEntryState || s instanceof StarLoopbackState) { stateLabel += "*"; } if ( s instanceof DecisionState && ((DecisionState)s).decision>=0 ) { stateLabel = stateLabel+"\\nd="+((DecisionState)s).decision; } return stateLabel; }
/** identify the ATN states where we need to set the outer alt number. * For regular rules, that's the block at the target to rule start state. * For left-recursive rules, we track the primary block, which looks just * like a regular rule's outer block, and the star loop block (always * there even if 1 alt). */ public BitSet findOuterMostDecisionStates() { BitSet track = new BitSet(atn.states.size()); int numberOfDecisions = atn.getNumberOfDecisions(); for (int i = 0; i < numberOfDecisions; i++) { DecisionState decisionState = atn.getDecisionState(i); RuleStartState startState = atn.ruleToStartState[decisionState.ruleIndex]; // Look for StarLoopEntryState that is in any left recursive rule if ( decisionState instanceof StarLoopEntryState) { StarLoopEntryState loopEntry = (StarLoopEntryState)decisionState; if ( loopEntry.isPrecedenceDecision ) { // Recursive alts always result in a (...)* in the transformed // left recursive rule and that always has a BasicBlockStartState // even if just 1 recursive alt exists. ATNState blockStart = loopEntry.transition(0).target; // track the StarBlockStartState associated with the recursive alternatives track.set(blockStart.stateNumber); } } else if ( startState.transition(0).target == decisionState ) { // always track outermost block for any rule if it exists track.set(decisionState.stateNumber); } } return track; }
@Override public Choice getEBNFBlock(GrammarAST ebnfRoot, List<CodeBlockForAlt> alts) { if (!g.tool.force_atn) { int decision; if ( ebnfRoot.getType()==ANTLRParser.POSITIVE_CLOSURE ) { decision = ((PlusLoopbackState)ebnfRoot.atnState).decision; } else if ( ebnfRoot.getType()==ANTLRParser.CLOSURE ) { decision = ((StarLoopEntryState)ebnfRoot.atnState).decision; } else { decision = ((DecisionState)ebnfRoot.atnState).decision; } if ( AnalysisPipeline.disjoint(g.decisionLOOK.get(decision)) ) { return getLL1EBNFBlock(ebnfRoot, alts); } } return getComplexEBNFBlock(ebnfRoot, alts); }
String getStateString(ATNState s) { int n = s.stateNumber; String stateStr = "s"+n; if ( s instanceof StarBlockStartState ) stateStr = "StarBlockStart_"+n; else if ( s instanceof PlusBlockStartState ) stateStr = "PlusBlockStart_"+n; else if ( s instanceof BlockStartState) stateStr = "BlockStart_"+n; else if ( s instanceof BlockEndState ) stateStr = "BlockEnd_"+n; else if ( s instanceof RuleStartState) stateStr = "RuleStart_"+g.getRule(s.ruleIndex).name+"_"+n; else if ( s instanceof RuleStopState ) stateStr = "RuleStop_"+g.getRule(s.ruleIndex).name+"_"+n; else if ( s instanceof PlusLoopbackState) stateStr = "PlusLoopBack_"+n; else if ( s instanceof StarLoopbackState) stateStr = "StarLoopBack_"+n; else if ( s instanceof StarLoopEntryState) stateStr = "StarLoopEntry_"+n; return stateStr; }
/** * From {@code (blk)*} build {@code ( blk+ )?} with *two* decisions, one for * entry and one for choosing alts of {@code blk}. * * <pre> * |-------------| * v | * o--[o-blk-o]->o o * | ^ * -----------------| * </pre> * * Note that the optional bypass must jump outside the loop as * {@code (A|B)*} is not the same thing as {@code (A|B|)+}. */ @Override public Handle star(GrammarAST starAST, Handle elem) { StarBlockStartState blkStart = (StarBlockStartState)elem.left; BlockEndState blkEnd = (BlockEndState)elem.right; preventEpsilonClosureBlocks.add(new Triple<Rule, ATNState, ATNState>(currentRule, blkStart, blkEnd)); StarLoopEntryState entry = newState(StarLoopEntryState.class, starAST); entry.nonGreedy = !((QuantifierAST)starAST).isGreedy(); atn.defineDecisionState(entry); LoopEndState end = newState(LoopEndState.class, starAST); StarLoopbackState loop = newState(StarLoopbackState.class, starAST); entry.loopBackState = loop; end.loopBackState = loop; BlockAST blkAST = (BlockAST)starAST.getChild(0); if ( ((QuantifierAST)starAST).isGreedy() ) { if (expectNonGreedy(blkAST)) { g.tool.errMgr.grammarError(ErrorType.EXPECTED_NON_GREEDY_WILDCARD_BLOCK, g.fileName, starAST.getToken(), starAST.getToken().getText()); } epsilon(entry, blkStart); // loop enter edge (alt 1) epsilon(entry, end); // bypass loop edge (alt 2) } else { // if not greedy, priority to exit branch; make it first epsilon(entry, end); // bypass loop edge (alt 1) epsilon(entry, blkStart); // loop enter edge (alt 2) } epsilon(blkEnd, loop); // block end hits loop back epsilon(loop, entry); // loop back to entry/exit decision starAST.atnState = entry; // decision is to enter/exit; blk is its own decision return new Handle(entry, end); }
public StarBlock(OutputModelFactory factory, GrammarAST blkOrEbnfRootAST, List<CodeBlockForAlt> alts) { super(factory, blkOrEbnfRootAST, alts); loopLabel = factory.getGenerator().getTarget().getLoopLabel(blkOrEbnfRootAST); StarLoopEntryState star = (StarLoopEntryState)blkOrEbnfRootAST.atnState; loopBackStateNumber = star.loopBackState.stateNumber; decision = star.decision; }
public ParserInterpreter(String grammarFileName, Collection<String> tokenNames, Collection<String> ruleNames, ATN atn, TokenStream input) { super(input); this.grammarFileName = grammarFileName; this.atn = atn; this.tokenNames = tokenNames.toArray(new String[tokenNames.size()]); this.ruleNames = ruleNames.toArray(new String[ruleNames.size()]); this.decisionToDFA = new DFA[atn.getNumberOfDecisions()]; for (int i = 0; i < decisionToDFA.length; i++) { decisionToDFA[i] = new DFA(atn.getDecisionState(i), i); } // identify the ATN states where pushNewRecursionContext must be called this.pushRecursionContextStates = new BitSet(atn.states.size()); for (ATNState state : atn.states) { if (!(state instanceof StarLoopEntryState)) { continue; } if (((StarLoopEntryState)state).precedenceRuleDecision) { this.pushRecursionContextStates.set(state.stateNumber); } } // get atn simulator that knows how to do predictions setInterpreter(new ParserATNSimulator(this, atn, decisionToDFA, sharedContextCache)); }