Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Scanning a plsql package body to make package headers... regexp requested

by princepawn (Parson)
on Mar 27, 2001 at 21:53 UTC ( #67671=perlquestion: print w/replies, xml ) Need Help??

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

So, I have a file which contains a number of PL/SQL procedure and function definitions which look like this:
procedure x (x in varchar2, y in number) is BEGIN ... END; function m (z in number) is BEGIN ... END;

And what I would like to do is create a "package header" file. That is a file which contains the function declaration, including its arguments. Like so:

procedure x (x in varchar2, y in number); function m (z in number);

If someone could remedy my pathetic, pathologically uninformed desparate hack below, I would appreciate it.

#!/arudev/bin/perl use strict; my $file = shift or die "must supply body file"; open F, $file; my $text = join '', <F>; my $regex = '(procedure|function).*?\(.*?\)'; while ($text =~ /$regex/gs) { print "*$1*",$/; }

Replies are listed 'Best First'.
Re: Scanning a plsql package body to make package headers... regexp requested
by sachmet (Scribe) on Mar 27, 2001 at 22:02 UTC
    Close...
    #!/usr/bin/perl -w use strict; my $file = shift or die "must supply body file"; open F, $file; my $text = join '', <F>; my $regex = '(procedure|function)\b(.*?)\((.*?)\)'; while ($text =~ /$regex/mgs) { print $1,$2,"($3);",$/; }
    The m is important to enable multi-line matching, or your regex will not scan across newlines.
      Actually m made no difference in output. And what I had was working, it's just that the word "function" was in a comment and my regexp was lapping it up, so I will simply filter comments from the text before parsing it:
      #!/arudev/bin/perl use strict; my $file = shift or die "must supply body file"; open F, $file; my @text = <F>; my $text = join '', grep { ! /\s+\-{2,}/ } @text; my $regex = '(procedure|function)\b(.*?)\((.*?)\)'; while ($text =~ /$regex/gs) { print "*$1+$2-$3*",$/; }
      Prince "I knew I was the regexp overlord" Pawn
Re: Scanning a plsql package body to make package headers... regexp requested
by johannz (Hermit) on Mar 27, 2001 at 23:02 UTC

    This passes use strict and -w.

    sub readPackage { my $filename = shift; open FILE, $filename || die "cannot open $filename\n"; local $/ = undef; my $file = <FILE>; close(FILE); $file ||= ''; while( $file =~ m/^[^\n]*(FUNCTION|PROCEDURE)(.*?)IS/msgi ) { my ($type, $declaration) = ($1, $2); print "$1 $2;\n\n"; } }

    The other option is

    my @procedures = ( $file =~ m/^[^\n]*(FUNCTION|PROCEDURE)(.*?)IS/msgi )

    This will create an array of procedure type, declaration pairs, as a flat list. So grap them 2 at a time, and process.

    The key to the regex is that using /s allows '.' to match across newlines, and /m allows the '^' to match the beginning of the line. I use the character class [^\n] to act like the '.' but without /s's special abilities.

    This was based on reading the regex sections in the cookbook. This version does not handle comments. The one the I use at work is actually for 'use lib' lines and does handle comments.

Re: Scanning a plsql package body to make package headers... regexp requested
by arturo (Vicar) on Mar 27, 2001 at 23:33 UTC

    If you have access to SQL*Plus, you can get the interface of a function or procedure documented with a fairly straightforward output. Just do

    SPOOL output.filename DESCRIBE PROCEDURE &lt;procedure_name&gt; SPOOL off

    This yields up output of the form:

    PROCEDURE new_item
    Argument Name	Type		In/Out      Default?
     ------------------------------ -------  --------------
      FOO		VARCHAR2(28)	   IN
      BAR		VARCHAR2(25)	   IN
      BAZ		VARCHAR2(25)	   IN
      NEWID		NUMBER(38)	   OUT
    

    Which is pretty easy to parse, or may even be the sort of output you wanted in the first place. I'm sure you could even snag such info out of DBI (not that I've tried it ... )

    HTH

    Philosophy can be made out of anything. Or less -- Jerry A. Fodor

Re: Scanning a plsql package body to make package headers... regexp requested
by princepawn (Parson) on Mar 27, 2001 at 22:58 UTC
    And for posterity, here is my final version which correctly handles function and procedure text:
    #!/arudev/bin/perl use strict; my $file = shift or die "must supply body file"; open F, $file; my @text = <F>; my $text = join '', grep { ! /\s+\-{2,}/ } @text; my $p_regex = '(procedure\b.*?\(.*?\))'; my $f_regex = '(function\b.*?\(.*?\)\s+return\s+\S+)'; while ($text =~ /($p_regex|$f_regex)/gs) { print "$1;\n"; }

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://67671]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (4)
As of 2021-05-16 17:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Perl 7 will be out ...





    Results (152 votes). Check out past polls.

    Notices?