![]() |
Parse::RecDescent erreichbarkeit von Variablen
Hallo NG,
folgendes Problem: Ich habe ein Package mit dem Namen DhcpParser. In diesem Package gibt es eine Methode parseFile. Innerhalb der Grammatik möchte ich nun die geparsten Werte in einen Array schreiben und aus der Methode via return Anweisung zurückgeben. Leider habe ich außerhalb der Grammatik keinen Zugriff auf die Variablen (namentlich @hosts). In der Doku steht, dass die Variablen im Kontext von Parse::RecDescent zu sehen sind, wie kann ich aber darauf aus der Methode parseFile() zugreifen? Da steh ich wirklich auf dem Schlauch. Weiss jemand Rat? Ich habe auch schon versucht, die Variable @hosts mit our ganz oben im package zu deklarieren, leider auch ohne Erfolg. Hier meine package (gekürzt) --Schnipp package DhcpParser; [...] use Parse::RecDescent; [...] sub new { [...] } sub parseFile { my $self = shift; my %tmp = (); my @hosts; my $grammar = <<'EOGRAMMAR'; IDHOST : /[a-zA-Z-0-9]+/ IDMAC : /[a-fA-F0-9:]+/ IDIP : /[0-9.]+/ IDCOMMENT : /.*/ file : host(s?) host : /^host/ IDHOST { $::tmp{'name'} = $item[2]; } /{/ comment(?) option(s?) terminator(1) comment : <skip: qr/[ \t]*/> word(s?) newline word : /#/ IDCOMMENT { $::tmp{'comment'} = $item[2]; } newline : /\n/ option : mac | ip | other mac : /hardware ethernet/ IDMAC /;/ { $::tmp{'mac'} = $item[2]; } ip : /fixed-address/ IDIP /;/ { $::tmp{'ip'} = $item[2]; } other : /[^}]/ terminator : /}/ { push(@::hosts, { 'name' => $::tmp{'name'}, 'comment' => $::tmp{'comment'}, 'mac' => $::tmp{'mac'}, 'ip' => $::tmp{'ip'} } ); %::tmp = (); } EOGRAMMAR my $parse = new Parse::RecDescent($grammar); # Datei einlesen my $text; open( IN, "<" . $self->{FILENAME} ) or die "Fehler: parseFile: ($!)"; while (<IN>) { next if ( $_ =~ /^#/ || $_ =~ /^\s+$/ ); $text .= $_; } close(IN); my $tree = $parse->file($text); if (not $tree) { exit 1; } else { my $cnt= (@hosts); # <-- @hosts ist hier leer (im Kontext der Grammatik allerdings nicht) print $cnt, "\n"; } [...] } [...] 1; --Schnapp Danke und Gruß, Martin |
Re: Parse::RecDescent erreichbarkeit von Variablen
Hi folks,
sorry for posting in german - I didn't mention the missing 'de' prior the groupname. My problem points to variables used inside the grammar in the method parseFile(). I'm not able to access the variable @hosts outside the grammar and would like to know, how to get the data out of the parsed file. Inside the grammar @hosts is filled with records, outside it is empty. Documentation says, all variables are in context of Parse::RecDescent. So how to access them in there? Thank for any hints. Regards, Martin |
Re: Parse::RecDescent erreichbarkeit von Variablen
On 1/5/2010 7:53 PM, Martin Bley wrote:
> Documentation says, all variables are in context of Parse::RecDescent. > So how to > access them in there? Thank for any hints. If package-compiiled, then @P::RD::hosts should work; if lexical, then you're out of luck. Though usually, it's an input problem and you shouldn't be messing with module internals. |
Re: Parse::RecDescent erreichbarkeit von Variablen
Hi,
> If package-compiiled, then @P::RD::hosts should work; if lexical, then > you're out of luck. > > Though usually, it's an input problem and you shouldn't be messing with > module internals. I know, this is not clean code. I just don't get how to use the parsed values outside the Parse::RecDescent package. Right now, I declare hosts at the beginning of my package DhcpParser with our @hosts; This way I can access the variable via @::hosts outside the package. How is it done in a "clean" way? Thanks, Martin |
Re: Parse::RecDescent erreichbarkeit von Variablen
On 1/5/2010 9:26 PM, Martin Bley wrote:
> Hi, > >> If package-compiiled, then @P::RD::hosts should work; if lexical, then >> you're out of luck. >> >> Though usually, it's an input problem and you shouldn't be messing with >> module internals. > I know, this is not clean code. I just don't get how to use the > parsed > values outside the Parse::RecDescent package. Right now, I declare > hosts > at the beginning of my package DhcpParser with > > our @hosts; > > This way I can access the variable via @::hosts outside the package. > How is > it done in a "clean" way? usually, you write a function to return a ro copy of @hosts. But why @::hosts if it's in the DhcpParser package? Try @DhcpParser::hosts? |
Re: Parse::RecDescent erreichbarkeit von Variablen
On Tue, 5 Jan 2010 05:26:28 -0800 (PST) Martin Bley <martinbley@yahoo.de> wrote:
MB> I know, this is not clean code. I just don't get how to use the MB> parsed values outside the Parse::RecDescent package. Right now, I MB> declare hosts at the beginning of my package DhcpParser with our MB> @hosts; MB> This way I can access the variable via @::hosts outside the package. MB> How is it done in a "clean" way? This is pretty clean. Do your work inside a package, declare "our @hosts" and then you'll have a nice clean @DhcpParser::hosts to use. But I have two comments. First, have you seen http://search.cpan.org/~jhthorsen/Ne.../ISC/DHCPd.pm? It may be useful and handles parsing the leases as well. Your MAC and IP rules in particular can be improved, perhaps with Regexp::Common. Generally when I write a P::RD parser I try to keep interaction with global variables to a minimum. Sometimes it can't be avoided. In your case, you do (as a summary): match A and set $tmp{A}, then B and set $tmp{B}, then match a terminal and add the hash ref { A => $tmp{A}, B => $tmp{B} } to @hosts. This is not the best way to do it, though it may work sometimes. What you want is: # this rule will return an array ref to all the matches all: match(s) # this rule will return the hash ref you wanted to build # you could also return \%item but you'll get unnecessary junk in there # you could also return { A => $item[1], B => $item[2] } but you'd be # hard-coding the positions; it may be necessary sometimes match: A B terminal { $return = { A => $item{A}, B => $item{B} } } Now, when you call the 'all' rule, you'll get an array ref to all the matches. The external @hosts and %tmp are not needed. $return is also nice as a way to indicate rule failure in code--you just set it to undef. You can call an external function with the just-parsed arguments, too. You may also want to look at Hash::Merge to simplify your return values and the <autotree> P::RD directive to build these hashes automatically for you. <autotree> can be very verbose, though. I like it for debugging but usually construct my own data structures in the end. Ted |
| All times are GMT. The time now is 01:58 PM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.