mainly theoratical work
This commit is contained in:
@@ -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
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user