Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > eof and nested while (<$fh>) {...}

Reply
Thread Tools

eof and nested while (<$fh>) {...}

 
 
Greg Bacon
Guest
Posts: n/a
 
      06-24-2004
I was writing code to scan an assembly-language definition of
operational data and produce a report and ended up writing code
that gave me the "there has to be a better way" feeling.

Single parameters are easy to spot, e.g.,

label1 .word 1234ABCDh
label2 .float 3.14159

Most arrays are trivial too:

label3 .word 1, 2, 3

Array specifications can span multiple lines, however. For example:

label4 .float 0.0, 0.5, 1.0
.float 1.5, 2.0, 2.5

At first, I used a regular expression to feed individual values into
a sub that kept track of the last label grabbed and determined whether
the current value was a new parameter or a continuation of an array.

The code -- and the approach, really -- was unsatisfying, so I
considered a two-pass scan: grab and decompose the chunks and then
coalesce the arrays in a second pass. I made a start in that
direction but didn't like the way it was playing out.

I saw that scanning an entire array would be straightforward too.
I could safely look ahead. Lines without labels continued the
current array, and I could pretend the values were on one line by
appending to the end of what I've already recognized.

If the lookahead line had a label, I could process what I had and then
C<redo> to process the lookahead line that's already in $_.

Here's a sketch of the code:

while (<$fh>) {
next unless /^(\w+)\s+\.(word|float)\s+(.+?),?\s*$/;
my($label,$type,$data) = ($1,$2,$3);


# look for continued spec
my $needredo = 0;
while (<$fh>) {
if (/^\s*\.(word|float)\s+(.+?),?\s*$/) {
$data .= ", $2";
}
else {
$needredo = 1;
}
}

# now $label, $type, and $data comprise an
# entire parameter
...;

redo if $needredo;
}

That's already kind of klunky, but I also saw that the inner while loop
will exhaust the input, which the outer loop's implicitly tests too. I
tested for C<eof $fh> at each iteration of the inner loop and reset
$needredo if I needed to C<last> out of the inner loop.

The code now feels very klunky. Is there a more elegant way to code
this scan?

Greg
--
A democracy is nothing more than mob rule, where fifty-one percent of
the people may take away the rights of the other forty-nine.
-- Thomas Jefferson
 
Reply With Quote
 
 
 
 
Steven Kuo
Guest
Posts: n/a
 
      06-24-2004
On Thu, 24 Jun 2004, Greg Bacon wrote:

> I was writing code to scan an assembly-language definition of
> operational data and produce a report and ended up writing code
> that gave me the "there has to be a better way" feeling.
>
> Single parameters are easy to spot, e.g.,
>
> label1 .word 1234ABCDh
> label2 .float 3.14159
>
> Most arrays are trivial too:
>
> label3 .word 1, 2, 3
>
> Array specifications can span multiple lines, however. For example:
>
> label4 .float 0.0, 0.5, 1.0
> .float 1.5, 2.0, 2.5
>


(snipped)

> Here's a sketch of the code:
>
> while (<$fh>) {
> next unless /^(\w+)\s+\.(word|float)\s+(.+?),?\s*$/;
> my($label,$type,$data) = ($1,$2,$3);
>
>
> # look for continued spec
> my $needredo = 0;
> while (<$fh>) {
> if (/^\s*\.(word|float)\s+(.+?),?\s*$/) {
> $data .= ", $2";
> }
> else {
> $needredo = 1;
> }
> }
>
> # now $label, $type, and $data comprise an
> # entire parameter
> ...;
>
> redo if $needredo;
> }
>
> That's already kind of klunky, but I also saw that the inner while loop
> will exhaust the input, which the outer loop's implicitly tests too. I
> tested for C<eof $fh> at each iteration of the inner loop and reset
> $needredo if I needed to C<last> out of the inner loop.
>
> The code now feels very klunky. Is there a more elegant way to code
> this scan?
>





I don't think nested loops are needed. How about:

#!/usr/local/bin/perl
use strict;
use warnings;

my ($label, $type, $data);

while (<DATA>) {
if (/^\s*\.(word|float)\s+(.+?),?\s*$/) {
$data .= ", $2";
} elsif (/^(\w+)\s+\.(word|float)\s+(.+?),?\s*$/) {
do_stuff($label, $type, $data) if ($label); # previously found label
($label, $type, $data) = ($1, $2, $3);
}

}

do_stuff($label, $type, $data) if ($label);

sub do_stuff {
print "$label, $type, $data\n";
}

__DATA__

label1 .word 1234ABCDh
label2 .float 3.14159

label3 .word 1, 2, 3

label4 .float 0.0, 0.5, 1.0
.float 1.5, 2.0, 2.5


--
Hope this helps,
Steven

 
Reply With Quote
 
 
 
 
Anno Siegel
Guest
Posts: n/a
 
      06-29-2004
Greg Bacon <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> I was writing code to scan an assembly-language definition of
> operational data and produce a report and ended up writing code
> that gave me the "there has to be a better way" feeling.
>
> Single parameters are easy to spot, e.g.,
>
> label1 .word 1234ABCDh
> label2 .float 3.14159
>
> Most arrays are trivial too:
>
> label3 .word 1, 2, 3
>
> Array specifications can span multiple lines, however. For example:
>
> label4 .float 0.0, 0.5, 1.0
> .float 1.5, 2.0, 2.5


[snip]

Ah, ye olde continuation line problem. Subtype 2, where you know if a
line *is* a continuation but not if a line *has* a continuation.

Here is one way of doing that. A continuation line is one that starts
with 10 blanks.

my $coll = '';
while ( <DATA> ) {
chomp;
if ( substr( $_, 0, 10) =~ /\S/ ) {
print "$coll\n" if length $coll;
$coll = $_;
} else {
$coll .= $_;
}
}
print "$coll\n" if length $coll;

This only collects continued lines into one. It would be simple
to add further processing to the loop so that it spits out ready-
to-use records.

Anno
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[Windows] Any way to distinguish ^C Induced EOF from ^Z EOF? Jan Burse Java 67 03-14-2012 12:21 AM
ifstream eof not reporting eof? SpreadTooThin C++ 10 06-15-2007 08:49 AM
try... except SyntaxError: unexpected EOF while parsing oscartheduck Python 7 04-04-2007 06:46 PM
nested while - how to go to the beginning of the first while? invni C Programming 36 07-27-2005 09:17 PM
if EOF = -1, can't a valid character == EOF and cause problems? Kobu C Programming 10 03-04-2005 10:40 PM



Advertisments