protected virtual void OptimizeExitBranches(DFAState d) { int sI = d.stateNumber; if (_visited.Contains(sI)) { return; // already visited } _visited.Add(sI); int nAlts = d.dfa.NumberOfAlts; for (int i = 0; i < d.NumberOfTransitions; i++) { Transition edge = (Transition)d.Transition(i); DFAState edgeTarget = ((DFAState)edge.target); /* * [email protected](d.stateNumber+"-"+ * edge.label.toString(d.dfa.nfa.grammar)+"->"+ * edgeTarget.stateNumber); */ // if target is an accept state and that alt is the exit alt if (edgeTarget.IsAcceptState && edgeTarget.GetUniquelyPredictedAlt() == nAlts) { /* * [email protected]("ignoring transition "+i+" to max alt "+ * d.dfa.getNumberOfAlts()); */ d.RemoveTransition(i); i--; // back up one so that i++ of loop iteration stays within bounds } OptimizeExitBranches(edgeTarget); } }
protected virtual void OptimizeEOTBranches(DFAState state) { if (state == null) { throw new ArgumentNullException("state"); } int sI = state.StateNumber; if (_visited.Contains(sI)) { return; // already visited } _visited.Add(sI); for (int i = 0; i < state.NumberOfTransitions; i++) { Transition edge = state.GetTransition(i); DFAState edgeTarget = ((DFAState)edge.Target); /* * [email protected](d.stateNumber+"-"+ * edge.label.toString(d.dfa.nfa.grammar)+"->"+ * edgeTarget.stateNumber); */ // if only one edge coming out, it is EOT, and target is accept prune if (PRUNE_TOKENS_RULE_SUPERFLUOUS_EOT_EDGES && edgeTarget.IsAcceptState && state.NumberOfTransitions == 1 && edge.Label.IsAtom && edge.Label.Atom == Label.EOT) { //[email protected]("state "+d+" can be pruned"); // remove the superfluous EOT edge state.RemoveTransition(i); state.IsAcceptState = true; // make it an accept state // force it to uniquely predict the originally predicted state state.CachedUniquelyPredicatedAlt = edgeTarget.GetUniquelyPredictedAlt(); i--; // back up one so that i++ of loop iteration stays within bounds } OptimizeEOTBranches(edgeTarget); } }
/** figure out if this state eventually reaches an accept state and * modify the instance variable 'reduced' to indicate if we find * at least one state that cannot reach an accept state. This implies * that the overall DFA is not reduced. This algorithm should be * linear in the number of DFA states. * * The algorithm also tracks which alternatives have no accept state, * indicating a nondeterminism. * * Also computes whether the DFA is cyclic. * * TODO: I call getUniquelyPredicatedAlt too much; cache predicted alt */ protected virtual bool DoesStateReachAcceptState( DFAState d ) { if ( d.IsAcceptState ) { // accept states have no edges emanating from them so we can return d.AcceptStateReachable = Reachable.Yes; // this alt is uniquely predicted, remove from nondeterministic list int predicts = d.GetUniquelyPredictedAlt(); UnreachableAlts.Remove( predicts ); return true; } // avoid infinite loops d.AcceptStateReachable = Reachable.Busy; bool anEdgeReachesAcceptState = false; // Visit every transition, track if at least one edge reaches stop state // Cannot terminate when we know this state reaches stop state since // all transitions must be traversed to set status of each DFA state. for ( int i = 0; i < d.NumberOfTransitions; i++ ) { Transition t = d.GetTransition( i ); DFAState edgeTarget = (DFAState)t.Target; Reachable targetStatus = edgeTarget.AcceptStateReachable; if ( targetStatus == Reachable.Busy ) { // avoid cycles; they say nothing _cyclic = true; continue; } if ( targetStatus == Reachable.Yes ) { // avoid unnecessary work anEdgeReachesAcceptState = true; continue; } if ( targetStatus == Reachable.No ) { // avoid unnecessary work continue; } // target must be REACHABLE_UNKNOWN (i.e., unvisited) if ( DoesStateReachAcceptState( edgeTarget ) ) { anEdgeReachesAcceptState = true; // have to keep looking so don't break loop // must cover all states even if we find a path for this state } } if ( anEdgeReachesAcceptState ) { d.AcceptStateReachable = Reachable.Yes; } else { d.AcceptStateReachable = Reachable.No; _reduced = false; } return anEdgeReachesAcceptState; }
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; }