Skip to content

(*ACCEPT) behavior when forward-matching and when backtracking #21825

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
rsFalse opened this issue Jan 12, 2024 · 1 comment
Open

(*ACCEPT) behavior when forward-matching and when backtracking #21825

rsFalse opened this issue Jan 12, 2024 · 1 comment

Comments

@rsFalse
Copy link

rsFalse commented Jan 12, 2024

https://perldoc.perl.org/perlre#(*ACCEPT)-(*ACCEPT:arg)

Description
From documentation:

... causes the end of successful matching at the point at which the (*ACCEPT) pattern was encountered, regardless of whether there is actually more to match in the string.

... is not clear when it should be encountered: 1) on backtracking (like (*SKIP)), or 2) on forward-tracking like (*FAIL) aka (?!).

Steps to Reproduce
In simplest case a verb is encountered on forward-tracking (b haven't match):

perlbrew exec perl -wle ' "ab" =~ /(?:a(*ACCEPT))b/; print "[$&]" '
perl-5.38.2, 5.36.0, 5.32.0, 5.20.1, 5.14.3
[a]

In this example it could be either forward-tracking behavior (look-ahead isn't even reached), or backtracking (third match with b survives because of acception):

perlbrew exec perl -we ' print "[$-[0]:$&]" while ( "b" x 3 ) =~ m/(?:b(*ACCEPT))(?=b)/g; print "\n" '
perl-5.38.2, 5.36.0
==========
[0:b][1:b][2:b]

perl-5.32.0, 5.20.1
==========
[0:b][1:b][2:b]

Same example but with atomic ((?>...)):

perlbrew exec perl -we ' print "[$-[0]:$&]" while ( "b" x 3 ) =~ m/(?>b(*ACCEPT))(?=b)/g; print "\n" '
perl-5.38.2, 5.36.0
==========
[0:b][1:b]

perl-5.32.0, 5.20.1
==========
[0:b][1:b]

...it looks like on the third match attempt (*ACCEPT) was not encountered at forward-tracking (otherwise it would succeed), and after a failure on look-ahead, it couldn't finish matching attempt because an atomic group haven't let to backtrack into itself and encounter a verb.
...same output as with possessive {1}+, except perl-5.20.1 where it was a bug.

Same as in non-atomic example, but with quantifier {1} added. Should be the same. Differences are in older versions:

perlbrew exec perl -we ' print "[$-[0]:$&]" while ( "b" x 3 ) =~ m/(?:b(*ACCEPT)){1}(?=b)/g; print "\n" '
perl-5.38.2, 5.36.0
==========
[0:b][1:b][2:b]

perl-5.32.0, 5.20.1
==========
[0:b][1:b]

Same but with quantifier +. Both (?>...) (not shown) and (?:...) outputs the same:

perlbrew exec perl -we ' print "[$-[0]:$&]" while ( "b" x 3 ) =~ m/(?:b(*ACCEPT))+(?=b)/g; print "\n" '
perl-5.38.2, 5.36.0
==========
[0:b][1:b][2:b]

perl-5.32.0, 5.20.1
==========
[0:bb]

...in the latest versions a verb seems to be encountered on forward-tracking. Otherwise it should have matched [0:bbb] IMO, which is somehow similar to the outputs of earlier versions.

Expected behavior
Not clearly defined when a verb should be encountered.

@florian-pe
Copy link

florian-pe commented Apr 30, 2025

It acts when "forward-matching", but there is an implementation issue concerning backtracking control.

You can match on backtracking with something like / ... (*PRUNE) (?: | (*ACCEPT)) ... /.

edit: (*PRUNE) is irrelevant however.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants