// 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)); }