# $Id: Fstream.pm,v 1.1 1997/04/30 21:15:52 jake Exp $ # Copyright 1997 Jake Donham # You may distribute under the terms of either the GNU General # Public License or the Artistic License, as specified in the README # file. package Fstream; # ---------------------------------------------------------------------------- =head1 NAME Fstream - a class to encapsulate a filehandle as a stream; =head1 SYNOPSIS use Fstream; =head1 DESCRIPTION Fstream wraps a filehandle and provides methods that make it easier to write a lexer. Why doesn't Perl have ungetc? =cut # ---------------------------------------------------------------------------- =head2 Class Methods =over 4 =item new($filehandle, $name) Creates an Fstream object from $filehandle (a filehandle glob reference). $name is a string which is stored for debugging purposes and may be accessed with &name. =back =cut sub new { my ($class, $fh, $name) = @_; my $stream = {}; $stream->{'fh'} = $fh; $stream->{'name'} = $name; $stream->{'lineno'} = 1; $stream->{'save'} = undef; $stream->{'saved'} = 0; bless $stream, $class; } # ---------------------------------------------------------------------------- =head2 Object Methods =over 4 =item getc Returns the next character in the stream, or the empty string if the stream has been exhausted. =cut sub getc { my ($stream) = @_; my ($c); if ($stream->{'saved'}) { $stream->{'saved'} = 0; $c = $stream->{'save'}; if ($c eq "\n") { $stream->{'lineno'}++; } return $c; } elsif (($c = getc($stream->{'fh'})) eq '') { return ''; } else { $stream->{'save'} = $c; if ($c eq "\n") { $stream->{'lineno'}++; } return $c; } } =item ungetc Pushes the last character read back onto the stream, where it will be returned on the next call to getc. You may only push one character back on the stream. =cut sub ungetc { my ($stream) = @_; $stream->{'saved'} = 1; if ($stream->{'save'} eq "\n") { $stream->{'lineno'}--; } } =item lineno Returns the line-number of the stream (based on the number of newlines seen). =cut sub lineno { my ($stream) = @_; return $stream->{'lineno'}; } =item name Returns the name that was given in the constructor. =back =cut sub name { my ($stream) = @_; return $stream->{'name'}; } 1;