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; }
private void InstantiateFromRegex(RegExpr re) { _startState = NewState(); _finishState.Add(NewState()); foreach (var alt in re.Alternatives) { var altnfa = new NFAGraph(alt); CopyInto(altnfa); var nsl = new NFALink(); var nfl = new NFALink(); nsl.IsEmpty = true; nfl.IsEmpty = true; nsl.Target = altnfa._startState; nfl.Target = _finishState.Single(); _adjList[_startState].Add(nsl); _adjList[altnfa._finishState.Single()].Add(nfl); } }
private void InstantiateFromMatchFactorOp(MatchFactorWithOp mop) { var mf = new NFAGraph(mop.Factor); CopyIntoWithTerminals(mf); switch (mop.Op.Type) { case UnaryOperatorType.None: break; case UnaryOperatorType.Optional: var elink1 = new NFALink(); elink1.IsEmpty = true; elink1.Target = _finishState.Single(); _adjList[_startState].Add(elink1); break; case UnaryOperatorType.OneMany: var elink2 = new NFALink(); elink2.IsEmpty = true; elink2.Target = _startState; _adjList[_finishState.Single()].Add(elink2); break; case UnaryOperatorType.NoneMany: var newend = NewState(); var blink = new NFALink(); var flink = new NFALink(); blink.IsEmpty = true; flink.IsEmpty = true; blink.Target = _startState; flink.Target = newend; _adjList[_finishState.Single()].Add(blink); _adjList[_startState].Add(flink); _finishState = new HashSet<NFAState>{newend}; break; } }
private void InstantiateFromAlternative(Alternative alt) { _startState = NewState(); _finishState.Add(NewState()); var curtail = _startState; foreach (var mf in alt.Factors) { var mfnfa = new NFAGraph(mf); CopyInto(mfnfa); var nl = new NFALink(); nl.IsEmpty = true; nl.Target = mfnfa._startState; _adjList[curtail].Add(nl); curtail = mfnfa._finishState.Single(); } var nel = new NFALink(); nel.IsEmpty = true; nel.Target = _finishState.Single(); _adjList[curtail].Add(nel); }
private void CopyIntoWithTerminals(NFAGraph other) { CopyInto(other); this._startState = other._startState; this._finishState = other._finishState; }
private void CopyInto(NFAGraph other) { foreach (var node in other._nodes) this._nodes.Add(node); foreach (var kvp in other._adjList) this._adjList[kvp.Key] = kvp.Value; }