private void RecurseIntoChildren(RegexNode node, RegexOptions options) { foreach (var child in node) { if (child.IsNode) { // When we see a SimpleOptionsGroup ```(?opts)``` then determine what the options will // be for successive nodes in the sequence. var childNode = child.Node; if (childNode is RegexSimpleOptionsGroupingNode simpleOptions) { options = GetNewOptionsFromToken(options, simpleOptions.OptionsToken); } CollectCaptures(child.Node, options); } } }
private void CollectCaptures(RegexNode node, RegexOptions options) { switch (node.Kind) { case RegexKind.CaptureGrouping: var captureGrouping = (RegexCaptureGroupingNode)node; RecordCapture(captureGrouping.CaptureToken, GetGroupingSpan(captureGrouping)); break; case RegexKind.BalancingGrouping: var balancingGroup = (RegexBalancingGroupingNode)node; RecordCapture(balancingGroup.FirstCaptureToken, GetGroupingSpan(balancingGroup)); break; case RegexKind.ConditionalExpressionGrouping: // Explicitly recurse into conditionalGrouping.Grouping. That grouping // itself does not create a capture group, but nested groupings inside of it // will. var conditionalGrouping = (RegexConditionalExpressionGroupingNode)node; RecurseIntoChildren(conditionalGrouping.Grouping, options); CollectCaptures(conditionalGrouping.Result, options); return; case RegexKind.SimpleGrouping: RecordSimpleGroupingCapture((RegexSimpleGroupingNode)node, options); break; case RegexKind.NestedOptionsGrouping: // When we see (?opts:...) // Recurse explicitly, setting the new options as we process the inner expression. // When this pops out we'll be back to these options we're currently at now. var nestedOptions = (RegexNestedOptionsGroupingNode)node; CollectCaptures(nestedOptions.Expression, GetNewOptionsFromToken(options, nestedOptions.OptionsToken)); return; } RecurseIntoChildren(node, options); }