use new exit lable

This commit is contained in:
Youmu Liu
2026-09-14 18:21:23 +08:00
parent 9e9078ced1
commit 57587bec16
6 changed files with 169 additions and 197 deletions
@@ -17,7 +17,8 @@ namespace Nitload.RegularAnalysis.Text
in SequenceEmitter<string> sc,
in List<SequenceEmitter<string>> func_list,
in SourceGenContext context,
in ExitLabel exit_label
in ExitLabel local_fail,
ref ExitLabel backtrack
)
{
// A special rule owns the entire matched subtree. Returning false leaves emission
@@ -25,7 +26,7 @@ namespace Nitload.RegularAnalysis.Text
return node.Label switch
{
RegexElementLabel.CONCAT => TryGenerateFindConcat(node, sc, func_list, context,
exit_label),
local_fail, ref backtrack),
_ => false,
};
}
@@ -166,10 +167,12 @@ namespace Nitload.RegularAnalysis.Text
in ExitLabel success
)
{
ExitLabel failure = context.RequestExitLabel(ExitMode.Goto);
ExitLabel failure = context.RequestExitLabel(ExitKind.AltNext);
string entry = $"__alt_entry_{context.RequestScratchScopeIndex()}";
_ = sc.AppendLine($"{ROS_char} {entry} = {context.RemainSpan};");
GenerateMethodSource(node, sc, func_list, context, failure);
// Keep branch-local retries isolated from both siblings and the caller's path.
ExitLabel branch_backtrack = failure;
GenerateMethodSource(node, sc, func_list, context, failure, ref branch_backtrack);
_ = sc.AppendLine($"goto {success.GetLabelName()};")
.AppendLine($"{failure.GetLabelName()}:")
.AppendLine($"{context.RemainSpan} = {entry};");
@@ -180,50 +183,6 @@ namespace Nitload.RegularAnalysis.Text
#endregion
#region CONCAT continuation
private static void AppendConcatNodes(
RegexAstNode node,
List<RegexAstNode> sequence
)
{
if (RegexAstNode.IsNullOrEmpty(node)) {
return;
}
if (node.Label == RegexElementLabel.CONCAT &&
!RegexAstNode.IsDotStar(node.Left) && !IsNamedFind(node))
{
AppendConcatNodes(node.Left, sequence);
AppendConcatNodes(node.Right, sequence);
} else {
sequence.Add(node);
}
}
private static void GenerateConcatTail(
IReadOnlyList<RegexAstNode> sequence,
int start,
in SequenceEmitter<string> sc,
in List<SequenceEmitter<string>> func_list,
in SourceGenContext context,
in ExitLabel exit_label
)
{
for (int i = start; i < sequence.Count; i++)
{
RegexAstNode node = sequence[i];
if (node.Label == RegexElementLabel.COUNT)
{
// COUNT owns both its repetition and the continuation that may retry it.
GenerateCount(node, sc, func_list, context, exit_label, sequence, i + 1);
return;
}
GenerateMethodSource(node, sc, func_list, context, exit_label);
}
}
#endregion
#region FIND concatenation
private static bool TryGenerateFindConcat(
@@ -231,7 +190,8 @@ namespace Nitload.RegularAnalysis.Text
in SequenceEmitter<string> sc,
in List<SequenceEmitter<string>> func_list,
in SourceGenContext context,
in ExitLabel exit_label
in ExitLabel local_fail,
ref ExitLabel backtrack
)
{
RegexAstNode left = node.Left;
@@ -246,7 +206,7 @@ namespace Nitload.RegularAnalysis.Text
{
// TODO(NGRA): Emit the unnamed FIND candidate loop and retry the right subtree
// until it succeeds or no anchor candidate remains.
GenerateMethodSource(right, sc, func_list, context, exit_label, true);
GenerateMethodSource(right, sc, func_list, context, local_fail, ref backtrack, true);
return true;
}
@@ -256,7 +216,7 @@ namespace Nitload.RegularAnalysis.Text
{
// TODO(NGRA): Emit named FIND retry and capture the text preceding the
// successful anchor candidate.
GenerateMethodSource(right, sc, func_list, context, exit_label, true);
GenerateMethodSource(right, sc, func_list, context, local_fail, ref backtrack, true);
} else
{
// TODO(NGRA): Capture the remaining input for a terminal named dot-star.