in reply to aliasing !! and Parse::RecDescent?

The reason the alias is not accessible in other rules is because of the local *a Local gives a variable a temporary value that last until you exit the current set of curly brackets so
$a = 1; { local $a = 2; print "$a\n"; } print "$a\n";
prints
2 1
So basically your alias disappears as soon as you exit ruleX.

So the answer is to not use local. This has a downside of course, if you don't use local then the alias will never go away, so you might have to do something funky like emulating localisation.

WARNING: doing this sucks, it's very easy to make a mistake. If I ever saw this in a module, I would have serious doubts about the author!

my $grammar = q{ {our @a, @as} ruleX: r1 local_a r2 r3 unlocal_a local_a: { push(@as, \@a); *a{ARRAY} = undef; } unlocal_a: { *a{ARRAY} = pop(@as); } r2: 'keyword' /[a-z]+/ { local *a = \@::{$item[2]}; } r3: 'value' /[a-z]+/ { print @a; } }
What will happen is:
  • r1 will be matched and executed
  • local_a will save a ref to the current @a onto the @as stack
  • r2 will alias something to @a
  • r3 can now use @a and get the value that r2 put into
  • finally unlocal_a will put @a back to whatever it was beforehand.
  • So using the above lets you share aliases between rules of the grammar and it lets you nest those rules too because it makes sure it always saves the previous alias and restores it when you're done. However it is very easy to forget the unlocal_a at the end. Plus it's a lot of work and you have to write 2 rules for every variable you want to use for aliases. So don't do this unless you really really really have to.

    As to the second question, I don't really know what you mean. Can you rephrase it.

    Replies are listed 'Best First'.
    Re: Re: aliasing !! and Parse::RecDescent?
    by bugsbunny (Scribe) on Jul 28, 2003 at 11:52 UTC
      hmm.. thanx for the answers.
      As I thought it seems counterproductive to use aliasing..
      Lets rephrase the second question :

      the idea is to have the result of the parsing as internal object data but not global..
      this way I can create many objects that can parse different string-flows.. so that i do :
      my $obj = new Parser(); $obj->parse; print "$_\n" for @{$$obj{_data}};
      this mean I have to write directly into $$obj{_data} array during the parse..
      I can't figure out how to access object data from the parse..probably class var which will work as intermediate reference...
      package Parser; our $ref; my $grammar = q{ { my $data = $ref } start : ..... ruleX : blah hmm { push @{$$data{_data}}, $item[2] } } sub parse { my $self = shift; $ref = $self{_data}; $parser = new Parse::RecDescent; $parser->start($$self{str}) ... }
      havent tested..is this the correct way of doing it ?! what bothers me in this variant is that $ref can be overwriten from different objects..(which can be problem in multiuser env., not that i will use it in such way but who know :"))
      Using array/stack will not solve this problem either..