Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Parse::RecDescent grammar definition

by citromatik (Curate)
on Mar 21, 2011 at 11:17 UTC ( [id://894476]=perlquestion: print w/replies, xml ) Need Help??

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

Hi all

I am trying to write a simple grammar just to learn how to use Parse::RecDescent. Why this doesn't work "as expected"?:

my $p2 = Parse::RecDescent->new(q( hyphen : "-" option : "a" | "b" | "c" Format : Entry(s) Pre : hyphen option Post : option hyphen Entry : Pre | Post { use Data::Dumper; print Dumper \%ite +m;} )); $p2->Format('a-'); $p2->Format('-a');

I would expect both strings matching and printing "-a" or "a-", but I get:

$VAR1 = { 'Post' => '-', '__RULE__' => 'Entry' };

i.e. Both are valid patterns, but only the first one triggers the action

I would expect getting this:

$VAR1 = { 'Post' => 'a-', '__RULE__' => 'Entry' }; $VAR1 = { 'Post' => '-a', '__RULE__' => 'Entry' };

I am not getting something obvious here... Any help would be appreciated

citromatik

Replies are listed 'Best First'.
Re: Parse::RecDescent grammar definition
by jethro (Monsignor) on Mar 21, 2011 at 12:09 UTC

    Return value (if you don't specify anything through $return) is the value of the last successfully matched items. The information can be found in the documentation in section 'Subrules':

    The value associated with a subrule is the value associated with its $return variable (see "Actions" below), or with the last successfully matched item in the subrule match.

    The second problem is that your print statement only belongs to the second rule, i.e. if Pre is matched, nothing is done at all. You might check the return value of your call to $p2->Format to see if a production was parsed successfully

      The second problem is that your print statement only belongs to the second rule, i.e. if Pre is matched, nothing is done at all.

      Wow, there is something I am not getting here. I would expect %item to have what matches in the rule, so if the rule is "Pre | Post", %item would have either the "Pre" or the "Post" matching part.

      Obviously I am getting all this wrong

      citromatik

        You are right, %item has either the Pre or Post matching part. But only in one case does it print anything!

        Entry : Pre | Post { use Data::Dumper; print Dumper \%item;} # is equivalent to Entry : Pre Entry : Post { use Data::Dumper; print Dumper \%item; } # is equivalent to Entry : Post { use Data::Dumper; print Dumper \%item; } Entry : Pre # is NOT equivalent to Entry : Pre { use Data::Dumper; print Dumper \%item; } Entry : Post { use Data::Dumper; print Dumper \%item; }

        And the last example is what you want

Re: Parse::RecDescent grammar definition
by lancer (Scribe) on Mar 21, 2011 at 12:10 UTC

    I get this when I try to run it:

    ERROR: Internal error in generated parser code! (Hint: Set $::RD_HINT (or -RD_HINT if you're using "pe +rl -s") for hints on fixing these problems.) Can't call method "Format" on an undefined value at ./temp.pl line 17.

    When run with "$::RD_HINT" set, as it recommends, I get this:

    ERROR: Internal error in generated parser code! (Hint: Global symbol "%ite" requires explicit package +name at (eval 8) line 472. syntax error at (eval 8) line 475, near ") {" syntax error at (eval 8) line 480, near "} Parse::RecDescent::_trace" BEGIN not safe after errors- -compilation aborted at (eval 8) line 541. ) Can't call method "Format" on an undefined value at ./temp.pl line 20.

    I'm using Perl version 5.12.

    Update: Ok, the problem was that I copy-pasted the code, and one of the lines was broken from that. I've used the "download" link, and now it runs fine. (though with citromatik's original problem) (thanks, jethro!)

      I don't have any problem running the example I posted in Perl 5.10:

      #!/usr/bin/perl use strict; use warnings; use Parse::RecDescent; my $p2 = Parse::RecDescent->new(q( hyphen : "-" option : "a" | "b" | "c" Format : Entry(s) Pre : hyphen option Post : option hyphen Entry : Pre | Post { use Data::Dumper; print Dumper \%ite +m;} )); $p2->Format('a-'); $p2->Format('-a');

      output:

      $VAR1 = { 'Post' => '-', '__RULE__' => 'Entry' };

      citromatik

Re: Parse::RecDescent grammar definition
by Anonymous Monk on Mar 21, 2011 at 14:39 UTC
    FYI, I found it very useful to define a module of utility subroutines to do various things to the result variables (for instance) which I "use" within the grammar (generated...) code. If I always want a list, for example, but the parser might in some cases hand me undef or a scalar, an appropriate utility sub can easily make that a non-issue and always do the right thing. "Using" them provides consistency and avoids repetition of source code.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://894476]
Approved by Corion
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (4)
As of 2024-04-25 05:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found