compile
:
1 package PL::Tutu; 2 use 5.008004; 3 use strict; 4 use warnings; 5 use IO::File; 6 use Carp; 7 8 require Exporter; 9 10 our @ISA = qw(Exporter); 11 our @EXPORT = qw( compile compile_from_file); 12 our $VERSION = '0.01'; 13 14 our %symbol_table; 15 our $data; 16 our $target; 17 our @tokens; 18 our $errorflag; 19 our ($lookahead, $value); 20 our $tree; 21 our $global_address; 22 23 # Lexical analyzer 24 package Lexical::Analysis; 25 sub scanner { 26 } 27 28 package Syntax::Analysis; 29 sub parser { 30 } 31 32 package Machine::Independent::Optimization; 33 sub Optimize { 34 } 35 36 package Code::Generation; 37 sub code_generator { 38 } 39 40 package Peephole::Optimization; 41 sub transform { 42 } 43 44 package PL::Tutu; 45 sub compile { 46 my ($input) = @_; 47 local %symbol_table = (); 48 local $data = ""; # Contiene todas las cadenas en el programa fuente 49 local $target = ""; # target code 50 local @tokens =(); 51 local $errorflag = 0; 52 local ($lookahead, $value) = (); 53 local $tree = undef; # abstract syntax tree 54 local $global_address = 0; 55 56 ########lexical analysis 57 &Lexical::Analysis::scanner($input); 58 59 ########syntax (and semantic) analysis 60 $tree = &Syntax::Analysis::parser; 61 62 ########machine independent optimizations 63 &Machine::Independent::Optimization::Optimize; 64 65 ########code generation 66 &Code::Generation::code_generator; 67 68 ########peephole optimization 69 &Peephole::Optimization::transform($target); 70 71 return \$target; 72 } 73 74 sub compile_from_file { 75 my ($input_name, $output_name) = @_; # Nombres de ficheros 76 my $fhi; 77 my $targetref; 78 79 if ($input_name and (-r $input_name)) { 80 $fhi = IO::File->new("< $input_name"); 81 } 82 else { $fhi = 'STDIN'; } 83 84 ########source input 85 local $/ = undef; 86 my $input = <$fhi>; 87 88 $targetref = compile($input); 89 90 ########code output 91 my $fh = $output_name? IO::File->new("> $output_name") : 'STDOUT'; 92 $fh->print($$targetref); 93 $fh->close; 94 1; 95 } 96 97 1; 98 # Sigue la documentación ...
Vamos a añadir un script que use el módulo
PL::Tutu
para asi poder ejecutar nuestro compilador:
lhp@nereida:~/Lperl/src/topdown/PL0506/02fases/PL-Tutu/$ mkdir scripts lhp@nereida:~/Lperl/src/topdown/PL0506/02fases/PL-Tutu$ cd scripts/A continuación creamos dos versiones del compilador
tutu.pl
y tutu
y un programa de prueba test01.tutu
:
... # despues de crear los ficheros lhp@nereida:~/Lperl/src/topdown/PL0506/02fases/PL-Tutu/scripts$ ls test01.tutu tutu tutu.pl lhp@nereida:~/Lperl/src/topdown/PL0506/02fases/PL-Tutu/scripts$ cat tutu.pl #!/usr/bin/perl -w -I../lib/ use PL::Tutu; PL::Tutu::compile_from_file(@ARGV);El programa
tutu
ilustra otra forma de conseguir que el intérprete
Perl busque por la librearía que está siendo desarrollada, mediante el
uso de use lib
:
lhp@nereida:~/Lperl/src/topdown/PL0506/02fases/PL-Tutu/scripts$ cat tutu #!/usr/bin/perl -w use lib ('../lib'); use PL::Tutu; &PL::Tutu::compile_from_file(@ARGV);Veamos los contenidos del programa fuente
test01.tutu
que usaremos para hacer una prueba:
lhp@nereida:~/Lperl/src/topdown/PL0506/02fases/PL-Tutu/scripts$ cat test01.tutu int a,b; a = 4Ahora tenemos que añadir estos ficheros en
MANIFEST
para que formen
parte del proyecto. En vez de eso lo que hacemos es crear un fichero
MANIFEST.SKIP
:
lhp@nereida:~/Lperl/src/topdown/PL0506/02fases/PL-Tutu$ cat MANIFEST.SKIP \.o$ ^\.cvsignore$ /\.cvsignore$ \.cvsignore$ CVS/[^/]+$ ^Makefile$ /Makefile$ ^blib/ \.swp$ \.bak$ \.pdf$ \.ps$ \.sal$ pm_to_blib \.pdf$ \.tar.gz$ \.tgz$ ^META.yml$Para saber mas sobre
MANIFEST
léa la sección
6.16.4.
Es necesario indicarle a Perl que los ficheros añadidos son ejecutables:
lhp@nereida:~/Lperl/src/topdown/PL0506/02fases/PL-Tutu$ cat Makefile.PL use 5.008004; use ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. WriteMakefile( NAME => 'PL::Tutu', VERSION_FROM => 'lib/PL/Tutu.pm', # finds $VERSION PREREQ_PM => {}, # e.g., Module::Name => 1.1 EXE_FILES => [ 'scripts/tutu.pl', 'scripts/tutu' ], ($] >= 5.005 ? ## Add these new keywords supported since 5.005 (ABSTRACT_FROM => 'lib/PL/Tutu.pm', # retrieve abstract from module AUTHOR => 'Lenguajes y Herramientas de Programacion <lhp@>') : ()), );Perl utilizará esa información durante la fase de instalación para instalar los ejecutables en el path de búsqueda.
A continuación hay que rehacer el Makefile
:
lhp@nereida:~/Lperl/src/topdown/PL0506/02fases/PL-Tutu$ perl Makefile.PL Writing Makefile for PL::TutuPara crear una versión funcional hacemos
make
:
lhp@nereida:~/Lperl/src/topdown/PL0506/02fases/PL-Tutu$ make cp scripts/tutu blib/script/tutu /usr/bin/perl "-MExtUtils::MY" -e "MY->fixin(shift)" blib/script/tutu cp scripts/tutu.pl blib/script/tutu.pl /usr/bin/perl "-MExtUtils::MY" -e "MY->fixin(shift)" blib/script/tutu.pl Manifying blib/man3/PL::Tutu.3pmPara crear el
MANIFEST
hacemos make manifest
:
lhp@nereida:~/Lperl/src/topdown/PL0506/02fases/PL-Tutu$ make manifest /usr/bin/perl "-MExtUtils::Manifest=mkmanifest" -e mkmanifest Added to MANIFEST: scripts/tutuComprobemos que el test de prueba generado automáticamente por
h2xs
se pasa correctamente:
lhp@nereida:~/Lperl/src/topdown/PL0506/02fases/PL-Tutu$ make test PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t t/PL-Tutu....ok All tests successful. Files=1, Tests=1, 0 wallclock secs ( 0.08 cusr + 0.00 csys = 0.08 CPU)
Podemos ahora ejecutar los guiones:
lhp@nereida:~/Lperl/src/topdown/PL0506/02fases/PL-Tutu$ cd scripts/ lhp@nereida:~/Lperl/src/topdown/PL0506/02fases/PL-Tutu/scripts$ ls -l total 12 -rw-r--r-- 1 lhp lhp 15 2005-09-29 12:56 test01.tutu -rwxr-xr-x 1 lhp lhp 92 2005-09-29 13:29 tutu -rwxr-xr-x 1 lhp lhp 80 2005-09-29 12:58 tutu.pl lhp@nereida:~/Lperl/src/topdown/PL0506/02fases/PL-Tutu/scripts$ tutu test01.tutu test01.sal lhp@nereida:~/Lperl/src/topdown/PL0506/02fases/PL-Tutu/scripts$ ls -l total 12 -rw-r--r-- 1 lhp lhp 0 2005-09-29 13:53 test01.sal -rw-r--r-- 1 lhp lhp 15 2005-09-29 12:56 test01.tutu -rwxr-xr-x 1 lhp lhp 92 2005-09-29 13:29 tutu -rwxr-xr-x 1 lhp lhp 80 2005-09-29 12:58 tutu.pl
Para hacer una distribución instalable hacemos make dist
:
lhp@nereida:~/Lperl/src/topdown/PL0506/02fases/PL-Tutu$ make dist rm -rf PL-Tutu-0.01 /usr/bin/perl "-MExtUtils::Manifest=manicopy,maniread" \ -e "manicopy(maniread(),'PL-Tutu-0.01', 'best');" mkdir PL-Tutu-0.01 mkdir PL-Tutu-0.01/scripts mkdir PL-Tutu-0.01/lib mkdir PL-Tutu-0.01/lib/PL mkdir PL-Tutu-0.01/t tar cvf PL-Tutu-0.01.tar PL-Tutu-0.01 PL-Tutu-0.01/ PL-Tutu-0.01/scripts/ PL-Tutu-0.01/scripts/test01.tutu PL-Tutu-0.01/scripts/tutu PL-Tutu-0.01/scripts/tutu.pl PL-Tutu-0.01/META.yml PL-Tutu-0.01/Changes PL-Tutu-0.01/MANIFEST PL-Tutu-0.01/lib/ PL-Tutu-0.01/lib/PL/ PL-Tutu-0.01/lib/PL/Tutu.pm PL-Tutu-0.01/MANIFEST.SKIP PL-Tutu-0.01/t/ PL-Tutu-0.01/t/PL-Tutu.t PL-Tutu-0.01/Makefile.PL PL-Tutu-0.01/README rm -rf PL-Tutu-0.01 gzip --best PL-Tutu-0.01.tarDespués de esto tenemos en el directorio de trabajo el fichero
PL-Tutu-0.01.tar.gz
con la distribución:
lhp@nereida:~/Lperl/src/topdown/PL0506/02fases/PL-Tutu$ ls -ltr total 72 drwxr-xr-x 2 lhp lhp 4096 2005-09-29 12:01 t -rw-r--r-- 1 lhp lhp 1196 2005-09-29 12:01 README drwxr-xr-x 3 lhp lhp 4096 2005-09-29 12:01 lib -rw-r--r-- 1 lhp lhp 152 2005-09-29 12:01 Changes -rw-r--r-- 1 lhp lhp 167 2005-09-29 13:23 MANIFEST.SKIP -rw-r--r-- 1 lhp lhp 0 2005-09-29 13:23 pm_to_blib drwxr-xr-x 6 lhp lhp 4096 2005-09-29 13:23 blib -rw-r--r-- 1 lhp lhp 113 2005-09-29 13:23 MANIFEST.bak drwxr-xr-x 2 lhp lhp 4096 2005-09-29 13:29 scripts -rw-r--r-- 1 lhp lhp 616 2005-09-29 13:49 Makefile.PL -rw-r--r-- 1 lhp lhp 20509 2005-09-29 13:51 Makefile -rw-r--r-- 1 lhp lhp 3654 2005-09-29 16:34 PL-Tutu-0.01.tar.gz -rw-r--r-- 1 lhp lhp 298 2005-09-29 16:34 META.yml -rw-r--r-- 1 lhp lhp 205 2005-09-29 16:34 MANIFEST