=== modified file 'lib2to3/pytree.py' --- lib2to3/pytree.py 2008-06-10 04:12:51 +0000 +++ lib2to3/pytree.py 2008-07-15 03:54:41 +0000 @@ -653,29 +653,40 @@ r[self.name] = nodes[:count] yield count, r else: - for count, r in self._recursive_matches(nodes, 0): + for count, r in self._iterative_matches(nodes): if self.name: r[self.name] = nodes[:count] yield count, r - def _recursive_matches(self, nodes, count): - """Helper to recursively yield the matches.""" - assert self.content is not None - if count >= self.min: - r = {} - if self.name: - r[self.name] = nodes[:0] - yield 0, r - if count < self.max: - for alt in self.content: - for c0, r0 in generate_matches(alt, nodes): - for c1, r1 in self._recursive_matches(nodes[c0:], count+1): - r = {} - r.update(r0) - r.update(r1) - yield c0 + c1, r - - + def _iterative_matches(self, nodes): + """Helper to iteratively yield the matches.""" + nodelen = len(nodes) + if 0 >= self.min: + yield 0, {} + + results = [] + # generate matches that use just one alt from self.content + for alt in self.content: + for c, r in generate_matches(alt, nodes): + yield c, r + results.append((c, r)) + + # for each match, iterate down the nodes + while len(results): + new_results = [] + for c0, r0 in results: + # stop if the entire set of nodes has been matched + if c0 < nodelen and c0 <= self.max: + for alt in self.content: + for c1, r1 in generate_matches(alt, nodes[c0:]): + if c1 > 0: + r = {} + r.update(r0) + r.update(r1) + yield c0 + c1, r + new_results.append((c0 + c1, r)) + results = new_results + class NegatedPattern(BasePattern): def __init__(self, content=None): === modified file 'lib2to3/tests/test_pytree.py' --- lib2to3/tests/test_pytree.py 2008-06-10 04:12:51 +0000 +++ lib2to3/tests/test_pytree.py 2008-07-15 03:43:46 +0000 @@ -428,7 +428,7 @@ [pa, pb], [pc, pd], [pe, pf]], min=1, max=4, name="pw") self.assertEqual([x[0] for x in pw.generate_matches(leaves)], - [3, 5, 2, 4, 6]) + [3, 2, 5, 4, 6]) pr = pytree.NodePattern(type=1000, content=[pw], name="pr") matches = list(pytree.generate_matches([pr], [root])) self.assertEqual(len(matches), 1)