[PATCH] speed up parsing somewhat

[email protected] ("Sean O'Rourke") Thu, 4 Jul 2002 12:12:49 -0700 (PDT)
Newsgroups perl.recdescent
Message-ID <[email protected]>
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
recdescent.patch (text/plain, 5.2 KB)
--- 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;