/// <summary> /// Create Deterministic Finite Automaton by lazy form of subset construction (Rabin and Scott, ) /// </summary> /// <returns>Deterministic Finite Automaton created by lazy form of subset construction</returns> public LrItemsDfa <TTokenKind> ToDfa() { // The subset construction is an example of a fixed-point computation, where an application of a // monotone function to some collection of sets drawn from a domain whose structure is known is // performed iteratively. The computation will terminate when an iteration step produces a state // where further iteration produces the same answer — a “fixed point” in the space of successive // iterates. // // For the subset construction, the domain is the power set of all possible subsets of the NFA states. // The while loop adds elements (subsets) to Q; it cannot remove an element from Q. We can view // the while loop as a monotone increasing function f, which means that for a set x, f(x) ≥ x. (The // comparison operator ≥ is ⊇.) Since Q can have at most 2^N distinct elements, the while loop can iterate // at most 2^N times. It may, of course, reach a fixed point and halt more quickly than that. var newStartState = EpsilonClose(StartState.AsSingletonEnumerable()); var newAcceptStates = new HashSet <ProductionItemSet <TTokenKind> >(); var newTransitions = new List <Transition <Symbol, ProductionItemSet <TTokenKind> > >(); var newStates = new InsertionOrderedSet <ProductionItemSet <TTokenKind> > { newStartState }; // Lazy form of Subset Construction where only reachable nodes // are added to the following work list of marked subsets var markedVisitedStates = new Queue <ProductionItemSet <TTokenKind> >(); // work list that preserves insertion order markedVisitedStates.Enqueue(newStartState); while (markedVisitedStates.Count != 0) { // subset S ProductionItemSet <TTokenKind> subsetSourceState = markedVisitedStates.Dequeue(); if (subsetSourceState.Overlaps(GetAcceptStates())) { newAcceptStates.Add(subsetSourceState); } // For all non-epsilon labels foreach (var label in GetAlphabet()) { // subset T var subsetTargetState = new Set <ProductionItem <TTokenKind> >(); // kernel items: For all s in S, add all non-epsilon transitions (s, label) → t to T foreach (ProductionItem <TTokenKind> s in subsetSourceState) { subsetTargetState.AddRange(Delta(Transition.FromPair(s, label))); } // Ignore empty subset (implicit transition to dead state in this case) if (subsetTargetState.Count == 0) { continue; } // Closure Items: Epsilon-close all T such that (S, label) → T var closure = EpsilonClose(subsetTargetState); if (!newStates.Contains(closure)) { newStates.Add(closure); markedVisitedStates.Enqueue(closure); } // Add (S, label) → T transition newTransitions.Add(Transition.Move(subsetSourceState, label, closure)); } } return(new LrItemsDfa <TTokenKind>(newStates, GetAlphabet(), newTransitions, newStartState, newAcceptStates)); }