1369 references to RegexNodeKind
System.Text.RegularExpressions (1369)
System\Text\RegularExpressions\RegexCompiler.cs (144)
513
if (RegexPrefixAnalyzer.FindTrailingAnchor(_regexTree.Root) ==
RegexNodeKind
.End &&
669
case
RegexNodeKind
.Bol:
753
case
RegexNodeKind
.End or
RegexNodeKind
.EndZ when _regexTree.FindOptimizations.MaxPossibleLength is int maxLength:
1274
Debug.Assert(target.LoopNode.Kind is
RegexNodeKind
.Setloop or
RegexNodeKind
.Setlazy or
RegexNodeKind
.Setloopatomic);
1457
Debug.Assert(node.Kind ==
RegexNodeKind
.Capture, "Every generated tree should begin with a capture node");
1467
case
RegexNodeKind
.Multi or
RegexNodeKind
.Notone or
RegexNodeKind
.One or
RegexNodeKind
.Set:
1473
int length = node.Kind ==
RegexNodeKind
.Multi ? node.Str!.Length : 1;
1673
Debug.Assert(node.Kind is
RegexNodeKind
.Alternate, $"Unexpected type: {node.Kind}");
2033
case
RegexNodeKind
.One:
2034
case
RegexNodeKind
.Set:
2039
case
RegexNodeKind
.Multi:
2045
case
RegexNodeKind
.Concatenate when child.Child(0) == startingLiteralNode && (startingLiteralNode.Kind is
RegexNodeKind
.One or
RegexNodeKind
.Set or
RegexNodeKind
.Multi):
2055
child.Child(0).Kind is
RegexNodeKind
.Multi ?
2057
new RegexNode(
RegexNodeKind
.Empty, child.Options));
2095
Debug.Assert(multi.Kind is
RegexNodeKind
.Multi, $"Expected a Multi node, got {multi.Kind}");
2097
new(
RegexNodeKind
.One, multi.Options, multi.Str[1]) :
2098
new(
RegexNodeKind
.Multi, multi.Options, multi.Str.Substring(1));
2105
Debug.Assert(node.Kind is
RegexNodeKind
.Backreference, $"Unexpected type: {node.Kind}");
2295
Debug.Assert(node.Kind is
RegexNodeKind
.BackreferenceConditional, $"Unexpected type: {node.Kind}");
2309
RegexNode? noBranch = node.Child(1) is { Kind: not
RegexNodeKind
.Empty } childNo ? childNo : null;
2454
Debug.Assert(node.Kind is
RegexNodeKind
.ExpressionConditional, $"Unexpected type: {node.Kind}");
2470
RegexNode? noBranch = node.Child(2) is { Kind: not
RegexNodeKind
.Empty } childNo ? childNo : null;
2647
Debug.Assert(node.Kind is
RegexNodeKind
.Capture, $"Unexpected type: {node.Kind}");
2773
Debug.Assert(node.Kind is
RegexNodeKind
.PositiveLookaround, $"Unexpected type: {node.Kind}");
2817
Debug.Assert(node.Kind is
RegexNodeKind
.NegativeLookaround, $"Unexpected type: {node.Kind}");
2968
case
RegexNodeKind
.Beginning:
2969
case
RegexNodeKind
.Start:
2970
case
RegexNodeKind
.Bol:
2971
case
RegexNodeKind
.Eol:
2972
case
RegexNodeKind
.End:
2973
case
RegexNodeKind
.EndZ:
2977
case
RegexNodeKind
.Boundary:
2978
case
RegexNodeKind
.NonBoundary:
2979
case
RegexNodeKind
.ECMABoundary:
2980
case
RegexNodeKind
.NonECMABoundary:
2984
case
RegexNodeKind
.Multi:
2988
case
RegexNodeKind
.One:
2989
case
RegexNodeKind
.Notone:
2990
case
RegexNodeKind
.Set:
2994
case
RegexNodeKind
.Oneloop:
2995
case
RegexNodeKind
.Notoneloop:
2996
case
RegexNodeKind
.Setloop:
3000
case
RegexNodeKind
.Onelazy:
3001
case
RegexNodeKind
.Notonelazy:
3002
case
RegexNodeKind
.Setlazy:
3006
case
RegexNodeKind
.Oneloopatomic:
3007
case
RegexNodeKind
.Notoneloopatomic:
3008
case
RegexNodeKind
.Setloopatomic:
3012
case
RegexNodeKind
.Loop:
3016
case
RegexNodeKind
.Lazyloop:
3020
case
RegexNodeKind
.Alternate:
3024
case
RegexNodeKind
.Concatenate:
3028
case
RegexNodeKind
.Atomic:
3032
case
RegexNodeKind
.Backreference:
3036
case
RegexNodeKind
.BackreferenceConditional:
3040
case
RegexNodeKind
.ExpressionConditional:
3044
case
RegexNodeKind
.Capture:
3048
case
RegexNodeKind
.PositiveLookaround:
3052
case
RegexNodeKind
.NegativeLookaround:
3056
case
RegexNodeKind
.Nothing:
3060
case
RegexNodeKind
.Empty:
3064
case
RegexNodeKind
.UpdateBumpalong:
3076
Debug.Assert(node.Kind is
RegexNodeKind
.Atomic or
RegexNodeKind
.PositiveLookaround or
RegexNodeKind
.NegativeLookaround or
RegexNodeKind
.ExpressionConditional, $"Unexpected type: {node.Kind}");
3077
Debug.Assert(node.Kind is
RegexNodeKind
.ExpressionConditional ? node.ChildCount() >= 1 : node.ChildCount() == 1, $"Unexpected number of children: {node.ChildCount()}");
3083
if (node.Kind is
RegexNodeKind
.Atomic && !analysis.MayBacktrack(child))
3120
Debug.Assert(node.Kind is
RegexNodeKind
.UpdateBumpalong, $"Unexpected type: {node.Kind}");
3140
Debug.Assert(node.Kind is
RegexNodeKind
.Concatenate, $"Unexpected type: {node.Kind}");
3198
if (next.Kind is not
RegexNodeKind
.UpdateBumpalong) // skip node types that don't have a semantic impact
3286
Debug.Assert(node.Kind is
RegexNodeKind
.Boundary or
RegexNodeKind
.NonBoundary or
RegexNodeKind
.ECMABoundary or
RegexNodeKind
.NonECMABoundary, $"Unexpected type: {node.Kind}");
3304
case
RegexNodeKind
.Boundary or
RegexNodeKind
.NonBoundary:
3318
if (node.Kind is
RegexNodeKind
.Boundary)
3331
if (node.Kind is
RegexNodeKind
.ECMABoundary)
3346
Debug.Assert(node.Kind is
RegexNodeKind
.Beginning or
RegexNodeKind
.Start or
RegexNodeKind
.Bol or
RegexNodeKind
.End or
RegexNodeKind
.EndZ or
RegexNodeKind
.Eol, $"Unexpected type: {node.Kind}");
3353
case
RegexNodeKind
.Beginning:
3354
case
RegexNodeKind
.Start:
3365
if (node.Kind ==
RegexNodeKind
.Beginning)
3377
case
RegexNodeKind
.Bol:
3408
case
RegexNodeKind
.End:
3425
case
RegexNodeKind
.EndZ:
3442
goto case
RegexNodeKind
.Eol;
3444
case
RegexNodeKind
.Eol:
3484
Debug.Assert(node.Kind is
RegexNodeKind
.Multi, $"Unexpected type: {node.Kind}");
3536
Debug.Assert(node.Kind is
RegexNodeKind
.Oneloop or
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Setloop, $"Unexpected type: {node.Kind}");
3675
case
RegexNodeKind
.One or
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic or
RegexNodeKind
.Onelazy:
3680
case
RegexNodeKind
.Notone or
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Notoneloopatomic or
RegexNodeKind
.Notonelazy:
3685
case
RegexNodeKind
.Multi:
3811
Debug.Assert(node.Kind is
RegexNodeKind
.Onelazy or
RegexNodeKind
.Notonelazy or
RegexNodeKind
.Setlazy, $"Unexpected type: {node.Kind}");
3912
node.Kind is
RegexNodeKind
.Notonelazy &&
4053
node.Kind is
RegexNodeKind
.Setlazy &&
4158
Debug.Assert(node.Kind is
RegexNodeKind
.Lazyloop, $"Unexpected type: {node.Kind}");
4670
Debug.Assert(node.Kind is
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic or
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Notoneloopatomic or
RegexNodeKind
.Setloop or
RegexNodeKind
.Setloopatomic, $"Unexpected type: {node.Kind}");
4917
Debug.Assert(node.Kind is
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic or
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Notoneloopatomic or
RegexNodeKind
.Setloop or
RegexNodeKind
.Setloopatomic, $"Unexpected type: {node.Kind}");
5006
Debug.Assert(node.Kind is
RegexNodeKind
.Loop or
RegexNodeKind
.Lazyloop, $"Unexpected type: {node.Kind}");
5044
Debug.Assert(node.Kind is
RegexNodeKind
.Loop or
RegexNodeKind
.Lazyloop, $"Unexpected type: {node.Kind}");
5442
if (node.Kind ==
RegexNodeKind
.Multi)
5475
if (node.Kind ==
RegexNodeKind
.Multi)
5668
if (root.Kind is
RegexNodeKind
.Multi or
RegexNodeKind
.One or
RegexNodeKind
.Notone or
RegexNodeKind
.Set)
5686
Ldc((root.Kind ==
RegexNodeKind
.Multi ? root.Str!.Length : 1) * (!rtl ? 1 : -1));
System\Text\RegularExpressions\RegexFindOptimizations.cs (23)
56
if (rightToLeft && LeadingAnchor ==
RegexNodeKind
.Bol)
59
LeadingAnchor =
RegexNodeKind
.Unknown;
61
if (LeadingAnchor is
RegexNodeKind
.Beginning or
RegexNodeKind
.Start or
RegexNodeKind
.EndZ or
RegexNodeKind
.End)
65
(
RegexNodeKind
.Beginning, false) => FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Beginning,
66
(
RegexNodeKind
.Beginning, true) => FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Beginning,
67
(
RegexNodeKind
.Start, false) => FindNextStartingPositionMode.LeadingAnchor_LeftToRight_Start,
68
(
RegexNodeKind
.Start, true) => FindNextStartingPositionMode.LeadingAnchor_RightToLeft_Start,
69
(
RegexNodeKind
.End, false) => FindNextStartingPositionMode.LeadingAnchor_LeftToRight_End,
70
(
RegexNodeKind
.End, true) => FindNextStartingPositionMode.LeadingAnchor_RightToLeft_End,
83
if (TrailingAnchor is
RegexNodeKind
.End or
RegexNodeKind
.EndZ &&
90
FindMode = TrailingAnchor ==
RegexNodeKind
.End ?
280
LeadingAnchor ==
RegexNodeKind
.Bol; // there's a leading BOL anchor we can otherwise search for
286
public
RegexNodeKind
LeadingAnchor { get; private set; }
289
public
RegexNodeKind
TrailingAnchor { get; }
409
Debug.Assert(LeadingAnchor !=
RegexNodeKind
.Bol, "BOL isn't enabled for RTL");
535
if (LeadingAnchor ==
RegexNodeKind
.Bol)
822
Debug.Assert(loopNode.Kind is
RegexNodeKind
.Setloop or
RegexNodeKind
.Setlazy or
RegexNodeKind
.Setloopatomic);
System\Text\RegularExpressions\RegexNode.cs (749)
23
public
RegexNodeKind
Kind { get; private set; }
26
/// <remarks>For a <see cref="
RegexNodeKind
.Multi"/>, this is the string from the expression. For an <see cref="IsSetFamily"/> node, this is the character class string from <see cref="RegexCharClass"/>.</remarks>
51
public RegexNode(
RegexNodeKind
kind, RegexOptions options)
57
public RegexNode(
RegexNodeKind
kind, RegexOptions options, char ch)
64
public RegexNode(
RegexNodeKind
kind, RegexOptions options, string str)
71
public RegexNode(
RegexNodeKind
kind, RegexOptions options, int m)
78
public RegexNode(
RegexNodeKind
kind, RegexOptions options, int m, int n)
89
Debug.Assert(Kind is
RegexNodeKind
.Onelazy or
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic or
90
RegexNodeKind
.Notonelazy or
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Notoneloopatomic or
91
RegexNodeKind
.Setlazy or
RegexNodeKind
.Setloop or
RegexNodeKind
.Setloopatomic);
121
return new RegexNode(
RegexNodeKind
.One, options & ~RegexOptions.IgnoreCase, ch);
127
return new RegexNode(
RegexNodeKind
.Set, options & ~RegexOptions.IgnoreCase, stringSet);
131
return new RegexNode(
RegexNodeKind
.One, options, ch);
138
Kind ==
RegexNodeKind
.Concatenate &&
150
private void MakeRep(
RegexNodeKind
kind, int min, int max)
152
Kind += kind -
RegexNodeKind
.One;
169
case
RegexNodeKind
.Oneloop or
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Setloop:
172
Kind +=
RegexNodeKind
.Oneloopatomic -
RegexNodeKind
.Oneloop;
175
case
RegexNodeKind
.Onelazy or
RegexNodeKind
.Notonelazy or
RegexNodeKind
.Setlazy:
179
Kind +=
RegexNodeKind
.Oneloopatomic -
RegexNodeKind
.Onelazy;
189
Kind =
RegexNodeKind
.Empty;
193
else if (Kind ==
RegexNodeKind
.Oneloopatomic && N is >= 2 and <= MultiVsRepeaterLimit)
197
Kind =
RegexNodeKind
.Multi;
204
case
RegexNodeKind
.Loop:
205
if (Parent is not { Kind:
RegexNodeKind
.Atomic })
207
RegexNode loopAsChild = new(
RegexNodeKind
.Loop, Options, M, N);
208
Kind =
RegexNodeKind
.Atomic;
215
case
RegexNodeKind
.Lazyloop:
225
goto case
RegexNodeKind
.Loop;
228
Kind =
RegexNodeKind
.Empty;
243
Debug.Assert(Kind ==
RegexNodeKind
.Capture, "Every generated tree should begin with a capture node");
262
Debug.Assert(Kind !=
RegexNodeKind
.Group, "All Group nodes should have been removed.");
267
case
RegexNodeKind
.Group:
271
case
RegexNodeKind
.Beginning:
272
case
RegexNodeKind
.Bol:
273
case
RegexNodeKind
.Boundary:
274
case
RegexNodeKind
.ECMABoundary:
275
case
RegexNodeKind
.Empty:
276
case
RegexNodeKind
.End:
277
case
RegexNodeKind
.EndZ:
278
case
RegexNodeKind
.Eol:
279
case
RegexNodeKind
.Multi:
280
case
RegexNodeKind
.NonBoundary:
281
case
RegexNodeKind
.NonECMABoundary:
282
case
RegexNodeKind
.Nothing:
283
case
RegexNodeKind
.Notone:
284
case
RegexNodeKind
.Notonelazy:
285
case
RegexNodeKind
.Notoneloop:
286
case
RegexNodeKind
.Notoneloopatomic:
287
case
RegexNodeKind
.One:
288
case
RegexNodeKind
.Onelazy:
289
case
RegexNodeKind
.Oneloop:
290
case
RegexNodeKind
.Oneloopatomic:
291
case
RegexNodeKind
.Backreference:
292
case
RegexNodeKind
.Set:
293
case
RegexNodeKind
.Setlazy:
294
case
RegexNodeKind
.Setloop:
295
case
RegexNodeKind
.Setloopatomic:
296
case
RegexNodeKind
.Start:
297
case
RegexNodeKind
.UpdateBumpalong:
301
case
RegexNodeKind
.Atomic:
302
case
RegexNodeKind
.Capture:
303
case
RegexNodeKind
.Lazyloop:
304
case
RegexNodeKind
.Loop:
305
case
RegexNodeKind
.NegativeLookaround:
306
case
RegexNodeKind
.PositiveLookaround:
310
case
RegexNodeKind
.BackreferenceConditional:
314
case
RegexNodeKind
.ExpressionConditional:
318
case
RegexNodeKind
.Concatenate:
319
case
RegexNodeKind
.Alternate:
331
case
RegexNodeKind
.Multi:
336
case
RegexNodeKind
.Set:
337
case
RegexNodeKind
.Setloop:
338
case
RegexNodeKind
.Setloopatomic:
339
case
RegexNodeKind
.Setlazy:
351
case
RegexNodeKind
.Backreference:
372
Debug.Assert(rootNode.Kind ==
RegexNodeKind
.Capture);
429
case
RegexNodeKind
.Atomic:
433
case
RegexNodeKind
.Concatenate:
438
case
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic or
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Notoneloopatomic or
RegexNodeKind
.Setloop or
RegexNodeKind
.Setloopatomic when node.N == int.MaxValue:
439
case
RegexNodeKind
.Onelazy or
RegexNodeKind
.Notonelazy or
RegexNodeKind
.Setlazy when node.N == int.MaxValue && !atomicByAncestry:
440
if (node.Parent is { Kind:
RegexNodeKind
.Concatenate } parent)
442
parent.InsertChild(1, new RegexNode(
RegexNodeKind
.UpdateBumpalong, node.Options));
523
case
RegexNodeKind
.Oneloop or
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Setloop:
524
case
RegexNodeKind
.Onelazy or
RegexNodeKind
.Notonelazy or
RegexNodeKind
.Setlazy:
530
case
RegexNodeKind
.Atomic:
531
case
RegexNodeKind
.PositiveLookaround:
532
case
RegexNodeKind
.NegativeLookaround:
542
case
RegexNodeKind
.Capture:
543
case
RegexNodeKind
.Concatenate when !rtl:
545
if ((existingChild.Kind is
RegexNodeKind
.Alternate or
RegexNodeKind
.BackreferenceConditional or
RegexNodeKind
.ExpressionConditional or
RegexNodeKind
.Loop or
RegexNodeKind
.Lazyloop) &&
546
node.Parent is not { Kind:
RegexNodeKind
.Atomic }) // validate grandparent isn't atomic
548
var atomic = new RegexNode(
RegexNodeKind
.Atomic, existingChild.Options);
558
case
RegexNodeKind
.Alternate:
559
case
RegexNodeKind
.BackreferenceConditional:
560
case
RegexNodeKind
.ExpressionConditional:
568
if (node.Kind !=
RegexNodeKind
.ExpressionConditional) // ReduceExpressionConditional will have already applied ending backtracking removal
583
case
RegexNodeKind
.Lazyloop:
584
case
RegexNodeKind
.Loop:
589
Debug.Assert(node.Kind is
RegexNodeKind
.Atomic or
RegexNodeKind
.Empty or
RegexNodeKind
.Loop or
RegexNodeKind
.Lazyloop);
591
if (node.Kind is
RegexNodeKind
.Atomic)
594
Debug.Assert(node.Kind is
RegexNodeKind
.Loop or
RegexNodeKind
.Lazyloop);
597
if (node.Kind is
RegexNodeKind
.Loop or
RegexNodeKind
.Lazyloop)
631
case
RegexNodeKind
.Backreference:
638
RegexNodeKind
.Alternate => ReduceAlternation(),
639
RegexNodeKind
.Atomic => ReduceAtomic(),
640
RegexNodeKind
.Concatenate => ReduceConcatenation(),
641
RegexNodeKind
.Group => ReduceGroup(),
642
RegexNodeKind
.Loop or
RegexNodeKind
.Lazyloop => ReduceLoops(),
643
RegexNodeKind
.PositiveLookaround or
RegexNodeKind
.NegativeLookaround => ReduceLookaround(),
644
RegexNodeKind
.Set or
RegexNodeKind
.Setloop or
RegexNodeKind
.Setloopatomic or
RegexNodeKind
.Setlazy => ReduceSet(),
645
RegexNodeKind
.ExpressionConditional => ReduceExpressionConditional(),
646
RegexNodeKind
.BackreferenceConditional => ReduceBackreferenceConditional(),
659
Debug.Assert(Kind is
RegexNodeKind
.Alternate or
RegexNodeKind
.Concatenate);
662
0 => new RegexNode(Kind ==
RegexNodeKind
.Alternate ?
RegexNodeKind
.Nothing :
RegexNodeKind
.Empty, Options),
676
Debug.Assert(Kind ==
RegexNodeKind
.Group);
679
while (u.Kind ==
RegexNodeKind
.Group)
704
Debug.Assert(Kind ==
RegexNodeKind
.Atomic);
709
while (child.Kind ==
RegexNodeKind
.Atomic)
719
case
RegexNodeKind
.Empty:
720
case
RegexNodeKind
.Nothing:
725
case
RegexNodeKind
.One:
726
case
RegexNodeKind
.Notone:
727
case
RegexNodeKind
.Set:
728
case
RegexNodeKind
.Multi:
732
case
RegexNodeKind
.Oneloopatomic:
733
case
RegexNodeKind
.Notoneloopatomic:
734
case
RegexNodeKind
.Setloopatomic:
739
case
RegexNodeKind
.Oneloop:
740
case
RegexNodeKind
.Notoneloop:
741
case
RegexNodeKind
.Setloop:
742
case
RegexNodeKind
.Onelazy:
743
case
RegexNodeKind
.Notonelazy:
744
case
RegexNodeKind
.Setlazy:
750
case
RegexNodeKind
.Alternate:
759
if (branches[0].Kind ==
RegexNodeKind
.Empty)
761
return new RegexNode(
RegexNodeKind
.Empty, child.Options);
770
if (branches[i].Kind ==
RegexNodeKind
.Empty)
851
(child.Child(0).Kind is
RegexNodeKind
.Empty || child.Child(1).Kind is
RegexNodeKind
.Empty); // can be transformed into a ? or ??
866
return child.Kind ==
RegexNodeKind
.Empty ?
881
Debug.Assert(Kind is
RegexNodeKind
.Loop or
RegexNodeKind
.Lazyloop);
884
RegexNodeKind
kind = Kind;
897
if (kind ==
RegexNodeKind
.Loop)
901
case
RegexNodeKind
.Oneloop:
902
case
RegexNodeKind
.Oneloopatomic:
903
case
RegexNodeKind
.Notoneloop:
904
case
RegexNodeKind
.Notoneloopatomic:
905
case
RegexNodeKind
.Setloop:
906
case
RegexNodeKind
.Setloopatomic:
915
case
RegexNodeKind
.Onelazy:
916
case
RegexNodeKind
.Notonelazy:
917
case
RegexNodeKind
.Setlazy:
951
return new RegexNode(
RegexNodeKind
.Nothing, Options);
962
case
RegexNodeKind
.One:
963
case
RegexNodeKind
.Notone:
964
case
RegexNodeKind
.Set:
965
child.MakeRep(u.Kind ==
RegexNodeKind
.Lazyloop ?
RegexNodeKind
.Onelazy :
RegexNodeKind
.Oneloop, u.M, u.N);
969
case
RegexNodeKind
.Empty:
974
case
RegexNodeKind
.PositiveLookaround when ContainsKind(child, [
RegexNodeKind
.Capture]) is false:
975
case
RegexNodeKind
.NegativeLookaround or
976
RegexNodeKind
.Beginning or
RegexNodeKind
.Start or
977
RegexNodeKind
.Bol or
RegexNodeKind
.Eol or
978
RegexNodeKind
.End or
RegexNodeKind
.EndZ or
979
RegexNodeKind
.Boundary or
RegexNodeKind
.ECMABoundary or
980
RegexNodeKind
.NonBoundary or
RegexNodeKind
.NonECMABoundary:
990
u = u.M == 0 ? new RegexNode(
RegexNodeKind
.Empty, Options) : child;
1013
Debug.Assert(Kind is
RegexNodeKind
.Set or
RegexNodeKind
.Setloop or
RegexNodeKind
.Setloopatomic or
RegexNodeKind
.Setlazy);
1018
Kind =
RegexNodeKind
.Nothing;
1026
Kind ==
RegexNodeKind
.Set ?
RegexNodeKind
.One :
1027
Kind ==
RegexNodeKind
.Setloop ?
RegexNodeKind
.Oneloop :
1028
Kind ==
RegexNodeKind
.Setloopatomic ?
RegexNodeKind
.Oneloopatomic :
1029
RegexNodeKind
.Onelazy;
1036
Kind ==
RegexNodeKind
.Set ?
RegexNodeKind
.Notone :
1037
Kind ==
RegexNodeKind
.Setloop ?
RegexNodeKind
.Notoneloop :
1038
Kind ==
RegexNodeKind
.Setloopatomic ?
RegexNodeKind
.Notoneloopatomic :
1039
RegexNodeKind
.Notonelazy;
1073
Debug.Assert(Kind ==
RegexNodeKind
.Alternate);
1078
return new RegexNode(
RegexNodeKind
.Nothing, Options);
1086
if (node.Kind ==
RegexNodeKind
.Alternate)
1089
if (node.Kind ==
RegexNodeKind
.Alternate)
1092
if (node.Kind ==
RegexNodeKind
.Alternate)
1100
if (node.Kind is
RegexNodeKind
.Alternate && node.ChildCount() == 2)
1102
if (node.Child(1).Kind is
RegexNodeKind
.Empty)
1106
else if (node.Child(0).Kind is
RegexNodeKind
.Empty)
1143
if (at.Kind ==
RegexNodeKind
.Alternate)
1161
else if (at.Kind is
RegexNodeKind
.Set or
RegexNodeKind
.One)
1166
if (at.Kind ==
RegexNodeKind
.Set)
1190
if (prev.Kind ==
RegexNodeKind
.One)
1200
if (at.Kind ==
RegexNodeKind
.One)
1210
prev.Kind =
RegexNodeKind
.Set;
1217
else if (at.Kind ==
RegexNodeKind
.Nothing)
1241
Debug.Assert(alternation.Kind ==
RegexNodeKind
.Alternate);
1260
RegexNode required = startingNode.Kind ==
RegexNodeKind
.Concatenate ? startingNode.Child(0) : startingNode;
1263
case
RegexNodeKind
.One or
RegexNodeKind
.Notone or
RegexNodeKind
.Set:
1264
case
RegexNodeKind
.Oneloopatomic or
RegexNodeKind
.Notoneloopatomic or
RegexNodeKind
.Setloopatomic:
1265
case
RegexNodeKind
.Oneloop or
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Setloop or
RegexNodeKind
.Onelazy or
RegexNodeKind
.Notonelazy or
RegexNodeKind
.Setlazy when required.M == required.N:
1266
case
RegexNodeKind
.Beginning or
RegexNodeKind
.Start or
RegexNodeKind
.Bol
1267
or
RegexNodeKind
.End or
RegexNodeKind
.EndZ or
RegexNodeKind
.Eol
1268
or
RegexNodeKind
.Boundary or
RegexNodeKind
.ECMABoundary
1269
or
RegexNodeKind
.NonBoundary or
RegexNodeKind
.NonECMABoundary:
1281
RegexNode other = endingNode.Kind ==
RegexNodeKind
.Concatenate ? endingNode.Child(0) : endingNode;
1300
var newAlternate = new RegexNode(
RegexNodeKind
.Alternate, alternation.Options);
1303
if (children[i].Kind ==
RegexNodeKind
.Concatenate)
1311
newAlternate.AddChild(new RegexNode(
RegexNodeKind
.Empty, children[i].Options));
1316
if (alternation.Parent is RegexNode { Kind:
RegexNodeKind
.Atomic })
1318
var atomic = new RegexNode(
RegexNodeKind
.Atomic, alternation.Options);
1325
var newConcat = new RegexNode(
RegexNodeKind
.Concatenate, alternation.Options);
1341
Debug.Assert(node.Kind ==
RegexNodeKind
.Alternate);
1352
case
RegexNodeKind
.Empty when !seenEmpty:
1356
case
RegexNodeKind
.Empty:
1357
case
RegexNodeKind
.Nothing:
1384
Debug.Assert(alternation.Kind ==
RegexNodeKind
.Alternate);
1414
if (startingNode.Kind ==
RegexNodeKind
.One)
1434
if (startingNode.Kind ==
RegexNodeKind
.One)
1448
Debug.Assert(startingNode.Kind ==
RegexNodeKind
.Multi);
1479
new RegexNode(
RegexNodeKind
.One, startingNodeOptions, startingSpan[0]) :
1480
new RegexNode(
RegexNodeKind
.Multi, startingNodeOptions, startingSpan.ToString());
1481
var newAlternate = new RegexNode(
RegexNodeKind
.Alternate, startingNodeOptions);
1485
ProcessOneOrMulti(branch.Kind ==
RegexNodeKind
.Concatenate ? branch.Child(0) : branch, startingSpan);
1493
if (node.Kind ==
RegexNodeKind
.One)
1497
node.Kind =
RegexNodeKind
.Empty;
1502
Debug.Assert(node.Kind ==
RegexNodeKind
.Multi);
1506
node.Kind =
RegexNodeKind
.Empty;
1511
node.Kind =
RegexNodeKind
.One;
1523
if (alternation.Parent is RegexNode parent && parent.Kind ==
RegexNodeKind
.Atomic)
1525
var atomic = new RegexNode(
RegexNodeKind
.Atomic, startingNodeOptions);
1530
var newConcat = new RegexNode(
RegexNodeKind
.Concatenate, startingNodeOptions);
1550
RegexNode branch = Kind ==
RegexNodeKind
.Concatenate ? Child(0) : this;
1551
return branch.Kind is
RegexNodeKind
.One or
RegexNodeKind
.Multi ? branch : null;
1557
Debug.Assert(Kind is
RegexNodeKind
.One or
RegexNodeKind
.Multi || (IsOneFamily && M > 0));
1572
Debug.Assert(Kind is
RegexNodeKind
.Alternate);
1596
if (startingLiteralNode.IsOneFamily || startingLiteralNode.Kind is
RegexNodeKind
.Multi)
1642
case
RegexNodeKind
.One:
1643
case
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic or
RegexNodeKind
.Onelazy when node.M > 0:
1644
case
RegexNodeKind
.Notone:
1645
case
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Notoneloopatomic or
RegexNodeKind
.Notonelazy when node.M > 0:
1646
case
RegexNodeKind
.Set:
1647
case
RegexNodeKind
.Setloop or
RegexNodeKind
.Setloopatomic or
RegexNodeKind
.Setlazy when node.M > 0:
1648
case
RegexNodeKind
.Multi:
1651
case
RegexNodeKind
.Atomic:
1652
case
RegexNodeKind
.Concatenate:
1653
case
RegexNodeKind
.Capture:
1654
case
RegexNodeKind
.Group:
1655
case
RegexNodeKind
.Loop or
RegexNodeKind
.Lazyloop when node.M > 0:
1656
case
RegexNodeKind
.PositiveLookaround when allowZeroWidth:
1677
case
RegexNodeKind
.One or
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic or
RegexNodeKind
.Onelazy:
1680
case
RegexNodeKind
.Notone or
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Notoneloopatomic or
RegexNodeKind
.Notonelazy:
1683
case
RegexNodeKind
.Set or
RegexNodeKind
.Setloop or
RegexNodeKind
.Setloopatomic or
RegexNodeKind
.Setlazy:
1699
case
RegexNodeKind
.Multi:
1742
Debug.Assert(Kind ==
RegexNodeKind
.Concatenate);
1748
return new RegexNode(
RegexNodeKind
.Empty, Options);
1758
if (child.Kind ==
RegexNodeKind
.Nothing)
1784
Debug.Assert(Kind ==
RegexNodeKind
.Concatenate);
1801
if (at.Kind ==
RegexNodeKind
.Concatenate &&
1820
else if (at.Kind is
RegexNodeKind
.Multi or
RegexNodeKind
.One)
1834
if (prev.Kind ==
RegexNodeKind
.One)
1836
prev.Kind =
RegexNodeKind
.Multi;
1841
((at.Kind ==
RegexNodeKind
.One) ? $"{prev.Str}{at.Ch}" : prev.Str + at.Str) :
1842
((at.Kind ==
RegexNodeKind
.One) ? $"{at.Ch}{prev.Str}" : at.Str + prev.Str);
1844
else if (at.Kind ==
RegexNodeKind
.Empty)
1867
Debug.Assert(Kind ==
RegexNodeKind
.Concatenate);
1905
case
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic or
RegexNodeKind
.Onelazy or
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Notoneloopatomic or
RegexNodeKind
.Notonelazy when nextNode.Kind == currentNode.Kind && currentNode.Ch == nextNode.Ch:
1906
case
RegexNodeKind
.Setloop or
RegexNodeKind
.Setloopatomic or
RegexNodeKind
.Setlazy when nextNode.Kind == currentNode.Kind && currentNode.Str == nextNode.Str:
1908
currentNode.Kind is
RegexNodeKind
.Oneloopatomic or
RegexNodeKind
.Notoneloopatomic or
RegexNodeKind
.Setloopatomic)
1931
case
RegexNodeKind
.Oneloop or
RegexNodeKind
.Onelazy when nextNode.Kind ==
RegexNodeKind
.One && currentNode.Ch == nextNode.Ch:
1932
case
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Notonelazy when nextNode.Kind ==
RegexNodeKind
.Notone && currentNode.Ch == nextNode.Ch:
1933
case
RegexNodeKind
.Setloop or
RegexNodeKind
.Setlazy when nextNode.Kind ==
RegexNodeKind
.Set && currentNode.Str == nextNode.Str:
1947
case
RegexNodeKind
.Oneloop or
RegexNodeKind
.Onelazy when
1948
nextNode.Kind ==
RegexNodeKind
.Multi &&
1981
nextNode.Kind =
RegexNodeKind
.One;
1999
case
RegexNodeKind
.One when (nextNode.Kind is
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic or
RegexNodeKind
.Onelazy) && currentNode.Ch == nextNode.Ch:
2000
case
RegexNodeKind
.Notone when (nextNode.Kind is
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Notoneloopatomic or
RegexNodeKind
.Notonelazy) && currentNode.Ch == nextNode.Ch:
2001
case
RegexNodeKind
.Set when (nextNode.Kind is
RegexNodeKind
.Setloop or
RegexNodeKind
.Setloopatomic or
RegexNodeKind
.Setlazy) && currentNode.Str == nextNode.Str:
2014
case
RegexNodeKind
.Notone when nextNode.Kind == currentNode.Kind && currentNode.Ch == nextNode.Ch:
2015
case
RegexNodeKind
.Set when nextNode.Kind ==
RegexNodeKind
.Set && currentNode.Str == nextNode.Str:
2016
currentNode.MakeRep(
RegexNodeKind
.Oneloop, 2, 2);
2021
case
RegexNodeKind
.Beginning or
RegexNodeKind
.Start or
2022
RegexNodeKind
.End or
RegexNodeKind
.EndZ or
2023
RegexNodeKind
.Bol or
RegexNodeKind
.Eol or
2024
RegexNodeKind
.Boundary or
RegexNodeKind
.NonBoundary or
2025
RegexNodeKind
.ECMABoundary or
RegexNodeKind
.NonECMABoundary
2069
if (Kind is not
RegexNodeKind
.Concatenate)
2093
while (node.Kind is
RegexNodeKind
.Capture or
RegexNodeKind
.Concatenate)
2101
case
RegexNodeKind
.Oneloop or
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Setloop when CanBeMadeAtomic(node, subsequent, iterateNullableSubsequent: true, allowLazy: false):
2110
case
RegexNodeKind
.Onelazy or
RegexNodeKind
.Notonelazy or
RegexNodeKind
.Setlazy when CanBeMadeAtomic(node, subsequent, iterateNullableSubsequent: false, allowLazy: true):
2126
node.Kind -=
RegexNodeKind
.Onelazy -
RegexNodeKind
.Oneloop; // lazy to greedy
2130
case
RegexNodeKind
.Loop when CanBeMadeAtomic(node, subsequent, iterateNullableSubsequent: true, allowLazy: false):
2131
case
RegexNodeKind
.Lazyloop when CanBeMadeAtomic(node, subsequent, iterateNullableSubsequent: false, allowLazy: true):
2145
while (loopChild.Kind is
RegexNodeKind
.Capture or
RegexNodeKind
.Concatenate)
2157
RegexNodeKind
.Boundary or
RegexNodeKind
.ECMABoundary or
2158
RegexNodeKind
.Multi or
2159
RegexNodeKind
.One or
RegexNodeKind
.Notone or
RegexNodeKind
.Set &&
2164
else if (node.Kind is
RegexNodeKind
.Loop or
RegexNodeKind
.Lazyloop)
2168
goto case
RegexNodeKind
.Loop;
2176
case
RegexNodeKind
.Loop:
2186
case
RegexNodeKind
.Lazyloop:
2196
case
RegexNodeKind
.Alternate or
RegexNodeKind
.BackreferenceConditional or
RegexNodeKind
.ExpressionConditional:
2207
for (int b = node.Kind ==
RegexNodeKind
.ExpressionConditional ? 1 : 0; b < alternateBranches; b++)
2221
Debug.Assert(Kind is
RegexNodeKind
.PositiveLookaround or
RegexNodeKind
.NegativeLookaround);
2229
if (Kind is
RegexNodeKind
.NegativeLookaround && ContainsKind(Child(0), [
RegexNodeKind
.Backreference,
RegexNodeKind
.BackreferenceConditional]) is false)
2244
if (node is { Kind:
RegexNodeKind
.Capture, N: -1 })
2275
if (Kind is
RegexNodeKind
.PositiveLookaround)
2278
child.Kind is
RegexNodeKind
.Empty)
2283
else if (Kind is
RegexNodeKind
.NegativeLookaround)
2288
if (child.Kind is
RegexNodeKind
.Empty)
2290
Kind =
RegexNodeKind
.Nothing;
2298
private static bool IsZeroWidthAssertion(
RegexNodeKind
kind) => kind is
2299
RegexNodeKind
.PositiveLookaround or
RegexNodeKind
.NegativeLookaround or
2300
RegexNodeKind
.Beginning or
RegexNodeKind
.Start or
2301
RegexNodeKind
.Bol or
RegexNodeKind
.Eol or
2302
RegexNodeKind
.End or
RegexNodeKind
.EndZ or
2303
RegexNodeKind
.Boundary or
RegexNodeKind
.ECMABoundary or
2304
RegexNodeKind
.NonBoundary or
RegexNodeKind
.NonECMABoundary or
2305
RegexNodeKind
.UpdateBumpalong;
2309
private static bool? ContainsKind(RegexNode node, ReadOnlySpan<
RegexNodeKind
> kinds)
2311
foreach (
RegexNodeKind
kind in kinds)
2341
Debug.Assert(Kind ==
RegexNodeKind
.BackreferenceConditional);
2350
AddChild(new RegexNode(
RegexNodeKind
.Empty, Options));
2359
Debug.Assert(Kind ==
RegexNodeKind
.ExpressionConditional);
2368
AddChild(new RegexNode(
RegexNodeKind
.Empty, Options));
2377
if (condition.Kind ==
RegexNodeKind
.PositiveLookaround && (condition.Options & RegexOptions.RightToLeft) == 0)
2402
Debug.Assert(loopNode.Kind is
RegexNodeKind
.Oneloop or
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Setloop);
2413
case
RegexNodeKind
.One when CharInLoopSet(loopNode, literal.Ch): // e.g. \w+a\s : 'a' is in \w, check \s is disjoint
2414
case
RegexNodeKind
.Set when loopNode.Kind is
RegexNodeKind
.Setloop && RegexCharClass.IsSubsetOf(literal.Str!, loopNode.Str!): // e.g. \d+[0-9]\s
2426
case
RegexNodeKind
.Multi when CharInLoopSet(loopNode, literal.Str![0]) && !CharInLoopSet(loopNode, literal.Str[1]):
2438
RegexNodeKind
.Oneloop => loopNode.Ch == ch,
2439
RegexNodeKind
.Notoneloop => loopNode.Ch != ch,
2440
RegexNodeKind
.Setloop => RegexCharClass.CharInClass(ch, loopNode.Str!),
2462
while (node.Kind is
RegexNodeKind
.Capture or
RegexNodeKind
.Concatenate)
2480
case
RegexNodeKind
.Concatenate:
2481
case
RegexNodeKind
.Capture:
2482
case
RegexNodeKind
.Atomic:
2486
case
RegexNodeKind
.Loop or
RegexNodeKind
.Lazyloop when subsequent.M > 0:
2494
case
RegexNodeKind
.PositiveLookaround when (subsequent.Options & RegexOptions.RightToLeft) == 0:
2518
case
RegexNodeKind
.Alternate:
2519
case
RegexNodeKind
.ExpressionConditional when childCount is 3: // condition, yes, and no branch
2534
case
RegexNodeKind
.Oneloop:
2535
case
RegexNodeKind
.Onelazy when allowLazy:
2538
case
RegexNodeKind
.One when node.Ch != subsequent.Ch:
2539
case
RegexNodeKind
.Notone when node.Ch == subsequent.Ch:
2540
case
RegexNodeKind
.Set when !RegexCharClass.CharInClass(node.Ch, subsequent.Str!):
2541
case
RegexNodeKind
.Onelazy or
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic when subsequent.M > 0 && node.Ch != subsequent.Ch:
2542
case
RegexNodeKind
.Notonelazy or
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Notoneloopatomic when subsequent.M > 0 && node.Ch == subsequent.Ch:
2543
case
RegexNodeKind
.Setlazy or
RegexNodeKind
.Setloop or
RegexNodeKind
.Setloopatomic when subsequent.M > 0 && !RegexCharClass.CharInClass(node.Ch, subsequent.Str!):
2544
case
RegexNodeKind
.Multi when node.Ch != subsequent.Str![0]:
2545
case
RegexNodeKind
.End:
2546
case
RegexNodeKind
.EndZ or
RegexNodeKind
.Eol when node.Ch != '\n':
2547
case
RegexNodeKind
.Boundary when node.M > 0 && RegexCharClass.IsBoundaryWordChar(node.Ch):
2548
case
RegexNodeKind
.NonBoundary when node.M > 0 && !RegexCharClass.IsBoundaryWordChar(node.Ch):
2549
case
RegexNodeKind
.ECMABoundary when node.M > 0 && RegexCharClass.IsECMAWordChar(node.Ch):
2550
case
RegexNodeKind
.NonECMABoundary when node.M > 0 && !RegexCharClass.IsECMAWordChar(node.Ch):
2553
case
RegexNodeKind
.Onelazy or
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic when subsequent.M == 0 && node.Ch != subsequent.Ch:
2554
case
RegexNodeKind
.Notonelazy or
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Notoneloopatomic when subsequent.M == 0 && node.Ch == subsequent.Ch:
2555
case
RegexNodeKind
.Setlazy or
RegexNodeKind
.Setloop or
RegexNodeKind
.Setloopatomic when subsequent.M == 0 && !RegexCharClass.CharInClass(node.Ch, subsequent.Str!):
2564
case
RegexNodeKind
.Notoneloop:
2565
case
RegexNodeKind
.Notonelazy when allowLazy:
2568
case
RegexNodeKind
.One when node.Ch == subsequent.Ch:
2569
case
RegexNodeKind
.Onelazy or
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic when subsequent.M > 0 && node.Ch == subsequent.Ch:
2570
case
RegexNodeKind
.Multi when node.Ch == subsequent.Str![0]:
2571
case
RegexNodeKind
.End:
2574
case
RegexNodeKind
.Onelazy or
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic when subsequent.M == 0 && node.Ch == subsequent.Ch:
2583
case
RegexNodeKind
.Setloop:
2584
case
RegexNodeKind
.Setlazy when allowLazy:
2587
case
RegexNodeKind
.One when !RegexCharClass.CharInClass(subsequent.Ch, node.Str!):
2588
case
RegexNodeKind
.Set when !RegexCharClass.MayOverlap(node.Str!, subsequent.Str!):
2589
case
RegexNodeKind
.Onelazy or
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic when subsequent.M > 0 && !RegexCharClass.CharInClass(subsequent.Ch, node.Str!):
2590
case
RegexNodeKind
.Setlazy or
RegexNodeKind
.Setloop or
RegexNodeKind
.Setloopatomic when subsequent.M > 0 && !RegexCharClass.MayOverlap(node.Str!, subsequent.Str!):
2591
case
RegexNodeKind
.Multi when !RegexCharClass.CharInClass(subsequent.Str![0], node.Str!):
2592
case
RegexNodeKind
.End:
2593
case
RegexNodeKind
.EndZ or
RegexNodeKind
.Eol when !RegexCharClass.CharInClass('\n', node.Str!):
2594
case
RegexNodeKind
.Boundary when node.M > 0 && RegexCharClass.IsSubsetOf(node.Str!, RegexCharClass.WordClass):
2595
case
RegexNodeKind
.NonBoundary when node.M > 0 && node.Str is RegexCharClass.NotWordClass or RegexCharClass.NotDigitClass:
2596
case
RegexNodeKind
.ECMABoundary when node.M > 0 && node.Str is RegexCharClass.ECMAWordClass or RegexCharClass.ECMADigitClass:
2597
case
RegexNodeKind
.NonECMABoundary when node.M > 0 && node.Str is RegexCharClass.NotECMAWordClass or RegexCharClass.NotDigitClass:
2600
case
RegexNodeKind
.Onelazy or
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic when subsequent.M == 0 && !RegexCharClass.CharInClass(subsequent.Ch, node.Str!):
2601
case
RegexNodeKind
.Setlazy or
RegexNodeKind
.Setloop or
RegexNodeKind
.Setloopatomic when subsequent.M == 0 && !RegexCharClass.MayOverlap(node.Str!, subsequent.Str!):
2610
case
RegexNodeKind
.Loop:
2611
case
RegexNodeKind
.Lazyloop when allowLazy:
2634
case
RegexNodeKind
.One when !CharInStartingOrEndingSet(subsequent.Ch):
2635
case
RegexNodeKind
.Set when !MayOverlapStartingOrEndingSet(subsequent.Str!):
2636
case
RegexNodeKind
.Onelazy or
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic when subsequent.M > 0 && !CharInStartingOrEndingSet(subsequent.Ch):
2637
case
RegexNodeKind
.Setlazy or
RegexNodeKind
.Setloop or
RegexNodeKind
.Setloopatomic when subsequent.M > 0 && !MayOverlapStartingOrEndingSet(subsequent.Str!):
2638
case
RegexNodeKind
.Multi when !CharInStartingOrEndingSet(subsequent.Str![0]):
2639
case
RegexNodeKind
.End:
2640
case
RegexNodeKind
.EndZ or
RegexNodeKind
.Eol when !CharInStartingOrEndingSet('\n'):
2641
case
RegexNodeKind
.Boundary when node.M > 0 && RegexCharClass.IsSubsetOf(loopStartingSet, RegexCharClass.WordClass) && RegexCharClass.IsSubsetOf(loopEndingSet, RegexCharClass.WordClass):
2642
case
RegexNodeKind
.NonBoundary when node.M > 0 && (loopStartingSet is RegexCharClass.NotWordClass or RegexCharClass.NotDigitClass) && (loopEndingSet is RegexCharClass.NotWordClass or RegexCharClass.NotDigitClass):
2643
case
RegexNodeKind
.ECMABoundary when node.M > 0 && (loopStartingSet is RegexCharClass.ECMAWordClass or RegexCharClass.ECMADigitClass) && (loopEndingSet is RegexCharClass.ECMAWordClass or RegexCharClass.ECMADigitClass):
2644
case
RegexNodeKind
.NonECMABoundary when node.M > 0 && (loopStartingSet is RegexCharClass.NotECMAWordClass or RegexCharClass.NotDigitClass) && (loopEndingSet is RegexCharClass.NotECMAWordClass or RegexCharClass.NotDigitClass):
2647
case
RegexNodeKind
.Onelazy or
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic when subsequent.M == 0 && !CharInStartingOrEndingSet(subsequent.Ch):
2648
case
RegexNodeKind
.Setlazy or
RegexNodeKind
.Setloop or
RegexNodeKind
.Setloopatomic when subsequent.M == 0 && !MayOverlapStartingOrEndingSet(subsequent.Str!):
2703
case
RegexNodeKind
.Atomic:
2704
case
RegexNodeKind
.Alternate:
2705
case
RegexNodeKind
.Capture:
2709
case
RegexNodeKind
.Concatenate:
2740
RegexNodeKind
.Alternate => true,
2741
RegexNodeKind
.Loop or
RegexNodeKind
.Lazyloop when M != N => true,
2742
RegexNodeKind
.Oneloop or
RegexNodeKind
.Onelazy or
2743
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Notonelazy or
2744
RegexNodeKind
.Setloop or
RegexNodeKind
.Setlazy when M != N => true,
2788
Debug.Assert(node.Kind is not
RegexNodeKind
.Concatenate, "The existing logic assumes that the node itself isn't a concatenation.");
2801
case
RegexNodeKind
.Atomic:
2802
case
RegexNodeKind
.Alternate:
2803
case
RegexNodeKind
.Capture:
2807
case
RegexNodeKind
.Concatenate:
2843
case
RegexNodeKind
.One:
2844
case
RegexNodeKind
.Notone:
2845
case
RegexNodeKind
.Set:
2849
case
RegexNodeKind
.Multi:
2853
case
RegexNodeKind
.Notonelazy:
2854
case
RegexNodeKind
.Notoneloop:
2855
case
RegexNodeKind
.Notoneloopatomic:
2856
case
RegexNodeKind
.Onelazy:
2857
case
RegexNodeKind
.Oneloop:
2858
case
RegexNodeKind
.Oneloopatomic:
2859
case
RegexNodeKind
.Setlazy:
2860
case
RegexNodeKind
.Setloop:
2861
case
RegexNodeKind
.Setloopatomic:
2865
case
RegexNodeKind
.Lazyloop:
2866
case
RegexNodeKind
.Loop:
2870
case
RegexNodeKind
.Alternate:
2883
case
RegexNodeKind
.BackreferenceConditional:
2887
case
RegexNodeKind
.ExpressionConditional:
2891
case
RegexNodeKind
.Concatenate:
2903
case
RegexNodeKind
.Atomic:
2904
case
RegexNodeKind
.Capture:
2905
case
RegexNodeKind
.Group:
2910
case
RegexNodeKind
.Empty:
2911
case
RegexNodeKind
.Nothing:
2912
case
RegexNodeKind
.UpdateBumpalong:
2916
case
RegexNodeKind
.Beginning:
2917
case
RegexNodeKind
.Bol:
2918
case
RegexNodeKind
.Boundary:
2919
case
RegexNodeKind
.ECMABoundary:
2920
case
RegexNodeKind
.End:
2921
case
RegexNodeKind
.EndZ:
2922
case
RegexNodeKind
.Eol:
2923
case
RegexNodeKind
.NonBoundary:
2924
case
RegexNodeKind
.NonECMABoundary:
2925
case
RegexNodeKind
.Start:
2926
case
RegexNodeKind
.NegativeLookaround:
2927
case
RegexNodeKind
.PositiveLookaround:
2929
case
RegexNodeKind
.Backreference:
2937
goto case
RegexNodeKind
.Empty;
2956
case
RegexNodeKind
.One:
2957
case
RegexNodeKind
.Notone:
2958
case
RegexNodeKind
.Set:
2962
case
RegexNodeKind
.Multi:
2966
case
RegexNodeKind
.Notonelazy or
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Notoneloopatomic or
2967
RegexNodeKind
.Onelazy or
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic or
2968
RegexNodeKind
.Setlazy or
RegexNodeKind
.Setloop or
RegexNodeKind
.Setloopatomic:
2972
case
RegexNodeKind
.Loop or
RegexNodeKind
.Lazyloop:
2987
case
RegexNodeKind
.Alternate:
3010
case
RegexNodeKind
.BackreferenceConditional:
3011
case
RegexNodeKind
.ExpressionConditional:
3014
int i = Kind ==
RegexNodeKind
.BackreferenceConditional ? 0 : 1;
3020
case
RegexNodeKind
.Concatenate:
3042
case
RegexNodeKind
.Atomic:
3043
case
RegexNodeKind
.Capture:
3048
case
RegexNodeKind
.Empty:
3049
case
RegexNodeKind
.Nothing:
3050
case
RegexNodeKind
.UpdateBumpalong:
3051
case
RegexNodeKind
.Beginning:
3052
case
RegexNodeKind
.Bol:
3053
case
RegexNodeKind
.Boundary:
3054
case
RegexNodeKind
.ECMABoundary:
3055
case
RegexNodeKind
.End:
3056
case
RegexNodeKind
.EndZ:
3057
case
RegexNodeKind
.Eol:
3058
case
RegexNodeKind
.NonBoundary:
3059
case
RegexNodeKind
.NonECMABoundary:
3060
case
RegexNodeKind
.Start:
3061
case
RegexNodeKind
.PositiveLookaround:
3062
case
RegexNodeKind
.NegativeLookaround:
3066
case
RegexNodeKind
.Backreference:
3074
goto case
RegexNodeKind
.Empty;
3105
Debug.Assert(Kind ==
RegexNodeKind
.Concatenate, $"Expected Concatenate, got {Kind}");
3127
while (child.Kind is
RegexNodeKind
.Capture or
RegexNodeKind
.Atomic)
3133
if (child.Kind is
RegexNodeKind
.One)
3146
else if (child.Kind is
RegexNodeKind
.Multi)
3158
else if (child.Kind is
RegexNodeKind
.Set ||
3159
(child.Kind is
RegexNodeKind
.Setloop or
RegexNodeKind
.Setlazy or
RegexNodeKind
.Setloopatomic && child.M == child.N))
3168
vsb.Append((char)(twoChars[0] | 0x20), child.Kind is
RegexNodeKind
.Set ? 1 : child.M);
3170
else if (child.Kind is
RegexNodeKind
.Concatenate)
3190
else if (child.Kind is
RegexNodeKind
.Empty)
3241
Debug.Assert(Kind ==
RegexNodeKind
.Concatenate, $"Expected Concatenate, got {Kind}");
3245
RegexNodeKind
.One or
RegexNodeKind
.Notone or
RegexNodeKind
.Set => true,
3246
RegexNodeKind
.Multi => true,
3247
RegexNodeKind
.Oneloop or
RegexNodeKind
.Onelazy or
RegexNodeKind
.Oneloopatomic or
3248
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Notonelazy or
RegexNodeKind
.Notoneloopatomic or
3249
RegexNodeKind
.Setloop or
RegexNodeKind
.Setlazy or
RegexNodeKind
.Setloopatomic
3291
return new RegexNode(
RegexNodeKind
.Empty, Options);
3297
case <= MultiVsRepeaterLimit when Kind ==
RegexNodeKind
.One:
3303
Kind =
RegexNodeKind
.Multi;
3312
case
RegexNodeKind
.One:
3313
case
RegexNodeKind
.Notone:
3314
case
RegexNodeKind
.Set:
3315
MakeRep(lazy ?
RegexNodeKind
.Onelazy :
RegexNodeKind
.Oneloop, min, max);
3319
var result = new RegexNode(lazy ?
RegexNodeKind
.Lazyloop :
RegexNodeKind
.Loop, Options, min, max);
3450
public bool IsSetFamily => Kind is
RegexNodeKind
.Set or
RegexNodeKind
.Setloop or
RegexNodeKind
.Setloopatomic or
RegexNodeKind
.Setlazy;
3453
public bool IsOneFamily => Kind is
RegexNodeKind
.One or
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic or
RegexNodeKind
.Onelazy;
3456
public bool IsNotoneFamily => Kind is
RegexNodeKind
.Notone or
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Notoneloopatomic or
RegexNodeKind
.Notonelazy;
3507
case
RegexNodeKind
.Oneloop:
3508
case
RegexNodeKind
.Oneloopatomic:
3509
case
RegexNodeKind
.Notoneloop:
3510
case
RegexNodeKind
.Notoneloopatomic:
3511
case
RegexNodeKind
.Onelazy:
3512
case
RegexNodeKind
.Notonelazy:
3513
case
RegexNodeKind
.One:
3514
case
RegexNodeKind
.Notone:
3517
case
RegexNodeKind
.Capture:
3524
case
RegexNodeKind
.Backreference:
3525
case
RegexNodeKind
.BackreferenceConditional:
3528
case
RegexNodeKind
.Multi:
3536
case
RegexNodeKind
.Set:
3537
case
RegexNodeKind
.Setloop:
3538
case
RegexNodeKind
.Setloopatomic:
3539
case
RegexNodeKind
.Setlazy:
3546
case
RegexNodeKind
.Oneloop:
3547
case
RegexNodeKind
.Oneloopatomic:
3548
case
RegexNodeKind
.Notoneloop:
3549
case
RegexNodeKind
.Notoneloopatomic:
3550
case
RegexNodeKind
.Onelazy:
3551
case
RegexNodeKind
.Notonelazy:
3552
case
RegexNodeKind
.Setloop:
3553
case
RegexNodeKind
.Setloopatomic:
3554
case
RegexNodeKind
.Setlazy:
3555
case
RegexNodeKind
.Loop:
3556
case
RegexNodeKind
.Lazyloop:
System\Text\RegularExpressions\RegexParser.cs (87)
277
StartGroup(new RegexNode(
RegexNodeKind
.Capture, (_options & ~RegexOptions.IgnoreCase), 0, -1));
347
_unit = new RegexNode(
RegexNodeKind
.Set, _options & ~RegexOptions.IgnoreCase, setString);
400
_unit = new RegexNode((_options & RegexOptions.Multiline) != 0 ?
RegexNodeKind
.Bol :
RegexNodeKind
.Beginning, _options);
411
_unit = new RegexNode((_options & RegexOptions.Multiline) != 0 ?
RegexNodeKind
.Eol :
RegexNodeKind
.EndZ, _options);
418
_unit = new RegexNode(
RegexNodeKind
.Set, _options & ~RegexOptions.IgnoreCase, RegexCharClass.AnyClass);
422
_unit = new RegexNode(
RegexNodeKind
.Set, _options & ~RegexOptions.IgnoreCase, RegexCharClass.NotAnyNewLineClass);
426
_unit = new RegexNode(
RegexNodeKind
.Notone, _options & ~RegexOptions.IgnoreCase, '\n');
544
_concatenation = new RegexNode(
RegexNodeKind
.Concatenate, _options);
829
return new RegexNode(
RegexNodeKind
.Group, _options);
833
return new RegexNode(
RegexNodeKind
.Capture, _options, _autocap++, -1);
846
RegexNodeKind
nodeType;
853
nodeType =
RegexNodeKind
.Group;
859
nodeType =
RegexNodeKind
.PositiveLookaround;
865
nodeType =
RegexNodeKind
.NegativeLookaround;
870
nodeType =
RegexNodeKind
.Atomic;
893
nodeType =
RegexNodeKind
.PositiveLookaround;
904
nodeType =
RegexNodeKind
.NegativeLookaround;
1007
return new RegexNode(
RegexNodeKind
.Capture, _options, capnum, uncapnum);
1029
return new RegexNode(
RegexNodeKind
.BackreferenceConditional, _options, capnum);
1043
return new RegexNode(
RegexNodeKind
.BackreferenceConditional, _options, tmpCapnum);
1048
nodeType =
RegexNodeKind
.ExpressionConditional;
1072
nodeType =
RegexNodeKind
.Group;
1075
if (_group!.Kind !=
RegexNodeKind
.ExpressionConditional || _group.ChildCount() > 0)
1166
(_options & RegexOptions.AnyNewLine) != 0 ? AnyNewLineEndZNode() : new RegexNode(
RegexNodeKind
.EndZ, _options);
1171
new RegexNode(
RegexNodeKind
.Set, (_options & ~RegexOptions.IgnoreCase), (_options & RegexOptions.ECMAScript) != 0 ? RegexCharClass.ECMAWordClass : RegexCharClass.WordClass);
1176
new RegexNode(
RegexNodeKind
.Set, (_options & ~RegexOptions.IgnoreCase), (_options & RegexOptions.ECMAScript) != 0 ? RegexCharClass.NotECMAWordClass : RegexCharClass.NotWordClass);
1181
new RegexNode(
RegexNodeKind
.Set, (_options & ~RegexOptions.IgnoreCase), (_options & RegexOptions.ECMAScript) != 0 ? RegexCharClass.ECMASpaceClass : RegexCharClass.SpaceClass);
1186
new RegexNode(
RegexNodeKind
.Set, (_options & ~RegexOptions.IgnoreCase), (_options & RegexOptions.ECMAScript) != 0 ? RegexCharClass.NotECMASpaceClass : RegexCharClass.NotSpaceClass);
1191
new RegexNode(
RegexNodeKind
.Set, (_options & ~RegexOptions.IgnoreCase), (_options & RegexOptions.ECMAScript) != 0 ? RegexCharClass.ECMADigitClass : RegexCharClass.DigitClass);
1196
new RegexNode(
RegexNodeKind
.Set, (_options & ~RegexOptions.IgnoreCase), (_options & RegexOptions.ECMAScript) != 0 ? RegexCharClass.NotECMADigitClass : RegexCharClass.NotDigitClass);
1213
return new RegexNode(
RegexNodeKind
.Set, (_options & ~RegexOptions.IgnoreCase), cc.ToStringClass());
1217
if (result != null && result.Kind ==
RegexNodeKind
.Backreference && (result.Options & RegexOptions.IgnoreCase) != 0)
1278
IsCaptureSlot(capnum) ? new RegexNode(
RegexNodeKind
.Backreference, _options, capnum) :
1310
return scanOnly ? null : new RegexNode(
RegexNodeKind
.Backreference, _options, capnum);
1324
return new RegexNode(
RegexNodeKind
.Backreference, _options, capnum);
1344
_capnames?[capname] is int tmpCapnum ? new RegexNode(
RegexNodeKind
.Backreference, _options, tmpCapnum) :
1420
return new RegexNode(
RegexNodeKind
.Backreference, _options, capnum);
1430
return new RegexNode(
RegexNodeKind
.Backreference, _options, capnum);
1442
return new RegexNode(
RegexNodeKind
.Backreference, _options, tmpCapnum);
1480
return new RegexNode(
RegexNodeKind
.Backreference, _options, capnum);
1741
var lookbehindCr = new RegexNode(
RegexNodeKind
.PositiveLookaround, lookbehindOpts);
1742
lookbehindCr.AddChild(new RegexNode(
RegexNodeKind
.One, lookbehindOptsNoCase, '\r'));
1745
var crThenLf = new RegexNode(
RegexNodeKind
.Concatenate, lookaheadOpts);
1747
crThenLf.AddChild(new RegexNode(
RegexNodeKind
.One, lookaheadOptsNoCase, '\n'));
1750
var guard = new RegexNode(
RegexNodeKind
.NegativeLookaround, lookaheadOpts);
1769
var crlfEnd = new RegexNode(
RegexNodeKind
.Concatenate, lookaheadOpts);
1770
crlfEnd.AddChild(new RegexNode(
RegexNodeKind
.One, lookaheadOptsNoCase, '\r'));
1771
crlfEnd.AddChild(new RegexNode(
RegexNodeKind
.One, lookaheadOptsNoCase, '\n'));
1772
crlfEnd.AddChild(new RegexNode(
RegexNodeKind
.End, lookaheadOpts));
1775
var anyNewLineOptEnd = new RegexNode(
RegexNodeKind
.Concatenate, lookaheadOpts);
1776
anyNewLineOptEnd.AddChild(new RegexNode(
RegexNodeKind
.Set, lookaheadOptsNoCase, RegexCharClass.AnyNewLineClass).MakeQuantifier(false, 0, 1));
1777
anyNewLineOptEnd.AddChild(new RegexNode(
RegexNodeKind
.End, lookaheadOpts));
1780
var innerAlt = new RegexNode(
RegexNodeKind
.Alternate, lookaheadOpts);
1783
var lookahead = new RegexNode(
RegexNodeKind
.PositiveLookaround, lookaheadOpts);
1787
var result = new RegexNode(
RegexNodeKind
.Concatenate, opts);
1806
var innerAlt = new RegexNode(
RegexNodeKind
.Alternate, lookaheadOpts);
1807
innerAlt.AddChild(new RegexNode(
RegexNodeKind
.Set, lookaheadOptsNoCase, RegexCharClass.AnyNewLineClass));
1808
innerAlt.AddChild(new RegexNode(
RegexNodeKind
.End, lookaheadOpts));
1809
var lookahead = new RegexNode(
RegexNodeKind
.PositiveLookaround, lookaheadOpts);
1813
var result = new RegexNode(
RegexNodeKind
.Concatenate, opts);
1832
var innerAlt = new RegexNode(
RegexNodeKind
.Alternate, lookbehindOpts);
1833
innerAlt.AddChild(new RegexNode(
RegexNodeKind
.Set, lookbehindOptsNoCase, RegexCharClass.AnyNewLineClass));
1834
innerAlt.AddChild(new RegexNode(
RegexNodeKind
.Beginning, lookbehindOpts));
1835
var lookbehind = new RegexNode(
RegexNodeKind
.PositiveLookaround, lookbehindOpts);
1839
var result = new RegexNode(
RegexNodeKind
.Concatenate, opts);
1847
private readonly
RegexNodeKind
TypeFromCode(char ch) =>
1850
'b' => (_options & RegexOptions.ECMAScript) != 0 ?
RegexNodeKind
.ECMABoundary :
RegexNodeKind
.Boundary,
1851
'B' => (_options & RegexOptions.ECMAScript) != 0 ?
RegexNodeKind
.NonECMABoundary :
RegexNodeKind
.NonBoundary,
1852
'A' =>
RegexNodeKind
.Beginning,
1853
'G' =>
RegexNodeKind
.Start,
1854
'Z' =>
RegexNodeKind
.EndZ,
1855
'z' =>
RegexNodeKind
.End,
1856
_ =>
RegexNodeKind
.Nothing,
2198
_concatenation!.AddChild(new RegexNode(
RegexNodeKind
.Multi, _options & ~RegexOptions.IgnoreCase, _pattern.Substring(pos, cch)));
2228
if (_group.Kind ==
RegexNodeKind
.ExpressionConditional && _group.ChildCount() == 0)
2244
_alternation = new RegexNode(
RegexNodeKind
.Alternate, _options);
2245
_concatenation = new RegexNode(
RegexNodeKind
.Concatenate, _options);
2253
if (_group!.Kind is
RegexNodeKind
.ExpressionConditional or
RegexNodeKind
.BackreferenceConditional)
2262
_concatenation = new RegexNode(
RegexNodeKind
.Concatenate, _options);
2268
if (_group!.Kind is
RegexNodeKind
.ExpressionConditional or
RegexNodeKind
.BackreferenceConditional)
2272
if (_group.Kind ==
RegexNodeKind
.BackreferenceConditional && _group.ChildCount() > 2 || _group.ChildCount() > 3)
System\Text\RegularExpressions\RegexPrefixAnalyzer.cs (224)
84
case
RegexNodeKind
.Atomic:
85
case
RegexNodeKind
.Capture:
90
case
RegexNodeKind
.Bol:
91
case
RegexNodeKind
.Eol:
92
case
RegexNodeKind
.Boundary:
93
case
RegexNodeKind
.ECMABoundary:
94
case
RegexNodeKind
.NonBoundary:
95
case
RegexNodeKind
.NonECMABoundary:
96
case
RegexNodeKind
.Beginning:
97
case
RegexNodeKind
.Start:
98
case
RegexNodeKind
.EndZ:
99
case
RegexNodeKind
.End:
100
case
RegexNodeKind
.Empty:
101
case
RegexNodeKind
.UpdateBumpalong:
102
case
RegexNodeKind
.PositiveLookaround:
103
case
RegexNodeKind
.NegativeLookaround:
112
case
RegexNodeKind
.One or
RegexNodeKind
.Oneloop or
RegexNodeKind
.Onelazy or
RegexNodeKind
.Oneloopatomic when !ignoreCase || !RegexCharClass.ParticipatesInCaseConversion(node.Ch):
114
int reps = node.Kind is
RegexNodeKind
.One ? 1 : Math.Min(node.M, MaxPrefixLength);
119
return node.Kind is
RegexNodeKind
.One || reps == node.N;
124
case
RegexNodeKind
.Multi:
156
case
RegexNodeKind
.Set or
RegexNodeKind
.Setloop or
RegexNodeKind
.Setlazy or
RegexNodeKind
.Setloopatomic when !RegexCharClass.IsNegated(node.Str!): // negated sets are too complex to analyze
164
int reps = node.Kind is
RegexNodeKind
.Set ? 1 : Math.Min(node.M, MaxPrefixLength);
209
return node.Kind is
RegexNodeKind
.Set || reps == node.N;
212
case
RegexNodeKind
.Concatenate:
226
case
RegexNodeKind
.Loop or
RegexNodeKind
.Lazyloop when node.M > 0:
242
case
RegexNodeKind
.Alternate:
363
case
RegexNodeKind
.Concatenate:
377
case
RegexNodeKind
.Alternate when !rtl: // for RTL we'd need to be matching the suffixes of the alternation cases
422
case
RegexNodeKind
.One:
427
case
RegexNodeKind
.Multi:
432
case
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic or
RegexNodeKind
.Onelazy when node.M > 0:
439
case
RegexNodeKind
.Loop or
RegexNodeKind
.Lazyloop when node.M > 0:
454
case
RegexNodeKind
.Atomic:
455
case
RegexNodeKind
.Capture:
459
case
RegexNodeKind
.Bol:
460
case
RegexNodeKind
.Eol:
461
case
RegexNodeKind
.Boundary:
462
case
RegexNodeKind
.ECMABoundary:
463
case
RegexNodeKind
.NonBoundary:
464
case
RegexNodeKind
.NonECMABoundary:
465
case
RegexNodeKind
.Beginning:
466
case
RegexNodeKind
.Start:
467
case
RegexNodeKind
.EndZ:
468
case
RegexNodeKind
.End:
469
case
RegexNodeKind
.Empty:
470
case
RegexNodeKind
.UpdateBumpalong:
471
case
RegexNodeKind
.PositiveLookaround:
472
case
RegexNodeKind
.NegativeLookaround:
491
case
RegexNodeKind
.Atomic:
492
case
RegexNodeKind
.Capture:
493
case
RegexNodeKind
.Loop or
RegexNodeKind
.Lazyloop when node.M > 0:
497
case
RegexNodeKind
.Concatenate:
600
case
RegexNodeKind
.One:
609
case
RegexNodeKind
.Onelazy or
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic when node.M > 0:
621
case
RegexNodeKind
.Multi:
633
case
RegexNodeKind
.Set:
641
case
RegexNodeKind
.Setlazy or
RegexNodeKind
.Setloop or
RegexNodeKind
.Setloopatomic when node.M > 0:
652
case
RegexNodeKind
.Notone:
658
case
RegexNodeKind
.Notonelazy or
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Notoneloopatomic when node.M == node.N:
662
case
RegexNodeKind
.Beginning:
663
case
RegexNodeKind
.Bol:
664
case
RegexNodeKind
.Boundary:
665
case
RegexNodeKind
.ECMABoundary:
666
case
RegexNodeKind
.Empty:
667
case
RegexNodeKind
.End:
668
case
RegexNodeKind
.EndZ:
669
case
RegexNodeKind
.Eol:
670
case
RegexNodeKind
.NonBoundary:
671
case
RegexNodeKind
.NonECMABoundary:
672
case
RegexNodeKind
.UpdateBumpalong:
673
case
RegexNodeKind
.Start:
674
case
RegexNodeKind
.NegativeLookaround:
675
case
RegexNodeKind
.PositiveLookaround:
681
case
RegexNodeKind
.Atomic:
682
case
RegexNodeKind
.Group:
683
case
RegexNodeKind
.Capture:
686
case
RegexNodeKind
.Lazyloop or
RegexNodeKind
.Loop when node.M > 0:
696
case
RegexNodeKind
.Concatenate:
709
case
RegexNodeKind
.Alternate when thorough:
954
case
RegexNodeKind
.One or
RegexNodeKind
.Oneloop or
RegexNodeKind
.Onelazy or
RegexNodeKind
.Oneloopatomic:
959
return node.Kind is
RegexNodeKind
.One || node.M > 0 ? true : null;
963
case
RegexNodeKind
.Notone or
RegexNodeKind
.Notoneloop or
RegexNodeKind
.Notoneloopatomic or
RegexNodeKind
.Notonelazy:
977
return node.Kind is
RegexNodeKind
.Notone || node.M > 0 ? true : null;
981
case
RegexNodeKind
.Set or
RegexNodeKind
.Setloop or
RegexNodeKind
.Setlazy or
RegexNodeKind
.Setloopatomic:
996
node.Kind is
RegexNodeKind
.Set || node.M > 0 ? true :
1000
case
RegexNodeKind
.Multi:
1012
case
RegexNodeKind
.Empty:
1013
case
RegexNodeKind
.Nothing:
1014
case
RegexNodeKind
.Bol:
1015
case
RegexNodeKind
.Eol:
1016
case
RegexNodeKind
.Boundary:
1017
case
RegexNodeKind
.NonBoundary:
1018
case
RegexNodeKind
.ECMABoundary:
1019
case
RegexNodeKind
.NonECMABoundary:
1020
case
RegexNodeKind
.Beginning:
1021
case
RegexNodeKind
.Start:
1022
case
RegexNodeKind
.EndZ:
1023
case
RegexNodeKind
.End:
1024
case
RegexNodeKind
.UpdateBumpalong:
1025
case
RegexNodeKind
.PositiveLookaround:
1026
case
RegexNodeKind
.NegativeLookaround:
1030
case
RegexNodeKind
.Atomic:
1031
case
RegexNodeKind
.Capture:
1037
case
RegexNodeKind
.Loop:
1038
case
RegexNodeKind
.Lazyloop:
1050
case
RegexNodeKind
.Concatenate:
1081
case
RegexNodeKind
.Alternate:
1102
case
RegexNodeKind
.BackreferenceConditional:
1103
case
RegexNodeKind
.ExpressionConditional:
1104
int branchStart = node.Kind is
RegexNodeKind
.BackreferenceConditional ? 0 : 1;
1113
case
RegexNodeKind
.Backreference:
1138
while (node.Kind is
RegexNodeKind
.Atomic or
RegexNodeKind
.Capture)
1142
if (node.Kind !=
RegexNodeKind
.Concatenate)
1155
while (firstChild.Kind is
RegexNodeKind
.Atomic or
RegexNodeKind
.Capture)
1159
if (firstChild.Kind is not (
RegexNodeKind
.Setloop or
RegexNodeKind
.Setloopatomic or
RegexNodeKind
.Setlazy) || firstChild.N != int.MaxValue)
1167
if (nextChild.Kind ==
RegexNodeKind
.UpdateBumpalong)
1224
while ((nextChild.Kind is
RegexNodeKind
.Atomic or
RegexNodeKind
.Capture or
RegexNodeKind
.Concatenate) ||
1225
(nextChild.Kind is
RegexNodeKind
.Loop or
RegexNodeKind
.Lazyloop && nextChild.M >= 1))
1233
(nextChild.Kind is
RegexNodeKind
.Set || nextChild.M >= 1))
1279
case
RegexNodeKind
.PositiveLookaround:
1284
case
RegexNodeKind
.Bol:
1285
case
RegexNodeKind
.Eol:
1286
case
RegexNodeKind
.Beginning:
1287
case
RegexNodeKind
.Start:
1288
case
RegexNodeKind
.EndZ:
1289
case
RegexNodeKind
.End:
1290
case
RegexNodeKind
.Boundary:
1291
case
RegexNodeKind
.ECMABoundary:
1292
case
RegexNodeKind
.NegativeLookaround:
1293
case
RegexNodeKind
.Empty:
1297
case
RegexNodeKind
.Atomic:
1298
case
RegexNodeKind
.Capture:
1303
case
RegexNodeKind
.Loop or
RegexNodeKind
.Lazyloop when node.M >= 1:
1309
case
RegexNodeKind
.Concatenate:
1330
public static
RegexNodeKind
FindLeadingAnchor(RegexNode node) =>
1334
public static
RegexNodeKind
FindTrailingAnchor(RegexNode node) =>
1338
private static
RegexNodeKind
FindLeadingOrTrailingAnchor(RegexNode node, bool leading)
1344
return
RegexNodeKind
.Unknown;
1351
case
RegexNodeKind
.Bol:
1352
case
RegexNodeKind
.Eol:
1353
case
RegexNodeKind
.Beginning:
1354
case
RegexNodeKind
.Start:
1355
case
RegexNodeKind
.EndZ:
1356
case
RegexNodeKind
.End:
1360
case
RegexNodeKind
.Atomic:
1361
case
RegexNodeKind
.Capture:
1362
case
RegexNodeKind
.Loop or
RegexNodeKind
.Lazyloop when leading && node.M >= 1:
1363
case
RegexNodeKind
.PositiveLookaround when leading && (node.Options & RegexOptions.RightToLeft) == 0:
1373
case
RegexNodeKind
.Concatenate:
1380
RegexNodeKind
bestAnchorFound =
RegexNodeKind
.Unknown;
1388
case
RegexNodeKind
.Empty or
RegexNodeKind
.NegativeLookaround:
1389
case
RegexNodeKind
.PositiveLookaround when ((node.Options | tmpChild.Options) & RegexOptions.RightToLeft) != 0:
1390
case
RegexNodeKind
.Boundary or
RegexNodeKind
.ECMABoundary or
RegexNodeKind
.NonBoundary or
RegexNodeKind
.NonECMABoundary:
1394
case
RegexNodeKind
.PositiveLookaround:
1416
if (node.Child(i).Kind is not (
RegexNodeKind
.Empty or
RegexNodeKind
.PositiveLookaround or
RegexNodeKind
.NegativeLookaround))
1424
if (bestAnchorFound is not
RegexNodeKind
.Unknown)
1446
static
RegexNodeKind
ChooseBetterAnchor(
RegexNodeKind
anchor1,
RegexNodeKind
anchor2)
1449
anchor1 ==
RegexNodeKind
.Unknown ? anchor2 :
1450
anchor2 ==
RegexNodeKind
.Unknown ? anchor1 :
1454
static int RankAnchorQuality(
RegexNodeKind
node) =>
1457
RegexNodeKind
.Beginning => 3,
1458
RegexNodeKind
.Start => 3,
1459
RegexNodeKind
.End => 3,
1460
RegexNodeKind
.EndZ => 3,
1462
RegexNodeKind
.Bol => 2,
1463
RegexNodeKind
.Eol => 2,
1465
RegexNodeKind
.Boundary => 1,
1466
RegexNodeKind
.ECMABoundary => 1,
1472
static bool IsBestAnchor(
RegexNodeKind
anchor) =>
1474
anchor is
RegexNodeKind
.Beginning or
RegexNodeKind
.Start or
RegexNodeKind
.End or
RegexNodeKind
.EndZ;
1477
case
RegexNodeKind
.Alternate:
1481
RegexNodeKind
anchor = FindLeadingOrTrailingAnchor(node.Child(0), leading);
1482
if (anchor ==
RegexNodeKind
.Unknown)
1484
return
RegexNodeKind
.Unknown;
1494
return
RegexNodeKind
.Unknown;
1504
return
RegexNodeKind
.Unknown;
System\Text\RegularExpressions\RegexReplacement.cs (4)
36
Debug.Assert(concat.Kind ==
RegexNodeKind
.Concatenate, $"Expected Concatenate, got {concat.Kind}");
50
case
RegexNodeKind
.Multi:
54
case
RegexNodeKind
.One:
58
case
RegexNodeKind
.Backreference:
System\Text\RegularExpressions\RegexTreeAnalyzer.cs (16)
59
case
RegexNodeKind
.Atomic:
60
case
RegexNodeKind
.NegativeLookaround:
61
case
RegexNodeKind
.PositiveLookaround:
66
case
RegexNodeKind
.Capture:
71
case
RegexNodeKind
.Loop:
72
case
RegexNodeKind
.Lazyloop:
90
RegexNodeKind
.Atomic or
RegexNodeKind
.NegativeLookaround or
RegexNodeKind
.PositiveLookaround => true,
94
RegexNodeKind
.Alternate or
RegexNodeKind
.BackreferenceConditional or
RegexNodeKind
.ExpressionConditional => true,
97
RegexNodeKind
.Capture => true,
101
RegexNodeKind
.Concatenate => i == childCount - 1,
107
RegexNodeKind
.Loop or
RegexNodeKind
.Lazyloop when node.N == 1 => true,
System\Text\RegularExpressions\RegexWriter.cs (56)
14
private const
RegexNodeKind
BeforeChild = (
RegexNodeKind
)64;
15
private const
RegexNodeKind
AfterChild = (
RegexNodeKind
)128;
201
private void EmitFragment(
RegexNodeKind
nodeType, RegexNode node, int curIndex)
215
case
RegexNodeKind
.Concatenate | BeforeChild:
216
case
RegexNodeKind
.Concatenate | AfterChild:
217
case
RegexNodeKind
.Empty:
220
case
RegexNodeKind
.Alternate | BeforeChild:
228
case
RegexNodeKind
.Alternate | AfterChild:
247
case
RegexNodeKind
.BackreferenceConditional | BeforeChild:
260
case
RegexNodeKind
.BackreferenceConditional | AfterChild:
278
case
RegexNodeKind
.ExpressionConditional | BeforeChild:
290
case
RegexNodeKind
.ExpressionConditional | AfterChild:
311
case
RegexNodeKind
.Loop | BeforeChild:
312
case
RegexNodeKind
.Lazyloop | BeforeChild:
327
case
RegexNodeKind
.Loop | AfterChild:
328
case
RegexNodeKind
.Lazyloop | AfterChild:
331
int Lazy = (nodeType - (
RegexNodeKind
.Loop | AfterChild));
343
case
RegexNodeKind
.Capture | BeforeChild:
347
case
RegexNodeKind
.Capture | AfterChild:
351
case
RegexNodeKind
.PositiveLookaround | BeforeChild:
356
case
RegexNodeKind
.PositiveLookaround | AfterChild:
361
case
RegexNodeKind
.NegativeLookaround | BeforeChild:
367
case
RegexNodeKind
.NegativeLookaround | AfterChild:
373
case
RegexNodeKind
.Atomic | BeforeChild:
377
case
RegexNodeKind
.Atomic | AfterChild:
381
case
RegexNodeKind
.One:
382
case
RegexNodeKind
.Notone:
386
case
RegexNodeKind
.Notoneloop:
387
case
RegexNodeKind
.Notoneloopatomic:
388
case
RegexNodeKind
.Notonelazy:
389
case
RegexNodeKind
.Oneloop:
390
case
RegexNodeKind
.Oneloopatomic:
391
case
RegexNodeKind
.Onelazy:
394
Emit(((node.Kind is
RegexNodeKind
.Oneloop or
RegexNodeKind
.Oneloopatomic or
RegexNodeKind
.Onelazy) ?
403
case
RegexNodeKind
.Setloop:
404
case
RegexNodeKind
.Setloopatomic:
405
case
RegexNodeKind
.Setlazy:
419
case
RegexNodeKind
.Multi:
423
case
RegexNodeKind
.Set:
427
case
RegexNodeKind
.Backreference:
431
case
RegexNodeKind
.Nothing:
432
case
RegexNodeKind
.Bol:
433
case
RegexNodeKind
.Eol:
434
case
RegexNodeKind
.Boundary:
435
case
RegexNodeKind
.NonBoundary:
436
case
RegexNodeKind
.ECMABoundary:
437
case
RegexNodeKind
.NonECMABoundary:
438
case
RegexNodeKind
.Beginning:
439
case
RegexNodeKind
.Start:
440
case
RegexNodeKind
.EndZ:
441
case
RegexNodeKind
.End:
442
case
RegexNodeKind
.UpdateBumpalong:
System\Text\RegularExpressions\Symbolic\RegexNodeConverter.cs (49)
57
case
RegexNodeKind
.One:
61
case
RegexNodeKind
.Notone:
65
case
RegexNodeKind
.Set:
69
case
RegexNodeKind
.Multi:
84
case
RegexNodeKind
.Concatenate:
85
case
RegexNodeKind
.Alternate:
86
case
RegexNodeKind
.Loop:
87
case
RegexNodeKind
.Lazyloop:
88
case
RegexNodeKind
.Capture when node.N == -1: // N == -1 because balancing groups (which have N >= 0) aren't supported
106
case
RegexNodeKind
.Oneloop:
107
case
RegexNodeKind
.Onelazy:
108
case
RegexNodeKind
.Notoneloop:
109
case
RegexNodeKind
.Notonelazy:
117
result.AddLast(_builder.CreateLoop(_builder.CreateSingleton(bdd), node.Kind is
RegexNodeKind
.Onelazy or
RegexNodeKind
.Notonelazy, node.M, node.N));
121
case
RegexNodeKind
.Setloop:
122
case
RegexNodeKind
.Setlazy:
128
result.AddLast(_builder.CreateLoop(_builder.CreateSingleton(setBdd), node.Kind ==
RegexNodeKind
.Setlazy, node.M, node.N));
132
case
RegexNodeKind
.Empty:
133
case
RegexNodeKind
.UpdateBumpalong: // UpdateBumpalong is a directive relevant only to backtracking and can be ignored just like Empty
136
case
RegexNodeKind
.Nothing:
142
case
RegexNodeKind
.Beginning:
146
case
RegexNodeKind
.Bol:
151
case
RegexNodeKind
.End: // \z anchor
155
case
RegexNodeKind
.EndZ: // \Z anchor
160
case
RegexNodeKind
.Eol:
165
case
RegexNodeKind
.Boundary:
170
case
RegexNodeKind
.NonBoundary:
180
RegexNodeKind
.Atomic or
RegexNodeKind
.Setloopatomic or
RegexNodeKind
.Oneloopatomic or
RegexNodeKind
.Notoneloopatomic => SR.ExpressionDescription_AtomicSubexpressions,
181
RegexNodeKind
.Backreference => SR.ExpressionDescription_Backreference,
182
RegexNodeKind
.BackreferenceConditional => SR.ExpressionDescription_Conditional,
183
RegexNodeKind
.Capture => SR.ExpressionDescription_BalancingGroup,
184
RegexNodeKind
.ExpressionConditional => SR.ExpressionDescription_IfThenElse,
185
RegexNodeKind
.NegativeLookaround => SR.ExpressionDescription_NegativeLookaround,
186
RegexNodeKind
.PositiveLookaround => SR.ExpressionDescription_PositiveLookaround,
187
RegexNodeKind
.Start => SR.ExpressionDescription_ContiguousMatches,
195
string description = $"Unexpected ({nameof(
RegexNodeKind
)}: {node.Kind})";
211
case
RegexNodeKind
.Concatenate:
221
case
RegexNodeKind
.Alternate:
250
case
RegexNodeKind
.Loop:
251
case
RegexNodeKind
.Lazyloop:
260
result.AddLast(_builder.CreateLoop(body, node.Kind ==
RegexNodeKind
.Lazyloop, node.M, node.N));
267
Debug.Assert(node.Kind ==
RegexNodeKind
.Capture && node.N == -1);
285
Debug.Assert(rootResult.Count == 1 || root.Kind ==
RegexNodeKind
.Concatenate || root.Kind ==
RegexNodeKind
.Capture);
312
Debug.Assert(node.Kind ==
RegexNodeKind
.Set);
System\Text\RegularExpressions\Symbolic\SymbolicRegexKind.cs (16)
9
/// <summary>An empty node that matches a zero-width input (e.g. <see cref="
RegexNodeKind
.Empty"/>).</summary>
11
/// <summary>A node that matches a single character (i.e. <see cref="
RegexNodeKind
.One"/>, <see cref="
RegexNodeKind
.Notone"/>, or <see cref="
RegexNodeKind
.Set"/>).</summary>
13
/// <summary>A node that matches a sequence of nodes (i.e. <see cref="
RegexNodeKind
.Concatenate"/>).</summary>
15
/// <summary>A node that matches a loop (e.g. <see cref="
RegexNodeKind
.Loop"/>, <see cref="
RegexNodeKind
.Lazyloop"/>, <see cref="
RegexNodeKind
.Setloop"/>, etc.).</summary>
17
/// <summary>A node that matches if any of its nodes match and that matches them in a fixed order that mirrors how the backtracking engines operate (e.g. <see cref="
RegexNodeKind
.Alternate"/>).</summary>
20
/// <summary>A node that represents a beginning anchor (i.e. <see cref="
RegexNodeKind
.Beginning"/>).</summary>
22
/// <summary>A node that represents an ending anchor (i.e. <see cref="
RegexNodeKind
.End"/>).</summary>
24
/// <summary>A node that represents an ending \Z anchor (i.e. <see cref="
RegexNodeKind
.EndZ"/>).</summary>
28
/// <summary>A node that represents a beginning-of-line anchor (i.e. <see cref="
RegexNodeKind
.Bol"/>).</summary>
30
/// <summary>A node that represents a end-of-line anchor (i.e. <see cref="
RegexNodeKind
.Eol"/>).</summary>
32
/// <summary>A node that represents a word boundary anchor (i.e. <see cref="
RegexNodeKind
.Boundary"/>).</summary>
34
/// <summary>A node that represents a word non-boundary anchor (i.e. <see cref="
RegexNodeKind
.NonBoundary"/>).</summary>
System\Text\RegularExpressions\Symbolic\SymbolicRegexMatcher.cs (1)
211
findOptimizations.LeadingAnchor is not
RegexNodeKind
.Beginning)