next up previous contents index practicapracticaPP2moodleLHPmoodlepserratacpanmodulospauseperlgoogleetsiiullpcgull
Sig: Esquemas de Traducción Sup: Análisis Sintáctico Predictivo Recursivo Ant: Práctica: Un analizador APDR Err: Si hallas una errata ...


Práctica: Generación Automática de Analizadores Predictivos

Escriba un módulo GAP.pm que provea una subrutina gap para la generación automática de un APDR supuesto que la gramática de entrada es LL(1).

La subrutina gap recibe como entrada la gramática según la estructura de datos generada por la función Grammar::Parse de la versión 0.3 del módulo Grammar. Dicha estructura de datos se explicó en la práctica 11.6.8. La estructura de datos generada por Grammar::Parse ha sido extendida en esta versión para incluir el código que se sitúe en la zona de cola. Por ejemplo, dada la gramática de entrada:

  Grammar/03/scripts$ cat -n aSb.yp
       1  %%
       2  S:
       3      |   'a' S 'b'
       4  ;
       5  %%
       6
       7  sub Lex {
       8    local $_ = shift; # input
       9    my @tokens;
      10
      11
      12    while ($_) {
      13      s/^\s*//; # fuera blancos
      14      push @tokens, $1, $1 if s/^(.)//s
      15    }
      16    @tokens;
      17  }
      18
      19  sub main {
      20    my $filename = shift;
      21    my $input;
      22
      23    if (defined($filename)) {
      24      local $/ = undef;
      25      open FILE, $filename or die "No se pudo abrir $filename\n";
      26      $input = <FILE>;
      27      close(FILE);
      28    }
      29    else { $input = <STDIN> }
      30
      31    my @tokens = Lex($input);
      32    Parse(@tokens); # Llamada al analizador generado
      33    print "Sintácticamente correcto\n";
      34  }
se genera la siguiente estructura de datos:
{
  'SYMS' => { 'S' => 2, '\'b\'' => 3, '\'a\'' => 3 }, 'NULL' => { 'S' => 1 },
  'RULES' => [
               [ 'S', [] ],
               [ 'S', [ '\'a\'', 'S', '\'b\'' ] ]
             ],
  'START' => 'S',
  'TERM' => [ '\'b\'', '\'a\'' ], 'NTERM' => { 'S' => [ 0, 1 ] }
  'TAIL' => [ '

  sub Lex {
    local $_ = shift; # input
    my @tokens;


    while ($_) {
      s/^\\s*//; # fuera blancos
      push @tokens, $1, $1 if s/^(.)//s
    }
    @tokens;
  }

  sub main {
    my $filename = shift;
    my $input;

    if (defined($filename)) {
      local $/ = undef;
      open FILE, $filename or die "No se pudo abrir $filename\\n";
      $input = <FILE>;
      close(FILE);
    }
    else { $input = <STDIN> }

    my @tokens = Lex($input);
    my $ok = Parse(@tokens); # Llamada al analizador generado
    print "Sintácticamente correcto\\n" if $ok;
  }

  ', 5 ], # línea en la que está el segundo %%
 };

Asi pues la entrada con clave TAIL contiene el código auxiliar de cola. Este código debe ser incluido por su programa dentro del texto del paquete generado por gap. La función gap también recibe como entrada el nombre del package:

$package_text = &gap($grammar, 'Package_name');
La función gap retorna una cadena conteniendo el package en el que estan las subrutinas del analizador sintáctico. La idea es que dicha cadena se salvará en un fichero con nombre Package_name.pm que podrá posteriormente ser usado (use Package_name) por un programa que necesite analizar entradas que se conforman de acuerdo a la especificación de la gramática. La rutina principal del paquete generado se ha de llamar Parser (esto es, su nombre completo es: Package_name::Parser. Evidentemente Package_name debe ser un nombre Perl válido). Ninguna subrutina deberá ser exportada sino que deberán ser llamadas por su nombre completo. La subrutina Parser recibe como argumento el array de terminales, obtiene el primer terminal y llama a la subrutina asociada con el símbolo de arranque. Los terminales están representados como parejas $ (terminal, atributo)$.

Observe que, una vez que la cadena $package_text conteniendo el paquete ha sido generada y salvada en un fichero con nombre Package_name.pm, podemos escribir un programa cliente:

use strict;
use Package_name.pm;

&Package_name::main;

Este programa espera una entrada desde fichero o STDIN e informa si dicha entrada es sintácticamente correcta o no para la gramática en cuestión.

Para la escritura de GAP.pm haga uso del módulo que calcula los $ FIRST$ y los $ FOLLOW$ que desarrolló durante la práctica 11.6.8.


next up previous contents index practicapracticaPP2moodleLHPmoodlepserratacpanmodulospauseperlgoogleetsiiullpcgull
Sig: Esquemas de Traducción Sup: Análisis Sintáctico Predictivo Recursivo Ant: Práctica: Un analizador APDR Err: Si hallas una errata ...
Casiano Rodríguez León
2006-02-21