mainly theoratical work

This commit is contained in:
Youmu Liu
2026-07-20 20:20:21 +08:00
parent b9dab20752
commit a698c47a1c
2 changed files with 109 additions and 132 deletions
@@ -0,0 +1,75 @@
// -----------------------------------------------------------------------------
// file="TextRegexSourceGen.GenClass.MultiIR"
// Project: StgSharp
// Copyright (c) Nitload.
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
using StgSharp.RegularAnalysis.Abstraction;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace StgSharp.RegularAnalysis.Text
{
internal partial class TextRegexSourceGen
{
private static void GenerateRegion(
ReadOnlySpan<RegexIR> region_ir,
SourceGenContext sc,
in SequenceEmitter<string> main_emitter,
in List<SequenceEmitter<string>> sub_emitter_list
)
{
int current_region = region_ir[0].Prefix.WorkingRegion;
ReadOnlySpan<RegexIR> ir_sp = region_ir;
ReadOnlySpan<RegexIR> scan_win;
int index = 0;
do
{
int result;
int count = 0;
scan_win = ir_sp[index..];
if ((result = TryGenerateFindSeq(scan_win, sc, in main_emitter,
in sub_emitter_list)) > 0)
{
count += result;
} else
if (TryGenerateMatchSeq(scan_win, main_emitter, sc) > 0)
{
count += 1;
} else if (TryGenerateMatchSet(scan_win, main_emitter, sc) > 0)
{
count++;
} else if (TryGenerateFindSeq(scan_win, main_emitter, sc) > 0)
{
count++;
} else { }
index += count;
} while (index < ir_sp.Length);
}
private static int TryGenerateFindSeq(
ReadOnlySpan<RegexIR> scan_win,
SourceGenContext sc,
in SequenceEmitter<string> main_emitter,
in List<SequenceEmitter<string>> sub_emitter_list
)
{
if (scan_win[0] is not RegexFindSeqIR find) {
return -1;
}
_ = main_emitter.AppendLine()
.AppendLine(@$"//Find sequence:{FormatStringLiteral(find.Pattern)} at any pos")
.AppendLine(@"do")
.AppendLine(@"{");
return 1;
}
}
}
@@ -12,8 +12,11 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace StgSharp.RegularAnalysis.Text namespace StgSharp.RegularAnalysis.Text
@@ -31,7 +34,7 @@ namespace StgSharp.RegularAnalysis.Text
{ {
SequenceEmitter<string> se = new(); SequenceEmitter<string> se = new();
List<SequenceEmitter<string>> sub_match_list = []; List<SequenceEmitter<string>> sub_match_list = [];
SourceGenContext ng = new(); SourceGenContext sc = new();
RegexInfo info = source.Info; RegexInfo info = source.Info;
List<RegexIR> ir = source.IRs; List<RegexIR> ir = source.IRs;
@@ -41,25 +44,20 @@ namespace StgSharp.RegularAnalysis.Text
SequenceEmitter<string> match_e = new(); SequenceEmitter<string> match_e = new();
int index = 0; int index = 0;
do int end = FindRrgionEnd(ir_sp, index);
ReadOnlySpan<RegexIR> region = ir_sp[0..end];
while (true)
{ {
int result; GenerateRegion(region, sc, match_e, sub_match_list);
if (end >= ir_sp.Length)
int count = int.Min(8, ir_sp.Length - index);
ir_sp.Slice(index, count).CopyTo(scan_win);
if (TryGenerateMatchSeq(scan_win, match_e, ng) > 0)
{ {
count += 1; break;
} else if (TryGenerateMatchSet(scan_win, match_e, ng) > 0) }
{ index = end;
count++; end = FindRrgionEnd(ir_sp, end);
} else if (TryGenerateFindSeq(scan_win, match_e, ng) > 0) region = ir_sp[index..end];
{ }
count++;
} else { }
index += count;
} while (index < ir.Count);
_ = se.AppendLine($@"public override MatchResult Match({ROS_char} text)")// _ = se.AppendLine($@"public override MatchResult Match({ROS_char} text)")//
.AppendLine(@"{"); .AppendLine(@"{");
@@ -76,7 +74,7 @@ namespace StgSharp.RegularAnalysis.Text
.AppendLine($@"int {offset} = 0;") .AppendLine($@"int {offset} = 0;")
.AppendLine(); .AppendLine();
_ = ng.GenVarDefine(se); _ = sc.GenVarDefine(se);
_ = se.Append(match_e); _ = se.Append(match_e);
@@ -91,15 +89,25 @@ namespace StgSharp.RegularAnalysis.Text
return se; return se;
} }
private static string FormatStringLiteral( [MethodImpl(MethodImplOptions.AggressiveInlining)]
string str private static int FindRrgionEnd(
ReadOnlySpan<RegexIR> ir_sp,
int current
) )
{ {
return SyntaxFactory.Literal(str).Text; int cur_depth = ir_sp[current].Prefix.WorkingRegion;
int end = ir_sp.Length;
for (; end > 0; end--)
{
if (ir_sp[end].Prefix.WorkingRegion == cur_depth) {
return end;
}
}
return 1;
} }
private static string FormatStringLiteral( private static string FormatStringLiteral(
char str string str
) )
{ {
return SyntaxFactory.Literal(str).Text; return SyntaxFactory.Literal(str).Text;
@@ -108,7 +116,7 @@ namespace StgSharp.RegularAnalysis.Text
#region sub generator #region sub generator
private static int TryGenerateFindSeq( private static int TryGenerateFindSeq(
Span<RegexIR> scan_win, ReadOnlySpan<RegexIR> scan_win,
SequenceEmitter<string> se, SequenceEmitter<string> se,
SourceGenContext ng SourceGenContext ng
) )
@@ -129,7 +137,7 @@ namespace StgSharp.RegularAnalysis.Text
} }
private static int TryGenerateMatchSeq( private static int TryGenerateMatchSeq(
Span<RegexIR> scan_win, ReadOnlySpan<RegexIR> scan_win,
SequenceEmitter<string> se, SequenceEmitter<string> se,
SourceGenContext ng SourceGenContext ng
) )
@@ -148,114 +156,8 @@ namespace StgSharp.RegularAnalysis.Text
return length; return length;
} }
private static int TryGenerateFindSet(
Span<RegexIR> scan_win,
SequenceEmitter<string> se,
SourceGenContext ng
)
{
if (scan_win[0] is not RegexFindSetIR seq) {
return -1;
}
string pattern = seq.Charset;
RegexCharSet[] set_pattern = FigureCharSetType(pattern, out bool accept);
bool first = seq.IsFirst;
string remain = ng.CurRemain;
string offset = ng.FindResult;
_ = se.AppendLine($@"// match charset of {pattern}")
.AppendLine($@"{remain} = {orig_text}[{current_ptr}..];")
.AppendLine();
_ = se.AppendLine("if(");
RegexCharSet p = set_pattern[0];
string _case = accept ? GenerateAcceptCase(p) : GenerateDenyCase(p);
_ = se.AppendLine($@"if ({_case}||");
for (int i = 1; i < set_pattern.Length - 1; i++)
{
p = set_pattern[i];
_case = accept ? GenerateAcceptCase(p) : GenerateDenyCase(p);
if (string.IsNullOrEmpty(_case))
{
continue;
}
_ = se.AppendLine($@" {_case} ||");
}
p = set_pattern[^1];
_case = accept ? GenerateAcceptCase(p) : GenerateDenyCase(p);
_ = se.AppendLine($@"{_case})")
.AppendLine("{")
.AppendLine($@"{current_ptr} += 1;")
.AppendLine("}");
return 1;
string GenerateAcceptCase(
RegexCharSet c
)
{
string caller;
switch (c.Type)
{
// Handle single character
case CharSetType.Single:
string literal = FormatStringLiteral(c.Value);
caller = first ? "IndexOfAny" : "LastIndexOfAny";
return $@"({offset} = {remain}.{caller}(""{literal}"") != -1)";
// Handle range of characters
case CharSetType.Range:
caller = first ? "IndexOfAnyInRange" : "LastIndexOfAnyInRange";
return $@"({offset} = {remain}.{caller}('{FormatStringLiteral(c.Value[0])}', '{FormatStringLiteral(c.Value[1])}') != -1)";
// Handle set of characters
case CharSetType.Set:
switch (c.Value)
{
case "s":
caller = first ? "IndexOfAnyWhiteSpace" : "LastIndexOfAnyWhiteSpace";
return $@"({offset} = {remain}.{caller}() != -1)";
case "w":
default:
break;
}
case CharSetType.None:
return string.Empty;
default:
return string.Empty;
}
}
string GenerateDenyCase(
RegexCharSet c
)
{
switch (c.Type)
{
// Handle single character
case CharSetType.Single:
// Handle range of characters
case CharSetType.Range:
// Handle set of characters
case CharSetType.Set:
case CharSetType.None:
return string.Empty;
default:
return string.Empty;
}
}
}
private static int TryGenerateMatchSet( private static int TryGenerateMatchSet(
Span<RegexIR> scan_win, ReadOnlySpan<RegexIR> scan_win,
SequenceEmitter<string> se, SequenceEmitter<string> se,
SourceGenContext ng SourceGenContext ng
) )