Skip to content

Commit 4f585a5

Browse files
committed
Refactor Alternative class to handle cases without backreferences;
1 parent 9e59758 commit 4f585a5

File tree

1 file changed

+47
-4
lines changed

1 file changed

+47
-4
lines changed

regex_enumerator/regex_tree.py

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@ def _first(self) -> list[str]:
2525
if self._max_len is not None and self._max_len == self._min_len:
2626
self.done = True
2727

28-
if self._min_len == 0:
29-
self._last = ['']
30-
return ['']
31-
3228
result = ['']
3329
for _ in range(self._min_len):
3430
result = [pfx + sfx for pfx in self._chars for sfx in result]
@@ -98,11 +94,16 @@ class Alternative:
9894
def __init__(self, elements: list[CharClass | RegexTree | BackReference]):
9995
self._index = 0
10096
self._elements = [e for e in elements if not e.done or len(e.current)]
97+
self._noBackreference = not any(isinstance(
98+
e, BackReference) for e in self._elements)
10199
self._base = len(self._elements)
102100
self.done = self._base == 0
103101
self.current = self._first()
104102

105103
def next(self) -> set[str]:
104+
if self._noBackreference:
105+
return self._next_no_backreference()
106+
106107
assert not self.done
107108
assert not isinstance(self._elements[0], BackReference)
108109

@@ -153,10 +154,52 @@ def next(self) -> set[str]:
153154
self.current.update(new_strings)
154155
return new_strings
155156

157+
def _first_no_backreference(self) -> set[str]:
158+
result: set[str] = {''}
159+
done = True
160+
161+
for element in self._elements:
162+
done = done and element.done
163+
result = {pfx + sfx for pfx in result for sfx in element.current}
164+
165+
self.done = done
166+
return result
167+
168+
def _next_no_backreference(self) -> set[str]:
169+
assert not self.done
170+
171+
index = self._index + 1
172+
if index >= self._base:
173+
index = 0
174+
while self._elements[index].done:
175+
index += 1
176+
if index >= self._base:
177+
index = 0
178+
179+
self._index = index
180+
result: set[str] = {''}
181+
done = True
182+
183+
for i, element in enumerate(self._elements):
184+
if i == index:
185+
strings = element.next()
186+
else:
187+
strings = element.current
188+
done = done and element.done
189+
result = {pfx + sfx for pfx in result for sfx in strings}
190+
191+
self.done = done
192+
result -= self.current
193+
self.current.update(result)
194+
return result
195+
156196
def _first(self) -> set[str]:
157197
if self.done:
158198
return {''}
159199

200+
if self._noBackreference:
201+
return self._first_no_backreference()
202+
160203
assert not isinstance(self._elements[0], BackReference)
161204

162205
result: list[tuple[str, dict[RegexTree, str]]] = []

0 commit comments

Comments
 (0)