in reply to getting the body text of a sub

UPDATE to the UPDATE:
just use B::Deparse :P

UPDATE:
My first code example would only grab the inner body of a subroutine that had NO inner blocks - not very useful. After toying with look aheads, i can up with this regex:

/sub\s+$name\s+{\s+(.*?(?=^}\s*$))/sm
Where $name is the name of the subroutine to be parsed. The catch is that the closing bracket of the subroutine HAS to be the first character on it's own line.

You don't have to use the __DATA__ and seek trick, you could always just open the file if you need to parse other scripts or modules.

Here is the whole program. Improvements are very, very welcome :)

#!/usr/bin/perl -w seek(DATA,0,0); my $slurp; { local $/; $slurp = <DATA>; } print_sub($slurp,'bar'); print_sub($slurp,'foo'); sub print_sub { my ($content,$name) = @_; my ($body) = $content =~ /sub\s+$name\s+{\s+(.*?(?=^}\s*$))/sm; print $body; } sub foo { if (1) { return $_[0] + 5; } else { return 0; } # a comment } sub bar { print "howdy"; } __DATA__
FIXES:
Thanks to Hofmator for pointing out cut and paste error. Thanks again for pointing out the paran regex in Camel 3.

Jeff

R-R-R--R-R-R--R-R-R--R-R-R--R-R-R--
L-L--L-L--L-L--L-L--L-L--L-L--L-L--

Replies are listed 'Best First'.
Re: (jeffa) Re: getting the body text of a sub
by Hofmator (Curate) on Jun 25, 2001 at 16:41 UTC

    Two small things:

    • in print_sub
      my ($body) = $slurp =~ /sub\s+$name\s+{\s+(.*?(?=^}\s*$))/sm;
      $slurb should be replaced by $content
      my ($body) = $content =~ /sub\s+$name\s+{\s+(.*?(?=^}\s*$))/sm;
      small copy and paste error ... it actually works here but just because the sub declaration and the my declaration of slurp are by chance in the same scope.
    • The 'Camel' (3rd edition, chapter 5.10.3.4 - sorry no page number, this is from the bookshelf CD) has a very witty regex to match matching parens. This might also be helpful in such cases although I prefer here the suggested B::Deparse method

      $np = qr{ \( (?: (?> [^()]+ ) # Non-parens without backtracking | (??{ $np }) # Group with matching parens )* \) }x;
      [replace round parens with braces]

    -- Hofmator