I've built a simple grammar using Parse-RecDescent to return only the function names found
in a file. Basically all I care about at this point is the function name (later on I will return
the contents of the function, rather than the name, but am having troubles which
are mentioned in the Output section.
#!/usr/bin/perl
use strict; # Enforces safer, clearer code.
use warnings; # Detects common programming errors
use Time::HiRes qw(gettimeofday);
use Parse::RecDescent;
#---------------------------------------------------------------------
+-
# Build the grammar.
#---------------------------------------------------------------------
+-
my ($grammar);
my ($startCompile) = gettimeofday;
$grammar = q {
statement: (
(
function_method |
brace_statement |
parenthesis_statement |
bracket_statement |
stuff_we_ignore
) (';')(?)
{ $return = $item[1]; }
)(s?)
function_method: 'function' identifier
parenthesis_statement brace_statement
{ $return = $item[2]; }
brace_statement: '\{' statement '\}'
{ $return = $item[2]; }
parenthesis_statement: '(' statement ')'
{ $return = ""; }
bracket_statement: '[' statement ']'
{ $return = ""; }
stuff_we_ignore: ( identifier | punctuators )(s?)
+
{ $return = ""; }
identifier: /\w+/
punctuators: /[><=!~:&^%,\?\|\+\-\*\/\.]+/
# stuff_we_ignore: /[\w><=!~:&^%,\?\|\+\-\*\/\.]+/
# others: /[;(){}\[\]]+/
};
#---------------------------------------------------------------------
+-
# Print the results.
#---------------------------------------------------------------------
+-
my @localDeclaredVars = <DATA>;
my $localDeclaredVar = join ' ', @localDeclaredVars;
my $parser = new Parse::RecDescent ($grammar) or die "*** Bad grammar!
+\n";
my $i = 1;
my ($endCompile) = gettimeofday;
print "\nCompile Time: " . (sprintf "%2.1f", ($endCompile - $startComp
+ile)) . " seconds\n";
print '-'x80 . "\n";
my $refParsedValues = $parser->statement($localDeclaredVar) || print "
+*** $localDeclaredVar\n";
# This is ugly - What can I do folks?
if (ref($refParsedValues) eq 'ARRAY') {
foreach my $parsedValue (@$refParsedValues) {
if (ref($parsedValue) eq 'ARRAY') {
foreach my $parsedSubValue (@$parsedValue) {
if (ref($parsedSubValue) eq 'ARRAY') {
chomp (@$parsedSubValue);
print sprintf ("%3d", $i++) . " %=> [@$parsedSubVa
+lue]\n";
} elsif (defined $parsedSubValue && $parsedSubValue ne
+ '1' && $parsedSubValue ne '') {
print sprintf ("%3d", $i++) . " ^-> [$parsedSubVal
+ue]\n";
}
}
} elsif (defined $parsedValue && $parsedValue ne '1' && $parse
+dValue ne '') {
print sprintf ("%3d", $i++) . " =-> [$parsedValue]\n";
}
}
} elsif (defined $refParsedValues && $refParsedValues ne '1' && $refPa
+rsedValues ne '') {
print sprintf ("%3d", $i++) . " --> [$refParsedValues]\n";
}
my ($parseEnd) = gettimeofday;
print '-'x80 . "\n";
print "Parse Time: " . (sprintf "%2.1f", ($parseEnd - $endCompile)) .
+ " seconds\n";
print "Total Time: " . (sprintf "%2.1f", ($parseEnd - $startCompile))
+ . " seconds\n";
__END__
var g1, g2 = __QUOTE__; var g3 = 10000000;
if (g1) { var XXXXXXX = __QUOTE__; }
if ( ! defaultCookieCrumbNav ) { cookieCrumbNavBarHTML = __QUOTE__ ; }
+
else { function funct1 () { }; var xxx = __QUOTE__ ; }
if (true == false) { alert(var1); }
if (1) { if (1) { if (1) { function funct2 (X) { fff = funct3 (1,2); }
+ } } }
function funct3 (a,b) { alert (1,2,3,4); return (a + b); }
function funct4 () { var aaa = 1; }
function funct5 (var1) {
if (1) { return true; } else if (1) { return true; } else { if (tr
+ue) { alert(var1); } }
}
var g4; var g7 = __QUOTE__;
function funct6 () { var b = __REGEX__; c = __REGEX__; if (test333())
+{ return true; } }
function funct7 () { var a = 111; }
alert ( 3 );
funct5 ( funct6 ( funct2 () ) );
var done_parsing;
Output
Compile Time: 0.0 seconds
----------------------------------------------------------------------
1 ^-> [funct1]
2 %=> [ ARRAY(0x25ec9bc) ]
3 =-> [funct3]
4 =-> [funct4]
5 =-> [funct5]
6 =-> [funct6]
7 =-> [funct7]
----------------------------------------------------------------------
Parse Time: 1.0 seconds
Total Time: 1.0 seconds
My Issues
Some issues I have:
I can't figure out how to return the "funct2()" that was matched several levels deep
from the brace_statement...
Is there anything else I should do to reduce Parse/Compile
times, please feel free to let me know... I've read some good resources such as the POD and FAQ,
and have gotten some hints there...
The display times never go into the decimal point (just integers)... why is this?
I'm running ActiveState's Perl 5.6.1 Build 631 on a W2K box.
My code to print the output
is very ugly... anything I can do to make the output code better?
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.