@@ -92,10 +92,10 @@ extension Processor {
9292 isScalarSemantics: isScalarSemantics)
9393 }
9494
95- case . builtin :
95+ case . builtinCC :
9696 if isZeroOrMore {
9797 matchResult = input. matchZeroOrMoreBuiltinCC (
98- payload. builtin ,
98+ payload. builtinCC ,
9999 at: currentPosition,
100100 limitedBy: end,
101101 produceSavePointRange: produceSavePointRange,
@@ -104,7 +104,7 @@ extension Processor {
104104 isScalarSemantics: isScalarSemantics)
105105 } else if isOneOrMore {
106106 matchResult = input. matchOneOrMoreBuiltinCC (
107- payload. builtin ,
107+ payload. builtinCC ,
108108 at: currentPosition,
109109 limitedBy: end,
110110 produceSavePointRange: produceSavePointRange,
@@ -113,7 +113,7 @@ extension Processor {
113113 isScalarSemantics: isScalarSemantics)
114114 } else {
115115 matchResult = input. matchQuantifiedBuiltinCC (
116- payload. builtin ,
116+ payload. builtinCC ,
117117 at: currentPosition,
118118 limitedBy: end,
119119 minMatches: minMatches,
@@ -158,6 +158,11 @@ extension String {
158158 ) -> Index ?
159159 ) -> ( next: Index , savePointRange: Range < Index > ? ) ? {
160160 var currentPosition = currentPosition
161+
162+ // The range of backtracking positions to try. For zero-or-more, starts
163+ // before any match happens. Always ends before the final match, since
164+ // the final match is what is tried without backtracking. An empty range
165+ // is valid and means a single backtracking position at rangeStart.
161166 var rangeStart = currentPosition
162167 var rangeEnd = currentPosition
163168
@@ -171,6 +176,12 @@ extension String {
171176 }
172177 numMatches &+= 1
173178 if numMatches == minMatches {
179+ // For this loop iteration, rangeEnd will actually trail rangeStart by
180+ // a single match position. Next iteration, they will be equal
181+ // (empty range denoting a single backtracking point). Note that we
182+ // only ever return a range if we have exceeded `minMatches`; if we
183+ // exactly mach `minMatches` there is no backtracking positions to
184+ // remember.
174185 rangeStart = next
175186 }
176187 rangeEnd = currentPosition
@@ -183,20 +194,22 @@ extension String {
183194 }
184195
185196 guard produceSavePointRange && numMatches > minMatches else {
186- // Consumed no input, no point saved
197+ // No backtracking positions to try
187198 return ( currentPosition, nil )
188199 }
189200 assert ( rangeStart <= rangeEnd)
190201
191- // NOTE: We can't assert that rangeEnd trails currentPosition by one
192- // position, because newline-sequence in scalar semantic mode still
202+ // NOTE: We can't assert that rangeEnd trails currentPosition by exactly
203+ // one position, because newline-sequence in scalar semantic mode still
193204 // matches two scalars
194205
195206 return ( currentPosition, rangeStart..< rangeEnd)
196207 }
197208
198- /// NOTE: [Zero|One]OrMore overloads are to specialize the inlined run loop,
199- /// which has a substantive perf impact (especially for zero-or-more)
209+ // NOTE: [Zero|One]OrMore overloads are to specialize the inlined run loop,
210+ // which has a perf impact. At the time of writing this, 10% for
211+ // zero-or-more and 5% for one-or-more improvement, which could very well
212+ // be much higher if/when the inner match functions are made faster.
200213
201214 fileprivate func matchZeroOrMoreASCIIBitset(
202215 _ asciiBitset: ASCIIBitset ,
0 commit comments