Skip Menu |

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

Report information
The Basics
Id: 62892
Status: open
Priority: 0/
Queue: Parse-RecDescent

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

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



Subject: failed subrules eat text
perl version 5.10.1 built for i686-cygwin-thread-multi-64int Parse::RecDescent version 1.965001 I would expect attached test to print "NO MATCH", but in fact, it matches. The problem seems to be this line in generated code: unless ( $_matched || defined($score) ) { ... $_[1] = $text; # NOT SURE THIS IS NEEDED <==== ... } $text is modified by the successful match of 'one'. Assigning back to the argument propagates this modification up the chain. Applying the attached patch fixes this bug, but I don't know what it might break. I can't think of a reason that you would ever want to propagate a $text change upwards on failure, but I may not have a good enough imagination.
Subject: failed_subrules_eat_text.pl
#!/usr/bin/perl -w use strict; use warnings; use Parse::RecDescent; my $text = "one ;"; my $parser = Parse::RecDescent->new(<<'EOGRAMMAR'); TOP: <leftop: element /,/ element>(s?) ';' element: 'one' 'two' EOGRAMMAR local $::RD_TRACE = 1; if (defined $parser->TOP($text)) { print "===== MATCHED ====\n"; } else { print "===== NO MATCH ===\n"; }
Subject: failed_subrules_eat_text.patch
*** RecDescent.pm.orig 2010-11-10 07:02:39.607127500 -0500 --- RecDescent.pm 2010-11-10 07:02:06.013162500 -0500 *************** sub ' . $namespace . '::' . $self->{"nam *** 441,447 **** ' : '') . ' ! $_[1] = $text; # NOT SURE THIS IS NEEDED Parse::RecDescent::_trace(q{<<Didn\'t match rule>>}, Parse::RecDescent::_tracefirst($_[1]), q{' . $self->{"name"} .'}, --- 441,447 ---- ' : '') . ' ! #$_[1] = $text; # NOT SURE THIS IS NEEDED Parse::RecDescent::_trace(q{<<Didn\'t match rule>>}, Parse::RecDescent::_tracefirst($_[1]), q{' . $self->{"name"} .'},
Thank you for the bug report! I'm preparing a set of changes for Parse::RecDescent that allow for the use of external lexers. A side effect of these changes are that all of the state saving/restoring code has been touched, and the provided test case appears to have the expected behavior against this new branch. It will be some time yet before this branch is production ready, so I will leave this ticket open until the lexer changes have been integrated. Jeremy
From: spam-bitcard [...] yary.ack.org
Hi, I've run into this same problem and had a devil of a time tracking it down, thanks for the patch! I wrote up a test program as well (before I saw this report) and am attaching it here, in case it is helpful for the test suite.
Subject: gramtest.pl
#!/usr/bin/env perl use strict; use Parse::RecDescent; my $parser = new Parse::RecDescent (<<'GRAMMA'); word: /\w+/ <reject: $item[1] eq 'nother'> {$item[1]} GRAMMA sub parse_word { if (defined (my $result=$parser->word($_[0]))) { print "parsed word '$result'\n"; } else { print "Could not parse here\n" } print "Left with '${$_[0]}'\n"; } my $text="an other"; # This is good parse_word(\$text); parse_word(\$text); # How come "nother" gets swallowed up? $text="a nother"; parse_word(\$text); parse_word(\$text); print "The previous line should have left with ' nother', if it \nsays '' then Parse::RecDescent ate unparsed text.\n";