 
 
 
 
 
 
 
 
 
 










 
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
 
 
 
 
 
 
 
 
 
 
 










