next up previous contents index PLPL moodlepserratamodulosperlmonksperldocapuntes LHPgoogleetsiiullpcgull
Sig: El Método descendant Sup: Análisis Sintáctico con Parse::Eyapp Ant: Agrupamiento y Operadores de Err: Si hallas una errata ...


El método str en Mas Detalle

El método str de los Nodos

Para dar soporte al análisis de los árboles y su representación, Parse::Eyapp provee el método str . El siguiente ejemplo con el depurador muestra el uso del método str . El método Parse::Eyapp::Node::str retorna una cadena que describe como término el árbol enraizado en el nodo que se ha pasado como argumento.

El método info

El método str cuando visita un nodo comprueba la existencia de un método info para la clase del nodo. Si es así el método será llamado. Obsérvese como en las líneas 5 y 6 proveemos de métodos info a los nodos TERMINAL y FUNCTION. La consecuencia es que en la llamada de la línea 7 el término que describe al árbol es decorado con los nombres de funciones y los atributos y números de línea de los terminales.

Modo de uso de str

El método str ha sido concebido como una herramienta de ayuda a la depuración y verificación de los programas árbol. La metodología consiste en incorporar las pequeñas funciones info al programa en el que trabajamos. Por ejemplo:

640  sub Run {
641   my($self)=shift;
...   ................
663  }
664
665  sub TERMINAL::info {
666    my @a = join ':', @{$_[0]->{attr}};
667    return "[@a]"
668  }
669
670  sub FUNCTION::info {
671    return "[".$_[0]->{function_name}[0]."]"
672  }
673
674  sub BLOCK::info {
675    return "[".$_[0]->{line}."]"
676  }

Variables que Gobiernan la Conducta de str

Las variables de paquete que gobiernan la conducta de str y sus valores por defecto aparecen en la siguiente lista:

Notas a Pié de Página o Footnotes

El siguiente ejemplo ilustra el manejo de notas a pié de árbol usando str . Se han definido los siguientes métodos:

nereida:~/doc/casiano/PLBOOK/PLBOOK/code> sed -ne '677,$p' Simple6.eyp
$Parse::Eyapp::Node::INDENT = 1;
sub TERMINAL::info {
  my @a = join ':', @{$_[0]->{attr}};
  return "@a"
}

sub PROGRAM::footnote {
  return "Types:\n"
         .Dumper($_[0]->{types}).
         "Symbol Table:\n"
         .Dumper($_[0]->{symboltable})
}

sub FUNCTION::info {
  return $_[0]->{function_name}[0]
}

sub FUNCTION::footnote {
  return Dumper($_[0]->{symboltable})
}

sub BLOCK::info {
  return $_[0]->{line}
}

sub VAR::info {
  return $_[0]->{definition}{type} if defined $_[0]->{definition}{type};
  return "No declarado!";
}

*FUNCTIONCALL::info = *VARARRAY::info = \&VAR::info;
El resultado para el programa de entrada:
nereida:~/doc/casiano/PLBOOK/PLBOOK/code> cat salida
int a,b;

int f(char c) {
 a[2] = 4;
 b[1][3] = a + b;
 c = c[5] * 2;
 return g(c);
}
produce una salida por stderr:
Identifier g not declared
y la siguiente descripción de la estructura de datos:
PROGRAM^{0}(
  FUNCTION{f}^{1}(
    ASSIGN(
      VARARRAY{INT}(
        TERMINAL{a:4},
        INDEXSPEC(
          INUM(
            TERMINAL{2:4}
          )
        )
      ),
      INUM(
        TERMINAL{4:4}
      )
    ),
    ASSIGN(
      VARARRAY{INT}(
        TERMINAL{b:5},
        INDEXSPEC(
          INUM(
            TERMINAL{1:5}
          ),
          INUM(
            TERMINAL{3:5}
          )
        )
      ),
      PLUS(
        VAR{INT}(
          TERMINAL{a:5}
        ),
        VAR{INT}(
          TERMINAL{b:5}
        )
      )
    ),
    ASSIGN(
      VAR{CHAR}(
        TERMINAL{c:6}
      ),
      TIMES(
        VARARRAY{CHAR}(
          TERMINAL{c:6},
          INDEXSPEC(
            INUM(
              TERMINAL{5:6}
            )
          )
        ),
        INUM(
          TERMINAL{2:6}
        )
      )
    ),
    RETURN(
      FUNCTIONCALL{No declarado!}(
        TERMINAL{g:7},
        ARGLIST(
          VAR{CHAR}(
            TERMINAL{c:7}
          )
        )
      )
    )
  )
)
---------------------------
0)
Types:
$VAR1 = {
  'F(X_1(CHAR),INT)' => bless( {
    'children' => [
      bless( {
        'children' => [
          bless( {
            'children' => []
          }, 'CHAR' )
        ]
      }, 'X_1' ),
      bless( {
        'children' => []
      }, 'INT' )
    ]
  }, 'F' ),
  'CHAR' => bless( {
    'children' => []
  }, 'CHAR' ),
  'INT' => bless( {
    'children' => []
  }, 'INT' )
};
Symbol Table:
$VAR1 = {
  'a' => {
    'type' => 'INT',
    'line' => 1
  },
  'b' => {
    'type' => 'INT',
    'line' => 1
  },
  'f' => {
    'type' => 'F(X_1(CHAR),INT)',
    'line' => 3
  }
};

---------------------------
1)
$VAR1 = {
  'c' => {
    'type' => 'CHAR',
    'param' => 1,
    'line' => 3
  }
};

Usando str sobre una Lista de Áboles

Para usar str sobre una lista de árboles la llamada deberá hacerse como método de clase, i.e. con el nombre de la clase como prefijo y no con el objeto:

Parse::Eyapp::Node->str(@forest)

cuando quiera convertir a su representación término mas de un árbol. El código:

nereida:~/doc/casiano/PLBOOK/PLBOOK/code> sed -ne '652,658p' Simple4.eyp \
                                          | cat -n
     1       local $Parse::Eyapp::Node::INDENT = 2;
     2       local $Parse::Eyapp::Node::DELIMITER = "";
     3       print $t->str."\n";
     4       {
     5         local $" = "\n";
     6         print Parse::Eyapp::Node->str(@blocks)."\n";
     7       }

produce la salida:

nereida:~/doc/casiano/PLBOOK/PLBOOK/code> eyapp Simple4 ;\
                                          treereg SimpleTrans.trg ;\
                                          usesimple4.pl
****************
f() {
  int a,b[1][2],c[1][2][3];
  char d[10];
  b[0][1] = a;
}

PROGRAM(
  FUNCTION[f](
    ASSIGN(
      VARARRAY(
        TERMINAL[b:4],
        INDEXSPEC(
          INUM(
            TERMINAL[0:4]
          ),
          INUM(
            TERMINAL[1:4]
          )
        ) # INDEXSPEC
      ) # VARARRAY,
      VAR(
        TERMINAL[a:4]
      )
    ) # ASSIGN
  ) # FUNCTION
) # PROGRAM

Match[PROGRAM:0:blocks](
  Match[FUNCTION:1:blocks:[f]]
)

Obsérvense los comentarios # TIPODENODO que acompañan a los paréntesis cerrar cuando estos están lejos (esto es, a una distancia de mas de $Parse::Eyapp::Node::LINESEP líneas) del correspondiente paréntesis abrir. Tales comentarios son consecuencia de haber establecido el valor de $Parse::Eyapp::Node::INDENT a 2.



Subsecciones
next up previous contents index PLPL moodlepserratamodulosperlmonksperldocapuntes LHPgoogleetsiiullpcgull
Sig: El Método descendant Sup: Análisis Sintáctico con Parse::Eyapp Ant: Agrupamiento y Operadores de Err: Si hallas una errata ...
Casiano Rodríguez León
2013-03-05