Your instinct is correct.  Simplest, most important suggestion:  always "use warnings;" when developing and testing code.

Ok... I know you asked not to receive rewritten code -- but your parse / gettoken functions cries out for simplification.   The sole purpose of your two functions is to get the elements from the array referenced by $lTokens and then process each token / array element.  The simple solution is "while (my $tok = shift(@$lTokens)) { #do something with $tok }".  

The following is your sample code -- with your parse function renamed to "oldparse", a new parse function "newparse", warnings enabled, and function prototypes specified.  [And yes I realize that "Perl Best Practices" says not to use function prototypes -- but I like to use them to catch parameter mismatches such as exist in your example code.  Your "parse" expected two parameters but you only passed one -- but is not the source of your problem.]   This will produce a warning message that explains the problem with $lToken in the embedded function gettoken.

Regards,

... Dewey

---CODE---
use strict;
use warnings;
sub newparse ($;$);
sub oldparse ($;$);

my $lTokens = [qw(2 * 2)];
my $errmsg = newparse($lTokens);
print($errmsg ? "ERROR: $errmsg\n" : "OK\n");

$lTokens = [qw(3 * 3)];
$errmsg = newparse($lTokens);
print($errmsg ? "ERROR: $errmsg\n" : "OK\n");

$lTokens = [qw(4 * 4)];
$errmsg = oldparse($lTokens);
print($errmsg ? "ERROR: $errmsg\n" : "OK\n");

$lTokens = [qw(5 * 5)];
$errmsg = oldparse($lTokens);
print($errmsg ? "ERROR: $errmsg\n" : "OK\n");

exit(0);
# -------------------------------------------

sub newparse ($;$) {
        my($lTokens, $callback) = @_;
       
        while (my $tok = shift(@$lTokens)) {
                print("TOKEN: $tok\n");
                #call the callback with $tok?
        }
        return;
}

sub oldparse ($;$) {
        my($lTokens, $callback) = @_;

        sub gettoken {        

                if (@$lTokens==0) {  #line 40
                        return undef;
                 }
                 my $token = shift(@$lTokens);
                 return $token;
        } # gettoken()

        my $tok = gettoken();
        print("TOKEN: '$tok'\n");
        return("Empty Input") if !$tok;
        $tok = gettoken();
        while ($tok) {
                print("TOKEN: $tok\n");
                $tok = gettoken();
        }
}

----- Output -----

Variable "$lTokens" will not stay shared at testtoken.pl line 40.
TOKEN: 2
TOKEN: *
TOKEN: 2
OK
TOKEN: 3
TOKEN: *
TOKEN: 3
OK
TOKEN: '4'
TOKEN: *
TOKEN: 4
OK
Use of uninitialized value in concatenation (.) or string at testtoken.pl line 5
0.
TOKEN: ''
ERROR: Empty Input






John Deighan <[EMAIL PROTECTED]>
Sent by: [EMAIL PROTECTED]

02/08/2006 09:40 AM

To
<perl-win32-users@listserv.ActiveState.com>
cc
Subject
Perl bug?





I realize that most things that look like bugs in Perl are in reality
programmer bugs, but I can't figure out why the second call to the
function "parse()" in the code below fails. According to my debugger
(from ActiveState's Perl Development Kit), the function parse() gets
a correct list of 3 tokens in parameter $lTokens, but when the
embedded function gettoken() is called, it thinks that $lTokens is an
empty list. This only happens the second time that parse() is called,
not the first time. I'm just completely baffled.

P.S. Please don't send me e-mails about how to get this working right
by modifying the code. I'm sure I can do that, and besides, the real
code is considerably more complicated than this. I want to know why
this code does not work as I expect. Anyway, here's the code and the
output I get (I'm running ActivePerl 5.8.7 Build 815 under Windows
2000 Server):

use strict;

my $lTokens = [qw(2 * 2)];
my $errmsg = parse($lTokens);
print($errmsg ? "ERROR: $errmsg\n" : "OK\n");

$lTokens = [qw(2 * 2)];
my $errmsg = parse($lTokens);
print($errmsg ? "ERROR: $errmsg\n" : "OK\n");

# -------------------------------------------

sub parse { my($lTokens, $callback) = @_;

                sub gettoken {

                if (@$lTokens==0) {
                                 return undef;
                                 }
                my $token = shift(@$lTokens);
                return $token;
                } # gettoken()

my $tok = gettoken();
print("TOKEN: '$tok'\n");
return("Empty Input") if !$tok;
$tok = gettoken();
while ($tok) {
                print("TOKEN: $tok\n");
                $tok = gettoken();
                }
}


---------------
OUTPUT:
---------------
C:\Scripts>testGrammar2.pl
TOKEN: '2'
TOKEN: *
TOKEN: 2
OK
TOKEN: ''
ERROR: Empty Input

_______________________________________________
Perl-Win32-Users mailing list
Perl-Win32-Users@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

_______________________________________________
Perl-Win32-Users mailing list
Perl-Win32-Users@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

Reply via email to