develooper Front page | perl.perl5.porters | Postings from May 2008

Re: [perl #51848] Deparse interpolation in regex literal

Thread Previous | Thread Next
From:
Rafael Garcia-Suarez
Date:
May 16, 2008 08:07
Subject:
Re: [perl #51848] Deparse interpolation in regex literal
Message ID:
b77c1dce0805160807i20e270a5v3e2455f34be88adf@mail.gmail.com
2008/3/18 via RT Zsban Ambrus <perlbug-followup@perl.org>:
> The following deparse command
>
>  perl -MO=Deparse -e '/${x}y/'
>
> gives a wrong output:
>
>  /$xy/;

The optree changed, op_concat is no longer used here:

$ perl5.8.8 -MO=Concise -e '/${x}y/'
9  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v ->3
8     </> match() vK/RTIME ->9
7        <|> regcomp(other->8) sK/1 ->8
3           <1> regcreset sK/1 ->4
6              <2> concat[t2] sK/2 ->7
-                 <1> ex-rv2sv sK/1 ->5
4                    <#> gvsv[*x] s ->5
5                 <$> const[PV "y"] s ->6
-e syntax OK

$ bleadperl -MO=Concise -e '/${x}y/'
9  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
8     </> match() vK/RTIME ->9
7        <|> regcomp(other->8)[t1] sKS/1 ->8
3           <1> regcreset sK/1 ->4
-              <1> ex-list sK ->7
4                 <0> pushmark s ->5
-                 <1> ex-rv2sv sK/1 ->6
5                    <$> gvsv(*x) s ->6
6                 <$> const(PV "y") s ->7
-e syntax OK

Once this is remarked, the fix is trivial. Just get the escaping code
from re_dq and put in in the deparse routine for regcomp :

--- ext/B/B/Deparse.pm  2008-04-21 17:14:12.000000000 +0200
+++ lib/B/Deparse.pm    2008-05-16 17:02:52.000000000 +0200
@@ -4156,7 +4156,16 @@
        my $str = '';
        $kid = $kid->first->sibling;
        while (!null($kid)) {
-           $str .= $self->re_dq($kid, $extended);
+
+           my $first = $str;
+           my $last = $self->re_dq($kid, $extended);
+           # Disambiguate "${foo}bar", "${foo}{bar}", "${foo}[1]"
+           ($last =~ /^[A-Z\\\^\[\]_?]/ &&
+               $first =~ s/([\$@])\^$/${1}{^}/)  # "${^}W" etc
+               || ($last =~ /^[{\[\w_]/ &&
+                   $first =~ s/([\$@])([A-Za-z_]\w*)$/${1}{$2}/);
+           $str = $first . $last;
+
            $kid = $kid->sibling;
        }
        return $str, 1;

But of course that patch is Wrong because I cutted and pasted instead
of Properly Refactored. And also it lacks tests.

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About