Example #1
0
        // ReduceAlternation:
        //
        // Basic optimization. Single-letter alternations can be replaced
        // by faster set specifications, and nested alternations with no
        // intervening operators can be flattened:
        //
        // a|b|c|def|g|h -> [a-c]|def|[gh]
        // apple|(?:orange|pear)|grape -> apple|orange|pear|grape
        //

        internal RegexNode ReduceAlternation()
        {
            // Combine adjacent sets/chars

            bool         wasLastSet;
            RegexOptions optionsLast;
            RegexOptions optionsAt;
            int          i;
            int          j;
            RegexNode    at;
            RegexNode    prev;

            if (_children == null)
            {
                return(new RegexNode(RegexNode.Nothing, _options));
            }

            wasLastSet  = false;
            optionsLast = 0;

            for (i = 0, j = 0; i < _children.Count; i++, j++)
            {
                at = (RegexNode)_children[i];

                if (j < i)
                {
                    _children[j] = at;
                }

                for (;;)
                {
                    if (at._type == Alternate)
                    {
                        for (int k = 0; k < at._children.Count; k++)
                        {
                            ((RegexNode)at._children[k])._next = this;
                        }

                        _children.InsertRange(i + 1, at._children);
                        j--;
                    }
                    else if (at._type == Set || at._type == One)
                    {
                        // Cannot merge sets if L or I options differ
                        optionsAt = at._options & (RegexOptions.RightToLeft | RegexOptions.IgnoreCase);

                        if (!wasLastSet || optionsLast != optionsAt)
                        {
                            wasLastSet  = true;
                            optionsLast = optionsAt;
                            break;
                        }

                        // The last node was a Set or a One, we're a Set or One and our options are the same.
                        // Merge the two nodes.
                        prev = (RegexNode)_children[--j];

                        if (prev._type == RegexNode.One)
                        {
                            prev._type = RegexNode.Set;
                            prev._str  = RegexCharClass.SetFromChar(prev._ch);
                        }

                        if (at._type == RegexNode.One)
                        {
                            prev._str = RegexCharClass.SetUnion(prev._str, RegexCharClass.SetFromChar(at._ch)); // no categories to worry about
                        }
                        else
                        {
                            prev._str  = RegexCharClass.SetUnion(prev._str, at._str);
                            prev._str2 = RegexCharClass.CategoryUnion(prev._str2, at._str2);
                        }
                    }
                    else if (at._type == RegexNode.Nothing)
                    {
                        j--;
                    }
                    else
                    {
                        wasLastSet = false;
                    }
                    break;
                }
            }

            if (j < i)
            {
                _children.RemoveRange(j, i - j);
            }

            return(StripEnation(RegexNode.Nothing));
        }
        internal RegexNode ReduceAlternation()
        {
            if (this._children == null)
            {
                return(new RegexNode(0x16, this._options));
            }
            bool         flag  = false;
            RegexOptions none  = RegexOptions.None;
            int          num   = 0;
            int          index = 0;

            while (num < this._children.Count)
            {
                RegexNode node = (RegexNode)this._children[num];
                if (index < num)
                {
                    this._children[index] = node;
                }
                if (node._type == 0x18)
                {
                    for (int i = 0; i < node._children.Count; i++)
                    {
                        ((RegexNode)node._children[i])._next = this;
                    }
                    this._children.InsertRange(num + 1, node._children);
                    index--;
                }
                else if ((node._type == 11) || (node._type == 9))
                {
                    RegexOptions options2 = node._options & (RegexOptions.RightToLeft | RegexOptions.IgnoreCase);
                    if (!flag || (none != options2))
                    {
                        flag = true;
                        none = options2;
                    }
                    else
                    {
                        RegexNode node2 = (RegexNode)this._children[--index];
                        if (node2._type == 9)
                        {
                            node2._type = 11;
                            node2._str  = RegexCharClass.SetFromChar(node2._ch);
                        }
                        if (node._type == 9)
                        {
                            node2._str = RegexCharClass.SetUnion(node2._str, RegexCharClass.SetFromChar(node._ch));
                        }
                        else
                        {
                            node2._str  = RegexCharClass.SetUnion(node2._str, node._str);
                            node2._str2 = RegexCharClass.CategoryUnion(node2._str2, node._str2);
                        }
                    }
                }
                else if (node._type == 0x16)
                {
                    index--;
                }
                else
                {
                    flag = false;
                }
                num++;
                index++;
            }
            if (index < num)
            {
                this._children.RemoveRange(index, num - index);
            }
            return(this.StripEnation(0x16));
        }