From b3e198dbaf1c07ea47e96ee583e102e1a1a40baa Mon Sep 17 00:00:00 2001
From: Youmu Liu <105042599+Nitload-NSI@users.noreply.github.com>
Date: Thu, 6 Aug 2026 18:05:06 +0800
Subject: [PATCH] add single ir generator methods
---
.../TextRegexSourceGen.GenClass.SingleIR.cs | 45 +++++++++++--------
.../Text/TextRegexSourceGen.GenClass.cs | 3 +-
.../Text/TextRegexSourceGen.GenContext.cs | 28 ++++++++----
3 files changed, 48 insertions(+), 28 deletions(-)
diff --git a/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenClass.SingleIR.cs b/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenClass.SingleIR.cs
index 14ca3d24..4def43ef 100644
--- a/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenClass.SingleIR.cs
+++ b/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenClass.SingleIR.cs
@@ -88,8 +88,8 @@ namespace StgSharp.RegularAnalysis.Text
return -1;
}
string group_name = pack.GroupName;
- string begin = sc.GroupBegin(group_name);
- string end = sc.GroupEnd(group_name);
+ string begin = sc.GetVarGroupBegin(group_name);
+ string end = sc.GetVarGroupEnd(group_name);
_ = code.AppendLine(begin).AppendLine(end);
return 1;
}
@@ -165,17 +165,21 @@ namespace StgSharp.RegularAnalysis.Text
string counter = sc.RequireNewCounter();
// TODO cannot check real count outside the cycle
- _ = code.AppendLine($@"int {counter} = 0;", //
+ _ = code.AppendLine($@"int {counter} = 0;", //
@$"for(; {counter}<{leave}; {counter}++)", //
"{", //
- @$"if({sc.InputSpan}[{sc.Position}..].StartWith({literal}))", //
+ @$"if(!{sc.RemainingSpan}.StartWith({literal}))", //
"{", //
- @$"{sc.Position}+={seq.Length};", //
+ $@"break;", //
"}", //
"}", //
- @$"if({counter}>{min})", // TODO match here
+ @$"if({counter}>{min})", //
+ "{", // in case match
+ sc.MakeRemainOffset(counter), //
+ "}", //
$@"else", //
- "}"); // TODO fail here
+ "{", // TODO fail here
+ "}"); //
return 1;
}
@@ -192,10 +196,13 @@ namespace StgSharp.RegularAnalysis.Text
}
string seq = match_seq.Pattern;
string literal = FormatStringLiteral(seq);
- _ = code.AppendLine(@$"if({sc.InputSpan}[{sc.Position}..].StartWith({literal}))")
+ _ = code.AppendLine(@$"if({sc.RemainingSpan}.StartWith({literal}))")
.AppendLine("{")
.AppendLine($"{sc.StepResult} = true;")
- .AppendLine($@"{sc.Position} += {seq.Length};")
+ .AppendLine(sc.MakeRemainOffset(seq.Length))
+ .AppendLine("}")
+ .AppendLine("else")
+ .AppendLine("{")//TODO fail here
.AppendLine("}");
return 1;
}
@@ -237,7 +244,7 @@ namespace StgSharp.RegularAnalysis.Text
_case_code = GenLine(set, sc, ")");
_ = code.AppendLine(_case_code)
.AppendLine("{")
- .AppendLine("-------------------------------------")// TODO case success
+ .AppendLine(sc.MakeRemainOffset(1))// TODO case success
.AppendLine("}");
return 1;
}
@@ -245,9 +252,11 @@ namespace StgSharp.RegularAnalysis.Text
private static string GenLine(
RegexCharSet set,
SourceGenContext sc,
- string end_of_line
+ string end_of_line,
+ string symbol_of_offset = ""
)
{
+ string offset = string.IsNullOrEmpty(symbol_of_offset) ? "0" : $"{symbol_of_offset}";
switch (set.Type)
{
case CharSetType.Single:
@@ -256,7 +265,7 @@ namespace StgSharp.RegularAnalysis.Text
{
// more than 8 different chars, using string match
string literal = FormatStringLiteral(cases);
- return $@"{literal}.Contains({sc.InputSpan}[{sc.Position}]) {end_of_line}";
+ return $@"{literal}.Contains({sc.RemainingSpan}[{offset}]) {end_of_line}";
} else
{
StringBuilder sb = new();
@@ -265,10 +274,10 @@ namespace StgSharp.RegularAnalysis.Text
for (int j = 0; j < cases.Length - 1; j++)
{
literal = FormatCharLiteral(cases[j]);
- _ = sb.Append(CultureInfo.InvariantCulture, $@"{sc.InputSpan}[{sc.Position}] == {literal} ||");
+ _ = sb.Append(CultureInfo.InvariantCulture, $@"{sc.RemainingSpan}[{offset}] == {literal} ||");
}
literal = FormatCharLiteral(cases[^1]);
- _ = sb.Append(CultureInfo.InvariantCulture, $@"{sc.InputSpan}[{sc.Position}] == {literal}")
+ _ = sb.Append(CultureInfo.InvariantCulture, $@"{sc.RemainingSpan}[{offset}] == {literal}")
.Append(CultureInfo.InvariantCulture, @$") {end_of_line}");
return sb.ToString();
}
@@ -276,15 +285,15 @@ namespace StgSharp.RegularAnalysis.Text
string rule = set.Value;
char lo = rule[0];
char hi = rule[1];
- return $@"({sc.InputSpan}[{sc.Position}] >= '{lo}' && {sc.InputSpan}[{sc.Position}] <= '{hi}') {end_of_line}";
+ return $@"({sc.RemainingSpan}[{offset}] >= '{lo}' && {sc.RemainingSpan}[{offset}] <= '{hi}') {end_of_line}";
case CharSetType.Set:
string accept_mark = set.Accept ? string.Empty : "!";
return set.Value switch
{
- "s" => $@"{accept_mark}char.IsWhiteSpace({sc.InputSpan}[{sc.Position}]) {end_of_line}",
- "d" => $@"{accept_mark}char.IsDigit({sc.InputSpan}[{sc.Position}]) {end_of_line}",
- "w" => $@"{accept_mark}IsCharWord({sc.InputSpan}[{sc.Position}]) {end_of_line}",
+ "s" => $@"{accept_mark}char.IsWhiteSpace({sc.RemainingSpan}[{offset})] {end_of_line}",
+ "d" => $@"{accept_mark}char.IsDigit({sc.RemainingSpan}[{offset})] {end_of_line}",
+ "w" => $@"{accept_mark}IsCharWord({sc.RemainingSpan}[{offset})] {end_of_line}",
_ => string.Empty
};
case CharSetType.None:
diff --git a/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenClass.cs b/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenClass.cs
index cf550287..18ac24ce 100644
--- a/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenClass.cs
+++ b/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenClass.cs
@@ -269,6 +269,7 @@ namespace StgSharp.RegularAnalysis.Text
_ = sb.Append(c);
}
list.Add(new(sb.ToString(), CharSetType.Single, true));
+ return [.. list];
} else
{
for (; seq.Length > 0; )
@@ -343,7 +344,7 @@ namespace StgSharp.RegularAnalysis.Text
case 'd':
sets.Add(new("d", CharSetType.Set, accept));
break;
- case '['or'('or')'or']'or'\\'or'\"':
+ case '[' or '(' or ')' or ']' or '\\' or '\"':
_ = single_char.Add(remain[pos + 1]);
break;
default:
diff --git a/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenContext.cs b/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenContext.cs
index 5cf3f20f..6186a4e5 100644
--- a/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenContext.cs
+++ b/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenContext.cs
@@ -5,6 +5,7 @@
// SPDX-License-Identifier: MIT
// -----------------------------------------------------------------------------
+using Microsoft.CodeAnalysis.Text;
using StgSharp.RegularAnalysis.Abstraction;
using System;
using System.Collections.Generic;
@@ -29,11 +30,6 @@ namespace StgSharp.RegularAnalysis.Text
private sealed class SourceGenContext
{
- ///
- /// Active pointer. Indexes the next unconsumed element of the input.
- ///
- public const string _cursor = "__cur";
-
///
/// Name of the match method parameter holding the input sequence.
///
@@ -54,7 +50,7 @@ namespace StgSharp.RegularAnalysis.Text
private readonly SortedSet _lineSlots = [];
private readonly SortedSet _regionSlots = [];
- public string Position { get; } = _cursor;
+ public string RemainingSpan { get; } = "__remaining_span";
public string InputSpan { get; } = _inputSpan;
@@ -75,7 +71,7 @@ namespace StgSharp.RegularAnalysis.Text
return null!;
}
- _ = emitter.AppendLine($@"int {_cursor} = 0;")
+ _ = emitter.AppendLine($@"{ROS_char} {RemainingSpan} = {_inputSpan};")
.AppendLine($@"bool {_stepResult} = true;");
foreach (int region in _regionSlots) {
@@ -95,14 +91,14 @@ namespace StgSharp.RegularAnalysis.Text
return emitter;
}
- public string GroupBegin(
+ public string GetVarGroupBegin(
string name
)
{
return $"__g{ResolveGroup(name)}_begin";
}
- public string GroupEnd(
+ public string GetVarGroupEnd(
string name
)
{
@@ -133,6 +129,20 @@ namespace StgSharp.RegularAnalysis.Text
return $"__l{line}_ok";
}
+ public string MakeRemainOffset(
+ string offset_name
+ )
+ {
+ return @$"{RemainingSpan} = {RemainingSpan}[{offset_name}..];";
+ }
+
+ public string MakeRemainOffset(
+ int offset
+ )
+ {
+ return @$"{RemainingSpan} = {RemainingSpan}[{offset}..];";
+ }
+
///
/// Records that some prefix observes the result of the instruction at line .