rkg has asked for the wisdom of the Perl Monks concerning the following question:

I'm having troubling referencing the RegExp::Common $RE variable from inside ParseRecDescent. The following code generates a "ERROR: Internal error in generated parser code!" P.R.D. error. Thanks for the advice --
rkg
use strict; use warnings; package Parser::RKG; use Parse::RecDescent; use Data::Dumper; use RegExp::Common qw(URI); use constant DEBUG => 0; $::RD_HINT = 1 if DEBUG; $::RD_TRACE = 1 if DEBUG; my $g = q( CommentLine: '#' /.*/ {{comment=>$item[2]}} UriLine: 'u=' /$RE{URI}{HTTP}/ {{uri => $item[2]}} Line: CommentLine | UriLine {$item[1]} ); sub new { my ($class) = @_; my $self = {}; bless ($self, $class); $self->{parser} = Parse::RecDescent->new($g); $self->{parse_results} = []; return $self; } sub parse_line { my ($self, $line) = @_; chomp $line; return 1 unless defined($line); # empty is a valid do-nothing return 1 unless $line =~ /\S/; # empty is a valid do-nothing print "parsing: $line\n" if DEBUG; my $pat = $self->{parser}->Line($line); return 0 unless $pat; # failure push ( @{$self->{parse_results}}, $pat ); return 1; # success } sub parse_results { my ($self) = @_; return $self->{parse_results}; } 1;

Replies are listed 'Best First'.
Re: Regexp::Common inside Parse::RecDescent
by gjb (Vicar) on Aug 21, 2003 at 11:33 UTC

    You'll have to have the use inside the parser code, i.e. in the generated code. This means you should use a start-up action since the first thing to do when the parser starts is to load the module. Try this for the grammar:

    my $g = q( { use Regexp::Common qw(URI); } CommentLine: '#' /.*/ {{comment=>$item[2]}} UriLine: 'u=' /$RE{URI}{HTTP}/ {{uri => $item[2]}} Line: CommentLine | UriLine {$item[1]} );
    See Parse::RecDescent's POD under 'Start-up actions' for details.

    IMHO, the grammar should definitely be in single quotes since it should not be interpolated in contrast with what Abigail-II says.

    Hope this helps, -gjb-

      IMHO, the grammar should definitely be in single quotes since it should not be interpolated in contrast with what Abigail-II says.

      You're both wrong. :-)

      No just kidding. You are both right. Abigails suggestion would work fine if the $RE expanded before P::RD ever saw it. OTOH, it makes more sense to me to use your approach of use()ing the module inside of the grammar.

      And personally I prefer single quoted here docs for my grammars because it avoids the double interpolation problem that can crop up unexpectedly if you arent careful.


      ---
      demerphq

      <Elian> And I do take a kind of perverse pleasure in having an OO assembly language...

        I suggest using here-docs for grammars.

        #!perl use warnings; use strict; my $one = q{/\d \\ \/ \\/ / }; my $two = <<'--snip--'; /\d \\ \/ \\/ / --snip-- print "\$one is `$one'\n\$two is `$two'\n"; __END__

        This prints

        $one is `/\d \ \/ \/ / ' $two is `/\d \\ \/ \\/ / '
        which means you needn't escape your backslashes in single-quote here-docs. This can make regexes more readable.

Re: Regexp::Common inside Parse::RecDescent
by Abigail-II (Bishop) on Aug 21, 2003 at 11:23 UTC
    Two things, first, it's Regexp::Common, not RegExp::Common. Second, your grammar is inside a single quoted string, so $RE doesn't interpolate. You get what you write.

    Abigail