[perl] Desesperado con los objetos
Han Solo
hsolo@maptel.es
15 Jul 2000 18:34:40 +0200
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hola a todos.
Estoy programando un analizador léxico para un buscador con
perl-byacc, y tengo algunos problemas.
El tema de la gramática lo tengo resuelto, y tengo una versión que
hace lo que yo quiero, adaptada de los ejemplos que vienen con la
documentación (en concreto de una calculadora), pero toma los datos
de la entrada estándar, y yo necesitaría que lo tomara como parámetros
de una función (y devolviera una expresión). El problema, es que
utiliza un módulo llamado Fstream, llamando a una serie de métodos, y
es aquí donde me pierdo. En principio, hasta donde he podido entender,
llama al constructor del objeto pasándole como parámetros ¿punteros? a
la entrada estándar. Mirando el código, he sido incapaz de adaptarlo
para que tome los datos de los parámetros de una función, y no de la
entrada estándar. Os mando el código para ver si me podéis echar una
mano.
Para probarlo, hay que guardar estos archivos en un directorio, y
ejecutar make, para que se genere el módulo CalcParser.pm. Después,
hay que ejecutar el programa calc.pl
Para que os hagáis una idea, esto resuelve cosas del estilo
(a+(b|c)). Esto es un ejemplo de lo que tendrá que hacer en un
futuro. La gramática no está completa, ni el tratamiento de errores,
pero eso me corre menos prisa de momento. Lo que intento, es que
expresiones de ese tipo se puedan pasar como parámetro al constructor,
y que devuelva otra cadena.
P.D. Siento haber mandado el código dentro del mensaje en lugar de
hacerlo como "attachment", pero desconozco si la lista los admite como
tales, o si por el contrario los elimina directamente.
Un saludo a todos y gracias por leerme.
Fstream.pm
- ---------------8<-------------8<------------8<---------------8<--------------
# $Id: Fstream.pm,v 1.2 1998/04/29 06:34:46 jake Exp $
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.
=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 = bless {}, $class;
$stream->{fh} = $fh;
$stream->{name} = $name;
$stream->{lineno} = 1;
$stream->{save} = undef;
$stream->{saved} = 0;
return $stream;
}
# ----------------------------------------------------------------------------
=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;
- ---------------8<-------------8<------------8<---------------8<--------------
calc.y
- ---------------8<-------------8<------------8<---------------8<--------------
%{
%}
%token PALABRA
%token EOL
%left '|'
%left '+' '-'
%left '*' '/'
%%
start: |
| start input
;
input: expr EOL { print $1 . "\n"; }
| EOL
;
expr: PALABRA { $$ = $1; }
| expr '+' expr { $$ = '('.$1.' y '. $3.')'; }
| expr '|' expr { $$ = '('.$1.' o '. $3.')'; }
| expr '-' expr { $$ = '('.$1.'-'. $3.')'; }
| '+' expr { $$ = $2; }
| expr '/' expr { $$ = $1 / $3; }
| '(' expr ')' { $$ = $2; }
;
%%
# $Id: calc.y,v 1.2 1998/04/29 06:34:46 jake Exp $
sub yylex
{
my ($s) = @_;
print @_;
print "Valor de \$s $s\n";
my ($c, $val);
while (($c = $s->getc) eq ' ' || $c eq "\t") {
/*while (($c = $s->getc) eq "\t") {*/
}
if ($c eq '') {
return 0;
}
elsif ($c eq "\n") {
return $EOL;
}
elsif ($c =~ /[0-9a-zA-Z\$\s]/) {
$val = $c;
while (($c = $s->getc) =~ /[0-9a-zA-Z]/) {
$val .= $c;
}
$s->ungetc;
return ($PALABRA, $val);
}
else {
return ord($c);
}
}
sub yyerror {
my ($msg, $s) = @_;
die "$msg at " . $s->name . " line " . $s->lineno . ".\n";
}
- ---------------8<-------------8<------------8<---------------8<--------------
Makefile
- ---------------8<-------------8<------------8<---------------8<--------------
# $Id: Makefile,v 1.3 1998/04/29 06:37:25 jake Exp $
VERSION=0.6
all: CalcParser.pm GenParser.pm
CalcParser.pm: calc.y
pbyacc -P CalcParser calc.y
GenParser.pm: gen.y
pbyacc -P GenParser gen.y
clean:
-rm -f CalcParser.pm GenParser.pm
patch:
cd ..; \
diff -C 2 perl-byacc1.8.2.orig perl-byacc1.8.2 > patch; \
mv patch perl5-byacc-patches
dist:
cd ..; \
mv perl5-byacc-patches perl5-byacc-patches-$(VERSION); \
tar cvf perl5-byacc-patches-$(VERSION).tar \
`find perl5-byacc-patches-$(VERSION) -type f | grep -v CVS`; \
gzip perl5-byacc-patches-$(VERSION).tar; \
mv perl5-byacc-patches-$(VERSION) perl5-byacc-patches; \
mv perl5-byacc-patches-$(VERSION).tar.gz perl5-byacc-patches
- ---------------8<-------------8<------------8<---------------8<--------------
calc.pl
- ---------------8<-------------8<------------8<---------------8<--------------
#!/usr/bin/perl
# $Id: calc.pl,v 1.2 1998/04/29 06:34:46 jake Exp $
# Really trivial calculator.
use CalcParser;
use Fstream;
$s = Fstream->new(\*STDIN, 'STDIN');
$p = CalcParser->new(\&CalcParser::yylex, \&CalcParser::yyerror, 0);
$p->yyparse($s);
- ---------------8<-------------8<------------8<---------------8<--------------
- --
Un Saludo
Han Solo
The Rebel Alliance
Emacs is not on every system
So what? [...] Do you tell your administrative people to stick with
notepad.exe? Do you tell your fat kids they can only have the crummy
games that come with their video games or plain dress that comes with
Barbie?
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.1 (GNU/Linux)
Comment: Processed by Mailcrypt 3.5.5 and Gnu Privacy Guard <http://www.gnupg.org/>
iEYEARECAAYFAjlwkp4ACgkQ4FjpJaPEp23lbACgu1qD4eNiD2zXg374f5r9x7zM
fikAn3YLPklUQc7My7hxRKd+zaK7+p9q
=RJuI
-----END PGP SIGNATURE-----
--------- Pie de mensaje --------------------------------
Visite: http://tlali.iztacala.unam.mx/~randrade/perl.shtml
Cancelar inscripcion:
mail to: majordomo@tlali.iztacala.unam.mx
text : unsubscribe perl