private void WalkCreatingDfaDgml(DFAState dfaState) { if (!_markedStates.Add(dfaState.stateNumber)) { return; } // first add this node string nodeCategory; if (dfaState.IsAcceptState) { nodeCategory = Categories.StopState; } else { nodeCategory = Categories.State; } XElement node = new XElement(Elements.Node, new XAttribute(Attributes.Id, "state_" + dfaState.stateNumber), new XAttribute(Attributes.Label, GetStateLabel(dfaState)), new XAttribute(Attributes.Category, nodeCategory)); _nodes.Add(dfaState, node); if (GroupNodes) { _extraLinks.Add(CreateContainmentLink(_groupId, "state_" + dfaState.stateNumber)); } // make an edge for each transition for (int i = 0; i < dfaState.NumberOfTransitions; i++) { Transition edge = dfaState.Transition(i); if (StripNonreducedStates) { DFAState target = edge.target as DFAState; // don't generate nodes for terminal states if (target != null && target.AcceptStateReachable != DFA.REACHABLE_YES) { continue; } } string edgeCategory = Categories.Edge; XElement edgeElement = new XElement(Elements.Link, new XAttribute(Attributes.Source, "state_" + dfaState.stateNumber), new XAttribute(Attributes.Target, "state_" + edge.target.stateNumber), new XAttribute(Attributes.Category, edgeCategory), new XAttribute(Attributes.Label, GetEdgeLabel(edge))); _links.Add(new KeyValuePair <State, Transition>(dfaState, edge), edgeElement); WalkCreatingDfaDgml((DFAState)edge.Target); } }
/** Do a depth-first walk of the state machine graph and * fill a DOT description template. Keep filling the * states and edges attributes. */ protected virtual void WalkCreatingDFADOT(StringTemplate dot, DFAState s) { if (markedStates.Contains(s.stateNumber)) { return; // already visited this node } markedStates.Add(s.stateNumber); // mark this node as completed. // first add this node StringTemplate st; if (s.IsAcceptState) { st = stlib.GetInstanceOf(Path.Combine(dfaTemplateDirectoryName, "stopstate")); } else { st = stlib.GetInstanceOf(Path.Combine(dfaTemplateDirectoryName, "state")); } st.SetAttribute("name", GetStateLabel(s)); dot.SetAttribute("states", st); // make a DOT edge for each transition for (int i = 0; i < s.NumberOfTransitions; i++) { Transition edge = (Transition)s.Transition(i); //Console.Out.WriteLine( "dfa " + s.dfa.decisionNumber + " edge from s" // + s.stateNumber + " [" + i + "] of " + s.NumberOfTransitions ); if (StripNonreducedStates) { if (edge.target is DFAState && ((DFAState)edge.target).AcceptStateReachable != DFA.REACHABLE_YES) { continue; // don't generate nodes for terminal states } } st = stlib.GetInstanceOf(Path.Combine(dfaTemplateDirectoryName, "edge")); st.SetAttribute("label", GetEdgeLabel(edge)); st.SetAttribute("src", GetStateLabel(s)); st.SetAttribute("target", GetStateLabel(edge.target)); st.SetAttribute("arrowhead", arrowhead); dot.SetAttribute("edges", st); WalkCreatingDFADOT(dot, (DFAState)edge.target); // keep walkin' } }
/** 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.Transition(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( StringTemplateGroup 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.Transition(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.GetFormalArgument("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.Transition(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); }