/* * 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; bool lastNodeCannotMerge; RegexOptions optionsLast; RegexOptions optionsAt; int i; int j; RegexNode at; RegexNode prev; if (_children == null) { return(new RegexNode(RegexNode.Nothing, _options)); } wasLastSet = false; lastNodeCannotMerge = false; optionsLast = 0; for (i = 0, j = 0; i < _children.Count; i++, j++) { at = _children[i]; if (j < i) { _children[j] = at; } for (; ;) { if (at._type == Alternate) { for (int k = 0; k < at._children.Count; k++) { 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, or if either are negated. optionsAt = at._options & (RegexOptions.RightToLeft | RegexOptions.IgnoreCase); if (at._type == Set) { if (!wasLastSet || optionsLast != optionsAt || lastNodeCannotMerge || !RegexCharClass.IsMergeable(at._str)) { wasLastSet = true; lastNodeCannotMerge = !RegexCharClass.IsMergeable(at._str); optionsLast = optionsAt; break; } } else if (!wasLastSet || optionsLast != optionsAt || lastNodeCannotMerge) { wasLastSet = true; lastNodeCannotMerge = false; 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. j--; prev = _children[j]; RegexCharClass prevCharClass; if (prev._type == RegexNode.One) { prevCharClass = new RegexCharClass(); prevCharClass.AddChar(prev._ch); } else { prevCharClass = RegexCharClass.Parse(prev._str); } if (at._type == RegexNode.One) { prevCharClass.AddChar(at._ch); } else { RegexCharClass atCharClass = RegexCharClass.Parse(at._str); prevCharClass.AddCharClass(atCharClass); } prev._type = RegexNode.Set; prev._str = prevCharClass.ToStringClass(); } else if (at._type == RegexNode.Nothing) { j--; } else { wasLastSet = false; lastNodeCannotMerge = 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; bool flag2 = false; RegexOptions none = RegexOptions.None; int num = 0; int index = 0; while (num < this._children.Count) { RegexCharClass class2; RegexNode node = this._children[num]; if (index < num) { this._children[index] = node; } if (node._type == 0x18) { for (int i = 0; i < node._children.Count; i++) { node._children[i]._next = this; } this._children.InsertRange(num + 1, node._children); index--; goto Label_01C2; } if ((node._type != 11) && (node._type != 9)) { goto Label_01AB; } RegexOptions options2 = node._options & (RegexOptions.RightToLeft | RegexOptions.IgnoreCase); if (node._type == 11) { if ((flag && (none == options2)) && (!flag2 && RegexCharClass.IsMergeable(node._str))) { goto Label_011B; } flag = true; flag2 = !RegexCharClass.IsMergeable(node._str); none = options2; goto Label_01C2; } if ((!flag || (none != options2)) || flag2) { flag = true; flag2 = false; none = options2; goto Label_01C2; } Label_011B: index--; RegexNode node2 = this._children[index]; if (node2._type == 9) { class2 = new RegexCharClass(); class2.AddChar(node2._ch); } else { class2 = RegexCharClass.Parse(node2._str); } if (node._type == 9) { class2.AddChar(node._ch); } else { RegexCharClass cc = RegexCharClass.Parse(node._str); class2.AddCharClass(cc); } node2._type = 11; node2._str = class2.ToStringClass(); goto Label_01C2; Label_01AB: if (node._type == 0x16) { index--; } else { flag = false; flag2 = false; } Label_01C2: num++; index++; } if (index < num) { this._children.RemoveRange(index, num - index); } return(this.StripEnation(0x16)); }
/* * 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; bool lastNodeCannotMerge; RegexOptions optionsLast; RegexOptions optionsAt; int i; int j; RegexNode at; RegexNode prev; if (_children == null) return new RegexNode(RegexNode.Nothing, _options); wasLastSet = false; lastNodeCannotMerge = false; optionsLast = 0; for (i = 0, j = 0; i < _children.Count; i++, j++) { at = _children[i]; if (j < i) _children[j] = at; for (;;) { if (at._type == Alternate) { for (int k = 0; k < at._children.Count; k++) 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, or if either are negated. optionsAt = at._options & (RegexOptions.RightToLeft | RegexOptions.IgnoreCase); if (at._type == Set) { if (!wasLastSet || optionsLast != optionsAt || lastNodeCannotMerge || !RegexCharClass.IsMergeable(at._str)) { wasLastSet = true; lastNodeCannotMerge = !RegexCharClass.IsMergeable(at._str); optionsLast = optionsAt; break; } } else if (!wasLastSet || optionsLast != optionsAt || lastNodeCannotMerge) { wasLastSet = true; lastNodeCannotMerge = false; 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. j--; prev = _children[j]; RegexCharClass prevCharClass; if (prev._type == RegexNode.One) { prevCharClass = new RegexCharClass(); prevCharClass.AddChar(prev._ch); } else { prevCharClass = RegexCharClass.Parse(prev._str); } if (at._type == RegexNode.One) { prevCharClass.AddChar(at._ch); } else { RegexCharClass atCharClass = RegexCharClass.Parse(at._str); prevCharClass.AddCharClass(atCharClass); } prev._type = RegexNode.Set; prev._str = prevCharClass.ToStringClass(); } else if (at._type == RegexNode.Nothing) { j--; } else { wasLastSet = false; lastNodeCannotMerge = 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; bool flag2 = false; RegexOptions none = RegexOptions.None; int num = 0; int index = 0; while (num < this._children.Count) { RegexCharClass class2; RegexNode node = this._children[num]; if (index < num) { this._children[index] = node; } if (node._type == 0x18) { for (int i = 0; i < node._children.Count; i++) { node._children[i]._next = this; } this._children.InsertRange(num + 1, node._children); index--; goto Label_01C2; } if ((node._type != 11) && (node._type != 9)) { goto Label_01AB; } RegexOptions options2 = node._options & (RegexOptions.RightToLeft | RegexOptions.IgnoreCase); if (node._type == 11) { if ((flag && (none == options2)) && (!flag2 && RegexCharClass.IsMergeable(node._str))) { goto Label_011B; } flag = true; flag2 = !RegexCharClass.IsMergeable(node._str); none = options2; goto Label_01C2; } if ((!flag || (none != options2)) || flag2) { flag = true; flag2 = false; none = options2; goto Label_01C2; } Label_011B: index--; RegexNode node2 = this._children[index]; if (node2._type == 9) { class2 = new RegexCharClass(); class2.AddChar(node2._ch); } else { class2 = RegexCharClass.Parse(node2._str); } if (node._type == 9) { class2.AddChar(node._ch); } else { RegexCharClass cc = RegexCharClass.Parse(node._str); class2.AddCharClass(cc); } node2._type = 11; node2._str = class2.ToStringClass(); goto Label_01C2; Label_01AB: if (node._type == 0x16) { index--; } else { flag = false; flag2 = false; } Label_01C2: num++; index++; } if (index < num) { this._children.RemoveRange(index, num - index); } return this.StripEnation(0x16); }