Skip Menu |

This queue is for tickets about the Parse-RecDescent CPAN distribution.

Report information
The Basics
Id: 62909
Status: rejected
Priority: 0/
Queue: Parse-RecDescent

People
Owner: Nobody in particular
Requestors: mhhollomon [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 1.965001
Fixed in: (no value)



Subject: Improvements to left recursion detection
Attached is a patch against 1.965001 that significantly improves left recursion detection. Given the grammar: <autostub> direct: direct second: a(s?) second third : b(s?) c(?) third fourth: <leftop: a /,/ b>(s?) fourth fifth : <leftop: fifth /,/ b> # mutually recursive recurse1 : b(?) recurse2 recurse2 : a(?) recurse1 # these better not be tagged okay1 : a okay1 okay2 : <leftop: a /,/ okay2>(s?) b okay2 okay3 : a(..5) okay3 __END_GRAMMAR__ Output is: ERROR: Rule "direct" is left-recursive. (Hint: Set $::RD_HINT (or -RD_HINT if you're using "perl -s") for hints on fixing these problems.) ERROR: Rule "second" is left-recursive. (Hint: Set $::RD_HINT (or -RD_HINT if you're using "perl -s") for hints on fixing these problems.) ERROR: Rule "fifth" is left-recursive. (Hint: Set $::RD_HINT (or -RD_HINT if you're using "perl -s") for hints on fixing these problems.) ERROR: Rule "third" is left-recursive. ERROR: Rule "recurse2" is left-recursive. ERROR: Rule "recurse1" is left-recursive. ERROR: Rule "fourth" is left-recursive. (Hint: Set $::RD_HINT (or -RD_HINT if you're using "perl -s") for hints on fixing these problems.)
Subject: left_recursion_detection.patch
*** RecDescent.pm.orig 2010-11-10 19:09:38.817613072 -0500 --- RecDescent.pm 2010-11-10 19:10:35.075602785 -0500 *************** sub Precompile *** 82,87 **** --- 82,88 ---- print OUT "my "; require Data::Dumper; + local $Data::Dumper::Indent = 1; print OUT Data::Dumper->Dump([$self], [qw(self)]); print OUT "}"; *************** sub leftmostsubrule($) *** 542,554 **** { my $self = shift; ! if ( $#{$self->{"items"}} >= 0 ) ! { ! my $subrule = $self->{"items"}[0]->issubrule(); ! return $subrule if defined $subrule; } ! return (); } sub checkleftmost($) --- 543,558 ---- { my $self = shift; ! my @ret_subrules; ! my $item; ! foreach $item (@{$self->{'items'}}) { ! my $subrule = (ref($item) =~ /\AParse::RecDescent::Operator/) ? ! $item->{'leftarg'}->issubrule() : $item->issubrule(); ! push(@ret_subrules, $subrule) if defined $subrule; ! last unless (defined($item->{'min'}) && $item->{'min'} == 0) } ! return @ret_subrules; } sub checkleftmost($) *************** sub checkleftmost($) *** 571,576 **** --- 575,581 ---- } elsif (@items==1 && ($items[0]->describe||"") =~ /<rulevar|<autoscore/) { + return 0; # Do nothing } elsif (@items &&
Thank you for the patch. Unfortunately, detecting left-recursion in the manner can produce errors for grammar/input combinations that actually do parse correctly. See the attached grammar for an example. Because the "second: 'end'" production is checked before the left-recursive rule, it is possible for the grammar to parse some inputs without looping infinitely. I'd also guess that its possible to use Replace and Extend to create self-modifying grammars that start off left-recursive and eventually do finish correctly. Perhaps a better approach would be to detect: 1. Obviously left-recursive grammars of the form "second: second" as today, and throw an error. 2. Potentially left-recursive grammars of the sorts that you've provided, and throw a warning or hint. Thoughts/opinions? Thanks, Jeremy
Subject: leftRecursion.pl
#!/usr/bin/env perl use strict; use Parse::RecDescent; our $test = "a"; my $parser = Parse::RecDescent->new(<<'EOG'); second: 'end' { $return = $item[1]; } | a(s?) second { $return = [ @item[1..2] ] } a: "$::test" { $::test = ++$::test; $return = $item[1]; } EOG use Data::Dumper; print Dumper $parser->second('a b c d e f g end');
Rather than improve detection, I decided to take a stab at enabling left-recursion in grammars. If you're interested, you can find this (experimental!) feature here: https://github.com/jtbraun/Parse-RecDescent/tree/leftrecursion Once I'm more certain of its correctness, it will make its way into CPAN.
Damian pointed out to me that it is not possible to handle left-recursion correctly in this manner. On Mon Mar 26 01:40:02 2012, jtbraun wrote: Show quoted text
> Rather than improve detection, I decided to take a stab at enabling > left-recursion in grammars. If you're interested, you can find this > (experimental!) feature here: > > Once I'm more certain of its correctness, it will make its way into CPAN.