Пример #1
0
        public NFAGraph ToDFA()
        {
            //first, we need to know the alphabet
            var alphabet = new SortedSet<char>();
            foreach (var state in _adjList.Keys)
            {
                foreach (var link in _adjList[state].Where(l => !l.IsEmpty))
                {
                    alphabet.UnionWith(link.CharClass.CharSet());
                }
            }

            var dfa = new NFAGraph();
            var stateSetMap = new Dictionary<HashSet<NFAState>, NFAState>(HashSet<NFAState>.CreateSetComparer());
            var startStateSet = eClosure(_startState);
            dfa._startState = dfa.NewState();
            stateSetMap[startStateSet] = dfa._startState;

            //Follow the links of the start state
            var markedDFAStates = new HashSet<HashSet<NFAState>>(HashSet<NFAState>.CreateSetComparer());
            //Start at the start and continue whilst there are no unmarked states
            var DFAStateQueue = new Queue<HashSet<NFAState>>();
            DFAStateQueue.Enqueue(startStateSet);
            while (DFAStateQueue.Count > 0)
            {
                var thisstate = DFAStateQueue.Dequeue();
                var origdfastate = stateSetMap[thisstate];
                markedDFAStates.Add(thisstate);
                foreach (var c in alphabet)
                {
                    var cclass = new CharacterClass();
                    cclass.Elements.Add(new CharacterClassElement(c));
                    cclass.IsNegated = false;

                    var targetStates = new HashSet<NFAState>();
                    foreach (var nfastate in thisstate)
                    {
                        foreach (var link in _adjList[nfastate])
                        {
                            if (CanFollowLink(link, c))
                            {
                                targetStates.Add(link.Target);
                            }
                        }
                    }
                    var targetStateClosure = eClosure(targetStates);
                    NFAState ndfastate;
                    if (!markedDFAStates.Contains(targetStateClosure))
                    {
                        DFAStateQueue.Enqueue(targetStateClosure);

                        ndfastate = dfa.NewState();
                        stateSetMap[targetStateClosure] = ndfastate;
                        if (targetStateClosure.Any(s => _finishState.Contains(s)))
                            dfa._finishState.Add(ndfastate);
                    }
                    else
                    {
                        ndfastate = stateSetMap[targetStateClosure];
                    }

                    dfa._adjList[origdfastate].Add(new NFALink()
                    {
                        IsEmpty = false,
                        CharClass = cclass,
                        Target = ndfastate
                    });

                }
                //now check for . transitions
            }

            return dfa;
        }