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

I keep getting the following error from P::RD:

Can't call method "file" on an undefined value at ../scan_test.plx line 46, <> line 1.

file is my startup rule. I test my input text and it is defined and contains the data I expect.

As long as I am just printing out the tokens that have been extracted, everything works OK. But as soon as I try to save some of the data for later use, the grammar breaks down. Here's the entire grammar (yes, P::RD is overkill, but I figured it would be quick and easy to get running):
my $grammar = q{ file: hdr body ftr hdr: /^HDR.*\\n/ { print "HDR: $item[1]"; } body: batch(s) ftr: /^FTR.*\\n/ batch: bathdr tran(s) batftr bathdr: /^BHD.*\\n/ { # $str1= substr($item[1],30,3) 1; } tran: TR1 TR2 batftr: /^BFT.*\\n/ TR1: /^TR1.*\\n/ { # $str4= substr($item[1],35,8); # $str2= substr($item[1],122,5); 1; } TR2: /^TR2.*\\n/ { # $str3= substr($item[1],103,2); # print "DATA: $str1, $str2, $str3, $str4\\n"; 1; } };
If I run the script as is, it works. If I uncomment any one of the commented actions above, it fails with the 'undefined value' error.
Any help would be appreciated. So far, re-reading the perldoc and the P::RD FAQ haven't helped.

Thanks...

"The only things that are difficult are those that I know nothing about" -- Mark Twain

janitored by ybiC: Fix typo in nodetitle - s/Prarse/Parse/

Replies are listed 'Best First'.
Re: Parse::RecDescent startup/input error
by amw1 (Friar) on Aug 06, 2004 at 16:32 UTC
    I don't know wether it's a typo or not but you are missing a ; on the first commented line. You may also want to look at using $return to get data out of the productions rather than modifying global vars. Something like this may work
    file: hdr body ftr { $return = {hdr => $item{hdr}, body => $item{body}, }; } body: batch(s) hdr: /^HDR.*\\n/ ftr: /^FTR.*\\n/ batch: bathdr tran(s) batftr { $return = {bathdr => $item{bathdr}, tran => $item{"tran(s)"}, }; } bathdr: /^BHD.*\\n/ { $return = substr($item[1], 30, 3); } batftr : /^BFT.*\\n/ tran: TR1 TR2 { $return = {%{$item{TR1}}, %{$item{TR2}}, }; } TR1: /^TR1.*\\n/ { $return = { str4 => substr($item[1], 35, 8), str2 => substr($item[1], 122, 5), }; } TR2: /^TR2.*\\n/ { $return = {str3 => substr($item[1], 103,2)}; }
    the return from the parser will be the datastructure you created and you can then print/manipulate it outside of the parser. Not tested at all.
      Thanks for your suggestion; I'll give it a try.

      In the meantime, I figured out how to solve the problem; I just don't understand why.
      The P::RD docs say:

      "...since each rule is implemented inside a special namespace belonging to its parser,
      it is necessary to explicitly quantify variables form the main package."


      Therefore, I changed all variables to refer to the Main package. I.e., $str1 becomes $Main::str1, and now it works. But why it spits out this particular error message is beyond me.

      Thanks...

      "The only things that are difficult are thoese that I know nothing about" -- Mark Twain