/** Given an input stream, return the unique alternative predicted by * matching the input. Upon error, return NFA.INVALID_ALT_NUMBER * The first symbol of lookahead is presumed to be primed; that is, * input.lookahead(1) must point at the input symbol you want to start * predicting with. */ public int Predict(DFA dfa) { DFAState s = dfa.StartState; int c = input.LA(1); Transition eotTransition = null; dfaLoop: while (!s.IsAcceptState) { //Console.Out.WriteLine( "DFA.predict(" + s.stateNumber + ", " + dfa.nfa.Grammar.getTokenDisplayName( c ) + ")" ); // for each edge of s, look for intersection with current char for (int i = 0; i < s.NumberOfTransitions; i++) { Transition t = s.GetTransition(i); // special case: EOT matches any char if (t.Label.Matches(c)) { // take transition i s = (DFAState)t.Target; input.Consume(); c = input.LA(1); goto dfaLoop; } if (t.Label.Atom == Label.EOT) { eotTransition = t; } } if (eotTransition != null) { s = (DFAState)eotTransition.Target; goto dfaLoop; } /* * ErrorManager.error(ErrorManager.MSG_NO_VIABLE_DFA_ALT, * s, * dfa.nfa.Grammar.getTokenName(c)); */ return(NFA.INVALID_ALT_NUMBER); } // woohoo! We know which alt to predict // nothing emanates from a stop state; must terminate anyway //Console.Out.WriteLine( "DFA stop state " + s.stateNumber + " predicts " + s.getUniquelyPredictedAlt() ); return(s.GetUniquelyPredictedAlt()); }
protected virtual StringTemplate WalkFixedDFAGeneratingStateMachine( TemplateGroup templates, DFA dfa, DFAState s, int k) { //System.Console.Out.WriteLine( "walk " + s.stateNumber + " in dfa for decision " + dfa.decisionNumber ); if (s.IsAcceptState) { StringTemplate dfaST2 = templates.GetInstanceOf("dfaAcceptState"); dfaST2.SetAttribute("alt", s.GetUniquelyPredictedAlt()); return(dfaST2); } // the default templates for generating a state and its edges // can be an if-then-else structure or a switch string dfaStateName = "dfaState"; string dfaLoopbackStateName = "dfaLoopbackState"; string dfaOptionalBlockStateName = "dfaOptionalBlockState"; string dfaEdgeName = "dfaEdge"; if (_parentGenerator.CanGenerateSwitch(s)) { dfaStateName = "dfaStateSwitch"; dfaLoopbackStateName = "dfaLoopbackStateSwitch"; dfaOptionalBlockStateName = "dfaOptionalBlockStateSwitch"; dfaEdgeName = "dfaEdgeSwitch"; } StringTemplate dfaST = templates.GetInstanceOf(dfaStateName); if (dfa.NFADecisionStartState.decisionStateType == NFAState.LOOPBACK) { dfaST = templates.GetInstanceOf(dfaLoopbackStateName); } else if (dfa.NFADecisionStartState.decisionStateType == NFAState.OPTIONAL_BLOCK_START) { dfaST = templates.GetInstanceOf(dfaOptionalBlockStateName); } dfaST.SetAttribute("k", k); dfaST.SetAttribute("stateNumber", s.StateNumber); dfaST.SetAttribute("semPredState", s.IsResolvedWithPredicates); /* * string description = dfa.getNFADecisionStartState().Description; * description = parentGenerator.target.getTargetStringLiteralFromString( description ); * //System.Console.Out.WriteLine( "DFA: " + description + " associated with AST " + dfa.getNFADecisionStartState() ); * if ( description != null ) * { * dfaST.SetAttribute( "description", description ); * } */ int EOTPredicts = NFA.INVALID_ALT_NUMBER; DFAState EOTTarget = null; //System.Console.Out.WriteLine( "DFA state " + s.stateNumber ); for (int i = 0; i < s.NumberOfTransitions; i++) { Transition edge = (Transition)s.GetTransition(i); //System.Console.Out.WriteLine( "edge " + s.stateNumber + "-" + edge.label.ToString() + "->" + edge.target.stateNumber ); if (edge.Label.Atom == Label.EOT) { // don't generate a real edge for EOT; track alt EOT predicts // generate that prediction in the else clause as default case EOTTarget = (DFAState)edge.Target; EOTPredicts = EOTTarget.GetUniquelyPredictedAlt(); /* * System.Console.Out.WriteLine("DFA s"+s.stateNumber+" EOT goes to s"+ * edge.target.stateNumber+" predicates alt "+ * EOTPredicts); */ continue; } StringTemplate edgeST = templates.GetInstanceOf(dfaEdgeName); // If the template wants all the label values delineated, do that if (edgeST.impl.TryGetFormalArgument("labels") != null) { List <string> labels = edge.Label.Set.Select(value => _parentGenerator.GetTokenTypeAsTargetLabel(value)).ToList(); edgeST.SetAttribute("labels", labels); } else { // else create an expression to evaluate (the general case) edgeST.SetAttribute("labelExpr", _parentGenerator.GenLabelExpr(templates, edge, k)); } // stick in any gated predicates for any edge if not already a pred if (!edge.Label.IsSemanticPredicate) { DFAState target = (DFAState)edge.Target; SemanticContext preds = target.GetGatedPredicatesInNFAConfigurations(); if (preds != null) { //System.Console.Out.WriteLine( "preds=" + target.getGatedPredicatesInNFAConfigurations() ); StringTemplate predST = preds.GenExpr(_parentGenerator, _parentGenerator.Templates, dfa); edgeST.SetAttribute("predicates", predST); } } StringTemplate targetST = WalkFixedDFAGeneratingStateMachine(templates, dfa, (DFAState)edge.Target, k + 1); edgeST.SetAttribute("targetState", targetST); dfaST.SetAttribute("edges", edgeST); //System.Console.Out.WriteLine( "back to DFA " + dfa.decisionNumber + "." + s.stateNumber ); } // HANDLE EOT EDGE if (EOTPredicts != NFA.INVALID_ALT_NUMBER) { // EOT unique predicts an alt dfaST.SetAttribute("eotPredictsAlt", EOTPredicts); } else if (EOTTarget != null && EOTTarget.NumberOfTransitions > 0) { // EOT state has transitions so must split on predicates. // Generate predicate else-if clauses and then generate // NoViableAlt exception as else clause. // Note: these predicates emanate from the EOT target state // rather than the current DFAState s so the error message // might be slightly misleading if you are looking at the // state number. Predicates emanating from EOT targets are // hoisted up to the state that has the EOT edge. for (int i = 0; i < EOTTarget.NumberOfTransitions; i++) { Transition predEdge = (Transition)EOTTarget.GetTransition(i); StringTemplate edgeST = templates.GetInstanceOf(dfaEdgeName); edgeST.SetAttribute("labelExpr", _parentGenerator.GenSemanticPredicateExpr(templates, predEdge)); // the target must be an accept state //System.Console.Out.WriteLine( "EOT edge" ); StringTemplate targetST = WalkFixedDFAGeneratingStateMachine(templates, dfa, (DFAState)predEdge.Target, k + 1); edgeST.SetAttribute("targetState", targetST); dfaST.SetAttribute("edges", edgeST); } } return(dfaST); }
private string GetStateLabel(State state) { if (state == null) { return("null"); } string stateLabel = state.StateNumber.ToString(); DFAState dfaState = state as DFAState; NFAState nfaState = state as NFAState; if (dfaState != null) { StringBuilder builder = new StringBuilder(250); builder.Append('s'); builder.Append(state.StateNumber); if (AntlrTool.internalOption_ShowNFAConfigsInDFA) { if (dfaState.AbortedDueToRecursionOverflow) { builder.AppendLine(); builder.AppendLine("AbortedDueToRecursionOverflow"); } var alts = dfaState.AltSet; if (alts != null) { builder.AppendLine(); List <int> altList = alts.OrderBy(i => i).ToList(); ICollection <NFAConfiguration> configurations = dfaState.NfaConfigurations; for (int i = 0; i < altList.Count; i++) { int alt = altList[i]; if (i > 0) { builder.AppendLine(); } builder.AppendFormat("alt{0}:", alt); // get a list of configs for just this alt // it will help us print better later List <NFAConfiguration> configsInAlt = new List <NFAConfiguration>(); foreach (NFAConfiguration c in configurations) { if (c.Alt != alt) { continue; } configsInAlt.Add(c); } int n = 0; for (int cIndex = 0; cIndex < configsInAlt.Count; cIndex++) { NFAConfiguration c = configsInAlt[cIndex]; n++; builder.Append(c.ToString(false)); if ((cIndex + 1) < configsInAlt.Count) { builder.Append(", "); } if (n % 5 == 0 && (configsInAlt.Count - cIndex) > 3) { builder.Append("\\n"); } } } } } if (dfaState.IsAcceptState) { builder.Append("⇒" + dfaState.GetUniquelyPredictedAlt()); } stateLabel = builder.ToString(); } else if (nfaState != null) { if (nfaState.IsDecisionState) { stateLabel += ",d=" + nfaState.DecisionNumber; } if (nfaState.endOfBlockStateNumber != State.INVALID_STATE_NUMBER) { stateLabel += ",eob=" + nfaState.endOfBlockStateNumber; } } return(stateLabel); }