Skip to content

Commit

Permalink
Merge pull request #41 from goodmami/fix-38-pack-mach-diff
Browse files Browse the repository at this point in the history
Don't reuse instructions in repetitions
  • Loading branch information
goodmami authored Dec 28, 2023
2 parents 4167657 + 0e770fa commit 1142b83
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 1 deletion.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## [Unreleased][unreleased]

### Fixed

* Repetitions with mincount > 0 no longer reuse the instruction object ([#38])


## [v0.5.0][]

Expand Down Expand Up @@ -164,3 +168,4 @@ descent parser and a work-in-progress state-machine parser.
[#21]: https://github.com/goodmami/pe/issues/21
[#23]: https://github.com/goodmami/pe/issues/23
[#31]: https://github.com/goodmami/pe/issues/31
[#38]: https://github.com/goodmami/pe/issues/38
13 changes: 12 additions & 1 deletion pe/_cy_machine.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,17 @@ cdef class Instruction:
self.action = action
self.name = name

def copy(self) -> Instruction:
return Instruction(
self.opcode,
self.oploc,
scanner=self.scanner,
marking=self.marking,
capturing=self.capturing,
action=self.action,
name=self.name,
)


_Program = List[Instruction]

Expand Down Expand Up @@ -402,7 +413,7 @@ def _rpt(defn, mincount):
marking=pi.marking,
capturing=pi.capturing,
action=pi.action)]
return [*(pis * mincount),
return [*(pi.copy() for _ in range(mincount) for pi in pis),
Instruction(BRANCH, len(pis) + 2),
*pis,
Instruction(UPDATE, -len(pis))]
Expand Down
13 changes: 13 additions & 0 deletions test/test_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,16 @@ def test_multi_range_charclass(parser):
assert p.match('"1"') is not None
assert p.match('"\U0010ffff"') is not None
assert p.match('"a1"') is not None


@pytest.mark.parametrize('parser', ['packrat', 'machine', 'machine-python'])
def test_capture_repeated(parser):
m1 = pe.match('"a"+', 'aaa', parser=parser)
assert m1.group() == 'aaa'
assert m1.groups() == ()
m2 = pe.match('~"a"+', 'aaa', parser=parser)
assert m2.group() == 'aaa'
assert m2.groups() == ('aaa',)
m3 = pe.match('(~"a")+', 'aaa', parser=parser)
assert m3.group() == 'aaa'
assert m3.groups() == ('a', 'a', 'a')

0 comments on commit 1142b83

Please sign in to comment.