コード例 #1
0
        //    //int nextEdge = 0;
        //    var delayed = new Stack<Tuple<IFsmState, int>>();
        //    while (currState.IsFinal == false || pos == text.Length)
        //    {
        //        var visitedTransitions = new SortedSet<string>();

        //        var transitions = currState.Flatten(s => s.OutTransitions.Where(nt => nt.Condition.IsSigma).Select(x => x.To), tt => visitedTransitions.Add(tt.ToString()))
        //            .SelectMany(ct => ct.OutTransitions.Where(nt => !nt.Condition.IsSigma));

        //        delayed.Push(Tuple.Create(currState, pos));

        //        foreach (var transition in transitions)
        //        {
        //            bool edge = MatchEdge(text, pos, transition);
        //            if (edge)
        //            {
        //                currState = transition.To;
        //                pos++;
        //                break;
        //            }
        //            else
        //            {
        //                if (delayed.Count > 0)
        //                {
        //                    var retState = delayed.Pop();
        //                    currState = retState.Item1;
        //                    pos = retState.Item2;
        //                    //nextEdge = retState.Item3;
        //                }
        //            }
        //        }
        //    }
        //    return currState.IsFinal;
        //}

        private bool IsMatch(string text, ref int pos, ref IFsmState tmpState)
        {
            if (tmpState.IsFinal)
            {
                return(true);
            }

            var delayed    = new Stack <(IFsmState fallbackState, int fallbackPos)>();
            var backStates = new List <(int pos, int fallbackLimit, int fallbackCount)>();

            //сохранять outtransitions, pos с которого откат и считать откаты.
            // если кол-во откатов больше кол-ва outTransitions, false
            while ((tmpState.IsFinal == false || pos != text.Length) && pos < text.Length)
            {
                if (tmpState.OutTransitions.Any(t => t.Condition.IsSigma))
                {
                    delayed.Push((tmpState, pos));
                }

                var visitedTransitions = new SortedSet <string>();
                var transitions        = tmpState.Flatten(
                    s => s.OutTransitions.Where(nt => nt.Condition.IsSigma).Select(x => x.To),
                    tt => visitedTransitions.Add(tt.ToString())
                    ).SelectMany(ct => ct.OutTransitions.Where(nt => !nt.Condition.IsSigma));

                bool succ = false;

                foreach (var transition in transitions)
                {
                    bool edge = this.MatchEdge(text, pos, transition);
                    if (edge)
                    {
                        tmpState = transition.To;
                        pos++;
                        succ = true;
                        break;
                    }
                }

                if (!succ)
                {
                    if (backStates.Count == 0 || backStates.Last().pos != pos)
                    {
                        backStates.Add((pos, tmpState.OutTransitions.Count, 1));
                    }
                    else
                    {
                        var last = backStates.Last();
                        if (last.fallbackLimit < last.fallbackCount)
                        {
                            break;
                        }
                        else
                        {
                            var count = last.fallbackCount;
                            count++;
                            backStates.Remove(backStates.Last());
                            backStates.Add((last.pos, last.fallbackLimit, count));
                        }
                    }

                    var backState = delayed.Pop();
                    tmpState = backState.fallbackState;
                    pos      = backState.fallbackPos;
                }
            }
            return(tmpState.IsFinal);
        }