Exemplo n.º 1
0
        /// <Summary>
        /// Convert compiled regular expression node into graph of non-deterministic
        /// states connected to given parent state and return final state of
        /// produced graph.
        /// </Summary>
        public NonDeterministicNode <TValue> ConnectTo <TValue>(NonDeterministicAutomata <TValue> automata, NonDeterministicNode <TValue> parent)
        {
            NonDeterministicNode <TValue> next;

            switch (Type)
            {
            case NodeType.Alternative:
                //           /-- [child1] --\
                // [parent] ---- [child2] ---> [next]
                //           \-- [child3] --/

                next = automata.PushEmpty();

                foreach (var child in Children)
                {
                    child.ConnectTo(automata, parent).EpsilonTo(next);
                }

                break;

            case NodeType.Character:
                // [parent] --{begin, end}--> [next]

                next = automata.PushEmpty();

                foreach (var range in Ranges)
                {
                    parent.BranchTo(range.Begin, range.End, next);
                }

                break;

            case NodeType.Repeat:
                //                           /-- [child] --\ * (max - min)
                // [parent] - [child] * min ----------------> [next]
                //                           \-- [child] --/ * infinite

                // Convert until lower bound is reached
                for (var i = 0; i < RepeatMin; ++i)
                {
                    parent = Children[0].ConnectTo(automata, parent);
                }

                next = automata.PushEmpty();

                parent.EpsilonTo(next);

                // Bounded repeat sequence, perform conversion (max - min) times
                if (RepeatMax >= 0)
                {
                    for (var i = 0; i < RepeatMax - RepeatMin; ++i)
                    {
                        parent = Children[0].ConnectTo(automata, parent);
                        parent.EpsilonTo(next);
                    }
                }

                // Unbounded repeat sequence, loop converted state over itself
                else
                {
                    var loop = Children[0].ConnectTo(automata, parent);

                    loop.EpsilonTo(parent);
                    loop.EpsilonTo(next);
                }

                return(next);

            case NodeType.Sequence:
                // [parent] -> [child1] -> [child2] -> ... -> [next]

                next = parent;

                foreach (var child in Children)
                {
                    next = child.ConnectTo(automata, next);
                }

                break;

            default:
                throw new InvalidOperationException();
            }

            return(next);
        }