void DrawGraph(Automaton automaton) { var graph = new Graph(); graph.Attr.LayerDirection = LayerDirection.LR; int i = 0; foreach (var s in automaton.States) { foreach (var o in s.Output) { var index = automaton.States.IndexOf(o.End); var end = ReferenceEquals(automaton.StartState, o.End) ? "Start" : index.ToString(); if (ReferenceEquals(s, automaton.StartState)) { graph.AddEdge("Start", o.ToString(), end); } else if (o.End.IsFinalState) { graph.AddEdge(i.ToString(), o.ToString(), "End"); } else { graph.AddEdge(i.ToString(), o.ToString(), end); } } i++; } graphViewer.Graph = graph; }
public RichInterpreter(Automaton dfa) { _dfa = dfa; foreach(var state in dfa.States) { int charEdgeCount = 0; bool hasPositive = false; foreach(var transition in state.Output) { //几种情况: //1. 对于只有一种非字符边的,那么没必要回溯了:说明根本不匹配。 //2. 对于有若干种非字符边的,应该保存状态,以备回溯。 //3. Positive 保存下来,匹配成功了要回到这里来。 if (transition.TransitionType == Transition.Type.Chars) charEdgeCount++; else if(transition.TransitionType == Transition.Type.Positive) { hasPositive = true; break; } } state.UserData = _userData[(hasPositive || charEdgeCount > 1 || (charEdgeCount != 0 && state.Output.Count != charEdgeCount)) ? 1 : 0]; } }
public static Automaton NfaToDfa(Automaton nfa, out MultiValueDictionary<State, State> dfaStatesToNfa) { var dfa = new Automaton(); dfa.CaptureNames = nfa.CaptureNames; var dfaStartState = dfa.AddState(); dfa.StartState = dfaStartState; var nfaTransitionsToDfa = new MultiValueDictionary<Transition, Transition>(); var transitionClasses = new List<Transition>(); var mergeStates = new HashSet<State>(); dfaStatesToNfa = new MultiValueDictionary<State, State>(); dfaStatesToNfa.Add(dfaStartState, nfa.StartState); //不动点算法,不能使用 foreach! for(int i = 0; i < dfa.States.Count; ++i) { var curDfaState = dfa.States[i]; var nfaStates = dfaStatesToNfa[curDfaState]; foreach(var nfaState in nfaStates) { foreach(var outTransition in nfaState.Output) { if (!nfaTransitionsToDfa.Values.SelectMany(transitions => transitions).Contains(outTransition)) { transitionClasses.Add(outTransition); nfaTransitionsToDfa.Add(outTransition, outTransition); } } } foreach(var transitionClass in transitionClasses) { var nfaTransitions = nfaTransitionsToDfa[transitionClass]; foreach(var nfaTransition in nfaTransitions) { var state = nfaTransition.End; if (!mergeStates.Contains(state)) mergeStates.Add(state); } mergeStates.OrderBy(state => state); //mergeStates 是候选的一个 DFA 状态。在这之前,还需要判断:这个候选状态是否已经存在于 DFA 中了? //var isContained = dfaStatesToNfa.Values.Contains((IReadOnlyCollection<State>)mergeStates); State newDfaState = null; foreach(var dfaState in dfaStatesToNfa.Keys) { var prevNfaStates = dfaStatesToNfa[dfaState]; if (prevNfaStates.Count == mergeStates.Count && prevNfaStates.SequenceEqual(mergeStates)) { newDfaState = dfaState; break; } } if(newDfaState == null) { newDfaState = dfa.AddState(); dfaStatesToNfa.AddRange(newDfaState, mergeStates); newDfaState.IsFinalState = mergeStates.Any(state => state.IsFinalState); } var dfaTransition = dfa.AddTransition(curDfaState, newDfaState, transitionClass.TransitionType); dfaTransition.Capture = transitionClass.Capture; dfaTransition.Range = transitionClass.Range; dfaTransition.Index = transitionClass.Index; mergeStates.Clear(); } transitionClasses.Clear(); nfaTransitionsToDfa.Clear(); } return dfa; }
public static Automaton RemoveEpsilon(Automaton source) { //标记所有输入的边都没有消耗字符的状态 var nfa = new Automaton(); nfa.CaptureNames = source.CaptureNames; var newStartstate = nfa.AddState(); nfa.StartState = newStartstate; List<Transition> transitions = new List<Transition>(); var oldToNew = new Dictionary<State, State> { [source.StartState] = newStartstate }; var newToOld = new Dictionary<State, State>() { [newStartstate] = source.StartState }; var epsilonStates = new List<State>(); for(int i = 0; i < nfa.States.Count; ++i) { var state = nfa.States[i]; var oldState = newToOld[state]; FindPath(oldState, state, transitions, epsilonStates); if (oldState.IsFinalState) state.IsFinalState = true; foreach (var trans in transitions) { var target = trans.End; if(!oldToNew.Keys.Contains(target)) { var newState = nfa.AddState(); oldToNew.Add(target, newState); newToOld.Add(newState, target); } var newTransition = nfa.AddTransition(state, oldToNew[target], trans.TransitionType); newTransition.Range = trans.Range; newTransition.Capture = trans.Capture; newTransition.Index = trans.Index; } transitions.Clear(); epsilonStates.Clear(); } return nfa; }
private void RegexMenuItem_Click(object sender, RoutedEventArgs e) { RegexInput inputWindow = new RegexInput(); inputWindow.Owner = this; inputWindow.ShowDialog(); regexString = inputWindow.RegexString; if(regexString != string.Empty) { RegexContent.Text = regexString; var parser = new RegexParser.Parser(regexString); var exp = parser.ParseExpression(); EpsilonNfa = exp.GenerateExpsilonNfa(); Nfa = Automaton.RemoveEpsilon(EpsilonNfa); MultiValueDictionary<State, State> statesMap; Dfa = Automaton.NfaToDfa(Nfa, out statesMap); } }
public Automaton GenerateExpsilonNfa() { var automation = new Automaton(); var result = new EpsilonNfaAlgorithm().Invoke(this, automation); automation.StartState = result.Start; result.End.IsFinalState = true; return automation; }