コード例 #1
0
        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;
        }
コード例 #2
0
        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];
            }
        }
コード例 #3
0
ファイル: Automaton.cs プロジェクト: LYP951018/FunnyThings
        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;
        }
コード例 #4
0
ファイル: Automaton.cs プロジェクト: LYP951018/FunnyThings
        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;
        }
コード例 #5
0
 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);
     }
 }
コード例 #6
0
ファイル: Expression.cs プロジェクト: LYP951018/FunnyThings
 public Automaton GenerateExpsilonNfa()
 {
     var automation = new Automaton();
     var result = new EpsilonNfaAlgorithm().Invoke(this, automation);
     automation.StartState = result.Start;
     result.End.IsFinalState = true;
     return automation;
 }