http://qs321.pair.com?node_id=894780


in reply to scope issues in Parse::RecDescent

As Parse::RecDescent gets its grammar as a string, I see no way to create clever closures or anything that will allow you to use lexical variables. One approach I can think of would be judicious use of local to isolate the effects, but that implies that your parsers won't call each other recursively:

... sub do_parse { local $parser_info = { tokens => [], }; my $p6 = Parse::RecDescent->new(q{ { push @{ $parser_info->{tokens} }, $item{letter} } }); }; ...

That way, you reduce your need for a global variable to one entry point, $parser_info. I think you can also instruct Parse::RecDescent to return you the whole parse tree as an AST instead of having it execute code immediately, by using the <autotree> directive. That wouldn't require any code within your parser, but you have to walk the tree yourself after it has been constructed.

Replies are listed 'Best First'.
Re^2: scope issues in Parse::RecDescent
by citromatik (Curate) on Mar 23, 2011 at 11:43 UTC

    It seems that you can define "top level" actions and define variables in them. So this would do the trick:

    use strict; use warnings; use Data::Dumper use Parse::RecDescent; ### use vars qw/@tokens/; Avoided using global variables my $p6 = Parse::RecDescent->new(q( {my @tokens} letter : /\w/ character : letter { push @tokens, $item{letter}; } Format : character(s) { \@tokens } )); my $tokens_ref = $p6->Format('abc'); die "Invalid pattern" unless (defined $tokens_ref); print Dumper $tokens_ref;

    Outputs:

    $VAR1 = [ 'a', 'b', 'c' ];

    citromatik