Oops, I needed to move the "no strict 'refs'" from the top of my script into the action.
But actually I've found a nicer solution, without symbolic refs: use strict; use vars qw($parser $text %top %wins %marm %bitmap %resource); use Data::Dumper; use Parse::RecDescent; $RD_WARN = 1; $RD_HINT = 1; $RD_TRACE = 120; $parser = Parse::RecDescent->new(q( mmpfile: chunk(s) /^\Z/ chunk: assignment[$arg[0]] | local | <error> assignment: keyword <skip: '[ \t]+'> value(s) { # a reference to a hash of lists my $href = $arg[0] || \%::top; push @{$href->{uc $item{keyword}}}, @{$item[3]}; } local: /START\b/i <skip: '[ \t]+'> ( platform | resource | bitmap ) <skip: $item[2]> chunk[$item[3]](s?) /END\b/i value: /VAL\d+\b/i keyword: /KEY\d+\b/i platform: /WINS\b/i { \%::wins } | /MARM\b/i { \%::marm } bitmap: /BITMAP\b/i value { # this action would fail if you return undef, # so create an empty hash if it doesn't exist yet $::bitmap{uc $item[-1]} ||= {}; $::bitmap{uc $item[-1]}; } resource: /RESOURCE\b/i value { # this action would fail if you return undef, # so create an empty hash if it doesn't exist yet $::resource{uc $item[-1]} ||= {}; $::resource{uc $item[-1]}; } )) or die 'Bad grammar'; $text .= $_ while (<DATA>); defined $parser->mmpfile($text) or die 'Bad text'; print Data::Dumper->Dump([\%top, \%wins, \%marm, \%bitmap, \%resource], [qw(top wins marm bitmap resource)]); __DATA__ key1 val1 START BITMAP val2 key2 val3 val4 END START WINS key2 val5 val6 END START RESOURCE val7 key3 val8 key4 val9 END > -----Original Message----- > From: ext Alexander Farber [mailto:[EMAIL PROTECTED] > > I have a text consisting of keyword/value assignments, > placed on 1 line (please see the __DATA__ on the bottom). > Some of the assignments are surrounded by START/END: > > START WINS > key1 val1 val2 > END > > START MARM > key1 val1 > END > > I would like to capture all of the assignments into hashes > of lists. The top-level assignments should go into %hol, > and the START/END-surrounded assignments should go into > %wins and %marm. I'm trying to achieve this by passing the > platform name (the word following START) as an argument to > the assignment rule and by using that name (lowercased) as > a symbolic reference. > > Unfortunately my script listed below dies with the error: > > Can't use string ("::hol") as a HASH ref while "strict refs" > in use at (eval 18) line 303, <DATA> line 6. > > Why does it mention "strict refs"? I'm explicitly setting > "no strict 'refs'" on the top of my script. > > Also, I wonder if there is a nicer way to solve my problem. > > The START/END areas do not nest, they are all 1-level deep. > > Thank you > Alex > > use strict; > no strict 'refs'; > use vars qw($parser $text %hol %wins %marm); > use Data::Dumper; > use Parse::RecDescent; > $RD_WARN = 1; > $RD_HINT = 1; > $RD_TRACE = 120; > $parser = Parse::RecDescent->new(q( > > mmpfile: chunk(s) /^\Z/ > chunk: assignment[$arg[0]] | local | <error> > assignment: keyword <skip: '[ \t]+'> value(s) { > my $hname = lc $arg[0] || 'hol'; > push @{${"::$hname"}{uc $item{keyword}}}, @{$item[3]}; > } > > local: /start/i <skip: '[ \t]+'> platform > <skip: $item[2]> chunk[$item[3]](s?) > /end/i { print "ITEM3: $item[3]\n" } > > value: /val\d+/i > keyword: /key\d+/i > platform: /wins/i || /marm/i > > )) or die 'Bad grammar'; > $text .= $_ while (<DATA>); > defined $parser->mmpfile($text) or die 'bad text'; > print Data::Dumper->Dump([\%hol, > \%wins, > \%marm], > [qw(hol wins marm)]); > __DATA__ > > key1 val1 > START WINS > key2 val2 val3 > END > >