Small changeds on text regex source gen
This commit is contained in:
@@ -41,6 +41,17 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
|
|
||||||
public int LabelOrder { get; init; }
|
public int LabelOrder { get; init; }
|
||||||
|
|
||||||
|
public string GetLabelName()
|
||||||
|
{
|
||||||
|
return Mode switch
|
||||||
|
{
|
||||||
|
ExitMode.Break => $@"__break_{LabelOrder}",
|
||||||
|
ExitMode.Continue => $@"__continue_{LabelOrder}",
|
||||||
|
ExitMode.Goto => $@"__goto_{LabelOrder}",
|
||||||
|
_ => throw new NotImplementedException(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,9 +183,10 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
RegexAstNode current = node.Right;
|
RegexAstNode current = node.Right;
|
||||||
|
|
||||||
// TODO(NGRA-NAMING): Reserve exclusive names for future ALT cursor/capture snapshots;
|
// TODO(NGRA-NAMING): Reserve exclusive names for future ALT cursor/capture snapshots;
|
||||||
// their lifetime extends through retry labels, not just the candidate's emitted block.
|
// their lifetime extends through retry labels, not just the candidate's emitted block.
|
||||||
string exit_label = context.RequestExitLabel();
|
ExitLabel exit_label = context.RequestExitLabel(ExitMode.Goto);
|
||||||
|
|
||||||
// TODO(NGRA): Walk every normalized ALT candidate exactly once. The final traversal
|
// TODO(NGRA): Walk every normalized ALT candidate exactly once. The final traversal
|
||||||
// shape and failure continuation are not wired yet.
|
// shape and failure continuation are not wired yet.
|
||||||
@@ -350,7 +351,7 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
bool is_greedy,
|
bool is_greedy,
|
||||||
[NotNull] in SequenceEmitter<string> sc,
|
[NotNull] in SequenceEmitter<string> sc,
|
||||||
in SourceGenContext context,
|
in SourceGenContext context,
|
||||||
string exit_label
|
in ExitLabel exit
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (min < 0 || (max >= 0 && max < min)) {
|
if (min < 0 || (max >= 0 && max < min)) {
|
||||||
@@ -366,9 +367,11 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
char expected = literal[0];
|
char expected = literal[0];
|
||||||
string expected_literal = FormatCharLiteral(expected);
|
string expected_literal = FormatCharLiteral(expected);
|
||||||
string remain_span = context.RemainSpan;
|
string remain_span = context.RemainSpan;
|
||||||
|
|
||||||
// TODO(NGRA-NAMING): Allocate required_rest, required_matched, required_chunk_index,
|
// TODO(NGRA-NAMING): Allocate required_rest, required_matched, required_chunk_index,
|
||||||
// and additional_count through the exclusive-name pool, including loop-local names.
|
// and additional_count through the exclusive-name pool, including loop-local names.
|
||||||
int scratch_scope_index = context.RequestScratchScopeIndex();
|
int scratch_scope_index = context.RequestScratchScopeIndex();
|
||||||
|
string exit_label_node = exit.GetLabelName();
|
||||||
string required_rest = $"__required_rest_{scratch_scope_index}";
|
string required_rest = $"__required_rest_{scratch_scope_index}";
|
||||||
string required_matched = $"__required_matched_{scratch_scope_index}";
|
string required_matched = $"__required_matched_{scratch_scope_index}";
|
||||||
string required_chunk_index = $"__required_chunk_index_{scratch_scope_index}";
|
string required_chunk_index = $"__required_chunk_index_{scratch_scope_index}";
|
||||||
@@ -384,7 +387,7 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
string required_prefix = new(expected, min);
|
string required_prefix = new(expected, min);
|
||||||
_ = sc.AppendLine($"if (!{remain_span}.{nameof(MemoryExtensions.StartsWith)}({FormatStringLiteral(required_prefix)}))")
|
_ = sc.AppendLine($"if (!{remain_span}.{nameof(MemoryExtensions.StartsWith)}({FormatStringLiteral(required_prefix)}))")
|
||||||
.AppendLine("{")
|
.AppendLine("{")
|
||||||
.AppendLine($"goto {exit_label};")
|
.AppendLine($"goto {exit_label_node};")
|
||||||
.AppendLine("}")
|
.AppendLine("}")
|
||||||
.AppendLine($"{remain_span} = {remain_span}.Slice({min});");
|
.AppendLine($"{remain_span} = {remain_span}.Slice({min});");
|
||||||
}
|
}
|
||||||
@@ -399,7 +402,7 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
|
|
||||||
_ = sc.AppendLine($"if ({remain_span}.Length < {min})")
|
_ = sc.AppendLine($"if ({remain_span}.Length < {min})")
|
||||||
.AppendLine("{")
|
.AppendLine("{")
|
||||||
.AppendLine($"goto {exit_label};")
|
.AppendLine($"goto {exit_label_node};")
|
||||||
.AppendLine("}")
|
.AppendLine("}")
|
||||||
.AppendLine($"{ROS_char} {required_rest} = {remain_span};")
|
.AppendLine($"{ROS_char} {required_rest} = {remain_span};")
|
||||||
.AppendLine($"bool {required_matched} = true;")
|
.AppendLine($"bool {required_matched} = true;")
|
||||||
@@ -424,7 +427,7 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
|
|
||||||
_ = sc.AppendLine($"if (!{required_matched})")
|
_ = sc.AppendLine($"if (!{required_matched})")
|
||||||
.AppendLine("{")
|
.AppendLine("{")
|
||||||
.AppendLine($"goto {exit_label};")
|
.AppendLine($"goto {exit_label_node};")
|
||||||
.AppendLine("}")
|
.AppendLine("}")
|
||||||
.AppendLine($"{remain_span} = {remain_span}.Slice({min});");
|
.AppendLine($"{remain_span} = {remain_span}.Slice({min});");
|
||||||
}
|
}
|
||||||
@@ -451,7 +454,6 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
// a future continuation attempt fails and requests another repetition.
|
// a future continuation attempt fails and requests another repetition.
|
||||||
_ = sc.AppendLine("// TODO(NGRA): Retry the lazy COUNT tail from its continuation.");
|
_ = sc.AppendLine("// TODO(NGRA): Retry the lazy COUNT tail from its continuation.");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GenerateUnitSetCount(
|
private static void GenerateUnitSetCount(
|
||||||
@@ -460,7 +462,8 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
int max,
|
int max,
|
||||||
bool is_greedy,
|
bool is_greedy,
|
||||||
[NotNull] in SequenceEmitter<string> sc,
|
[NotNull] in SequenceEmitter<string> sc,
|
||||||
in SourceGenContext context
|
in SourceGenContext context,
|
||||||
|
in ExitLabel exit_label
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (min < 0 || (max >= 0 && max < min)) {
|
if (min < 0 || (max >= 0 && max < min)) {
|
||||||
@@ -477,6 +480,7 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
|
|
||||||
IReadOnlyList<RegexCharSet> charset = payload.Set;
|
IReadOnlyList<RegexCharSet> charset = payload.Set;
|
||||||
string remain_span = context.RemainSpan;
|
string remain_span = context.RemainSpan;
|
||||||
|
|
||||||
// TODO(NGRA-NAMING): Allocate required_matched and additional_count through the
|
// TODO(NGRA-NAMING): Allocate required_matched and additional_count through the
|
||||||
// exclusive-name pool. Reserve required_rest/required_chunk_index if emitted later.
|
// exclusive-name pool. Reserve required_rest/required_chunk_index if emitted later.
|
||||||
int scratch_scope_index = context.RequestScratchScopeIndex();
|
int scratch_scope_index = context.RequestScratchScopeIndex();
|
||||||
@@ -533,7 +537,7 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
bool is_greedy,
|
bool is_greedy,
|
||||||
[NotNull] in SequenceEmitter<string> sc,
|
[NotNull] in SequenceEmitter<string> sc,
|
||||||
in SourceGenContext context,
|
in SourceGenContext context,
|
||||||
string exit_label
|
in ExitLabel exit
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (min < 0 || (max >= 0 && max < min)) {
|
if (min < 0 || (max >= 0 && max < min)) {
|
||||||
@@ -548,10 +552,12 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
|
|
||||||
string expected_literal = FormatStringLiteral(literal);
|
string expected_literal = FormatStringLiteral(literal);
|
||||||
string remain_span = context.RemainSpan;
|
string remain_span = context.RemainSpan;
|
||||||
|
|
||||||
// TODO(NGRA-NAMING): Allocate required_rest, required_matched, required_chunk_index,
|
// TODO(NGRA-NAMING): Allocate required_rest, required_matched, required_chunk_index,
|
||||||
// required_count, and additional_count through the exclusive-name pool. Flattened
|
// required_count, and additional_count through the exclusive-name pool. Flattened
|
||||||
// sibling COUNT nodes share the declaration space even after their exit labels.
|
// sibling COUNT nodes share the declaration space even after their exit labels.
|
||||||
int scratch_scope_index = context.RequestScratchScopeIndex();
|
int scratch_scope_index = context.RequestScratchScopeIndex();
|
||||||
|
string exit_label_node = exit.GetLabelName();
|
||||||
string required_rest = $"__required_rest_{scratch_scope_index}";
|
string required_rest = $"__required_rest_{scratch_scope_index}";
|
||||||
string required_matched = $"__required_matched_{scratch_scope_index}";
|
string required_matched = $"__required_matched_{scratch_scope_index}";
|
||||||
string required_chunk_index = $"__required_chunk_index_{scratch_scope_index}";
|
string required_chunk_index = $"__required_chunk_index_{scratch_scope_index}";
|
||||||
@@ -575,7 +581,7 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
.AppendLine("}")
|
.AppendLine("}")
|
||||||
.AppendLine($"if ({required_count} != {min})")
|
.AppendLine($"if ({required_count} != {min})")
|
||||||
.AppendLine("{")
|
.AppendLine("{")
|
||||||
.AppendLine($"goto {exit_label};")
|
.AppendLine($"goto {exit_label_node};")
|
||||||
.AppendLine("}")
|
.AppendLine("}")
|
||||||
.AppendLine($"{remain_span} = {required_rest};");
|
.AppendLine($"{remain_span} = {required_rest};");
|
||||||
} else if (min <= flattened_unit_count_threshold / literal.Length)
|
} else if (min <= flattened_unit_count_threshold / literal.Length)
|
||||||
@@ -589,7 +595,7 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
string required_prefix = required_prefix_span.ToString();
|
string required_prefix = required_prefix_span.ToString();
|
||||||
_ = sc.AppendLine($"if (!{remain_span}.{starts_with}({FormatStringLiteral(required_prefix)}))")
|
_ = sc.AppendLine($"if (!{remain_span}.{starts_with}({FormatStringLiteral(required_prefix)}))")
|
||||||
.AppendLine("{")
|
.AppendLine("{")
|
||||||
.AppendLine($"goto {exit_label};")
|
.AppendLine($"goto {exit_label_node};")
|
||||||
.AppendLine("}")
|
.AppendLine("}")
|
||||||
.AppendLine($"{remain_span} = {remain_span}.Slice({min * literal.Length});");
|
.AppendLine($"{remain_span} = {remain_span}.Slice({min * literal.Length});");
|
||||||
}
|
}
|
||||||
@@ -638,7 +644,7 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
|
|
||||||
_ = sc.AppendLine($"if (!{required_matched})")
|
_ = sc.AppendLine($"if (!{required_matched})")
|
||||||
.AppendLine("{")
|
.AppendLine("{")
|
||||||
.AppendLine($"goto {exit_label};")
|
.AppendLine($"goto {exit_label_node};")
|
||||||
.AppendLine("}")
|
.AppendLine("}")
|
||||||
.AppendLine($"{remain_span} = {required_rest};");
|
.AppendLine($"{remain_span} = {required_rest};");
|
||||||
}
|
}
|
||||||
@@ -665,14 +671,14 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
// a future continuation attempt fails and requests another repetition.
|
// a future continuation attempt fails and requests another repetition.
|
||||||
_ = sc.AppendLine("// TODO(NGRA): Retry the lazy COUNT tail from its continuation.");
|
_ = sc.AppendLine("// TODO(NGRA): Retry the lazy COUNT tail from its continuation.");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GenerateCount(
|
private static void GenerateCount(
|
||||||
RegexAstNode node,
|
RegexAstNode node,
|
||||||
[NotNull] in SequenceEmitter<string> sc,
|
[NotNull] in SequenceEmitter<string> sc,
|
||||||
in List<SequenceEmitter<string>> func_list,
|
in List<SequenceEmitter<string>> func_list,
|
||||||
in SourceGenContext context
|
in SourceGenContext context,
|
||||||
|
in ExitLabel exit
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
RegexAstNode value = RegexAstNode.IsNullOrEmpty(node.Left) ? node.Right : node.Left;
|
RegexAstNode value = RegexAstNode.IsNullOrEmpty(node.Left) ? node.Right : node.Left;
|
||||||
@@ -683,9 +689,10 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
int min = payload.Min;
|
int min = payload.Min;
|
||||||
int max = payload.Max;
|
int max = payload.Max;
|
||||||
bool is_greedy = payload.IsGreedy;
|
bool is_greedy = payload.IsGreedy;
|
||||||
|
|
||||||
// TODO(NGRA-NAMING): Reserve exclusive names for future repetition/rollback state
|
// TODO(NGRA-NAMING): Reserve exclusive names for future repetition/rollback state
|
||||||
// across complex COUNT retries; recursive children must use the same method pool.
|
// across complex COUNT retries; recursive children must use the same method pool.
|
||||||
string exit_label = context.RequestExitLabel();
|
ExitLabel exit_label = context.RequestExitLabel(ExitMode.Goto);
|
||||||
if ((value.Label & RegexElementLabel.SEQUENCE) == 0)
|
if ((value.Label & RegexElementLabel.SEQUENCE) == 0)
|
||||||
{
|
{
|
||||||
// TODO(NGRA): Emit min/max repetition, zero-width progress protection, greedy vs.
|
// TODO(NGRA): Emit min/max repetition, zero-width progress protection, greedy vs.
|
||||||
@@ -699,10 +706,7 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
GenerateUnitCount(value, min, max, is_greedy, sc, context, exit_label);
|
GenerateUnitCount(value, min, max, is_greedy, sc, context, exit_label);
|
||||||
break;
|
break;
|
||||||
case RegexElementLabel.UNIT_SET:
|
case RegexElementLabel.UNIT_SET:
|
||||||
GenerateUnitSetCount(value, min, max, is_greedy, sc, context);
|
GenerateUnitSetCount(value, min, max, is_greedy, sc, context, exit_label);
|
||||||
|
|
||||||
// TODO(NGRA): Emit a bounded/unbounded charset counting loop, preferably
|
|
||||||
// using IndexOfAnyExcept where the charset shape permits it.
|
|
||||||
break;
|
break;
|
||||||
case RegexElementLabel.UNIT_SPAN:
|
case RegexElementLabel.UNIT_SPAN:
|
||||||
GenerateUnitSpanCount(value, min, max, is_greedy, sc, context, exit_label);
|
GenerateUnitSpanCount(value, min, max, is_greedy, sc, context, exit_label);
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
|
|
||||||
public const string _remain_span = "__remain";
|
public const string _remain_span = "__remain";
|
||||||
|
|
||||||
private int _exit_alt_count;
|
private int _max_exit_lable;
|
||||||
|
|
||||||
private int _scratch_scope_count;
|
private int _scratch_scope_count;
|
||||||
|
|
||||||
@@ -53,13 +53,13 @@ namespace Nitload.RegularAnalysis.Text
|
|||||||
return sc.AppendLine($@"{ROS_char} {RemainSpan};");
|
return sc.AppendLine($@"{ROS_char} {RemainSpan};");
|
||||||
}
|
}
|
||||||
|
|
||||||
public string RequestExitLabel()
|
public ExitLabel RequestExitLabel(
|
||||||
|
ExitMode exitMode
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// TODO(NGRA-NAMING): Route ALT and COUNT labels through the method-wide label pool.
|
int index = _max_exit_lable;
|
||||||
// Keep every emitted label exclusive until method generation is complete.
|
_max_exit_lable++;
|
||||||
string code = $@"_exit_alt_{_exit_alt_count}";
|
return new(exitMode, index);
|
||||||
_exit_alt_count++;
|
|
||||||
return code;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int RequestScratchScopeIndex()
|
public int RequestScratchScopeIndex()
|
||||||
|
|||||||
Reference in New Issue
Block a user