next up previous contents index PLPL moodlepserratamodulosperlmonksperldocapuntes LHPgoogleetsiiullpcgull
Sig: Nombres para los Atributos Sup: Análisis Sintáctico con Parse::Eyapp Ant: Práctica: Análisis Sintáctico Err: Si hallas una errata ...


Podando el Arbol

Acciones Explícitas Bajo la Directiva % tree

Como se ha mencionado anteriormente, la directiva %tree es es equivalente a escribir:

         %default action { goto &Parse::Eyapp::Driver::YYBuildAST }

Donde el método Parse::Eyapp::Driver::YYBuildAST se encarga de retornar la referencia al objeto nodo recién construído.

La ubicación de acciones semánticas explícitas para una regla altera la forma del árbol de análisis. El método Parse::Eyapp::Driver::YYBuildAST no inserta en la lista de hijos de un nodo el atributo asociado con dicho símbolo a menos que este sea una referencia. Esto conlleva que una forma de eliminar un subárbol es estableciendo una acción semántica explícita que no retorne un nodo.

Las Declaraciones no se Incluyen en el Arbol de Análisis

El siguiente ejemplo ilustra como utilizar esta propiedad en el análisis de un lenguaje mínimo en el que los programas (P) son secuencias de declaraciones (DS) seguidas de sentencias (SS).

En un compilador típico, las declaraciones influyen en el análisis semántico (por ejemplo, enviando mensajes de error si el objeto ha sido repetidamente declarado o si es usado sin haber sido previamente declarado, etc.) y la información proveída por las mismas suele guardarse en una tabla de símbolos (declarada en la línea 5 en el siguiente código) para su utilización durante las fases posteriores.

pl@nereida:~/LEyapp/examples$ sed -ne '1,58p' RetUndef.eyp | cat -n
 1  /* File RetUndef.eyp */
 2
 3  %tree
 4  %{
 5    use Data::Dumper;
 6    my %s; # symbol table
 7  %}
 8
 9  %%
10  P:
11    %name PROG
12      $DS $SS
13        {
14          print Dumper($DS);
15          $SS->{symboltable} = \%s;
16          return $SS;
17        }
18  ;
19
20  SS:
21     %name ST
22       S
23   | %name STS
24       SS S
25  ;
26
27  DS:
28     %name DEC
29       D
30         {}
31   | %name DECS
32       DS  D
33         {}
34  ;
35
36  D : %name INTDEC
37      'int' $ID
38         {
39           die "Error: $ID declared twice\n" if exists($s{$ID});
40           $s{$ID} = 'int';
41         }
42    | %name STRDEC
43      'string' $ID
44        {
45          die "Error: $ID declared twice\n" if exists($s{$ID});
46          $s{$ID} = 'string';
47        }
48  ;
49
50  S: %name EXP
51      $ID
52        {
53          die "Error: $ID not declared\n" unless exists($s{$ID});
54          goto &Parse::Eyapp::Driver::YYBuildAST; # build the node
55        }
56  ;
57
58  %%

La Tabla de Símbolos

Las acciones explícitas en las líneas 37-41 y 44-47 no retornan referencias y eso significa que el subárbol de D no formará parte del árbol de análisis. En vez de ello las acciones tienen por efecto almacenar el tipo en la entrada de la tabla de símbolos asociada con la variable.

Dando Nombre a los Atributos

Cuando en la parte derecha de una regla de producción un símbolo va precedido de un dolar como ocurre en el ejemplo con ID:

36  D : %name INTDEC
37      'int' $ID
38         {
39           die "Error: $ID declared twice\n" if exists($s{$ID});
40           $s{$ID} = 'int';
41         }

le estamos indicamos a eyapp que construya una copia en una variable léxica $ID del atributo asociado con ese símbolo. Así el fragmento anterior es equivalente a escribir:

  D : %name INTDEC
      'int' ID
         {
           my $ID = $_[2];
           die "Error: $ID declared twice\n" if exists($s{$ID});
           $s{$ID} = 'int';
         }

Nótese que la tabla de símbolos es una variable léxica. Para evitar su pérdida cuando termine la fase de análisis sintáctico se guarda como un atributo del nodo programa:

10  P:
11    %name PROG
12      $DS $SS
13        {
14          print Dumper($DS);
15          $SS->{symboltable} = \%s;
16          return $SS;
17        }
18  ;

Si no se desea que el nombre del atributo coincida con el nombre de la variable se utiliza la notación punto. Por ejemplo:

exp : exp.left '+' exp.right { $left + $right }
;

es equivalente a:

exp : exp.left '+' exp.right 
       { 
         my $left  = $_[1];
         my $right = $_[2];
         $left + $right 
       }
;

Insertando Tareas Adicionales a la Construcción de un Nodo

Si queremos ejecutar ciertas tareas antes de la construcción de un nodo tendremos que insertar una acción semántica para las mismas. Para evitar la pérdida del subárbol deberemos llamar explícitamente a Parse::Eyapp::Driver::YYBuildAST. Este es el caso cuando se visitan los nodos sentencia (S):

50  S: %name EXP
51      $ID
52        {
53          die "Error: $ID not declared\n" unless exists($s{$ID});
54          goto &Parse::Eyapp::Driver::YYBuildAST; # build the node
55        }
56  ;

El Programa Cliente y su Ejecución

Veamos el programa cliente:

pl@nereida:~/LEyapp/examples$ cat -n useretundef.pl
 1  #!/usr/bin/perl -w
 2  use strict;
 3  use Parse::Eyapp;
 4  use RetUndef;
 5  use Data::Dumper;
 6
 7  sub TERMINAL::info { $_[0]{attr} }
 8
 9  my $parser = RetUndef->new();
10  my $t = $parser->Run;
11  print $t->str,"\n";
12
13  $Data::Dumper::Indent = 1;
14  print Dumper($t);
Observe como no hay nodos de tipo D al ejecutar el programa con entrada int a string b a b:

pl@nereida:~/LEyapp/examples$ useretundef.pl
int a string b a b
$VAR1 = undef;
STS(ST(EXP(TERMINAL[a])),EXP(TERMINAL[b]))
El volcado de Dumper en la línea 14 de RetUndef.eyp nos muestra que el atributo asociado con DS es undef.

El volcado de Dumper en la línea 14 de useretundef.pl da el siguiente resultado:

$VAR1 = bless( {
  'symboltable' => {
    'a' => 'int',
    'b' => 'string'
  },
  'children' => [
    bless( {
      'children' => [
        bless( {
          'children' => [
            bless( {
              'children' => [],
              'attr' => 'a',
              'token' => 'ID'
            }, 'TERMINAL' )
          ]
        }, 'EXP' )
      ]
    }, 'ST' ),
    bless( {
      'children' => [
        bless( {
          'children' => [],
          'attr' => 'b',
          'token' => 'ID'
        }, 'TERMINAL' )
      ]
    }, 'EXP' )
  ]
}, 'STS' );



Subsecciones
next up previous contents index PLPL moodlepserratamodulosperlmonksperldocapuntes LHPgoogleetsiiullpcgull
Sig: Nombres para los Atributos Sup: Análisis Sintáctico con Parse::Eyapp Ant: Práctica: Análisis Sintáctico Err: Si hallas una errata ...
Casiano Rodríguez León
2013-03-05