Hi dpelican,
I think this will do what you need. It uses the recursive subpatterns described in the perlre documentation. By the time I finished getting my example working I saw that roboticus had already mentioned them. (I had never used the recursive regex method, so it was a good learning experience for me).
Edit: Fixed some comments (specifically capture group numbering), and captured a little bit more.
Edit 2: Added output.
Edit 3: Allow keyword 'report' (somehow missed it the first time).
#!/usr/bin/perl
#
# References:
# http://perldoc.perl.org/perlre.html (See section on 'PARNO')
##
use strict;
use warnings;
use feature qw( say );
use Method::Signatures;
##################
## Main Program ##
##################
my $str = 'private function convert_wa_date_strings(iv_beg string, iv_
+end string, iv_read_date date, iv_step char(6)) returns (date, date,
+char(1))';
recursive_function_parsing_regex($str);
#################
## Subroutines ##
#################
func recursive_function_parsing_regex($str) {
my $re = qr{
( # Paren group 1 -- full function
(?:
(private|public) # Paren group 2 -- optional 'private
+' or 'public'
\s+)?
(function) # Paren group 3 -- required 'functio
+n' keyword
\s* # Optional space after 'function'
(\w+) # Paren group 4 -- function name
( # Paren group 5 -- args in parens
\(
( # Paren group 6 -- contents of paren
+s
(?:
(?> [^()]+ ) # Non-parens without backtracking
|
(?5) # Recurse to start of paren group 5
)*
)
\)
)
(?: # Optional return value
\s+
returns\s*
( # Paren group 7 -- return args in pa
+rens
\(
( # Paren group 8 -- return args
(?:
(?> [^()]+ ) # Non-parens without backtracking
|
(?7) # Recurse to start of paren group 7
)*
)
\)
)
)?
)
}x;
if ($str !~ /$re/) {
say "No match for '$str'";
return;
}
my ($full, $pp, $func, $name, $par, $args, $ret, $rargs) = ($1, $2
+ || "", $3, $4, $5, $6, $7 || "", $8 || "");
say "Match!";
say " \$full => '$full'"; # Full expression
say " \$pp => '$pp'"; # Optional 'private' or 'public' k
+eyword
say " \$func => '$func'"; # 'function' keyword
say " \$name => '$name'"; # Function name
say " \$par => '$par'"; # Func args (in parens)
say " \$args => '$args'"; # Func args (no parens)
say " \$ret => '$ret'"; # Optional return args (in parens)
say " \$rargs => '$rargs'"; # Optional return args (no parens)
}
Result:
Match!
$full => 'private function convert_wa_date_strings(iv_beg string, i
+v_end string, iv_read_date date, iv_step char(6)) returns (date, date
+, char(1))'
$pp => 'private'
$func => 'function'
$name => 'convert_wa_date_strings'
$par => '(iv_beg string, iv_end string, iv_read_date date, iv_step
+ char(6))'
$args => 'iv_beg string, iv_end string, iv_read_date date, iv_step
+char(6)'
$ret => '(date, date, char(1))'
$rargs => 'date, date, char(1)'
say
substr+lc crypt(qw $i3 SI$),4,5
|