Exemple #1
0
        /// <summary>
        /// Установить выходные связи frag на state
        /// </summary>
        /// <param name="frag"></param>
        /// <param name="state"></param>
        public static void Patch(NFAFragment frag, NFAState state)
        {
            var e = frag._outArrows.GetEnumerator();

            for (int i = 0; i < frag._outArrows.Count; i++)
            {
                frag._outArrows[i].value = state;
            }
        }
Exemple #2
0
        /// <summary>
        /// Конструируем НКА по постфиксному выражению по алгоритму Томпсона
        /// </summary>
        /// <param name="re"></param>
        /// <returns></returns>
        private static NFA FromPostfixRe(string re)
        {
            /*
             * Так как выражение поступает в постфиксной нотации алгоритм работает на стеке.
             * Для построения НКА используются такие абстрации:
             * NFAState - состояние НКА с выходным(-и) узлом. Может быть четырех типов:
             *      если c < 256 - это состояние с одним выходом, по которому можно перейти если очередной символ равен (char)c
             *      если c = 256 - это состояние с двумя е-переходами (Split)
             *      и если c = 257 - то это финальное состояние (оно одно такое)
             * NFAFragment - кусочек строящегося НКА, со ссылкой на стартовое состояние и указателями (NFAStatePointer) на
             * выходные узлы графа.
             * Таким образом соединение двух фрагментов f1, f2 например для случая конкатенации (последовательно)
             * осуществляется путем создания нового фрагмента f3, установки f3.Start = f1.Start, f3.OutArrows = f2.OutArrows
             * и установки всех указателей из f1.OutArrows на f2.Start (NFAFragment.Patch())
             */
            Stack <NFAFragment> stack = new Stack <NFAFragment>();
            NFAFragment         e, e1, e2;
            NFAState            s;

            foreach (char ch in re)
            {
                switch (ch)
                {
                default:     //Literal characters
                    s = new NFAState(ch, null, null);

                    stack.Push(new NFAFragment(s, new List <NFAStatePointer>()
                    {
                        s.OutArrowPtr
                    }));
                    break;

                case CONCAT:     //Concatenation
                    e2 = stack.Pop();
                    e1 = stack.Pop();
                    NFAFragment.Patch(e1, e2.Start);

                    stack.Push(new NFAFragment(e1.Start, e2.OutArrows));
                    break;

                case ALT:     //Alternation
                    e2 = stack.Pop();
                    e1 = stack.Pop();
                    s  = new NFAState(NFAStateName.Split, e1.Start, e2.Start);

                    stack.Push(new NFAFragment(s, NFAFragment.Concat(e1, e2)));
                    break;

                case QUEST:     //Zero or one
                    e = stack.Pop();
                    s = new NFAState(NFAStateName.Split, e.Start, null);

                    stack.Push(new NFAFragment(s, NFAFragment.Concat(e.OutArrows, new List <NFAStatePointer>()
                    {
                        s.OutArrow1Ptr
                    })));
                    break;

                case STAR:     //Zero or more
                    e = stack.Pop();
                    s = new NFAState(NFAStateName.Split, e.Start, null);
                    NFAFragment.Patch(e, s);

                    stack.Push(new NFAFragment(s, new List <NFAStatePointer>()
                    {
                        s.OutArrow1Ptr
                    }));
                    break;

                case PLUS:     //One or more
                    e = stack.Pop();
                    s = new NFAState(NFAStateName.Split, e.Start, null);
                    NFAFragment.Patch(e, s);

                    stack.Push(new NFAFragment(e.Start, new List <NFAStatePointer>()
                    {
                        s.OutArrow1Ptr
                    }));
                    break;
                }
            }
            //Осталось только взять верхний элемент стека, он и есть построенный НКА,
            //и все выходные связи установить в финальное состояние
            e = stack.Pop();
            NFAFragment.Patch(e, NFAState.MatchState);
            return(new NFA(e.Start));
        }
Exemple #3
0
 /// <summary>
 /// Склеить списки выходных связей двух фрагментов
 /// </summary>
 /// <param name="f1"></param>
 /// <param name="f2"></param>
 /// <returns></returns>
 public static IList <NFAStatePointer> Concat(NFAFragment f1, NFAFragment f2)
 {
     return(Concat(f1.OutArrows, f2.OutArrows));
 }