/** 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 virtual BitSet FindOuterMostDecisionStates() { BitSet track = new BitSet(atn.states.Count); int numberOfDecisions = atn.NumberOfDecisions; 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 is StarLoopEntryState) { StarLoopEntryState loopEntry = (StarLoopEntryState)decisionState; if (loopEntry.precedenceRuleDecision) { // 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); }
public StarBlock(OutputModelFactory factory, GrammarAST blkOrEbnfRootAST, IList <CodeBlockForAlt> alts) : base(factory, blkOrEbnfRootAST, alts) { loopLabel = factory.GetTarget().GetLoopLabel(blkOrEbnfRootAST); StarLoopEntryState star = (StarLoopEntryState)blkOrEbnfRootAST.atnState; loopBackStateNumber = star.loopBackState.stateNumber; decision = star.decision; }
public LL1StarBlockSingleAlt(OutputModelFactory factory, GrammarAST starRoot, IList <CodeBlockForAlt> alts) : base(factory, starRoot, alts) { StarLoopEntryState star = (StarLoopEntryState)starRoot.atnState; loopBackStateNumber = star.loopBackState.stateNumber; this.decision = star.decision; IntervalSet[] altLookSets = factory.GetGrammar().decisionLOOK[decision]; Debug.Assert(altLookSets.Length == 2); IntervalSet enterLook = altLookSets[0]; IntervalSet exitLook = altLookSets[1]; loopExpr = AddCodeForLoopLookaheadTempVar(enterLook); }
public virtual Handle Star([NotNull] GrammarAST starAST, [NotNull] Handle elem) { StarBlockStartState blkStart = (StarBlockStartState)elem.left; BlockEndState blkEnd = (BlockEndState)elem.right; preventEpsilonClosureBlocks.Add(Tuple.Create <Rule, ATNState, ATNState>(currentRule, blkStart, blkEnd)); StarLoopEntryState entry = NewState <StarLoopEntryState>(starAST); entry.nonGreedy = !((QuantifierAST)starAST).GetGreedy(); entry.sll = false; // no way to express SLL restriction atn.DefineDecisionState(entry); LoopEndState end = NewState <LoopEndState>(starAST); StarLoopbackState loop = NewState <StarLoopbackState>(starAST); entry.loopBackState = loop; end.loopBackState = loop; BlockAST blkAST = (BlockAST)starAST.GetChild(0); if (((QuantifierAST)starAST).GetGreedy()) { if (ExpectNonGreedy(blkAST)) { g.tool.errMgr.GrammarError(ErrorType.EXPECTED_NON_GREEDY_WILDCARD_BLOCK, g.fileName, starAST.Token, starAST.Token.Text); } 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)); }