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); } }
public List <DFAState> GetAnyDFAPathToTarget(DFAState startState, DFAState targetState, HashSet <DFAState> visited) { List <DFAState> dfaStates = new List <DFAState>(); visited.Add(startState); if (startState.Equals(targetState)) { dfaStates.Add(targetState); return(dfaStates); } // for (Edge e : startState.edges) { // walk edges looking for valid // path for (int i = 0; i < startState.NumberOfTransitions; i++) { Transition e = startState.GetTransition(i); if (!visited.Contains((DFAState)e.Target)) { List <DFAState> path = GetAnyDFAPathToTarget((DFAState)e.target, targetState, visited); if (path != null) { // found path, we're done dfaStates.Add(startState); dfaStates.AddRange(path); return(dfaStates); } } } return(null); }
/** Report the list of predicates found for each alternative; copy * the list because this set gets altered later by the method * tryToResolveWithSemanticPredicates() while flagging NFA configurations * in d as resolved. */ public virtual void ReportAltPredicateContext(DFAState d, IDictionary <int, SemanticContext> altPredicateContext) { IDictionary <int, SemanticContext> copy = new Dictionary <int, SemanticContext>(altPredicateContext); //copy.putAll( altPredicateContext ); _stateToAltSetWithSemanticPredicatesMap[d] = copy; }
/** Two DFAStates are equal if their NFA configuration sets are the * same. This method is used to see if a DFA state already exists. * * Because the number of alternatives and number of NFA configurations are * finite, there is a finite number of DFA states that can be processed. * This is necessary to show that the algorithm terminates. * * Cannot test the DFA state numbers here because in DFA.addState we need * to know if any other state exists that has this exact set of NFA * configurations. The DFAState state number is irrelevant. */ public override bool Equals(object o) { // compare set of NFA configurations in this set with other DFAState other = o as DFAState; if (other == null) { return(false); } if (object.ReferenceEquals(_nfaConfigurations, other._nfaConfigurations)) { return(true); } if (this._nfaConfigurations.Equals(other._nfaConfigurations)) { return(true); } if (_nfaConfigurations.SequenceEqual(other._nfaConfigurations)) { return(true); } return(false); }
/** Given a start state and a final state, find a list of edge labels * between the two ignoring epsilon. Limit your scan to a set of states * passed in. This is used to show a sample input sequence that is * nondeterministic with respect to this decision. Return IList<Label> as * a parameter. The incoming states set must be all states that lead * from startState to targetState and no others so this algorithm doesn't * take a path that eventually leads to a state other than targetState. * Don't follow loops, leading to short (possibly shortest) path. */ protected virtual void GetSampleInputSequenceUsingStateSet(State startState, State targetState, HashSet <object> states, IList <Label> labels) { _statesVisitedDuringSampleSequence.Add(startState.StateNumber); // pick the first edge in states as the one to traverse for (int i = 0; i < startState.NumberOfTransitions; i++) { Transition t = startState.GetTransition(i); DFAState edgeTarget = (DFAState)t.Target; if (states.Contains(edgeTarget) && !_statesVisitedDuringSampleSequence.Contains(edgeTarget.StateNumber)) { labels.Add(t.Label); // traverse edge and track label if (edgeTarget != targetState) { // get more labels if not at target GetSampleInputSequenceUsingStateSet(edgeTarget, targetState, states, labels); } // done with this DFA state as we've found a good path to target return; } } labels.Add(new Label(Label.EPSILON)); // indicate no input found // this happens on a : {p1}? a | A ; //ErrorManager.error(ErrorManager.MSG_CANNOT_COMPUTE_SAMPLE_INPUT_SEQ); }
public List<DFAState> GetAnyDFAPathToTarget(DFAState startState, DFAState targetState, HashSet<DFAState> visited) { List<DFAState> dfaStates = new List<DFAState>(); visited.Add(startState); if (startState.Equals(targetState)) { dfaStates.Add(targetState); return dfaStates; } // for (Edge e : startState.edges) { // walk edges looking for valid // path for (int i = 0; i < startState.NumberOfTransitions; i++) { Transition e = startState.GetTransition(i); if (!visited.Contains((DFAState)e.Target)) { List<DFAState> path = GetAnyDFAPathToTarget((DFAState)e.Target, targetState, visited); if (path != null) { // found path, we're done dfaStates.Add(startState); dfaStates.AddRange(path); return dfaStates; } } } return null; }
public virtual void ReportNondeterminism(DFAState d, HashSet <int> nondeterministicAlts) { _altsWithProblem.addAll(nondeterministicAlts); // track overall list _statesWithSyntacticallyAmbiguousAltsSet.Add(d); dfa.nfa.grammar.setOfNondeterministicDecisionNumbers.Add( dfa.DecisionNumber ); }
public virtual void ReportNondeterminism(DFAState d, HashSet <int> nondeterministicAlts) { _altsWithProblem.UnionWith(nondeterministicAlts); // track overall list _statesWithSyntacticallyAmbiguousAltsSet.Add(d); _dfa.Nfa.Grammar.setOfNondeterministicDecisionNumbers.Add( _dfa.NfaStartStateDecisionNumber ); }
public GrammarInsufficientPredicatesMessage( DecisionProbe probe, DFAState problemState, IDictionary<int, ICollection<IToken>> altToLocations ) : base(ErrorManager.MSG_INSUFFICIENT_PREDICATES) { this.probe = probe; this.problemState = problemState; this.altToLocations = altToLocations; }
/** Each state in the DFA represents a different input sequence for an * alt of the decision. Given a DFA state, what is the semantic * predicate context for a particular alt. */ public virtual SemanticContext GetSemanticContextForAlt(DFAState d, int alt) { var altToPredMap = _stateToAltSetWithSemanticPredicatesMap.get(d); if (altToPredMap == null) { return(null); } return(altToPredMap.get(alt)); }
// S U P P O R T /** Given a start state and a target state, return true if start can reach * target state. Also, compute the set of DFA states * that are on a path from start to target; return in states parameter. */ protected virtual bool ReachesState(DFAState startState, DFAState targetState, HashSet <object> states) { if (startState == targetState) { states.Add(targetState); //[email protected]("found target DFA state "+targetState.getStateNumber()); _stateReachable[startState.stateNumber] = REACHABLE_YES; return(true); } DFAState s = startState; // avoid infinite loops _stateReachable[s.stateNumber] = REACHABLE_BUSY; // look for a path to targetState among transitions for this state // stop when you find the first one; I'm pretty sure there is // at most one path to any DFA state with conflicting predictions for (int i = 0; i < s.NumberOfTransitions; i++) { Transition t = s.Transition(i); DFAState edgeTarget = (DFAState)t.target; int targetStatus; //= stateReachable.get( edgeTarget.stateNumber ); if (_stateReachable.TryGetValue(edgeTarget.stateNumber, out targetStatus)) { if (targetStatus == REACHABLE_BUSY) { // avoid cycles; they say nothing continue; } if (targetStatus == REACHABLE_YES) { // return success! _stateReachable[s.stateNumber] = REACHABLE_YES; return(true); } if (targetStatus == REACHABLE_NO) { // try another transition continue; } } // if null, target must be REACHABLE_UNKNOWN (i.e., unvisited) if (ReachesState(edgeTarget, targetState, states)) { states.Add(s); _stateReachable[s.stateNumber] = REACHABLE_YES; return(true); } } _stateReachable[s.stateNumber] = REACHABLE_NO; return(false); // no path to targetState found. }
private HashSet <object> GetUnaliasedDFAStateSet(HashSet <object> dfaStatesWithRecursionProblems) { HashSet <object> dfaStatesUnaliased = new HashSet <object>(); foreach (int stateI in dfaStatesWithRecursionProblems) { DFAState d = dfa.GetState(stateI); dfaStatesUnaliased.Add(d.stateNumber); } return(dfaStatesUnaliased); }
public RecursionOverflowMessage( DecisionProbe probe, DFAState sampleBadState, int alt, ICollection<string> targetRules, ICollection<ICollection<NFAState>> callSiteStates ) : base(ErrorManager.MSG_RECURSION_OVERLOW) { this.probe = probe; this.sampleBadState = sampleBadState; this.alt = alt; this.targetRules = targetRules; this.callSiteStates = callSiteStates; }
protected virtual HashSet <object> GetDFAPathStatesToTarget(DFAState targetState) { HashSet <object> dfaStates = new HashSet <object>(); _stateReachable = new Dictionary <int, int>(); if (dfa == null || dfa.startState == null) { return(dfaStates); } bool reaches = ReachesState(dfa.startState, targetState, dfaStates); return(dfaStates); }
public virtual void ReportNondeterminismResolvedWithSemanticPredicate(DFAState d) { // First, prevent a recursion warning on this state due to // pred resolution if (d.abortedDueToRecursionOverflow) { d.dfa.probe.RemoveRecursiveOverflowState(d); } _statesResolvedWithSemanticPredicatesSet.Add(d); //[email protected]("resolved with pred: "+d); dfa.nfa.grammar.setOfNondeterministicDecisionNumbersResolvedWithPredicates.Add( dfa.DecisionNumber ); }
/** Each state in the DFA represents a different input sequence for an * alt of the decision. Given a DFA state, what is the semantic * predicate context for a particular alt. */ public virtual SemanticContext GetSemanticContextForAlt(DFAState d, int alt) { IDictionary <int, SemanticContext> altToPredMap; _stateToAltSetWithSemanticPredicatesMap.TryGetValue(d, out altToPredMap); if (altToPredMap == null) { return(null); } SemanticContext result; altToPredMap.TryGetValue(alt, out result); return(result); }
public virtual void ReportRecursionOverflow(DFAState d, NFAConfiguration recursionNFAConfiguration) { // track the state number rather than the state as d will change // out from underneath us; hash wouldn't return any value // left-recursion is detected in start state. Since we can't // call resolveNondeterminism() on the start state (it would // not look k=1 to get min single token lookahead), we must // prevent errors derived from this state. Avoid start state if (d.stateNumber > 0) { int stateI = d.stateNumber; _stateToRecursionOverflowConfigurationsMap.Map(stateI, recursionNFAConfiguration); } }
/** Walk DFA states, unlinking the nfa configs and whatever else I * can to reduce memory footprint. */ protected virtual void UnlinkUnneededStateData(DFAState d) { int sI = d.stateNumber; if (visited.Contains(sI)) { return; // already visited } visited.Add(sI); d.nfaConfigurations = null; for (int i = 0; i < d.NumberOfTransitions; i++) { Transition edge = (Transition)d.transition(i); DFAState edgeTarget = ((DFAState)edge.target); UnlinkUnneededStateData(edgeTarget); } }
/** Return a IList<Label> indicating an input sequence that can be matched * from the start state of the DFA to the targetState (which is known * to have a problem). */ public virtual IList <Label> GetSampleNonDeterministicInputSequence(DFAState targetState) { HashSet <object> dfaStates = GetDFAPathStatesToTarget(targetState); _statesVisitedDuringSampleSequence = new HashSet <int>(); IList <Label> labels = new List <Label>(); // may access ith element; use array if (dfa == null || dfa.startState == null) { return(labels); } GetSampleInputSequenceUsingStateSet(dfa.startState, targetState, dfaStates, labels); return(labels); }
/** From list of lookahead sets (one per alt in decision), create * an LL(1) DFA. One edge per set. * * s0-{alt1}->:o=>1 * | \ * | -{alt2}->:o=>2 * | * ... */ public LL1DFA(int decisionNumber, NFAState decisionStartState, LookaheadSet[] altLook) : base(decisionNumber, decisionStartState) { DFAState s0 = NewState(); StartState = s0; UnreachableAlts.Clear(); for (int alt = 1; alt < altLook.Length; alt++) { DFAState acceptAltState = NewState(); acceptAltState.IsAcceptState = true; SetAcceptState(alt, acceptAltState); acceptAltState.LookaheadDepth = 1; acceptAltState.CachedUniquelyPredicatedAlt = alt; Label e = GetLabelForSet(altLook[alt].TokenTypeSet); s0.AddTransition(acceptAltState, e); } }
private void ComputeAltToProblemMaps(IEnumerable <int> dfaStatesUnaliased, IDictionary <int, IList <NFAConfiguration> > configurationsMap, IDictionary <int, IDictionary <string, ICollection <NFAState> > > altToTargetToCallSitesMap, IDictionary <int, DFAState> altToDFAState) { foreach (int stateI in dfaStatesUnaliased) { // walk this DFA's config list IList <NFAConfiguration> configs; configurationsMap.TryGetValue(stateI, out configs); for (int i = 0; i < configs.Count; i++) { NFAConfiguration c = (NFAConfiguration)configs[i]; NFAState ruleInvocationState = _dfa.Nfa.GetState(c.State); Transition transition0 = ruleInvocationState.transition[0]; RuleClosureTransition @ref = (RuleClosureTransition)transition0; string targetRule = ((NFAState)@ref.Target).enclosingRule.Name; int altI = c.Alt; IDictionary <string, ICollection <NFAState> > targetToCallSiteMap; altToTargetToCallSitesMap.TryGetValue(altI, out targetToCallSiteMap); if (targetToCallSiteMap == null) { targetToCallSiteMap = new Dictionary <string, ICollection <NFAState> >(); altToTargetToCallSitesMap[altI] = targetToCallSiteMap; } ICollection <NFAState> callSites; targetToCallSiteMap.TryGetValue(targetRule, out callSites); if (callSites == null) { callSites = new HashSet <NFAState>(); targetToCallSiteMap[targetRule] = callSites; } callSites.Add(ruleInvocationState); // track one problem DFA state per alt DFAState state; if (!altToDFAState.TryGetValue(altI, out state) || state == null) { DFAState sampleBadState = _dfa.GetState(stateI); altToDFAState[altI] = sampleBadState; } } } }
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); } }
/** Return a list of edge labels from start state to targetState. */ public List <IIntSet> GetEdgeLabels(DFAState targetState) { List <DFAState> dfaStates = GetAnyDFAPathToTarget(targetState); List <IIntSet> labels = new List <IIntSet>(); for (int i = 0; i < dfaStates.Count - 1; i++) { DFAState d = dfaStates[i]; DFAState nextState = dfaStates[i + 1]; // walk looking for edge whose target is next dfa state for (int j = 0; j < d.NumberOfTransitions; j++) { Transition e = d.GetTransition(j); if (e.Target.StateNumber == nextState.StateNumber) { labels.Add(e.Label.Set); } } } return(labels); }
// I N F O R M A T I O N A B O U T D E C I S I O N /** Return the sorted list of alts that conflict within a single state. * Note that predicates may resolve the conflict. */ public virtual IList <int> GetNonDeterministicAltsForState(DFAState targetState) { IEnumerable <int> nondetAlts = targetState.GetNonDeterministicAlts(); if (nondetAlts == null) { return(null); } return(nondetAlts.OrderBy(i => i).ToList()); //HashSet<int> nondetAlts = targetState.getNonDeterministicAlts(); //if ( nondetAlts == null ) //{ // return null; //} //List sorted = new LinkedList(); //sorted.addAll( nondetAlts ); //Collections.sort( sorted ); // make sure it's 1, 2, ... //return sorted; }
/** From list of lookahead sets (one per alt in decision), create * an LL(1) DFA. One edge per set. * * s0-{alt1}->:o=>1 * | \ * | -{alt2}->:o=>2 * | * ... */ public LL1DFA(int decisionNumber, NFAState decisionStartState, LookaheadSet[] altLook) { DFAState s0 = NewState(); startState = s0; nfa = decisionStartState.nfa; NumberOfAlts = nfa.grammar.GetNumberOfAltsForDecisionNFA(decisionStartState); this.decisionNumber = decisionNumber; this.NFADecisionStartState = decisionStartState; InitAltRelatedInfo(); UnreachableAlts = null; for (int alt = 1; alt < altLook.Length; alt++) { DFAState acceptAltState = NewState(); acceptAltState.acceptState = true; SetAcceptState(alt, acceptAltState); acceptAltState.LookaheadDepth = 1; acceptAltState.cachedUniquelyPredicatedAlt = alt; Label e = GetLabelForSet(altLook[alt].tokenTypeSet); s0.AddTransition(acceptAltState, e); } }
protected virtual void IssueRecursionWarnings() { // RECURSION OVERFLOW ICollection <int> dfaStatesWithRecursionProblems = _stateToRecursionOverflowConfigurationsMap.Keys; // now walk truly unique (unaliased) list of dfa states with inf recur // Goal: create a map from alt to map<target,IList<callsites>> // Map<Map<String target, IList<NFAState call sites>> IDictionary <int, IDictionary <string, ICollection <NFAState> > > altToTargetToCallSitesMap = new Dictionary <int, IDictionary <string, ICollection <NFAState> > >(); // track a single problem DFA state for each alt var altToDFAState = new Dictionary <int, DFAState>(); ComputeAltToProblemMaps(dfaStatesWithRecursionProblems, _stateToRecursionOverflowConfigurationsMap, altToTargetToCallSitesMap, // output param altToDFAState); // output param // walk each alt with recursion overflow problems and generate error ICollection <int> alts = altToTargetToCallSitesMap.Keys; List <int> sortedAlts = new List <int>(alts); sortedAlts.Sort(); //Collections.sort( sortedAlts ); foreach (int altI in sortedAlts) { var targetToCallSiteMap = altToTargetToCallSitesMap.get(altI); var targetRules = targetToCallSiteMap.Keys; var callSiteStates = targetToCallSiteMap.Values; DFAState sampleBadState = (DFAState)altToDFAState.get(altI); ErrorManager.RecursionOverflow(this, sampleBadState, altI, targetRules, callSiteStates); } }
// S U P P O R T /** Given a start state and a target state, return true if start can reach * target state. Also, compute the set of DFA states * that are on a path from start to target; return in states parameter. */ protected virtual bool ReachesState( DFAState startState, DFAState targetState, HashSet<object> states ) { if ( startState == targetState ) { states.Add( targetState ); //[email protected]("found target DFA state "+targetState.getStateNumber()); _stateReachable[startState.StateNumber] = Reachable.Yes; return true; } DFAState s = startState; // avoid infinite loops _stateReachable[s.StateNumber] = Reachable.Busy; // look for a path to targetState among transitions for this state // stop when you find the first one; I'm pretty sure there is // at most one path to any DFA state with conflicting predictions for ( int i = 0; i < s.NumberOfTransitions; i++ ) { Transition t = s.GetTransition( i ); DFAState edgeTarget = (DFAState)t.Target; Reachable targetStatus; //= stateReachable.get( edgeTarget.stateNumber ); if ( _stateReachable.TryGetValue( edgeTarget.StateNumber, out targetStatus ) ) { if ( targetStatus == Reachable.Busy ) { // avoid cycles; they say nothing continue; } if ( targetStatus == Reachable.Yes ) { // return success! _stateReachable[s.StateNumber] = Reachable.Yes; return true; } if ( targetStatus == Reachable.No ) { // try another transition continue; } } // if null, target must be REACHABLE_UNKNOWN (i.e., unvisited) if ( ReachesState( edgeTarget, targetState, states ) ) { states.Add( s ); _stateReachable[s.StateNumber] = Reachable.Yes; return true; } } _stateReachable[s.StateNumber] = Reachable.No; return false; // no path to targetState found. }
/** From a set of edgeset->list-of-alts mappings, create a DFA * that uses syn preds for all |list-of-alts|>1. */ public LL1DFA(int decisionNumber, NFAState decisionStartState, MultiMap <IntervalSet, int> edgeMap) { DFAState s0 = NewState(); startState = s0; nfa = decisionStartState.nfa; NumberOfAlts = nfa.grammar.GetNumberOfAltsForDecisionNFA(decisionStartState); this.decisionNumber = decisionNumber; this.NFADecisionStartState = decisionStartState; InitAltRelatedInfo(); UnreachableAlts = null; foreach (var edgeVar in edgeMap) { IntervalSet edge = edgeVar.Key; IList <int> alts = edgeVar.Value; alts = alts.OrderBy(i => i).ToList(); //Collections.sort( alts ); // make sure alts are attempted in order //[email protected](edge+" -> "+alts); DFAState s = NewState(); s.LookaheadDepth = 1; Label e = GetLabelForSet(edge); s0.AddTransition(s, e); if (alts.Count == 1) { s.acceptState = true; int alt = alts[0]; SetAcceptState(alt, s); s.cachedUniquelyPredicatedAlt = alt; } else { // resolve with syntactic predicates. Add edges from // state s that test predicates. s.IsResolvedWithPredicates = true; for (int i = 0; i < alts.Count; i++) { int alt = (int)alts[i]; s.cachedUniquelyPredicatedAlt = NFA.INVALID_ALT_NUMBER; DFAState predDFATarget = GetAcceptState(alt); if (predDFATarget == null) { predDFATarget = NewState(); // create if not there. predDFATarget.acceptState = true; predDFATarget.cachedUniquelyPredicatedAlt = alt; SetAcceptState(alt, predDFATarget); } // add a transition to pred target from d /* * int walkAlt = * decisionStartState.translateDisplayAltToWalkAlt(alt); * NFAState altLeftEdge = nfa.grammar.getNFAStateForAltOfDecision(decisionStartState, walkAlt); * NFAState altStartState = (NFAState)altLeftEdge.transition[0].target; * SemanticContext ctx = nfa.grammar.ll1Analyzer.getPredicates(altStartState); * [email protected]("sem ctx = "+ctx); * if ( ctx == null ) { * ctx = new SemanticContext.TruePredicate(); * } * s.addTransition(predDFATarget, new Label(ctx)); */ SemanticContext.Predicate synpred = GetSynPredForAlt(decisionStartState, alt); if (synpred == null) { synpred = new SemanticContext.TruePredicate(); } s.AddTransition(predDFATarget, new PredicateLabel(synpred)); } } } //[email protected]("dfa for preds=\n"+this); }
public void RemoveState( DFAState d ) { DFAState it; if ( _uniqueStates.TryGetValue( d, out it ) ) { _uniqueStates.Remove( d ); if ( it != null ) { _numberOfStates--; } } }
private int CalculateMaxLookaheadDepth(DFAState d, int depth) { // not cyclic; don't worry about termination // fail if pred edge. int max = depth; for (int i = 0; i < d.NumberOfTransitions; i++) { Transition t = d.GetTransition(i); // if ( t.isSemanticPredicate() ) return Integer.MAX_VALUE; if (!t.IsSemanticPredicate) { // if pure pred not gated, it must target stop state; don't count DFAState edgeTarget = (DFAState)t.Target; int m = CalculateMaxLookaheadDepth(edgeTarget, depth + 1); max = Math.Max(max, m); } } return max; }
protected virtual void CreateTransitionTableEntryForState( DFAState s ) { /* [email protected]("createTransitionTableEntryForState s"+s.stateNumber+ " dec "+s.dfa.decisionNumber+" cyclic="+s.dfa.isCyclic()); */ int smax = _max[s.StateNumber]; int smin = _min[s.StateNumber]; int[] stateTransitions = new int[smax - smin + 1]; for ( int i = 0; i < stateTransitions.Length; i++ ) stateTransitions[i] = EmptyValue; _transition[s.StateNumber] = stateTransitions; for ( int j = 0; j < s.NumberOfTransitions; j++ ) { Transition edge = s.GetTransition( j ); Label label = edge.Label; if ( label.IsAtom && label.Atom >= Label.MIN_CHAR_VALUE ) { int labelIndex = label.Atom - smin; // offset from 0 stateTransitions[labelIndex] = edge.Target.StateNumber; } else if ( label.IsSet ) { foreach ( var interval in ((IntervalSet)label.Set).Intervals ) { for ( int i = Math.Max( interval.a, Label.MIN_CHAR_VALUE ); i <= interval.b; i++ ) { stateTransitions[i - smin] = edge.Target.StateNumber; } } } } // track unique state transition tables so we can reuse int? edgeClass; // = edgeTransitionClassMap.get( stateTransitions ); if ( _edgeTransitionClassMap.TryGetValue( stateTransitions, out edgeClass ) && edgeClass != null ) { //[email protected]("we've seen this array before; size="+stateTransitions.size()); _transitionEdgeTables[s.StateNumber] = edgeClass; } else { edgeClass = _edgeTransitionClass; _transitionEdgeTables[s.StateNumber] = edgeClass; _edgeTransitionClassMap[stateTransitions] = edgeClass; _edgeTransitionClass++; } }
protected virtual void CreateMinMaxTables( DFAState s ) { int smin = Label.MAX_CHAR_VALUE + 1; int smax = Label.MIN_ATOM_VALUE - 1; for ( int j = 0; j < s.NumberOfTransitions; j++ ) { Transition edge = (Transition)s.GetTransition( j ); Label label = edge.Label; if ( label.IsAtom ) { if ( label.Atom >= Label.MIN_CHAR_VALUE ) { if ( label.Atom < smin ) { smin = label.Atom; } if ( label.Atom > smax ) { smax = label.Atom; } } } else if ( label.IsSet ) { IntervalSet labels = (IntervalSet)label.Set; int lmin = labels.GetMinElement(); // if valid char (don't do EOF) and less than current min if ( lmin < smin && lmin >= Label.MIN_CHAR_VALUE ) { smin = labels.GetMinElement(); } if ( labels.GetMaxElement() > smax ) { smax = labels.GetMaxElement(); } } } if ( smax < 0 ) { // must be predicates or pure EOT transition; just zero out min, max smin = Label.MIN_CHAR_VALUE; smax = Label.MIN_CHAR_VALUE; } _min[s.StateNumber] = (char)smin; _max[s.StateNumber] = (char)smax; if ( smax < 0 || smin > Label.MAX_CHAR_VALUE || smin < 0 ) { ErrorManager.InternalError( "messed up: min=" + _min + ", max=" + _max ); } }
internal List<DFAState> GetAnyDFAPathToTarget(DFAState targetState) { HashSet<DFAState> visited = new HashSet<DFAState>(); return GetAnyDFAPathToTarget(_dfa.StartState, targetState, visited); }
internal virtual bool CalculateHasCycle(DFAState d, IDictionary<DFAState, Cyclic> busy) { busy[d] = Cyclic.Busy; for (int i = 0; i < d.NumberOfTransitions; i++) { Transition t = d.GetTransition(i); DFAState target = (DFAState)t.Target; Cyclic cond; if (!busy.TryGetValue(target, out cond)) cond = Cyclic.Unknown; if (cond == Cyclic.Busy) return true; if (cond != Cyclic.Done && CalculateHasCycle(target, busy)) return true; } busy[d] = Cyclic.Done; return false; }
protected virtual void OptimizeEOTBranches( DFAState d ) { int sI = d.stateNumber; if ( _visited.Contains( sI ) ) { return; // already visited } _visited.Add( sI ); 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 only one edge coming out, it is EOT, and target is accept prune if ( PRUNE_TOKENS_RULE_SUPERFLUOUS_EOT_EDGES && edgeTarget.IsAcceptState && d.NumberOfTransitions == 1 && edge.label.IsAtom && edge.label.Atom == Label.EOT ) { //[email protected]("state "+d+" can be pruned"); // remove the superfluous EOT edge d.RemoveTransition( i ); d.IsAcceptState = true; // make it an accept state // force it to uniquely predict the originally predicted state d.cachedUniquelyPredicatedAlt = edgeTarget.GetUniquelyPredictedAlt(); i--; // back up one so that i++ of loop iteration stays within bounds } OptimizeEOTBranches( edgeTarget ); } }
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 ); } }
/** Walk DFA states, unlinking the nfa configs and whatever else I * can to reduce memory footprint. */ protected virtual void UnlinkUnneededStateData( DFAState d ) { int sI = d.stateNumber; if ( visited.Contains( sI ) ) { return; // already visited } visited.Add( sI ); d.nfaConfigurations = null; for ( int i = 0; i < d.NumberOfTransitions; i++ ) { Transition edge = (Transition)d.transition( i ); DFAState edgeTarget = ( (DFAState)edge.target ); UnlinkUnneededStateData( edgeTarget ); } }
/** Return a list of alts whose predicate context was insufficient to * resolve a nondeterminism for state d. */ public virtual IDictionary <int, ICollection <IToken> > GetIncompletelyCoveredAlts(DFAState d) { return(_stateToIncompletelyCoveredAltsMap.get(d)); }
internal List <DFAState> GetAnyDFAPathToTarget(DFAState targetState) { HashSet <DFAState> visited = new HashSet <DFAState>(); return(GetAnyDFAPathToTarget(_dfa.StartState, targetState, visited)); }
internal virtual bool CalculateHasSynPred(DFAState d, HashSet<DFAState> busy) { busy.Add(d); for (int i = 0; i < d.NumberOfTransitions; i++) { Transition t = d.GetTransition(i); if (t.IsSemanticPredicate) { SemanticContext ctx = t.Label.SemanticContext; // if ( ctx.toString().indexOf("synpred")>=0 ) { // System.out.println("has pred "+ctx.toString()+" "+ctx.isSyntacticPredicate()); // System.out.println(((SemanticContext.Predicate)ctx).predicateAST.token); // } if (ctx.IsSyntacticPredicate) return true; } DFAState edgeTarget = (DFAState)t.Target; if (!busy.Contains(edgeTarget) &&CalculateHasSynPred(edgeTarget, busy)) return true; } return false; }
/** A special state is huge (too big for state tables) or has a predicated * edge. Generate a simple if-then-else. Cannot be an accept state as * they have no emanating edges. Don't worry about switch vs if-then-else * because if you get here, the state is super complicated and needs an * if-then-else. This is used by the new DFA scheme created June 2006. */ public virtual StringTemplate GenerateSpecialState( DFAState s ) { StringTemplate stateST; stateST = templates.GetInstanceOf( "cyclicDFAState" ); stateST.SetAttribute( "needErrorClause", true ); stateST.SetAttribute( "semPredState", s.IsResolvedWithPredicates ); stateST.SetAttribute( "stateNumber", s.stateNumber ); stateST.SetAttribute( "decisionNumber", s.dfa.decisionNumber ); bool foundGatedPred = false; StringTemplate eotST = null; for ( int i = 0; i < s.NumberOfTransitions; i++ ) { Transition edge = (Transition)s.Transition( i ); StringTemplate edgeST; if ( edge.label.Atom == Label.EOT ) { // this is the default clause; has to held until last edgeST = templates.GetInstanceOf( "eotDFAEdge" ); stateST.RemoveAttribute( "needErrorClause" ); eotST = edgeST; } else { edgeST = templates.GetInstanceOf( "cyclicDFAEdge" ); StringTemplate exprST = GenLabelExpr( templates, edge, 1 ); edgeST.SetAttribute( "labelExpr", exprST ); } edgeST.SetAttribute( "edgeNumber", i + 1 ); edgeST.SetAttribute( "targetStateNumber", edge.target.stateNumber ); // stick in any gated predicates for any edge if not already a pred if ( !edge.label.IsSemanticPredicate ) { DFAState t = (DFAState)edge.target; SemanticContext preds = t.GetGatedPredicatesInNFAConfigurations(); if ( preds != null ) { foundGatedPred = true; StringTemplate predST = preds.GenExpr( this, Templates, t.dfa ); edgeST.SetAttribute( "predicates", predST.ToString() ); } } if ( edge.label.Atom != Label.EOT ) { stateST.SetAttribute( "edges", edgeST ); } } if ( foundGatedPred ) { // state has >= 1 edge with a gated pred (syn or sem) // must rewind input first, set flag. stateST.SetAttribute( "semPredState", foundGatedPred ); } if ( eotST != null ) { stateST.SetAttribute( "edges", eotST ); } return stateST; }
/** Return a list of edge labels from start state to targetState. */ public List<IIntSet> GetEdgeLabels(DFAState targetState) { List<DFAState> dfaStates = GetAnyDFAPathToTarget(targetState); List<IIntSet> labels = new List<IIntSet>(); for (int i = 0; i < dfaStates.Count - 1; i++) { DFAState d = dfaStates[i]; DFAState nextState = dfaStates[i + 1]; // walk looking for edge whose target is next dfa state for (int j = 0; j < d.NumberOfTransitions; j++) { Transition e = d.GetTransition(j); if (e.Target.StateNumber == nextState.StateNumber) { labels.Add(e.Label.Set); } } } return labels; }
internal virtual bool CalculateHasSemPred(DFAState d, HashSet<DFAState> busy) { busy.Add(d); for (int i = 0; i < d.NumberOfTransitions; i++) { Transition t = d.GetTransition(i); if (t.IsSemanticPredicate) { SemanticContext ctx = t.Label.SemanticContext; if (ctx.HasUserSemanticPredicate) return true; } DFAState edgeTarget = (DFAState)t.Target; if (!busy.Contains(edgeTarget) && CalculateHasSemPred(edgeTarget, busy)) return true; } return false; }
/** Currently the analysis reports issues between token definitions, but * we don't print out warnings in favor of just picking the first token * definition found in the grammar ala lex/flex. */ public virtual void ReportLexerRuleNondeterminism(DFAState d, HashSet <int> nondeterministicAlts) { stateToSyntacticallyAmbiguousTokensRuleAltsMap[d] = nondeterministicAlts; }
/** Set up the EOT and EOF tables; we cannot put -1 min/max values so * we need another way to test that in the DFA transition function. */ protected virtual void CreateEOTAndEOFTables( DFAState s ) { for ( int j = 0; j < s.NumberOfTransitions; j++ ) { Transition edge = s.GetTransition( j ); Label label = edge.Label; if ( label.IsAtom ) { if ( label.Atom == Label.EOT ) { // eot[s] points to accept state _eot[s.StateNumber] = edge.Target.StateNumber; } else if ( label.Atom == Label.EOF ) { // eof[s] points to accept state _eof[s.StateNumber] = edge.Target.StateNumber; } } else if ( label.IsSet ) { if ( label.Set.Contains( Label.EOT ) ) { _eot[s.StateNumber] = edge.Target.StateNumber; } if ( label.Set.Contains( Label.EOF ) ) { _eof[s.StateNumber] = edge.Target.StateNumber; } } } }
/** You can generate a switch rather than if-then-else for a DFA state * if there are no semantic predicates and the number of edge label * values is small enough; e.g., don't generate a switch for a state * containing an edge label such as 20..52330 (the resulting byte codes * would overflow the method 65k limit probably). */ protected internal virtual bool CanGenerateSwitch( DFAState s ) { if ( !GenerateSwitchesWhenPossible ) { return false; } int size = 0; for ( int i = 0; i < s.NumberOfTransitions; i++ ) { Transition edge = (Transition)s.Transition( i ); if ( edge.label.IsSemanticPredicate ) { return false; } // can't do a switch if the edges are going to require predicates if ( edge.label.Atom == Label.EOT ) { int EOTPredicts = ( (DFAState)edge.target ).GetUniquelyPredictedAlt(); if ( EOTPredicts == NFA.INVALID_ALT_NUMBER ) { // EOT target has to be a predicate then; no unique alt return false; } } // if target is a state with gated preds, we need to use preds on // this edge then to reach it. if ( ( (DFAState)edge.target ).GetGatedPredicatesInNFAConfigurations() != null ) { return false; } size += edge.label.Set.Count; } if ( s.NumberOfTransitions < MinSwitchAlts || size > MaxSwitchCaseLabels ) { return false; } return true; }
protected virtual void CreateSpecialTable( DFAState s ) { // number all special states from 0...n-1 instead of their usual numbers bool hasSemPred = false; // TODO this code is very similar to canGenerateSwitch. Refactor to share for ( int j = 0; j < s.NumberOfTransitions; j++ ) { Transition edge = (Transition)s.GetTransition( j ); Label label = edge.Label; // can't do a switch if the edges have preds or are going to // require gated predicates if ( label.IsSemanticPredicate || ( (DFAState)edge.Target ).GetGatedPredicatesInNFAConfigurations() != null ) { hasSemPred = true; break; } } // if has pred or too big for table, make it special int smax = _max[s.StateNumber]; int smin = _min[s.StateNumber]; if ( hasSemPred || smax - smin > MAX_STATE_TRANSITIONS_FOR_TABLE ) { _special[s.StateNumber] = _uniqueCompressedSpecialStateNum; _uniqueCompressedSpecialStateNum++; _specialStates.Add( s ); } else { _special[s.StateNumber] = EmptyValue; // not special } }
public virtual void ReportIncompletelyCoveredAlts(DFAState d, IDictionary <int, ICollection <IToken> > altToLocationsReachableWithoutPredicate) { _stateToIncompletelyCoveredAltsMap[d] = altToLocationsReachableWithoutPredicate; }
/** 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; }
public virtual DFAState NewState() { DFAState n = new DFAState( this ); n.StateNumber = _stateCounter; _stateCounter++; _states.Resize( n.StateNumber + 1 ); _states[n.StateNumber] = n; // track state num to state return n; }
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.GetTransition(i); if (StripNonreducedStates) { DFAState target = edge.Target as DFAState; // don't generate nodes for terminal states if (target != null && target.AcceptStateReachable != 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); } }
/** Add a transition from this state to target with label. Return * the transition number from 0..n-1. */ public virtual int AddTransition(DFAState target, Label label) { _transitions.Add(new Transition(label, target)); return(_transitions.Count - 1); }
public virtual void SetAcceptState( int alt, DFAState acceptState ) { _altToAcceptState[alt] = acceptState; }
/** 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' } }
public virtual void SetState( int stateNumber, DFAState d ) { _states[stateNumber] = d; }
protected virtual HashSet<object> GetDFAPathStatesToTarget( DFAState targetState ) { HashSet<object> dfaStates = new HashSet<object>(); _stateReachable = new Dictionary<int, Reachable>(); if ( _dfa == null || _dfa.StartState == null ) { return dfaStates; } bool reaches = ReachesState( _dfa.StartState, targetState, dfaStates ); return dfaStates; }
/** Add a new DFA state to this DFA if not already present. * To force an acyclic, fixed maximum depth DFA, just always * return the incoming state. By not reusing old states, * no cycles can be created. If we're doing fixed k lookahead * don't updated uniqueStates, just return incoming state, which * indicates it's a new state. */ protected internal virtual DFAState AddState( DFAState d ) { if ( UserMaxLookahead > 0 ) { return d; } // does a DFA state exist already with everything the same // except its state number? DFAState existing; _uniqueStates.TryGetValue(d, out existing); if ( existing != null ) { /* [email protected]("state "+d.stateNumber+" exists as state "+ existing.stateNumber); */ // already there...get the existing DFA state return existing; } // if not there, then add new state. _uniqueStates[d] = d; _numberOfStates++; return d; }
// T R A C K I N G M E T H O D S /** Report the fact that DFA state d is not a state resolved with * predicates and yet it has no emanating edges. Usually this * is a result of the closure/reach operations being unable to proceed */ public virtual void ReportDanglingState(DFAState d) { _danglingStates.Add(d); }
/** Add a transition from this state to target with label. Return * the transition number from 0..n-1. */ public virtual int AddTransition( DFAState target, Label label ) { _transitions.Add( new Transition( label, target ) ); return _transitions.Count - 1; }