prefix replaces CONDITION

This commit is contained in:
Youmu Liu
2026-07-06 18:19:32 +08:00
parent cd7a52bd60
commit b053567eb7
8 changed files with 1113 additions and 1105 deletions
+5
View File
@@ -3,3 +3,8 @@
[2026-05-13 11:33:26.040] [Info] Program StgSharpDebug, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null on GF-CHEN-LIU Started. [2026-05-13 11:33:26.040] [Info] Program StgSharpDebug, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null on GF-CHEN-LIU Started.
[2026-07-06 16:49:29.987] [Info] Program StgSharpDebug, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null on GF-CHEN-LIU Started.
@@ -0,0 +1,449 @@
//-----------------------------------------------------------------------
// -----------------------------------------------------------------------
// file="RegexAnalyzerFrontEnd.PrefixEmit"
// 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.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace StgSharp.RegularAnalysis.Text
{
public static partial class RegexAnalyzerFrontEnd
{
internal static List<RegexIR> EmitPrefix(
List<RegexIR> irList
)
{
List<RegexIR> origin = irList;
List<RegexIR> result = new(origin.Count);
Span<RegexIR> origin_span = CollectionsMarshal.AsSpan(origin);
int region_name = 1;
EmitPrefix(origin_span, result, 0, 0);
FixLineObservation(result);
return result;
void EmitPrefix(
ReadOnlySpan<RegexIR> region,
List<RegexIR> result,
int currentRegion,
int lineBase
)
{
ReadOnlySpan<RegexIR> emit_window;
int index = 0;
while (index < region.Length)
{
emit_window = region[index..];
int emitResult;
if ((emitResult = TryEmitGroupFindPack(emit_window, result, currentRegion, lineBase)) > 0)
{
index += emitResult;
} else if ((emitResult = TryEmitTryGroupTail(emit_window, result, currentRegion, lineBase)) > 0)
{
index += emitResult;
} else if ((emitResult = TryEmitAltChain(emit_window, result, currentRegion, lineBase)) > 0)
{
index += emitResult;
} else if ((emitResult = TryEmitAltSuccessTail(emit_window, result, currentRegion, lineBase)) > 0)
{
index += emitResult;
} else if ((emitResult = TryEmitAltFailTail(emit_window, result, currentRegion, lineBase)) > 0)
{
index += emitResult;
} else if ((emitResult = TryEmitTryIR(emit_window, result, currentRegion, lineBase)) > 0)
{
index += emitResult;
} else
{
result.Add(CloneIR(emit_window[0], currentRegion));
index++;
}
}
}
int TryEmitTryGroupTail(
ReadOnlySpan<RegexIR> origin,
List<RegexIR> result,
int currentRegion,
int lineBase
)
{
if (origin.Length < 5 || origin[0] is not RegexTryIR _try) {
return -1;
}
int tailOffset = _try.CommandCount + 1;
if (origin.Length < tailOffset + 3 ||
origin[tailOffset] is not RegexConditionIR { SuccessCase: 2, FailCase: 1 } condition ||
origin[tailOffset + 1] is not RegexPopIR { IsSuccess: false } pop ||
origin[tailOffset + 2] is not RegexPackIR { Condition: true } pack) {
return -1;
}
int tryOutputIndex = result.Count;
int emitCount = TryEmitTryIR(
origin,
result,
currentRegion,
lineBase,
foldSingleInstructionTry: false);
if (emitCount <= 0 || result[tryOutputIndex] is not RegexTryIR emittedTry) {
return -1;
}
_ = condition;
int regionId = emittedTry.Prefix.WorkingRegion;
RegexIR prefixedPop = CloneIR(pop, regionId);
ApplyPrefix(
prefixedPop,
regionId,
RegexIRPrefixMask.Prev_Fail | RegexIRPrefixMask.Observe_Region,
regionId);
RegexIR prefixedPack = CloneIR(pack, regionId);
ApplyPrefix(
prefixedPack,
regionId,
RegexIRPrefixMask.Prev_Success | RegexIRPrefixMask.Observe_Region,
regionId);
result.Add(prefixedPop);
result.Add(prefixedPack);
return emitCount + 3;
}
int TryEmitAltChain(
ReadOnlySpan<RegexIR> origin,
List<RegexIR> result,
int currentRegion,
int lineBase
)
{
if (origin.Length < 3 ||
origin[0] is not RegexConditionIR { SuccessCase: 1, FailCase: 2 } ||
origin[1] is not RegexPopIR { IsSuccess: true } ||
origin[2] is not RegexTryIR) {
return -1;
}
int observeRegion = currentRegion;
RegexIRPrefixMask observeMask = RegexIRPrefixMask.Observe_Region;
int observeSource = currentRegion;
if (result.Count > 0)
{
RegexIR previous = result[^1];
observeRegion = GetObservedRegion(previous, currentRegion);
GetObservation(previous, result, lineBase, currentRegion, out observeMask, out observeSource);
ApplyPrefix(previous, observeRegion, RegexIRPrefixMask.Pop_Success, observeRegion);
}
RegexIRPrefixMask mask = RegexIRPrefixMask.Prev_Fail | observeMask;
int emit_count = TryEmitTryIR(origin[2..], result, currentRegion, lineBase, mask, observeSource, observeRegion);
return emit_count < 0 ? -1 : emit_count + 2;
}
int TryEmitAltSuccessTail(
ReadOnlySpan<RegexIR> origin,
List<RegexIR> result,
int currentRegion,
int lineBase
)
{
if (origin.Length < 2 ||
origin[0] is not RegexConditionIR { SuccessCase: 1, FailCase: 2 } ||
origin[1] is not RegexPopIR { IsSuccess: true } ||
result.Count == 0) {
return -1;
}
RegexIR previous = result[^1];
int observeRegion = GetObservedRegion(previous, currentRegion);
ApplyPrefix(previous, observeRegion, RegexIRPrefixMask.Pop_Success, observeRegion);
return 2;
}
int TryEmitAltFailTail(
ReadOnlySpan<RegexIR> origin,
List<RegexIR> result,
int currentRegion,
int lineBase
)
{
if (origin.Length < 1 ||
origin[0] is not RegexPopIR { IsSuccess: false } pop ||
result.Count == 0) {
return -1;
}
RegexIR previous = result[^1];
if ((previous.Prefix.Mask & RegexIRPrefixMask.Pop_Success) == 0) {
return -1;
}
GetObservation(
previous,
result,
lineBase,
currentRegion,
out RegexIRPrefixMask observeMask,
out int observeSource);
RegexIR prefixedPop = CloneIR(pop, currentRegion);
ApplyPrefix(
prefixedPop,
currentRegion,
RegexIRPrefixMask.Prev_Fail | observeMask,
observeSource);
result.Add(prefixedPop);
return 1;
}
// convert TRY into region
int TryEmitTryIR(
ReadOnlySpan<RegexIR> origin,
List<RegexIR> result,
int currentRegion,
int lineBase,
RegexIRPrefixMask mask = 0,
int observeSource = 0,
int reuseRegion = 0,
bool foldSingleInstructionTry = true
)
{
if (origin.Length == 0 || origin[0] is not RegexTryIR _try) {
return -1;
}
int commandCount = _try.CommandCount;
if (origin.Length < commandCount + 1) {
return -1;
}
int regionId = reuseRegion == 0 ? region_name : reuseRegion;
if (reuseRegion == 0) {
region_name++;
}
if (foldSingleInstructionTry &&
commandCount == 1 &&
IsFoldableSingleTryInstruction(origin[1])) {
RegexIR folded = CloneIR(origin[1], regionId);
int foldedObserveSource =
(mask & RegexIRPrefixMask.ObserveMethod) != 0 ?
observeSource :
_try.Prefix.ObserveSource;
folded.Prefix = new RegexIRPrefix(
regionId,
folded.Prefix.Mask | _try.Prefix.Mask | mask,
foldedObserveSource);
result.Add(folded);
return commandCount + 1;
}
List<RegexIR> sub_ir = new(commandCount);
ReadOnlySpan<RegexIR> try_region = origin.Slice(1, commandCount);
EmitPrefix(try_region, sub_ir, regionId, lineBase + result.Count + 1);
RegexTryIR newTry = new(sub_ir.Count)
{
IsFullyOptimized = _try.IsFullyOptimized,
Prefix = new RegexIRPrefix(regionId, _try.Prefix.Mask | mask, observeSource)
};
result.Add(newTry);
result.AddRange(sub_ir);
return commandCount + 1;
}
int TryEmitGroupFindPack(
ReadOnlySpan<RegexIR> origin,
List<RegexIR> result,
int currentRegion,
int lineBase
)
{
if (origin.Length < 5 ||
origin[0] is not RegexTryIR { CommandCount: 1 } _try ||
origin[1] is not RegexFindComplexIR find ||
origin[2] is not RegexConditionIR { SuccessCase: 2, FailCase: 1 } ||
origin[3] is not RegexPopIR { IsSuccess: false } ||
origin[4] is not RegexPackIR { Condition: true } pack) {
return -1;
}
int regionId = region_name;
region_name++;
RegexIRPrefixMask findMask = find.Prefix.Mask | _try.Prefix.Mask;
int findObserveSource =
(find.Prefix.Mask & RegexIRPrefixMask.ObserveMethod) != 0 ?
find.Prefix.ObserveSource :
_try.Prefix.ObserveSource;
RegexFindComplexIR newFind = new(find.IsNearest, find.CommandCount)
{
IsFullyOptimized = find.IsFullyOptimized,
Prefix = new RegexIRPrefix(regionId, findMask, findObserveSource)
};
RegexPackIR newPack = new(pack.Condition, pack.GroupName)
{
Prefix = new RegexIRPrefix(
regionId,
pack.Prefix.Mask | RegexIRPrefixMask.Prev_Success | RegexIRPrefixMask.Observe_Line,
-1)
};
result.Add(newFind);
result.Add(newPack);
return 5;
}
static int GetObservedRegion(
RegexIR ir,
int currentRegion
)
{
return ir.Prefix.WorkingRegion == 0 ? currentRegion : ir.Prefix.WorkingRegion;
}
static void GetObservation(
RegexIR ir,
List<RegexIR> result,
int lineBase,
int currentRegion,
out RegexIRPrefixMask observeMask,
out int observeSource
)
{
if (IsLineObservable(ir))
{
observeMask = RegexIRPrefixMask.Observe_Line;
observeSource = -1;
} else
{
observeMask = RegexIRPrefixMask.Observe_Region;
observeSource = GetObservedRegion(ir, currentRegion);
}
}
static void FixLineObservation(
List<RegexIR> result
)
{
for (int i = 0; i < result.Count; i++)
{
RegexIRPrefix prefix = result[i].Prefix;
if ((prefix.Mask & RegexIRPrefixMask.Observe_Line) == 0) {
continue;
}
result[i].Prefix = new RegexIRPrefix(
prefix.WorkingRegion,
prefix.Mask,
i - 1);
}
}
static bool IsFoldableSingleTryInstruction(
RegexIR ir
)
{
return IsLineObservable(ir) &&
(ir.Prefix.Mask & RegexIRPrefixMask.ExeCondition) == 0 &&
(ir.Prefix.Mask & RegexIRPrefixMask.ObserveMethod) == 0;
}
static bool IsLineObservable(
RegexIR ir
)
{
return ir is RegexMatchSeqIR or
RegexMatchSetIR or
RegexCountSeqIR or
RegexCountSetIR or
RegexFindSeqIR or
RegexFindComplexIR;
}
static void ApplyPrefix(
RegexIR ir,
int workingRegion,
RegexIRPrefixMask mask,
int observeSource
)
{
ir.Prefix = new RegexIRPrefix(
workingRegion,
ir.Prefix.Mask | mask,
observeSource);
}
static RegexIR CloneIR(
RegexIR ir,
int currentRegion
)
{
RegexIR clone = ir switch
{
RegexFindComplexIR find => new RegexFindComplexIR(find.IsNearest, find.CommandCount)
{
IsFullyOptimized = find.IsFullyOptimized
},
RegexFindSeqIR find => new RegexFindSeqIR(find.Pattern, find.IsFirst),
RegexMatchSeqIR match => new RegexMatchSeqIR(match.Pattern),
RegexMatchSetIR match => new RegexMatchSetIR(match.Charset),
RegexConditionIR condition => new RegexConditionIR(condition.SuccessCase, condition.FailCase),
RegexPackIR pack => new RegexPackIR(pack.Condition, pack.GroupName),
RegexCountComplexIR count => new RegexCountComplexIR(count.Min, count.Max, count.IsGreedy, count.CommandCount)
{
IsFullyOptimized = count.IsFullyOptimized
},
RegexCountSeqIR count => new RegexCountSeqIR(count.Min, count.Max, count.IsGreedy, count.Sequence),
RegexCountSetIR count => new RegexCountSetIR(count.Min, count.Max, count.IsGreedy, count.CharSet),
RegexTryIR tryIR => new RegexTryIR(tryIR.CommandCount)
{
IsFullyOptimized = tryIR.IsFullyOptimized
},
RegexPopIR pop => new RegexPopIR(pop.IsSuccess),
_ => throw new NotSupportedException($"Unsupported IR type: {ir.GetType().Name}")
};
clone.Prefix = new RegexIRPrefix(
ir.Prefix.WorkingRegion == 0 ? currentRegion : ir.Prefix.WorkingRegion,
ir.Prefix.Mask,
ir.Prefix.ObserveSource);
return clone;
}
}
}
}
@@ -1,6 +1,6 @@
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// file="RegexAnalyzer" // file="RegexAnalyzerFrontEnd"
// Project: StgSharp // Project: StgSharp
// AuthorGroup: Nitload // AuthorGroup: Nitload
// Copyright (c) Nitload. All rights reserved. // Copyright (c) Nitload. All rights reserved.
@@ -29,6 +29,7 @@ using StgSharp.RegularAnalysis.Abstraction;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Linq.Expressions;
using System.Reflection.Emit; using System.Reflection.Emit;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text; using System.Text;
@@ -76,18 +77,35 @@ namespace StgSharp.RegularAnalysis.Text
{ {
// RegexAnalyzer interpreter = new(); // RegexAnalyzer interpreter = new();
// interpreter._source = regex; // interpreter._source = regex;
AbstractSyntaxTree<RegexAstNode, RegexElementLabel> tree;
try try
{ {
AbstractSyntaxTree<RegexAstNode, RegexElementLabel> tree = GenerateAST(regex); tree = GenerateAST(regex);
OptimizeTree(tree); OptimizeTree(tree);
List<RegexIR> base_ir = GenerateIR(tree);
ScanAndOptimizeIR(base_ir, out List<RegexIR> opt_ir);
return new TextRegexSource(regex, tree, base_ir, opt_ir);
} }
catch (Exception ex) catch (Exception ex)
{ {
return new TextRegexSource(regex, null, null, null, ex); return new TextRegexSource(regex, null, null, null, ex);
} }
List<RegexIR> base_ir;
try
{
base_ir = GenerateIR(tree);
}
catch (Exception ex)
{
return new TextRegexSource(regex, tree, null, null, ex);
}
try
{
ScanAndOptimizeIR(base_ir, out List<RegexIR> opt_ir);
List<RegexIR> prefix_ir = EmitPrefix(opt_ir);
return new TextRegexSource(regex, tree, base_ir, prefix_ir);
}
catch (Exception ex)
{
return new TextRegexSource(regex, tree, base_ir, null, ex);
}
} }
} }
@@ -0,0 +1,79 @@
//-----------------------------------------------------------------------
// -----------------------------------------------------------------------
// file="RegexIR.Prefix"
// 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
{
internal enum RegexIRPrefixMask
{
Prev_Success = 1 << 0,
Prev_Fail = 1 << 1,
Always = 1 << 2,
ExeCondition = Prev_Fail | Prev_Success | Always,
Pop_Fail = 1 << 3,
Pop_Success = 1 << 4,
PopCondition = Pop_Success | Pop_Fail,
Observe_Line = 1 << 5,
Observe_Region = 1 << 6,
ObserveMethod = Observe_Line | Observe_Region
}
internal record struct RegexIRPrefix(
int WorkingRegion,
RegexIRPrefixMask Mask,
int ObserveSource
)
{
public override string ToString()
{
return $"{WorkingRegion:D4}, {DisplayMask(Mask , RegexIRPrefixMask.ExeCondition):D1}, {DisplayMask(Mask , RegexIRPrefixMask.PopCondition):D1}, {DisplayMask(Mask ,RegexIRPrefixMask.ObserveMethod):D1}, {ObserveSource:D4}";
}
private int DisplayMask(
RegexIRPrefixMask mask,
RegexIRPrefixMask range
)
{
return range switch
{
RegexIRPrefixMask.ExeCondition => (int)(mask & RegexIRPrefixMask.ExeCondition) >> 0,
RegexIRPrefixMask.PopCondition => (int)(mask & RegexIRPrefixMask.PopCondition) >> 3,
RegexIRPrefixMask.ObserveMethod => (int)(mask & RegexIRPrefixMask.ObserveMethod) >> 5,
_ => throw new ArgumentOutOfRangeException(nameof(range), range, null)
};
}
}
}
+100 -47
View File
@@ -25,6 +25,7 @@
// //
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -55,19 +56,6 @@ namespace StgSharp.RegularAnalysis.Text
} }
internal enum RegexIRPrefix
{
Prev_Success = 1 << 0,
Prev_Fail = 1 << 1,
Always = 1 << 2,
ExeCondition = Prev_Fail | Prev_Success | Always,
Pop_Fail = 1 << 3,
Pop_Success = 1 << 4,
Pop_Condition = Pop_Success | Pop_Fail,
}
internal interface IRegexComplex internal interface IRegexComplex
{ {
@@ -92,7 +80,10 @@ namespace StgSharp.RegularAnalysis.Text
} }
internal sealed class RegexFindComplexIR(bool nearest, int count) : RegexIR, IRegexComplex internal sealed class RegexFindComplexIR(
bool nearest,
int count
) : RegexIR, IRegexComplex
{ {
public bool IsFullyOptimized { get; set; } public bool IsFullyOptimized { get; set; }
@@ -103,9 +94,11 @@ namespace StgSharp.RegularAnalysis.Text
internal override RegexIRCommand Command => RegexIRCommand.Find_Complex; internal override RegexIRCommand Command => RegexIRCommand.Find_Complex;
internal override string AsCommand(int lineNum) protected override string AsCommand(
)
{ {
return $"[{lineNum}]\t FIND_COMPLEX {(IsNearest ? "NEAREST" : "FURTHEST")} COUNT: {CommandCount}"; return $"FIND_COMPLEX {(IsNearest ? "NEAREST" : "FURTHEST")} COUNT: {CommandCount}";
} }
} }
@@ -113,13 +106,25 @@ namespace StgSharp.RegularAnalysis.Text
internal abstract class RegexIR internal abstract class RegexIR
{ {
public RegexIRPrefix Prefix { get; set; }
internal abstract RegexIRCommand Command { get; } internal abstract RegexIRCommand Command { get; }
internal abstract string AsCommand(int lineNum); internal string AsCommand(
int lineNum
)
{
return $"[{lineNum}]\t{Prefix}\t{AsCommand()}";
}
protected abstract string AsCommand();
} }
internal sealed class RegexFindSeqIR(string pattern, bool isFirst) : RegexIR internal sealed class RegexFindSeqIR(
string pattern,
bool isFirst
) : RegexIR
{ {
public bool IsFirst { get; } = isFirst; public bool IsFirst { get; } = isFirst;
@@ -128,9 +133,10 @@ namespace StgSharp.RegularAnalysis.Text
internal override RegexIRCommand Command => RegexIRCommand.Find_Seq; internal override RegexIRCommand Command => RegexIRCommand.Find_Seq;
internal override string AsCommand(int lineNum) protected override string AsCommand(
)
{ {
return $"[{lineNum}]\t FIND_SEQ \"{(string.IsNullOrEmpty(Pattern) ? "<EPSILON>" : Pattern)}\""; return $"FIND_SEQ \"{(string.IsNullOrEmpty(Pattern) ? "<EPSILON>" : Pattern)}\"";
} }
} }
@@ -138,35 +144,46 @@ namespace StgSharp.RegularAnalysis.Text
/// <summary> /// <summary>
/// Searches for a certain string pattern or charset from current position. /// Searches for a certain string pattern or charset from current position.
/// </summary> /// </summary>
internal sealed class RegexMatchSeqIR(string pattern) : RegexIR internal sealed class RegexMatchSeqIR(
string pattern
) : RegexIR
{ {
public string Pattern { get; } = pattern; public string Pattern { get; } = pattern;
internal override RegexIRCommand Command => RegexIRCommand.Match_Seq; internal override RegexIRCommand Command => RegexIRCommand.Match_Seq;
internal override string AsCommand(int lineNum) protected override string AsCommand(
)
{ {
return $"[{lineNum}]\t MATCH_SEQ \"{(string.IsNullOrEmpty(Pattern) ? "<EPSILON>" : Pattern)}\""; return $"MATCH_SEQ \"{(string.IsNullOrEmpty(Pattern) ? "<EPSILON>" : Pattern)}\"";
} }
} }
internal sealed class RegexMatchSetIR(string charset) : RegexIR internal sealed class RegexMatchSetIR(
string charset
) : RegexIR
{ {
public string Charset { get; } = charset; public string Charset { get; } = charset;
internal override RegexIRCommand Command => RegexIRCommand.Match_Set; internal override RegexIRCommand Command => RegexIRCommand.Match_Set;
internal override string AsCommand(int lineNum) protected override string AsCommand(
)
{ {
return $"[{lineNum}]\t MATCH_SET \"{Charset}\""; return $"MATCH_SET \"{Charset}\"";
} }
} }
internal sealed class RegexConditionIR(int success, int fail) : RegexIR internal sealed class RegexConditionIR(
int success,
int fail
) : RegexIR
{ {
public int SuccessCase { get; } = success; public int SuccessCase { get; } = success;
@@ -175,14 +192,19 @@ namespace StgSharp.RegularAnalysis.Text
internal override RegexIRCommand Command => RegexIRCommand.Condition; internal override RegexIRCommand Command => RegexIRCommand.Condition;
internal override string AsCommand(int lineNum) protected override string AsCommand(
)
{ {
return $"[{lineNum}]\t CONDITION SUCCESS: {SuccessCase} FAIL: {FailCase}"; return $"CONDITION SUCCESS: {SuccessCase} FAIL: {FailCase}";
} }
} }
internal sealed class RegexPackIR(bool condition, string name = "") : RegexIR internal sealed class RegexPackIR(
bool condition,
string name = ""
) : RegexIR
{ {
public bool Condition { get; } = condition; public bool Condition { get; } = condition;
@@ -191,14 +213,21 @@ namespace StgSharp.RegularAnalysis.Text
internal override RegexIRCommand Command => RegexIRCommand.Pack; internal override RegexIRCommand Command => RegexIRCommand.Pack;
internal override string AsCommand(int lineNum) protected override string AsCommand(
)
{ {
return $"[{lineNum}]\t PACK {(Condition ? "SUCCESS" : "FAIL")} GROUP: \"{GroupName}\""; return $"PACK {(Condition ? "SUCCESS" : "FAIL")} GROUP: \"{GroupName}\"";
} }
} }
internal sealed class RegexCountComplexIR(int min, int max, bool isGreedy, int operation) : RegexIR, IRegexCount, IRegexComplex internal sealed class RegexCountComplexIR(
int min,
int max,
bool isGreedy,
int operation
) : RegexIR, IRegexCount, IRegexComplex
{ {
public bool IsGreedy { get; } = isGreedy; public bool IsGreedy { get; } = isGreedy;
@@ -217,14 +246,21 @@ namespace StgSharp.RegularAnalysis.Text
internal override RegexIRCommand Command { get; } = RegexIRCommand.Count_Complex; internal override RegexIRCommand Command { get; } = RegexIRCommand.Count_Complex;
internal override string AsCommand(int lineNum) protected override string AsCommand(
)
{ {
return $"[{lineNum}]\t COUNT {(IsGreedy ? "GREEDY" : "NON_GREEDY")} MIN: {Min} MAX: {Max} OPERATION: {CommandCount}"; return $"COUNT {(IsGreedy ? "GREEDY" : "NON_GREEDY")} MIN: {Min} MAX: {Max} OPERATION: {CommandCount}";
} }
} }
internal sealed class RegexCountSeqIR(int min, int max, bool isGreedy, string seq) : RegexIR, IRegexCount internal sealed class RegexCountSeqIR(
int min,
int max,
bool isGreedy,
string seq
) : RegexIR, IRegexCount
{ {
public bool IsGreedy { get; } = isGreedy; public bool IsGreedy { get; } = isGreedy;
@@ -241,14 +277,21 @@ namespace StgSharp.RegularAnalysis.Text
internal override RegexIRCommand Command { get; } = RegexIRCommand.Count_Seq; internal override RegexIRCommand Command { get; } = RegexIRCommand.Count_Seq;
internal override string AsCommand(int lineNum) protected override string AsCommand(
)
{ {
return $"[{lineNum}]\t COUNT_SEQ {(IsGreedy ? "GREEDY" : "NON_GREEDY")} MIN: {Min} MAX: {Max} SEQ: \"{Sequence}\""; return $"COUNT_SEQ {(IsGreedy ? "GREEDY" : "NON_GREEDY")} MIN: {Min} MAX: {Max} SEQ: \"{Sequence}\"";
} }
} }
internal sealed class RegexCountSetIR(int min, int max, bool isGreedy, string set) : RegexIR, IRegexCount internal sealed class RegexCountSetIR(
int min,
int max,
bool isGreedy,
string set
) : RegexIR, IRegexCount
{ {
public bool IsGreedy { get; } = isGreedy; public bool IsGreedy { get; } = isGreedy;
@@ -267,14 +310,18 @@ namespace StgSharp.RegularAnalysis.Text
internal override RegexIRCommand Command => RegexIRCommand.Count_Set; internal override RegexIRCommand Command => RegexIRCommand.Count_Set;
internal override string AsCommand(int lineNum) protected override string AsCommand(
)
{ {
return $"[{lineNum}]\t COUNT_SET {(IsGreedy ? "GREEDY" : "NON_GREEDY")} MIN: {Min} MAX: {Max} SET: \"{CharSet}\""; return $"COUNT_SET {(IsGreedy ? "GREEDY" : "NON_GREEDY")} MIN: {Min} MAX: {Max} SET: \"{CharSet}\"";
} }
} }
internal sealed class RegexTryIR(int count) : RegexIR, IRegexComplex internal sealed class RegexTryIR(
int count
) : RegexIR, IRegexComplex
{ {
public bool IsFullyOptimized { get; set; } public bool IsFullyOptimized { get; set; }
@@ -283,23 +330,29 @@ namespace StgSharp.RegularAnalysis.Text
internal override RegexIRCommand Command => RegexIRCommand.Try; internal override RegexIRCommand Command => RegexIRCommand.Try;
internal override string AsCommand(int lineNum) protected override string AsCommand(
)
{ {
return $"[{lineNum}]\t TRY {CommandCount}"; return $"TRY {CommandCount}";
} }
} }
internal sealed class RegexPopIR(bool isSuccess) : RegexIR internal sealed class RegexPopIR(
bool isSuccess
) : RegexIR
{ {
public bool IsSuccess { get; } = isSuccess; public bool IsSuccess { get; } = isSuccess;
internal override RegexIRCommand Command => RegexIRCommand.Pop; internal override RegexIRCommand Command => RegexIRCommand.Pop;
internal override string AsCommand(int lineNum) protected override string AsCommand(
)
{ {
return $"[{lineNum}]\t POP {(IsSuccess ? "SUCCESS" : "FAIL")}"; return $"POP {(IsSuccess ? "SUCCESS" : "FAIL")}";
} }
} }
+4 -3
View File
@@ -41,13 +41,13 @@ namespace StgSharp
private static string[] regexSource = [ private static string[] regexSource = [
@"[.]*", @"[.]*",
/* /**/
@"http|https|ftp|ftps", @"http|https|ftp|ftps",
@"abc[0-9]x|abc[0-9]y|abd[0-9]x|abd[0-9]y|xyz", @"abc[0-9]x|abc[0-9]y|abd[0-9]x|abd[0-9]y|xyz",
@"get_name|get_value|get_type|set_name|set_value|set_type", @"get_name|get_value|get_type|set_name|set_value|set_type",
@"helix|hello|help|hero|hers|her", @"helix|hello|help|hero|hers|her",
@"a*.[abc]*(abcd|a(bc)c)+(?<name>.*)234" @"a*.[abc]*(?<a>abcd|a(bc)c)(?<name>.*)234"
/**/ /**/
]; ];
public static void Run() public static void Run()
@@ -75,6 +75,7 @@ namespace StgSharp
Console.WriteLine(opt_ir[i].AsCommand(i)); Console.WriteLine(opt_ir[i].AsCommand(i));
} }
Console.WriteLine(); Console.WriteLine();
Console.WriteLine(interpreterSource.AnalyseException);
Console.WriteLine(); Console.WriteLine();
Console.WriteLine(); Console.WriteLine();
} }
File diff suppressed because it is too large Load Diff
+453
View File
@@ -0,0 +1,453 @@
result of "[.]*"
| * COUNT
|| [.] UNIT_SET
-----IR-----
[0] 0000,0,0,0,0000 COUNT_SET GREEDY MIN: 0 MAX: -1 SET: "[.]"
-----Optimized once-----
[0] 0000,0,0,0,0000 COUNT_SET GREEDY MIN: 0 MAX: -1 SET: "[.]"
result of "http|https|ftp|ftps"
| ALT
|| CONCAT
||| http UNIT_SPAN
||| ALT
|||| UNIT
|||| s UNIT
|| CONCAT
||| ftp UNIT_SPAN
||| ALT
|||| UNIT
|||| s UNIT
-----IR-----
[0] 0000,0,0,0,0000 TRY 10
[1] 0000,0,0,0,0000 MATCH_SEQ "http"
[2] 0000,0,0,0,0000 TRY 1
[3] 0000,0,0,0,0000 MATCH_SEQ "<EPSILON>"
[4] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[5] 0000,0,0,0,0000 POP SUCCESS
[6] 0000,0,0,0,0000 TRY 1
[7] 0000,0,0,0,0000 MATCH_SEQ "s"
[8] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[9] 0000,0,0,0,0000 POP SUCCESS
[10] 0000,0,0,0,0000 POP FAIL
[11] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[12] 0000,0,0,0,0000 POP SUCCESS
[13] 0000,0,0,0,0000 TRY 10
[14] 0000,0,0,0,0000 MATCH_SEQ "ftp"
[15] 0000,0,0,0,0000 TRY 1
[16] 0000,0,0,0,0000 MATCH_SEQ "<EPSILON>"
[17] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[18] 0000,0,0,0,0000 POP SUCCESS
[19] 0000,0,0,0,0000 TRY 1
[20] 0000,0,0,0,0000 MATCH_SEQ "s"
[21] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[22] 0000,0,0,0,0000 POP SUCCESS
[23] 0000,0,0,0,0000 POP FAIL
[24] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[25] 0000,0,0,0,0000 POP SUCCESS
[26] 0000,0,0,0,0000 POP FAIL
-----Optimized once-----
[0] 0000,0,0,0,0000 TRY 10
[1] 0000,0,0,0,0000 MATCH_SEQ "http"
[2] 0000,0,0,0,0000 TRY 1
[3] 0000,0,0,0,0000 MATCH_SEQ "<EPSILON>"
[4] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[5] 0000,0,0,0,0000 POP SUCCESS
[6] 0000,0,0,0,0000 TRY 1
[7] 0000,0,0,0,0000 MATCH_SEQ "s"
[8] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[9] 0000,0,0,0,0000 POP SUCCESS
[10] 0000,0,0,0,0000 POP FAIL
[11] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[12] 0000,0,0,0,0000 POP SUCCESS
[13] 0000,0,0,0,0000 TRY 10
[14] 0000,0,0,0,0000 MATCH_SEQ "ftp"
[15] 0000,0,0,0,0000 TRY 1
[16] 0000,0,0,0,0000 MATCH_SEQ "<EPSILON>"
[17] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[18] 0000,0,0,0,0000 POP SUCCESS
[19] 0000,0,0,0,0000 TRY 1
[20] 0000,0,0,0,0000 MATCH_SEQ "s"
[21] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[22] 0000,0,0,0,0000 POP SUCCESS
[23] 0000,0,0,0,0000 POP FAIL
[24] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[25] 0000,0,0,0,0000 POP SUCCESS
[26] 0000,0,0,0,0000 POP FAIL
result of "abc[0-9]x|abc[0-9]y|abd[0-9]x|abd[0-9]y|xyz"
| ALT
|| CONCAT
||| ab UNIT_SPAN
||| ALT
|||| CONCAT
||||| c UNIT
||||| CONCAT
|||||| [0-9] UNIT_SET
|||||| ALT
||||||| x UNIT
||||||| y UNIT
|||| CONCAT
||||| d UNIT
||||| CONCAT
|||||| [0-9] UNIT_SET
|||||| ALT
||||||| x UNIT
||||||| y UNIT
|| CONCAT
||| xyz UNIT_SPAN
-----IR-----
[0] 0000,0,0,0,0000 TRY 30
[1] 0000,0,0,0,0000 MATCH_SEQ "ab"
[2] 0000,0,0,0,0000 TRY 11
[3] 0000,0,0,0,0000 MATCH_SEQ "c"
[4] 0000,0,0,0,0000 MATCH_SET "[0-9]"
[5] 0000,0,0,0,0000 TRY 1
[6] 0000,0,0,0,0000 MATCH_SEQ "x"
[7] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[8] 0000,0,0,0,0000 POP SUCCESS
[9] 0000,0,0,0,0000 TRY 1
[10] 0000,0,0,0,0000 MATCH_SEQ "y"
[11] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[12] 0000,0,0,0,0000 POP SUCCESS
[13] 0000,0,0,0,0000 POP FAIL
[14] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[15] 0000,0,0,0,0000 POP SUCCESS
[16] 0000,0,0,0,0000 TRY 11
[17] 0000,0,0,0,0000 MATCH_SEQ "d"
[18] 0000,0,0,0,0000 MATCH_SET "[0-9]"
[19] 0000,0,0,0,0000 TRY 1
[20] 0000,0,0,0,0000 MATCH_SEQ "x"
[21] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[22] 0000,0,0,0,0000 POP SUCCESS
[23] 0000,0,0,0,0000 TRY 1
[24] 0000,0,0,0,0000 MATCH_SEQ "y"
[25] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[26] 0000,0,0,0,0000 POP SUCCESS
[27] 0000,0,0,0,0000 POP FAIL
[28] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[29] 0000,0,0,0,0000 POP SUCCESS
[30] 0000,0,0,0,0000 POP FAIL
[31] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[32] 0000,0,0,0,0000 POP SUCCESS
[33] 0000,0,0,0,0000 TRY 1
[34] 0000,0,0,0,0000 MATCH_SEQ "xyz"
[35] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[36] 0000,0,0,0,0000 POP SUCCESS
[37] 0000,0,0,0,0000 POP FAIL
-----Optimized once-----
[0] 0000,0,0,0,0000 TRY 30
[1] 0000,0,0,0,0000 MATCH_SEQ "ab"
[2] 0000,0,0,0,0000 TRY 11
[3] 0000,0,0,0,0000 MATCH_SEQ "c"
[4] 0000,0,0,0,0000 MATCH_SET "[0-9]"
[5] 0000,0,0,0,0000 TRY 1
[6] 0000,0,0,0,0000 MATCH_SEQ "x"
[7] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[8] 0000,0,0,0,0000 POP SUCCESS
[9] 0000,0,0,0,0000 TRY 1
[10] 0000,0,0,0,0000 MATCH_SEQ "y"
[11] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[12] 0000,0,0,0,0000 POP SUCCESS
[13] 0000,0,0,0,0000 POP FAIL
[14] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[15] 0000,0,0,0,0000 POP SUCCESS
[16] 0000,0,0,0,0000 TRY 11
[17] 0000,0,0,0,0000 MATCH_SEQ "d"
[18] 0000,0,0,0,0000 MATCH_SET "[0-9]"
[19] 0000,0,0,0,0000 TRY 1
[20] 0000,0,0,0,0000 MATCH_SEQ "x"
[21] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[22] 0000,0,0,0,0000 POP SUCCESS
[23] 0000,0,0,0,0000 TRY 1
[24] 0000,0,0,0,0000 MATCH_SEQ "y"
[25] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[26] 0000,0,0,0,0000 POP SUCCESS
[27] 0000,0,0,0,0000 POP FAIL
[28] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[29] 0000,0,0,0,0000 POP SUCCESS
[30] 0000,0,0,0,0000 POP FAIL
[31] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[32] 0000,0,0,0,0000 POP SUCCESS
[33] 0000,0,0,0,0000 TRY 1
[34] 0000,0,0,0,0000 MATCH_SEQ "xyz"
[35] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[36] 0000,0,0,0,0000 POP SUCCESS
[37] 0000,0,0,0,0000 POP FAIL
result of "get_name|get_value|get_type|set_name|set_value|set_type"
| ALT
|| CONCAT
||| get_ UNIT_SPAN
||| ALT
|||| CONCAT
||||| name UNIT_SPAN
|||| CONCAT
||||| value UNIT_SPAN
|||| CONCAT
||||| type UNIT_SPAN
|| CONCAT
||| set_ UNIT_SPAN
||| ALT
|||| CONCAT
||||| name UNIT_SPAN
|||| CONCAT
||||| value UNIT_SPAN
|||| CONCAT
||||| type UNIT_SPAN
-----IR-----
[0] 0000,0,0,0,0000 TRY 14
[1] 0000,0,0,0,0000 MATCH_SEQ "get_"
[2] 0000,0,0,0,0000 TRY 1
[3] 0000,0,0,0,0000 MATCH_SEQ "name"
[4] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[5] 0000,0,0,0,0000 POP SUCCESS
[6] 0000,0,0,0,0000 TRY 1
[7] 0000,0,0,0,0000 MATCH_SEQ "value"
[8] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[9] 0000,0,0,0,0000 POP SUCCESS
[10] 0000,0,0,0,0000 TRY 1
[11] 0000,0,0,0,0000 MATCH_SEQ "type"
[12] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[13] 0000,0,0,0,0000 POP SUCCESS
[14] 0000,0,0,0,0000 POP FAIL
[15] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[16] 0000,0,0,0,0000 POP SUCCESS
[17] 0000,0,0,0,0000 TRY 14
[18] 0000,0,0,0,0000 MATCH_SEQ "set_"
[19] 0000,0,0,0,0000 TRY 1
[20] 0000,0,0,0,0000 MATCH_SEQ "name"
[21] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[22] 0000,0,0,0,0000 POP SUCCESS
[23] 0000,0,0,0,0000 TRY 1
[24] 0000,0,0,0,0000 MATCH_SEQ "value"
[25] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[26] 0000,0,0,0,0000 POP SUCCESS
[27] 0000,0,0,0,0000 TRY 1
[28] 0000,0,0,0,0000 MATCH_SEQ "type"
[29] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[30] 0000,0,0,0,0000 POP SUCCESS
[31] 0000,0,0,0,0000 POP FAIL
[32] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[33] 0000,0,0,0,0000 POP SUCCESS
[34] 0000,0,0,0,0000 POP FAIL
-----Optimized once-----
[0] 0000,0,0,0,0000 TRY 14
[1] 0000,0,0,0,0000 MATCH_SEQ "get_"
[2] 0000,0,0,0,0000 TRY 1
[3] 0000,0,0,0,0000 MATCH_SEQ "name"
[4] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[5] 0000,0,0,0,0000 POP SUCCESS
[6] 0000,0,0,0,0000 TRY 1
[7] 0000,0,0,0,0000 MATCH_SEQ "value"
[8] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[9] 0000,0,0,0,0000 POP SUCCESS
[10] 0000,0,0,0,0000 TRY 1
[11] 0000,0,0,0,0000 MATCH_SEQ "type"
[12] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[13] 0000,0,0,0,0000 POP SUCCESS
[14] 0000,0,0,0,0000 POP FAIL
[15] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[16] 0000,0,0,0,0000 POP SUCCESS
[17] 0000,0,0,0,0000 TRY 14
[18] 0000,0,0,0,0000 MATCH_SEQ "set_"
[19] 0000,0,0,0,0000 TRY 1
[20] 0000,0,0,0,0000 MATCH_SEQ "name"
[21] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[22] 0000,0,0,0,0000 POP SUCCESS
[23] 0000,0,0,0,0000 TRY 1
[24] 0000,0,0,0,0000 MATCH_SEQ "value"
[25] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[26] 0000,0,0,0,0000 POP SUCCESS
[27] 0000,0,0,0,0000 TRY 1
[28] 0000,0,0,0,0000 MATCH_SEQ "type"
[29] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[30] 0000,0,0,0,0000 POP SUCCESS
[31] 0000,0,0,0,0000 POP FAIL
[32] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[33] 0000,0,0,0,0000 POP SUCCESS
[34] 0000,0,0,0,0000 POP FAIL
result of "helix|hello|help|hero|hers|her"
| CONCAT
|| he UNIT_SPAN
|| ALT
||| CONCAT
|||| l UNIT
|||| ALT
||||| CONCAT
|||||| ix UNIT_SPAN
||||| CONCAT
|||||| lo UNIT_SPAN
||||| p UNIT
||| CONCAT
|||| r UNIT
|||| ALT
||||| o UNIT
||||| s UNIT
||||| UNIT
-----IR-----
[0] 0000,0,0,0,0000 MATCH_SEQ "he"
[1] 0000,0,0,0,0000 TRY 14
[2] 0000,0,0,0,0000 MATCH_SEQ "l"
[3] 0000,0,0,0,0000 TRY 1
[4] 0000,0,0,0,0000 MATCH_SEQ "ix"
[5] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[6] 0000,0,0,0,0000 POP SUCCESS
[7] 0000,0,0,0,0000 TRY 1
[8] 0000,0,0,0,0000 MATCH_SEQ "lo"
[9] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[10] 0000,0,0,0,0000 POP SUCCESS
[11] 0000,0,0,0,0000 TRY 1
[12] 0000,0,0,0,0000 MATCH_SEQ "p"
[13] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[14] 0000,0,0,0,0000 POP SUCCESS
[15] 0000,0,0,0,0000 POP FAIL
[16] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[17] 0000,0,0,0,0000 POP SUCCESS
[18] 0000,0,0,0,0000 TRY 14
[19] 0000,0,0,0,0000 MATCH_SEQ "r"
[20] 0000,0,0,0,0000 TRY 1
[21] 0000,0,0,0,0000 MATCH_SEQ "o"
[22] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[23] 0000,0,0,0,0000 POP SUCCESS
[24] 0000,0,0,0,0000 TRY 1
[25] 0000,0,0,0,0000 MATCH_SEQ "s"
[26] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[27] 0000,0,0,0,0000 POP SUCCESS
[28] 0000,0,0,0,0000 TRY 1
[29] 0000,0,0,0,0000 MATCH_SEQ "<EPSILON>"
[30] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[31] 0000,0,0,0,0000 POP SUCCESS
[32] 0000,0,0,0,0000 POP FAIL
[33] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[34] 0000,0,0,0,0000 POP SUCCESS
[35] 0000,0,0,0,0000 POP FAIL
-----Optimized once-----
[0] 0000,0,0,0,0000 MATCH_SEQ "he"
[1] 0000,0,0,0,0000 TRY 14
[2] 0000,0,0,0,0000 MATCH_SEQ "l"
[3] 0000,0,0,0,0000 TRY 1
[4] 0000,0,0,0,0000 MATCH_SEQ "ix"
[5] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[6] 0000,0,0,0,0000 POP SUCCESS
[7] 0000,0,0,0,0000 TRY 1
[8] 0000,0,0,0,0000 MATCH_SEQ "lo"
[9] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[10] 0000,0,0,0,0000 POP SUCCESS
[11] 0000,0,0,0,0000 TRY 1
[12] 0000,0,0,0,0000 MATCH_SEQ "p"
[13] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[14] 0000,0,0,0,0000 POP SUCCESS
[15] 0000,0,0,0,0000 POP FAIL
[16] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[17] 0000,0,0,0,0000 POP SUCCESS
[18] 0000,0,0,0,0000 TRY 14
[19] 0000,0,0,0,0000 MATCH_SEQ "r"
[20] 0000,0,0,0,0000 TRY 1
[21] 0000,0,0,0,0000 MATCH_SEQ "o"
[22] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[23] 0000,0,0,0,0000 POP SUCCESS
[24] 0000,0,0,0,0000 TRY 1
[25] 0000,0,0,0,0000 MATCH_SEQ "s"
[26] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[27] 0000,0,0,0,0000 POP SUCCESS
[28] 0000,0,0,0,0000 TRY 1
[29] 0000,0,0,0,0000 MATCH_SEQ "<EPSILON>"
[30] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[31] 0000,0,0,0,0000 POP SUCCESS
[32] 0000,0,0,0,0000 POP FAIL
[33] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[34] 0000,0,0,0,0000 POP SUCCESS
[35] 0000,0,0,0,0000 POP FAIL
result of "a*.[abc]*(?<a>abcd|a(bc)c)(?<name>.*)234"
| CONCAT
|| * COUNT
||| a UNIT
|| CONCAT
||| . UNIT_SET
||| CONCAT
|||| * COUNT
||||| [abc] UNIT_SET
|||| CONCAT
||||| (?<a> GROUP_BEGIN
|||||| CONCAT
||||||| abc UNIT_SPAN
||||||| ALT
|||||||| d UNIT
|||||||| c UNIT
||||| CONCAT
|||||| (?<name> GROUP_BEGIN
||||||| * COUNT
|||||||| . UNIT_SET
|||||| CONCAT
||||||| 234 UNIT_SPAN
-----IR-----
[0] 0000,0,0,0,0000 COUNT_SEQ GREEDY MIN: 0 MAX: -1 SEQ: "a"
[1] 0000,0,0,0,0000 MATCH_SET "."
[2] 0000,0,0,0,0000 COUNT_SET GREEDY MIN: 0 MAX: -1 SET: "[abc]"
[3] 0000,0,0,0,0000 TRY 10
[4] 0000,0,0,0,0000 MATCH_SEQ "abc"
[5] 0000,0,0,0,0000 TRY 1
[6] 0000,0,0,0,0000 MATCH_SEQ "d"
[7] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[8] 0000,0,0,0,0000 POP SUCCESS
[9] 0000,0,0,0,0000 TRY 1
[10] 0000,0,0,0,0000 MATCH_SEQ "c"
[11] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[12] 0000,0,0,0,0000 POP SUCCESS
[13] 0000,0,0,0,0000 POP FAIL
[14] 0000,0,0,0,0000 CONDITION SUCCESS: 2 FAIL: 1
[15] 0000,0,0,0,0000 POP FAIL
[16] 0000,0,0,0,0000 PACK SUCCESS GROUP: "a"
[17] 0000,0,0,0,0000 TRY 1
[18] 0000,0,0,0,0000 COUNT_SET GREEDY MIN: 0 MAX: -1 SET: "."
[19] 0000,0,0,0,0000 CONDITION SUCCESS: 2 FAIL: 1
[20] 0000,0,0,0,0000 POP FAIL
[21] 0000,0,0,0,0000 PACK SUCCESS GROUP: "name"
[22] 0000,0,0,0,0000 MATCH_SEQ "234"
-----Optimized once-----
[0] 0000,0,0,0,0000 COUNT_SEQ GREEDY MIN: 0 MAX: -1 SEQ: "a"
[1] 0000,0,0,0,0000 MATCH_SET "."
[2] 0000,0,0,0,0000 COUNT_SET GREEDY MIN: 0 MAX: -1 SET: "[abc]"
[3] 0000,0,0,0,0000 TRY 10
[4] 0000,0,0,0,0000 MATCH_SEQ "abc"
[5] 0000,0,0,0,0000 TRY 1
[6] 0000,0,0,0,0000 MATCH_SEQ "d"
[7] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[8] 0000,0,0,0,0000 POP SUCCESS
[9] 0000,0,0,0,0000 TRY 1
[10] 0000,0,0,0,0000 MATCH_SEQ "c"
[11] 0000,0,0,0,0000 CONDITION SUCCESS: 1 FAIL: 2
[12] 0000,0,0,0,0000 POP SUCCESS
[13] 0000,0,0,0,0000 POP FAIL
[14] 0000,0,0,0,0000 CONDITION SUCCESS: 2 FAIL: 1
[15] 0000,0,0,0,0000 POP FAIL
[16] 0000,0,0,0,0000 PACK SUCCESS GROUP: "a"
[17] 0000,0,0,0,0000 TRY 1
[18] 0000,0,0,0,0000 FIND_COMPLEX FURTHEST COUNT: -1
[19] 0000,0,0,0,0000 CONDITION SUCCESS: 2 FAIL: 1
[20] 0000,0,0,0,0000 POP FAIL
[21] 0000,0,0,0,0000 PACK SUCCESS GROUP: "name"
[22] 0000,0,0,0,0000 MATCH_SEQ "234"
Program has exited with no error, press any key to exit.