Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

changing P::RD error message from within an action

by cazz (Pilgrim)
on May 31, 2005 at 21:01 UTC ( [id://462229]=perlquestion: print w/replies, xml ) Need Help??

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

I'm working on a grammer that I would like to do some tests that I can't quite figure out how to do with the normal P::RD grammer tests.

Yes, I know I should figure out how to implement my tests with a more detailed grammer... until I get around to that, I'm hoping I can figure out how to modify the error message from the action block.

I know how to fail parsing, just set $return to undef. However, I'm having a difficult time modifying the error message produced by P::RD.

Getting to the error production from inside the action isn't difficult since the error production is the last production in the rule:

$thisrule->{'prods'}[ $#{ $thisrule->{'prods'} } ]
Which, in my example is:
$VAR1 = bless( { 'number' => '1', 'strcount' => 0, 'dircount' => 1, 'uncommit' => 0, 'error' => 1, 'patcount' => 0, 'actcount' => 0, 'items' => [ bless( { 'msg' => ' my message here', 'hashname' => '__DIRECTIVE1__', 'commitonly' => '', 'lookahead' => 0, 'line' => 82 }, 'Parse::RecDescent::Error' ) ], 'line' => 82 }, 'Parse::RecDescent::Production' );
I should be able to (though not very nicely) get to msg via this:
$thisrule->{'prods'}[ $#{ $thisrule->{'prods'} } ]->{'items'}- +>[0]->{'msg'}
Setting that to be a different value, then triggering the specific error I'm looking for causes the error message to be changed, in the data structure (so says DD) however, I still get the default error message.

Is there a better way than this ugly hack I'm struggling through? If not, what am I doing wrong in my ugly hack?

Replies are listed 'Best First'.
Re: changing P::RD error message from within an action
by ikegami (Patriarch) on May 31, 2005 at 22:21 UTC

    Looking at the code (grammar.pm) generated by

    use Parse::RecDescent; my $grammar = <<'__EOI__'; parse: <error:FOO!> __EOI__ Parse::RecDescent->Precompile($grammar, "grammar") or die("Bad grammar\n");

    reveals (rearranged to avoid forced line breaks)

    $_tok = do { if (1) { do { push @{$thisparser->{errors}}, [qq{FOO!},$thisline]; } unless $_noactions; undef } else { 0 } };

    Let's test it:

    use Parse::RecDescent; my $grammar = <<'__EOI__'; parse: { # Create error message. my $msg = 'FOO!'; # Create error. push(@{$thisparser->{errors}}, [ $msg, $thisline ]) unless $_noactions; # Fail the action. undef; } __EOI__ my $parser = Parse::RecDescent->new($grammar) or die("Bad grammar\n"); $parser->parse('');

    Output:

    ERROR (line 1): FOO!

    bingo!

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (2)
As of 2024-07-24 22:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.