

Para ello comenzamos creando un módulo conteniendo las rutinas de tratamiento de errores:
lhp@nereida:~/Lperl/src/topdown/PL0506/03lexico/PL-Tutu/lib/PL$ pwd
/home/lhp/Lperl/src/topdown/PL0506/03lexico/PL-Tutu/lib/PL
lhp@nereida:~/Lperl/src/topdown/PL0506/03lexico/PL-Tutu/lib/PL$ cat -n Error.pm
1 package Error;
2 use strict;
3 use warnings;
4 use Carp;
5
6 require Exporter;
7
8 our @ISA = qw(Exporter);
9 our @EXPORT = qw( error fatal);
10 our $VERSION = '0.01';
11
12 sub error {
13 my $msg = join " ", @_;
14 if (!$PL::Tutu::errorflag) {
15 carp("Error: $msg\n");
16 $PL::Tutu::errorflag = 1;
17 }
18 }
19
20 sub fatal {
21 my $msg = join " ", @_;
22 croak("Error: $msg\n");
23 }
Observa como accedemos a la variable errorflag del paquete
PL::Tutu.
Para usar este módulo desde PL::Tutu, tenemos que declarar su uso:
lhp@nereida:~/Lperl/src/topdown/PL0506/03lexico/PL-Tutu/lib/PL$ cat -n Tutu.pm | head -8
1 package PL::Tutu;
2
3 use 5.008004;
4 use strict;
5 use warnings;
6 use IO::File;
7 use Carp;
8 use PL::Error;
En la línea 8 hacemos use PL::Error y no use Error ya que el módulo
lo hemos puesto en el directorio PL.
No olvides hacer make manifest para actualizar el fichero MANIFEST.
Supongamos que además de modularizar el grupo de rutinas de tratamiento de errores
queremos hacer lo mismo con la parte del análisis léxico. Parece lógico que el
fichero lo pongamos en un subdirectorio de PL/ por lo que cambiamos
el nombre del módulo a PL::Lexical::Analysis quedando la jerarquía de ficheros
asi:
lhp@nereida:~/Lperl/src/topdown/PL0506/03lexico/PL-Tutu/lib/PL$ tree . |-- Error.pm |-- Lexical | `-- Analysis.pm `-- Tutu.pm
Por supuesto debemos modificar las correspondientes líneas en Tutu.pm:
1 package PL::Tutu;
2
3 use 5.008004;
4 use strict;
5 use warnings;
6 use IO::File;
7 use Carp;
8 use PL::Error;
9 use PL::Lexical::Analysis;
10 ...
11
12 sub compile {
13 my ($input) = @_;
14 local %symbol_table = ();
15 local $data = ""; # Contiene todas las cadenas en el programa fuente
16 local $target = ""; # target code
17 my @tokens = ();
18 local $errorflag = 0;
19 local ($lookahead, $value) = ();
20 local $tree = undef; # abstract syntax tree
21 local $global_address = 0;
22
23
24 ########lexical analysis
25 @tokens = &PL::Lexical::Analysis::scanner($input);
26 print "@tokens\n";
27
28 ...
29
30 return \$target;
31 }
Observe que ahora PL::Lexical::Analysis::scanner devuelve
ahora la
lista con los terminales y que @tokens se ha ocultado en
compile como una variable léxica (línea 17).
En la línea 26 mostramos el contenido de la lista de terminales.
Sigue el listado del módulo conteniendo el analizador léxico. Obsérve las líneas 6, 16 y 44.
lhp@nereida:~/Lperl/src/topdown/PL0506/03lexico/PL-Tutu/lib/PL/Lexical$ cat -n Analysis.pm
1 # Lexical analyzer
2 package PL::Lexical::Analysis;
3 use strict;
4 use warnings;
5 use Carp;
6 use PL::Error;
7
8 require Exporter;
9
10 our @ISA = qw(Exporter);
11 our @EXPORT = qw( scanner );
12 our $VERSION = '0.01';
13
14 sub scanner {
15 local $_ = shift;
16 my @tokens;
17
18 { # Con el redo del final hacemos un bucle "infinito"
19 if (m{\G\s*(\d+)}gc) {
20 push @tokens, 'NUM', $1;
21 }
.. ...
37 elsif (m{\G\s*([+*()=;,])}gc) {
38 push @tokens, 'PUN', $1;
39 }
40 elsif (m{\G\s*(\S)}gc) {
41 Error::fatal "Caracter invalido: $1\n";
42 }
43 else {
44 return @tokens;
45 }
46 redo;
47 }
48 }
Puesto que en el paquete PL::Lexical::Analysis
exportamos scanner no es necesario llamar la rutina por el nombre
completo desde compile. Podemos simplificar la línea en la
que se llama a scanner que queda así:
########lexical analysis @tokens = &scanner($input); print "@tokens\n";De la misma forma, dado que
PL::Tutu exporta la función compile_from_file,
no es necesario llamarla por su nombre completo desde el guión tutu. Reescribimos
la línea de llamada:
lhp@nereida:~/Lperl/src/topdown/PL0506/03lexico/PL-Tutu/scripts$ cat tutu
#!/usr/bin/perl -w
use lib ('../lib');
use PL::Tutu;
&compile_from_file(@ARGV);
Como siempre que se añaden o suprimen archivos es necesario actualizar
MANIFEST:
lhp@nereida:~/Lperl/src/topdown/PL0506/03lexico/PL-Tutu$ make manifest
/usr/bin/perl "-MExtUtils::Manifest=mkmanifest" -e mkmanifest
Added to MANIFEST: lib/PL/Lexical/Analysis.pm
lhp@nereida:~/Lperl/src/topdown/PL0506/03lexico/PL-Tutu$ cat -n MANIFEST
1 Changes
2 lib/PL/Error.pm
3 lib/PL/Lexical/Analysis.pm
4 lib/PL/Tutu.pm
5 Makefile.PL
6 MANIFEST
7 MANIFEST.SKIP
8 README
9 scripts/test01.tutu
10 scripts/tutu
11 scripts/tutu.pl
12 t/PL-Tutu.t

