Example #1
0
        /// <summary>
        /// Creates a node representing the concatenation of the languages described by a given pair of nodes.
        /// </summary>
        /// <param name="node1">The first node.</param>
        /// <param name="node2">The second node.</param>
        /// <returns>The created node.</returns>
        public static RegexpTreeNode <TElement, TElementSet> Concat(RegexpTreeNode <TElement, TElementSet> node1, RegexpTreeNode <TElement, TElementSet> node2)
        {
            Argument.CheckIfNotNull(node1, "node1");
            Argument.CheckIfNotNull(node2, "node2");

            if (node1.Type == RegexpTreeNodeType.Nothing || node2.Type == RegexpTreeNodeType.Nothing)
            {
                // Concatenation with an empty language results in an empty language
                return(Nothing());
            }

            if (node1.Type == RegexpTreeNodeType.Empty)
            {
                // Concatenation with an empty string is an identity
                return(node2);
            }

            if (node2.Type == RegexpTreeNodeType.Empty)
            {
                // Concatenation with an empty string is an identity
                return(node1);
            }

            var result = new RegexpTreeNode <TElement, TElementSet> {
                Type = RegexpTreeNodeType.Concat
            };

            result.children.Capacity = 2;
            result.children.Add(node1);
            result.children.Add(node2);

            return(result);
        }
Example #2
0
        /// <summary>
        /// Creates a node representing the union of the languages described by a given pair of nodes.
        /// </summary>
        /// <param name="node1">The first node.</param>
        /// <param name="node2">The second node.</param>
        /// <returns>The created node.</returns>
        public static RegexpTreeNode <TElement, TElementSet> Or(RegexpTreeNode <TElement, TElementSet> node1, RegexpTreeNode <TElement, TElementSet> node2)
        {
            Argument.CheckIfNotNull(node1, "node1");
            Argument.CheckIfNotNull(node2, "node2");

            if (node1.Type == RegexpTreeNodeType.Empty && node2.Type == RegexpTreeNodeType.Empty)
            {
                // Identical children
                return(node1);
            }

            if (node1.Type == RegexpTreeNodeType.Nothing)
            {
                // Union with an empty language is an identity
                return(node2);
            }

            if (node2.Type == RegexpTreeNodeType.Nothing)
            {
                // Union with an empty language is an identity
                return(node1);
            }

            var result = new RegexpTreeNode <TElement, TElementSet> {
                Type = RegexpTreeNodeType.Union
            };

            result.children.Capacity = 2;
            result.children.Add(node1);
            result.children.Add(node2);

            return(result);
        }
Example #3
0
        /// <summary>
        /// Copies the state of this node from another node.
        /// </summary>
        /// <param name="other">The node to copy the state from.</param>
        private void SetTo(RegexpTreeNode <TElement, TElementSet> other)
        {
            Debug.Assert(other != null, "A valid node must be provided.");

            this.Type       = other.Type;
            this.elementSet = other.elementSet;
            this.children.Clear();
            this.children.AddRange(other.children);
            this.simplified            = other.simplified;
            this.toStringVerboseCached = other.toStringVerboseCached;
        }
Example #4
0
        /// <summary>
        /// Simplifies a node representing Kleene star.
        /// </summary>
        private void SimplifyStar()
        {
            Debug.Assert(this.Type == RegexpTreeNodeType.Star, "Must be run for Kleene star nodes only.");
            Debug.Assert(this.children.Count == 1, "A Kleene star node must have a single child.");

            //// The simplification can affect the node itself, but not its children
            //// since children are shared by multiple parents.

            RegexpTreeNode <TElement, TElementSet> child = this.children[0];

            switch (child.Type)
            {
            case RegexpTreeNodeType.Empty:
            case RegexpTreeNodeType.Nothing:
            case RegexpTreeNodeType.Star:
                Debug.Fail("Should have been optimized away.");
                break;

            case RegexpTreeNodeType.Union:
                // 'Star' accepts the empty string anyway, no need to provide it as an alternative
                if (child.children.Any(c => c.Type == RegexpTreeNodeType.Empty))
                {
                    List <RegexpTreeNode <TElement, TElementSet> > nonEmptyUnionChildren =
                        child.children.Where(c => c.Type != RegexpTreeNodeType.Empty).ToList();
                    if (nonEmptyUnionChildren.Count == 0)
                    {
                        // Empty only
                        this.SetTo(RegexpTreeNode <TElement, TElementSet> .Empty());
                    }
                    else if (nonEmptyUnionChildren.Count == 1)
                    {
                        this.children.Clear();
                        this.children.AddRange(nonEmptyUnionChildren);
                        Debug.Assert(this.children.Count == 1, "There must be only one such node.");
                    }
                    else
                    {
                        // Can't modify child's children, so create a new node
                        this.children.Clear();
                        var newUnionNode = new RegexpTreeNode <TElement, TElementSet> {
                            Type = RegexpTreeNodeType.Union, children = nonEmptyUnionChildren, simplified = true
                        };
                        this.children.Add(newUnionNode);
                    }
                }

                break;
            }
        }
Example #5
0
        /// <summary>
        /// Creates a node representing the Kleene star of the language described by a given node.
        /// </summary>
        /// <param name="node">The node.</param>
        /// <returns>The created node.</returns>
        public static RegexpTreeNode <TElement, TElementSet> Star(RegexpTreeNode <TElement, TElementSet> node)
        {
            Argument.CheckIfNotNull(node, "node");

            if (node.Type == RegexpTreeNodeType.Nothing ||
                node.Type == RegexpTreeNodeType.Empty ||
                node.Type == RegexpTreeNodeType.Star)
            {
                // In all these cases star doesn't affect its argument
                return(node);
            }

            var result = new RegexpTreeNode <TElement, TElementSet> {
                Type = RegexpTreeNodeType.Star
            };

            result.children.Capacity = 1;
            result.children.Add(node);

            return(result);
        }