ikegami has asked for the wisdom of the Perl Monks concerning the following question:

The following works as expected:

use strict; use warnings; my $re; $re = qr/ (\d) (?{ print("[$1]\n") }) /x; 'thr33' =~ $re; __END__ output ====== [3]

However, it stops working when I start nesting regexps:

use strict; use warnings; my $re0; my $re1; $re1 = qr/ (\d) (?{ print("[$1]\n") }) /x; $re0 = qr/ (??{ $re1 }) /x; 'thr33' =~ $re0; __END__ output ====== Use of uninitialized value in concatenation (.) or string at (re_eval +1) line 1. []

Does anyone know of any workaround I can use?

$-[0] doesn't work:

use strict; use warnings; my $re0; my $re1; $re1 = qr/ (\d) (?{ print("[$-[0]]\n") }) /x; $re0 = qr/ (??{ $re1 }) (??{ $re1 }) /x; 'thr33' =~ $re0; __END__ output ====== [3] [3] expected ======== [3] [4]

$+ doesn't work either. It's undef.

Replies are listed 'Best First'.
Re: Using a capture in /(?{...})/
by ikegami (Patriarch) on Jul 25, 2005 at 21:35 UTC

    I found something that does work: pos (and $+[0]). Actually, argless pos works even if we're not operating on $_!

    Therefore, this hack works:

    use strict; use warnings; my $re0; my $re1; our $s_pos; $re1 = qr/ (?{ local $s_pos = pos; }) [A-Z] (?{ print("[", substr($_, $s_pos, pos()-$s_pos), "]\n") }) /x; $re0 = qr/ (??{ $re1 }) (??{ $re1 }) /x; 'abcDE' =~ $re0; __END__ output ====== [D] [E]

    yuck!

    Update: Adding an extra capture also works! Kudos to blokhead for this solution.

    use strict; use warnings; my $re0; my $re1; $re1 = qr/ ([A-Z]) (?{ print("[$1]\n") }) /x; $re0 = qr/ () (??{ $re1 }) (??{ $re1 }) /x; 'abcDE' =~ $re0; __END__ output ====== [D] [E]

      I spoke too soon, kinda.

      pos works, but gives a weird warning when + is used:

      use strict; use warnings; my $re0; my $re1; our $s_pos; $re1 = qr/ (?{ local $s_pos = pos; }) [A-Z] (?{ print("[", substr($_, $s_pos, pos()-$s_pos), "]\n") }) /x; $re0 = qr/ (?: (??{ $re1 }) )+ /x; 'abcDE' =~ $re0; __END__ output ====== (?: (??{ $re1 }) )+ matches null string many times before HERE mark in regex m/ (?: (??{ $re1 }) )+ << HERE / at script.pl line 19. [D] [E]

      Same with the extra capture:

      use strict; use warnings; my $re0; my $re1; $re1 = qr/ ([A-Z]) (?{ print("[$1]\n") }) /x; $re0 = qr/ (?: () (??{ $re1 }) )+ /x; 'abcDE' =~ $re0; __END__ (?: () (??{ $re1 }) )+ matches null string many times before HERE mark in regex m/ (?: () (??{ $re1 }) )+ << HERE / at script.pl line 17. [D] [E]

      However, the warning seems to be spurious. The warning check is using a variable that's not updated, but the pos truly is changing.

        The warning comes from the fact that Perl can't tell if (?{ ... }) matches any characters or not, so it's possible you're putting a quantifier on a zero-width assertion.

        Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
        How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
Re: Using a capture in /(?{...})/
by ikegami (Patriarch) on Jul 25, 2005 at 21:18 UTC

    Weird! $-[0] works if I put something between the two "3"s:

    use strict; use warnings; my $re0; my $re1; $re1 = qr/ (\d) (?{ print("[$-[0]]\n") }) /x; $re0 = qr/ (??{ $re1 }) (??{ $re1 }) /x; 'thr3.3' =~ $re0; __END__ output ====== [3] [5]

    That doesn't help any, though.

Re: Using a capture in /(?{...})/
by tphyahoo (Vicar) on Jul 26, 2005 at 08:26 UTC
    Maybe opaque regex warnings is a smell that you should be using P::RD... or Perl6::Rules, if you are in a brave new world mood. Very illuminating discussion though.
Re: Using a capture in /(?{...})/
by halley (Prior) on Jul 26, 2005 at 13:16 UTC
    In general, the Regexp engine in perl is not documented to support reentrancy, and from several experiments of my own and others here, I've found plenty to suggest that the code isn't designed to support reentrancy, either.

    My biggest experimentation in this area was in developing Pentominos Solving Quine, because using a backtracking position iterator would make complete sense for solving position puzzles. That is, if you could recurse. So instead, I grab and manipulate pos (there's only one) to emulate recursion.

    --
    [ e d @ h a l l e y . c c ]