From e60eb0ada6091469f3e533952de4564de4de92d8 Mon Sep 17 00:00:00 2001 From: Youmu Liu <105042599+Nitload-NSI@users.noreply.github.com> Date: Mon, 29 Jun 2026 17:14:52 +0800 Subject: [PATCH] regex ir opt code rewriting, use over-again opt method --- StgSharp.RegularAnalysis/Text/RegexIR.cs | 35 ++- .../Text/RegexIRGenerator.cs | 4 +- .../Text/RegexInterpreter.IREmit.cs | 280 ------------------ .../Text/RegexInterpreter.IRGenerate.cs | 4 +- .../Text/RegexInterpreter.IROptimize.cs | 239 ++++++++++----- .../Text/RegexInterpreter.SourceEmit.cs | 37 --- 6 files changed, 188 insertions(+), 411 deletions(-) delete mode 100644 StgSharp.RegularAnalysis/Text/RegexInterpreter.IREmit.cs delete mode 100644 StgSharp.RegularAnalysis/Text/RegexInterpreter.SourceEmit.cs diff --git a/StgSharp.RegularAnalysis/Text/RegexIR.cs b/StgSharp.RegularAnalysis/Text/RegexIR.cs index 6a28274f..dfc12c8c 100644 --- a/StgSharp.RegularAnalysis/Text/RegexIR.cs +++ b/StgSharp.RegularAnalysis/Text/RegexIR.cs @@ -55,6 +55,15 @@ namespace StgSharp.RegularAnalysis.Text } + internal interface IRegexComplex + { + + bool IsFullyOptimized { get; set; } + + int CommandCount { get; set; } + + } + internal interface IRegexCount { @@ -73,15 +82,17 @@ namespace StgSharp.RegularAnalysis.Text internal sealed class RegexFindComplexIR( bool nearest, int count - ) : RegexIR + ) : RegexIR, IRegexComplex { + public bool IsFullyOptimized { get; set; } + + public int CommandCount { get; set; } = count; + internal override RegexIRCommand Command => RegexIRCommand.Find_Complex; private bool IsNearest { get; } = nearest; - private int CommandCount { get; } = count; - internal override string AsCommand( int lineNum ) @@ -209,7 +220,7 @@ namespace StgSharp.RegularAnalysis.Text int max, bool isGreedy, int operation - ) : RegexIR, IRegexCount + ) : RegexIR, IRegexCount, IRegexComplex { public bool IsGreedy { get; } = isGreedy; @@ -218,11 +229,13 @@ namespace StgSharp.RegularAnalysis.Text public bool IsPlus => Min == 1 && Max < 0; + public bool IsFullyOptimized { get; set; } + public int Min { get; } = min; public int Max { get; } = max; - public int OperationCount { get; } = operation; + public int CommandCount { get; set; } = operation; internal override RegexIRCommand Command { get; } = RegexIRCommand.Count_Complex; @@ -230,7 +243,7 @@ namespace StgSharp.RegularAnalysis.Text int lineNum ) { - return $"[{lineNum}]\t COUNT {(IsGreedy ? "GREEDY" : "NON_GREEDY")} MIN: {Min} MAX: {Max} OPERATION: {OperationCount}"; + return $"[{lineNum}]\t COUNT {(IsGreedy ? "GREEDY" : "NON_GREEDY")} MIN: {Min} MAX: {Max} OPERATION: {CommandCount}"; } } @@ -253,7 +266,7 @@ namespace StgSharp.RegularAnalysis.Text public int Max { get; } = max; - public string Sequence { get; } = seq; + public string Sequence { get; } = seq.Length == 2 && seq[0] == '\\' ? seq[1..2] : seq; internal override RegexIRCommand Command { get; } = RegexIRCommand.Count_Seq; @@ -299,13 +312,17 @@ namespace StgSharp.RegularAnalysis.Text } - internal sealed class RegexTryIR( + internal sealed class RegexMatchComplexIR( int count - ) : RegexIR + ) : RegexIR, IRegexComplex { + public bool IsFullyOptimized { get; set; } + public int CountOfCommand { get; } = count; + public int CommandCount { get; set; } + internal override RegexIRCommand Command => RegexIRCommand.Try; internal override string AsCommand( diff --git a/StgSharp.RegularAnalysis/Text/RegexIRGenerator.cs b/StgSharp.RegularAnalysis/Text/RegexIRGenerator.cs index 190bd505..4c05aa47 100644 --- a/StgSharp.RegularAnalysis/Text/RegexIRGenerator.cs +++ b/StgSharp.RegularAnalysis/Text/RegexIRGenerator.cs @@ -134,11 +134,11 @@ namespace StgSharp.RegularAnalysis.Text Count++; } - public void EmitTry( + public void EmitMatchComplex( int count ) { - _tail.Add(new RegexTryIR(count)); + _tail.Add(new RegexMatchComplexIR(count)); Count++; } diff --git a/StgSharp.RegularAnalysis/Text/RegexInterpreter.IREmit.cs b/StgSharp.RegularAnalysis/Text/RegexInterpreter.IREmit.cs deleted file mode 100644 index af8a9397..00000000 --- a/StgSharp.RegularAnalysis/Text/RegexInterpreter.IREmit.cs +++ /dev/null @@ -1,280 +0,0 @@ -//----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -// file="RegexInterpreter.IREmit" -// Project: StgSharp -// AuthorGroup: Nitload -// Copyright (c) Nitload. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -// ----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -using StgSharp.RegularAnalysis.Abstraction; -using System; -using System.Collections.Generic; -using System.ComponentModel.Design; -using System.Data; -using System.Diagnostics.Metrics; -using System.Linq; -using System.Reflection.Emit; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; -using System.Xml; - -namespace StgSharp.RegularAnalysis.Text -{ - public partial class RegexAnalyzer - { - - internal static List GenerateIR(AbstractSyntaxTree tree) - { - return GenerateIRRecursion(tree.Root, 0).ToList(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void EmitCount( - int curDepth, - RegexIRGenerator ir, - int min, - int max, - bool isGreedy, -<<<<<<<< HEAD:StgSharp.RegularAnalysis/Text/RegexInterpreter.IREmit.cs - RegexAstNode right) -======== - RegexAstNode body - ) ->>>>>>>> 359dd6728716c1c0014d64b72ba70c6c65bb8cf8:StgSharp.RegularAnalysis/Text/RegexInterpreter.IRGenerate.cs - { - bool is_operator = !RegexAstNode.IsNullOrEmpty(body) && - (body.Source.Flag & RegexElementLabel.OPERATOR) != 0; - - if (is_operator) // seq to be count is complex - { - RegexIRGenerator body_ir = GenerateIRRecursion(body, curDepth + 1); - ir.EmitCountComplex(min, max, isGreedy, body_ir.Count); - ir.EmitIRStream(body_ir); - } else - { - RegexElementLabel count_source_mask = body.Source.Flag; - switch (count_source_mask) - { - case RegexElementLabel.UNIT: - ir.EmitCountSeq(min, max, isGreedy, body.Source.Value); - break; - case RegexElementLabel.UNIT_SET: - ir.EmitCountSet(min, max, isGreedy, body.Source.Value); - break; - case RegexElementLabel.UNIT_SPAN: - ir.EmitCountSeq(min, max, isGreedy, body.Source.Value); - break; - default: - throw new InvalidOperationException($"Unexpected regex element type for count operator: {count_source_mask}"); - } - } - } - - private static RegexIRGenerator GenerateIRRecursion(RegexAstNode node, int depth) - { -#pragma warning disable IDE0010 - if (depth > 1024) - { - throw new OverflowException("Regex parse exceeds maximum recursion depth"); - } - int curDepth = depth; - RegexAstNode left = node.Left; - RegexAstNode right = node.Right; - RegexIRGenerator leftIR; - RegexIRGenerator rightIR; - - Token token = node.Source; - - switch (node.Source.Flag) - { - case RegexElementLabel.GROUP_BEGIN: - string group_source = token.Value; - - // process group type - bool is_group = group_source.Length == 1; // simple group: (pattern) - string group_name = - group_source.StartsWith(@"(?<", StringComparison.Ordinal) ? - group_source[3..^1] : /* named group (?) */ - string.Empty; /* unnamed group (?:) */ - - RegexIRGenerator groupIR = new(); - rightIR = GenerateIRRecursion(right, curDepth + 1); - groupIR.EmitTry(rightIR.Count); - groupIR.EmitIRStream(rightIR); - groupIR.EmitCondition(2, 1); - groupIR.EmitPop(false); - groupIR.EmitPack(true, group_name); - return groupIR; - case RegexElementLabel.COUNT: - string count_source = token.Value; - bool isGreedy = !(count_source.Length > 1 && count_source.EndsWith('?')); - int seq_mask = (RegexAstNode.IsNullOrEmpty(left) ? 0 : 2) + (RegexAstNode.IsNullOrEmpty(right) ? - 0 : - 1); - RegexAstNode seq = seq_mask switch - { - // no seq, invalid count operator - 0 => throw new InvalidOperationException("Count operator must have a sequence to operate on"), - 1 => right,// right seq - 2 => left,// left seq - // both sides, invalid count operator - 3 => throw new InvalidOperationException("Count operator cannot have two sequences to operate on"), - _ => throw new InvalidOperationException("Unexpected sequence mask for count operator"), - }; - ReadOnlySpan count_source_span = count_source; - RegexIRGenerator count_ir = new(); - - if (count_source_span[0] == '*') // infinite count - { - EmitCount(curDepth, count_ir, 0, -1, isGreedy, seq); - } else if (count_source_span[0] == '+') // at least one - { - EmitCount(curDepth, count_ir, 1, -1, isGreedy, seq); - } else if (count_source_span[0] == '?') // zero or one - { - EmitCount(curDepth, count_ir, 0, 1, isGreedy, seq); - } else if (count_source_span[0] == '{') // zero or one, non-greedy - { - int comma_pos = count_source_span.IndexOf(','); - if (comma_pos == -1) - { - if (int.TryParse(count_source[1..(isGreedy ? ^2 : ^1)], out int count)) - { - EmitCount(curDepth, count_ir, count, count, isGreedy, seq); - } else - { - throw new InvalidCastException($"Invalid count format: {count_source}"); - } - } else - { - if (int.TryParse(count_source[1..comma_pos], out int min) && - int.TryParse(count_source[(comma_pos + 1)..(isGreedy ? ^1 : ^2)], out int max)) - { - EmitCount(curDepth, count_ir, min, max, isGreedy, seq); - } else - { - throw new InvalidCastException($"Invalid count format: {count_source}"); - } - } - } else - { - throw new InvalidOperationException(); - } // unknown count format - - return count_ir; - case RegexElementLabel.CONCAT: - RegexIRGenerator concat = new(); - - // process left node - if (RegexAstNode.IsNullOrEmpty(left)) - { - // do nothing - } else if ((left.Source.Flag & RegexElementLabel.SEQUENCE) != 0) - { - switch (left.Source.Flag) - { - case RegexElementLabel.UNIT_SPAN: - goto case RegexElementLabel.UNIT; - case RegexElementLabel.UNIT: - concat.EmitMatchSeq(left.Source.Value); - break; - case RegexElementLabel.UNIT_SET: - concat.EmitMatchSet(left.Source.Value); - break; - default: - break; - } - } else if ((left.Source.Flag & RegexElementLabel.VAST_OPERATOR) != 0) - { - leftIR = GenerateIRRecursion(left, curDepth + 1); - concat.EmitIRStream(leftIR); - } - - // process right node - if (RegexAstNode.IsNullOrEmpty(right)) - { - // do nothing - } else if ((right.Source.Flag & RegexElementLabel.SEQUENCE) != 0) - { - switch (right.Source.Flag) - { - case RegexElementLabel.UNIT_SPAN: - goto case RegexElementLabel.UNIT; - case RegexElementLabel.UNIT: - concat.EmitMatchSeq(right.Source.Value); - break; - case RegexElementLabel.UNIT_SET: - concat.EmitMatchSet(right.Source.Value); - break; - default: - break; - } - } else if ((right.Source.Flag & RegexElementLabel.VAST_OPERATOR) != 0) - { - rightIR = GenerateIRRecursion(right, curDepth + 1); - concat.EmitIRStream(rightIR); - } - return concat; - case RegexElementLabel.ALT: - RegexIRGenerator alt = new(); - List casesIRList = []; - RegexAstNode cur_node = right; - int ir_count = 0; - while (!RegexAstNode.IsNullOrEmpty(cur_node)) - { - RegexIRGenerator _case = GenerateIRRecursion(cur_node, curDepth + 1); - casesIRList.Add(_case); - ir_count += _case.Count; - cur_node = cur_node.Next; - } - int case_count = casesIRList.Count; - while (case_count != 0) - { - RegexIRGenerator cur_ir = casesIRList[^case_count]; - ir_count -= cur_ir.Count; - case_count--; - alt.EmitTry(cur_ir.Count); - alt.EmitIRStream(cur_ir); - alt.EmitCondition(1/* need to calc here */, 2); - alt.EmitPop(true); - } - alt.EmitPop(false); - return alt; - case RegexElementLabel.UNIT_SPAN: - goto case RegexElementLabel.UNIT; - case RegexElementLabel.UNIT: - RegexIRGenerator unit_seq = new(); - unit_seq.EmitMatchSeq(node.Source.Value); - return unit_seq; - case RegexElementLabel.UNIT_SET: - RegexIRGenerator unit_set = new(); - unit_set.EmitMatchSet(node.Source.Value); - return unit_set; - default: - return null!; - } -#pragma warning restore IDE0010 - } - - } -} diff --git a/StgSharp.RegularAnalysis/Text/RegexInterpreter.IRGenerate.cs b/StgSharp.RegularAnalysis/Text/RegexInterpreter.IRGenerate.cs index ef946a0d..1491e9b4 100644 --- a/StgSharp.RegularAnalysis/Text/RegexInterpreter.IRGenerate.cs +++ b/StgSharp.RegularAnalysis/Text/RegexInterpreter.IRGenerate.cs @@ -117,7 +117,7 @@ namespace StgSharp.RegularAnalysis.Text RegexIRGenerator groupIR = new(); rightIR = GenerateIRRecursion(right, curDepth + 1); - groupIR.EmitTry(rightIR.Count); + groupIR.EmitMatchComplex(rightIR.Count); groupIR.EmitIRStream(rightIR); groupIR.EmitCondition(2, 1); groupIR.EmitPop(false); @@ -251,7 +251,7 @@ namespace StgSharp.RegularAnalysis.Text RegexIRGenerator cur_ir = casesIRList[^case_count]; ir_count -= cur_ir.Count; case_count--; - alt.EmitTry(cur_ir.Count); + alt.EmitMatchComplex(cur_ir.Count); alt.EmitIRStream(cur_ir); alt.EmitCondition(1/* need to calc here */, 2); alt.EmitPop(true); diff --git a/StgSharp.RegularAnalysis/Text/RegexInterpreter.IROptimize.cs b/StgSharp.RegularAnalysis/Text/RegexInterpreter.IROptimize.cs index b1dc742c..8d548280 100644 --- a/StgSharp.RegularAnalysis/Text/RegexInterpreter.IROptimize.cs +++ b/StgSharp.RegularAnalysis/Text/RegexInterpreter.IROptimize.cs @@ -1,30 +1,27 @@ //----------------------------------------------------------------------- // ----------------------------------------------------------------------- -// file="RegexInterpreter.IROptimize.cs" +// file="RegexInterpreter.IROptimize" // Project: StgSharp // AuthorGroup: Nitload // Copyright (c) Nitload. All rights reserved. // -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, -// and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and -// this permission notice shall be included in all copies -// or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED “AS IS”, -// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -// ARISING FROM, OUT OF OR IN CONNECTION WITH -// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. // // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- @@ -44,13 +41,17 @@ namespace StgSharp.RegularAnalysis.Text { [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static RegexInfo ScanAndOptimizeIR(List baseIR, out List optIR) + internal static RegexInfo ScanAndOptimizeIR( + List baseIR, + out List optIR + ) { int index = 0; + List origin_ir = baseIR; Span origin_span = CollectionsMarshal.AsSpan(baseIR); List opt_ir = new(baseIR.Count); CapacityFixedList opt_window = new(8); - Span opt_win_sp = [ .. opt_window ]; + Span opt_win_sp = [.. opt_window]; RegexInfo info = new(); do { @@ -60,7 +61,23 @@ namespace StgSharp.RegularAnalysis.Text do { - if (true) { } + int result = 0; + if ((result = TryExpandPlus(opt_win_sp, opt_ir)) >= 0) + { + process_count++; + if (result > 0) + { + RegexCountComplexIR cc = Unsafe.As(opt_win_sp[0]); + Span sp = origin_span.Slice(index + 1, result); + TryExpandComplexPlus(cc.IsGreedy, sp, opt_ir); + process_count += result; + } + } else if ((result = TryOptDotCountCount(opt_win_sp, opt_ir)) >= 0) + { + process_count++; + } else if (TryFlattenCount(opt_win_sp, opt_ir)) { + process_count++; + } } while (false); index += process_count; @@ -69,67 +86,63 @@ namespace StgSharp.RegularAnalysis.Text return info; } - private void OptimizeRange(List origin, List target, int begin, int end) { } - - private static bool TryExpandComplexPlus(bool is_greedy, Span complex, List opt) + private static RegexInfo ScanAndOptimizeIR( + Span baseIR, + List opt_ir + ) { - int count = complex.Length; - opt.AddRange(complex); - opt.Add(new RegexCountComplexIR(0, -1, is_greedy, count)); - return true; + List originList = new(baseIR.Length); + CollectionsMarshal.SetCount(originList, baseIR.Length); + baseIR.CopyTo(CollectionsMarshal.AsSpan(originList)); + return ScanAndOptimizeIR(originList, out opt_ir); } - #region expand plus - - private static int TryExpandPlus(Span window, List opt) - { - /* a+ - * convert to - * aa* - */ - - RegexIR ir = window[0]; - if (ir is not IRegexCount { IsPlus: true } count) { - return -1; - } - bool is_greedy = count.IsGreedy; - string pattern; - switch (ir.Command & RegexIRCommand.Count) - { - case RegexIRCommand.Count_Complex: - RegexCountComplexIR complex = Unsafe.As(ir); - return complex.OperationCount; - case RegexIRCommand.Count_Seq: - RegexCountSeqIR seq = Unsafe.As(ir); - pattern = seq.Sequence; - opt.Add(new RegexMatchSeqIR(pattern)); - opt.Add(new RegexCountSeqIR(0, -1, is_greedy, pattern)); - return 0; - case RegexIRCommand.Count_Set: - RegexCountSeqIR set = Unsafe.As(ir); - pattern = set.Sequence; - opt.Add(new RegexMatchSeqIR(pattern)); - opt.Add(new RegexCountSeqIR(0, -1, is_greedy, pattern)); - return 0; - default: - return -1; - } - } - - #endregion - - private static bool TryFlattenCount(Span window, List opt) + private static bool TryFlattenCount( + Span window, + List opt + ) { + const int falttern_size = 32; RegexIR ir = window[0]; if (ir is not RegexCountSeqIR seq) { return false; } + string pattern = seq.Sequence; + int pattern_size = pattern.Length; + if (pattern_size > falttern_size) { + opt.Add(ir); + } + int min = seq.Min; + int max = seq.Max; + int min_expand = falttern_size / pattern_size; + min_expand = int.Min(min_expand, min); + string expand = string.Concat(Enumerable.Repeat(pattern, min_expand)); + int new_min = min / min_expand; + int new_rest = min % min_expand; + if (new_min == 1) + { + opt.Add(new RegexMatchSeqIR(pattern)); + } else + { + opt.Add(new RegexCountSeqIR(new_min, new_min, seq.IsGreedy, pattern)); + } + if (new_rest > 0) + { + string expand_tail = string.Concat(Enumerable.Repeat(pattern, new_rest)); + opt.Add(new RegexMatchSeqIR(expand_tail)); + } + int rest_count = max - min; + rest_count = int.Max(rest_count, -1); + opt.Add(new RegexCountSeqIR(0, rest_count, seq.IsGreedy, pattern)); return true; } #region dot count count - private static int TryOptDotCountCount(Span window, List opt) + private static int TryOptDotCountCount( + Span window, + List opt + ) { /* .* * * convert to @@ -146,15 +159,6 @@ namespace StgSharp.RegularAnalysis.Text { opt.Add(window[0]); return 0; - } else - { - /* - * .* ?a* is different - * it is something like - * FIND(a)?a* :.* - */ - RegexIRGenerator g = new(); - g.EmitTry(1); } return -1; } @@ -172,5 +176,78 @@ namespace StgSharp.RegularAnalysis.Text } + #region expand plus + + private static bool TryExpandComplexPlus( + bool is_greedy, + Span complex, + List opt + ) + { + int count = complex.Length; + List part_opt = new(count); + RegexInfo info = ScanAndOptimizeIR(complex, part_opt); + opt.AddRange(part_opt); + RegexCountComplexIR c_ir = new(0, -1, is_greedy, part_opt.Count) + { + IsFullyOptimized = true + }; + opt.Add(c_ir); + opt.AddRange(part_opt); + return true; + } + + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// Negative if cannot opt, 0 if match sucessfully, positive if meets an IRgexComplex + /// interface, need to call TryExpandComplexPlus + /// + private static int TryExpandPlus( + Span window, + List opt + ) + { + /* a+ + * convert to + * aa* + */ + + RegexIR ir = window[0]; + if (ir is not IRegexCount { IsPlus: true } count) { + return -1; + } + bool is_greedy = count.IsGreedy; + string pattern; + switch (ir.Command & RegexIRCommand.Count) + { + case RegexIRCommand.Count_Complex: + RegexCountComplexIR complex = Unsafe.As(ir); + return complex.CommandCount; + case RegexIRCommand.Count_Seq: + RegexCountSeqIR seq = Unsafe.As(ir); + pattern = seq.Sequence; + opt.Add(new RegexMatchSeqIR(pattern)); + opt.Add(new RegexCountSeqIR(0, -1, is_greedy, pattern)); + return 0; + case RegexIRCommand.Count_Set: + RegexCountSeqIR set = Unsafe.As(ir); + pattern = set.Sequence; + opt.Add(new RegexMatchSeqIR(pattern)); + opt.Add(new RegexCountSeqIR(0, -1, is_greedy, pattern)); + return 0; + default: + return -1; + } + } + + #endregion } } diff --git a/StgSharp.RegularAnalysis/Text/RegexInterpreter.SourceEmit.cs b/StgSharp.RegularAnalysis/Text/RegexInterpreter.SourceEmit.cs deleted file mode 100644 index efd7f319..00000000 --- a/StgSharp.RegularAnalysis/Text/RegexInterpreter.SourceEmit.cs +++ /dev/null @@ -1,37 +0,0 @@ -//----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -// file="RegexInterpreter.SourceEmit" -// Project: StgSharp -// AuthorGroup: Nitload -// Copyright (c) Nitload. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -// ----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace StgSharp.RegularAnalysis.Text -{ - public partial class RegexInterpreter { } -}