Re: Package variables and Parse::RecDescent
by Fletch (Bishop) on Jan 07, 2003 at 20:06 UTC
|
You don't, as you've declared $checksyntax as a lexical in the block enclosing init_parser. It's only visible to the code literally between the outer two {}'s in your example. You probably want to declare it with our $checksyntax, then it would be accessable as $TelnetClient::Functions::checksyntax elsewhere.
Addendum: An alternative to using package variables would be to implement some variant of the Builder pattern. You have a interface which your grammar calls when it recognizes chunks, and you pass different implementors of that interface (one which builds a syntax tree, the other which does nothing as just a check that the input is valid, etc.). Consult your copy of the GangOfFour book for more details.
| [reply] [d/l] [select] |
|
|
I've no idea what you mean by Builder pattern etc. Do you have an example of that?
C.
| [reply] |
|
|
| [reply] |
Re: Package variables and Parse::RecDescent
by Hofmator (Curate) on Jan 07, 2003 at 20:15 UTC
|
Your problem here is that my $checksyntax declares a lexical variable, while both $::checksyntax and $TelnetClient::Functions::checksyntax refer to (different!) package variables. For a good introduction read up Dominus' Coping with Scoping.
A different issue is that you can only access package variables out of a grammar of Parse::RecDescent. The grammar itself lives in its own lexical scope (if I understood that correctly). To do so you have to fully qualify them, like $TelnetClient::Functions::checksyntax
-- Hofmator | [reply] [d/l] [select] |
|
|
Hmm, so even though my grammar is in the same block as $checksyntax, by the time it is used the scope of $checksyntax is gone? So I'll have to make it global, hohum.
C.
| [reply] |
|
|
| [reply] |
Re: Package variables and Parse::RecDescent
by demerphq (Chancellor) on Jan 07, 2003 at 21:15 UTC
|
Two niggly comments to add to the existing correct explanations of your problem:
my $parser = new Parse::RecDescent($grammar);
Is a bad meme in Perl. I know its in the docs (it shouldnt be, even TheDamian has commented on why its a bad idea) but use the unambiguous and easier to read (IMO)
my $parser = Parse::RecDescent->new($grammar) or die "Failed to create
+ parser.\n";
and you'll one day save yourself some bizarre debugging. Note that checking the return of a constructor for an object you didnt write is usually a good idea.
The other is that while q§ ... §; sure is funky looking, it is not as suitable as using HereDoc quoting when using PRD and embedded code:
my $grammar=<<'END_OF_GRAMMAR';
...
END_OF_GRAMMAR
my $parser = Parse::RecDescent->new($grammar) or die "Failed to create
+ parser.\n";
Personally I tend to roll them into one:
my $parser = Parse::RecDescent->new(<<'END_OF_GRAMMAR') or die "Failed
+ to create parser.\n";
...
END_OF_GRAMMAR
The main reason that <<'END_OF_GRAMMAR' is better is that it is the only normal Perl quoting construct that does not require backslashes or quotes to be escaped. Which in turn can greatly simplify the embedded code that you have in your grammar.
HTH
--- demerphq
my friends call me, usually because I'm late....
| [reply] [d/l] [select] |
|
|
| [reply] |
|
|
Just another small niggle. According to my camel (page 63), quoting as I'm doing using q§ .. §; (or any other character), doesn't interpolate. In my embedded code I'm using quotes, double quotes, variables etc. without problems.
C.
| [reply] |
|
|
E:\blead> perl -e "print q§/\\\./§"
/\\./
So the regex that starts off being "match a backslash followed by a period" becomes "match a backslash followed by any non newline character". Not exactly the same thing. Whereas
#!perl
print <<'ENDOFHERE';
/\\\./
ENDOFHERE
Outputs the expected /\\\./
For this reason, I tend to do my best to avoid using the q// operator when Im trying to quote code. After all you never know when you'll stick a double backslash into the code, and it might save you hours of debugging trying to figure what the problem was, wheras the HEREDOC notation is only slightly more characters to write, with virtually no chance of this happening.
--- demerphq
my friends call me, usually because I'm late....
| [reply] [d/l] [select] |
Re: Package variables and Parse::RecDescent
by tall_man (Parson) on Jan 07, 2003 at 22:55 UTC
|
Since the "my" variables are within a local scope, and you are defining subroutines within that scope, you can take advantage of the fact that the subroutines act as closures.
Why not add another subroutine before init_parser, like this:
sub getChecksyntax {
return $checksyntax;
}
If you call it from the code blocks of your grammar you should have what you need. | [reply] [d/l] |
|
|
That works wonderfully, thanks!
C.
| [reply] |