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

What would be the best way of changing the following snippet so it prints (a,b)(c,d)(e,f)

use 5.010; # re features use strict; use warnings; for ('abcdef') { m{ (?(DEFINE) (?<x> ( . ) ( . ) (?{ '...' }) ) (?<y> ( . ) ( . ) (?{ print("(???,$^N)") }) ) (?<z> ( . ) ( . ) (?{ '...' }) ) ) (?&y)+ }x; } print("\n");

The most palatable solution I've found so far involves relying on the undocumented changing size of @- .

use 5.010; # re features use strict; use warnings; sub CAP { my ($idx) = $_[0]; $idx += @- if $idx < 0; # @+ isn't the same size as @- substr($_, $-[$idx], $+[$idx] - $-[$idx]) } for ('abcdef') { m{ (?(DEFINE) (?<x> ( . ) ( . ) (?{ '...' }) ) (?<y> ( . ) ( . ) # (?{ # printf('[%s,%s]', # ($#-), # Prints 6, the number of preceding captures # ($#+), # Prints 9, the total number of captures # ) # }) (?{ printf('(%s,%s)', CAP(-2), CAP(-1) ); }) ) (?<z> ( . ) ( . ) (?{ '...' }) ) ) (?&y)+ }x; } print("\n");

Replies are listed 'Best First'.
Re: \g{-2} for inside (?{ ... })
by gone2015 (Deacon) on Nov 06, 2008 at 11:49 UTC

    The following appears to work:

    (?<x> ( . . ) (?{ '...' }) ) (?<y> ( . . ) (?{ print("(", join(',', split(//,$^N)), ")") }) ) (?<z> ( . . ) (?{ '...' }) )
    but I suspect that is finessing the problem you're really interested in.

    I'd really love to know what on earth this is doing, and why !

      Playing with regexp as parsers. See An adventure with 5.10 regular expressions.

      The series of ( . ) represent a series arbitrarily complex grammar rules. I need to know what each rule matched.

      Update: As I write this, it strikes me that what I want is not necessarily what those rules matched, so my question is moot.

Re: \g{-2} for inside (?{ ... })
by JavaFan (Canon) on Nov 06, 2008 at 13:31 UTC
    m{ (?(DEFINE) (?<x> ( . ) ( . ) (?{ '...' }) ) (?<y> (?<y1> . ) (?<y2> . ) (?{ print("($+{y1},$+{y2})") }) ) (?<z> ( . ) ( . ) (?{ '...' }) ) ) (?&y)+ }x;
      Thanks. That's the only documented approach I've found that doesn't rely on counting captures, but it makes for mighty long patterns and mighty long names.
        and mighty long names

        Can't you just use 'x' and 'y' over and over? Doesn't %+ give you the most-recently matched instance matching the given name?

        - tye        

Re: \g{-2} for inside (?{ ... })
by Petras (Friar) on Nov 07, 2008 at 14:57 UTC
    Might one suggest:
    use 5.010; # re features use strict; use warnings; #for ('abcdef') { # m{ # (?(DEFINE) # (?<x> # ( . ) ( . ) # (?{ '...' }) # ) # (?<y> # ( . ) ( . ) # (?{ print("(???,$^N)") }) # ) # (?<z> # ( . ) ( . ) # (?{ '...' }) # ) # ) # # (?&y)+ # }x; #} print "(a,b)(c,d)(e,f)"; print("\n");

    :~)

    Cheers! ~P

    Ready.
    poke 53280,0
    poke 53281,0
    ctrl+2 load "zork",8,1

    West of House
      Thankyou - your post means I no longer have an urge to make the same suggestion. :-)

      That said, your solution doesn't work for me (using Perl 5.8) - would you consider changing the first line thus:

      #use 5.010; # re features

      --
      .sig : File not found.