The included patch, a result of a bit of time with Devel::Profiler, speeds up RecDescent by almost a factor of two on a grammar of mine by doing two things:
(1) Caching Rule::expected() results; (2) Inlining Expectation::is() and Expectation::at(). There's also a third change, removing a "my " where it gave me a syntax error in precompiled grammars. I've got the latest Data::Dumper installed, so I'm not sure why this would be a problem only for me. Please let me know if this seems like a good idea, or if some of you see other similar improvements. /s
--- lib/Parse/RecDescent.pm Fri Jan 19 10:02:51 2001 +++ /usr/local/lib/perl5/site_perl/5.6.1/Parse/RecDescent.pm Thu Jul 4 12:10:13 +2002 @@ -78,7 +78,8 @@ sub Precompile print OUT $self->_code(); print OUT "}\npackage $class; sub new { "; - print OUT "my "; +# SEAN: this is bad. +# print OUT "my "; require Data::Dumper; print OUT Data::Dumper->Dump([$self], [qw(self)]); @@ -260,6 +261,7 @@ sub leftmostsubrules($) sub expected($) { my $self = shift; + return $self->{"expected"} if exists($self->{"expected"}); my @expected = (); my $prod; @@ -272,7 +274,7 @@ sub expected($) } } - return join ', or ', @expected; + return $self->{"expected"} = join ', or ', @expected; } sub _contains($@) @@ -297,6 +299,7 @@ sub addprod($$) my ( $self, $prod ) = @_; push @{$self->{"prods"}}, $prod; $self->{"changed"} = 1; + delete $self->{"expected"}; $self->{"impcount"} = 0; $self->{"opcount"} = 0; $prod->{"number"} = $#{$self->{"prods"}}; @@ -382,7 +385,7 @@ sub ' . $namespace . '::' . $self->{"nam my $text; my $lastsep=""; my $expectation = new Parse::RecDescent::Expectation($thisrule->expected()); - $expectation->at($_[1]); + $expectation->{lastunexpected} = $_[1]; '. ($parser->{_check}{thisoffset}?' my $thisoffset; tie $thisoffset, q{Parse::RecDescent::OffsetCounter}, \$text, $thisparser; @@ -1099,8 +1102,9 @@ my $code = ' q{' . $rule->{name} . '}) if defined $::RD_TRACE; $lastsep = ""; - $expectation->is(q{' . ($rule->hasleftmost($self) ? '' - : $self->describe ) . '})->at($text); + $expectation->{lastexpected} = q{' . ($rule->hasleftmost($self) ? '' + : $self->describe ) . '}; + $expectation->{lastunexpected} = $text; ' . ($self->{"lookahead"} ? '$_savetext = $text;' : '' ) . ' ' . ($self->{"lookahead"}<0?'if':'unless') @@ -1170,8 +1174,9 @@ my $code = ' q{' . $rule->{name} . '}) if defined $::RD_TRACE; $lastsep = ""; - $expectation->is(q{' . ($rule->hasleftmost($self) ? '' - : $self->describe ) . '})->at($text); + $expectation->{lastexpected} = q{' . ($rule->hasleftmost($self) ? '' + : $self->describe ) . '}; + $expectation->{lastunexpected} = $text; ' . ($self->{"lookahead"} ? '$_savetext = $text;' : '' ) . ' ' . ($self->{"lookahead"}<0?'if':'unless') @@ -1239,8 +1244,9 @@ my $code = ' q{' . $rule->{name} . '}) if defined $::RD_TRACE; $lastsep = ""; - $expectation->is(q{' . ($rule->hasleftmost($self) ? '' - : $self->describe ) . '})->at($text); + $expectation->{lastexpected} = q{' . ($rule->hasleftmost($self) ? '' + : $self->describe ) . '}; + $expectation->{lastunexpected} = $text; ' . ($self->{"lookahead"} ? '$_savetext = $text;' : '' ) . ' ' . ($self->{"lookahead"}<0?'if':'unless') @@ -1321,9 +1327,10 @@ sub code($$$$) q{' . $rule->{"name"} . '}) if defined $::RD_TRACE; if (1) { no strict qw{refs}; - $expectation->is(' . ($rule->hasleftmost($self) ? 'q{}' - # WAS : 'qq{'.$self->describe.'}' ) . ')->at($text); - : 'q{'.$self->describe.'}' ) . ')->at($text); + $expectation->{lastexpected} = ' . ($rule->hasleftmost($self) ? 'q{}' + # WAS : 'qq{'.$self->describe.'}' ) . ')->($text); + : 'q{'.$self->describe.'}' ) . '; + $expectation->{lastunexpected} = $text; ' . ($self->{"lookahead"} ? '$_savetext = $text;' : '' ) . ($self->{"lookahead"}<0?'if':'unless') . ' (defined ($_tok = ' @@ -1434,9 +1441,9 @@ sub code($$$$) Parse::RecDescent::_tracefirst($text), q{' . $rule->{"name"} . '}) if defined $::RD_TRACE; - $expectation->is(' . ($rule->hasleftmost($self) ? 'q{}' - # WAS : 'qq{'.$self->describe.'}' ) . ')->at($text); - : 'q{'.$self->describe.'}' ) . ')->at($text); + $expectation->{lastexpected} = ' . ($rule->hasleftmost($self) ? 'q{}' + : 'q{'.$self->describe.'}' ) . '; + $expectation->{lastunexpected} = $text; ' . ($self->{"lookahead"} ? '$_savetext = $text;' : '' ) .' unless (defined ($_tok = $thisparser->_parserepeat($text, ' . $self->callsyntax($namespace.'::') @@ -1529,9 +1536,9 @@ sub code($$$$) Parse::RecDescent::_tracefirst($text), q{' . $rule->{"name"} . '}) if defined $::RD_TRACE; - $expectation->is(' . ($rule->hasleftmost($self) ? 'q{}' - # WAS : 'qq{'.$self->describe.'}' ) . ')->at($text); - : 'q{'.$self->describe.'}' ) . ')->at($text); + $expectation->{lastexpected} = ' . ($rule->hasleftmost($self) ? 'q{}' + : 'q{'.$self->describe.'}' ) . '; + $expectation->{lastunexpected} = $text; $_tok = undef; OPLOOP: while (1) @@ -1642,16 +1649,6 @@ sub new ($) }; } -sub is ($$) -{ - $_[0]->{lastexpected} = $_[1]; return $_[0]; -} - -sub at ($$) -{ - $_[0]->{lastunexpected} = $_[1]; return $_[0]; -} - sub failed ($) { return unless $_[0]->{lastexpected}; @@ -2767,7 +2764,8 @@ sub _parserepeat($$$$$$$$$$) # RETURNS A my $reps; for ($reps=0; $reps<$max;) { - $_[6]->at($text); # $_[6] IS $expectation FROM CALLER + # $_[6] IS $expectation FROM CALLER + $_[6]->{lastunexpected} = ($text); my $_savetext = $text; my $prevtextlen = length $text; my $_tok;