prefix replaces CONDITION
This commit is contained in:
@@ -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-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
|
||||
// AuthorGroup: Nitload
|
||||
// Copyright (c) Nitload. All rights reserved.
|
||||
@@ -29,6 +29,7 @@ using StgSharp.RegularAnalysis.Abstraction;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
@@ -76,18 +77,35 @@ namespace StgSharp.RegularAnalysis.Text
|
||||
{
|
||||
// RegexAnalyzer interpreter = new();
|
||||
// interpreter._source = regex;
|
||||
AbstractSyntaxTree<RegexAstNode, RegexElementLabel> tree;
|
||||
try
|
||||
{
|
||||
AbstractSyntaxTree<RegexAstNode, RegexElementLabel> tree = GenerateAST(regex);
|
||||
tree = GenerateAST(regex);
|
||||
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)
|
||||
{
|
||||
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)
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
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
|
||||
{
|
||||
|
||||
@@ -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; }
|
||||
@@ -103,9 +94,11 @@ namespace StgSharp.RegularAnalysis.Text
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
public RegexIRPrefix Prefix { get; set; }
|
||||
|
||||
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;
|
||||
@@ -128,9 +133,10 @@ namespace StgSharp.RegularAnalysis.Text
|
||||
|
||||
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>
|
||||
/// Searches for a certain string pattern or charset from current position.
|
||||
/// </summary>
|
||||
internal sealed class RegexMatchSeqIR(string pattern) : RegexIR
|
||||
internal sealed class RegexMatchSeqIR(
|
||||
string pattern
|
||||
) : RegexIR
|
||||
{
|
||||
|
||||
public string Pattern { get; } = pattern;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
@@ -175,14 +192,19 @@ namespace StgSharp.RegularAnalysis.Text
|
||||
|
||||
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;
|
||||
@@ -191,14 +213,21 @@ namespace StgSharp.RegularAnalysis.Text
|
||||
|
||||
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;
|
||||
@@ -217,14 +246,21 @@ namespace StgSharp.RegularAnalysis.Text
|
||||
|
||||
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;
|
||||
@@ -241,14 +277,21 @@ namespace StgSharp.RegularAnalysis.Text
|
||||
|
||||
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;
|
||||
@@ -267,14 +310,18 @@ namespace StgSharp.RegularAnalysis.Text
|
||||
|
||||
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; }
|
||||
@@ -283,23 +330,29 @@ namespace StgSharp.RegularAnalysis.Text
|
||||
|
||||
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;
|
||||
|
||||
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")}";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,13 +41,13 @@ namespace StgSharp
|
||||
|
||||
private static string[] regexSource = [
|
||||
@"[.]*",
|
||||
/*
|
||||
/**/
|
||||
@"http|https|ftp|ftps",
|
||||
@"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",
|
||||
@"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()
|
||||
@@ -75,6 +75,7 @@ namespace StgSharp
|
||||
Console.WriteLine(opt_ir[i].AsCommand(i));
|
||||
}
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(interpreterSource.AnalyseException);
|
||||
Console.WriteLine();
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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.
|
||||
Reference in New Issue
Block a user