🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: es.comp.os.linux.programacion
Article #15294

[perl] Desesperado con los objetos

#15294
From: Han Solo
Date: Thu, 13 Jul 2000 00:00
294 lines
7661 bytes
-----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 as� se que ning�n servidor de news se
los cepilla por el camino.


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<--------------
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.0 (GNU/Linux)
Comment: Processed by Mailcrypt 3.5.5 and Gnu Privacy Guard <http://www.gnupg.org/>

iEYEARECAAYFAjlt8E0ACgkQ4FjpJaPEp21ElACfUbSPuL0IHUxN/LM0ItnrrEAX
hpgAn1phf+14mm5dm9wTAs3Xn6uvrP50
=DDlE
-----END PGP SIGNATURE-----
Technical Details
Message-ID: <87n1jmgf57.fsf@hecate.aq.upm.es>
Path: arc1-ca.pugleaf.net!unknown!not-for-mail

Show Full Headers
Complete Article Headers
X-Google-Language: SPANISH,ASCII
X-Google-Thread: f86c8,bc16ed4276db9f87,start
X-Google-Attributes: gidf86c8,public
From: Han Solo <hsolo@maptel.es>
Subject: [perl] Desesperado con los objetos
Date: 2000/07/13
Message-ID: <87n1jmgf57.fsf@hecate.aq.upm.es>
X-Deja-AN: 645937866
Content-Transfer-Encoding: 8bit
X-Trace: 13 Jul 2000 17:26:28 +0100, 138.100.42.196
Content-Type: text/plain; charset=iso-8859-1
User-Agent: Gnus/5.070096 (Pterodactyl Gnus v0.96) Emacs/20.6
MIME-Version: 1.0
Newsgroups: es.comp.os.linux.programacion