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 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.
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 }
Las variables de paquete que gobiernan la conducta
de str
y sus valores por defecto aparecen en la siguiente lista:
our @PREFIXES = qw(Parse::Eyapp::Node::)
La variable de paquete Parse::Eyapp::Node::PREFIXES contiene
la lista de prefijos de los nombres de tipo que serán eliminados
cuando str
muestra el término. Por defecto contiene
la cadena 'Parse::Eyapp::Node::'
.
our $INDENT = 0
La variable $Parse::Eyapp::Node::INDENT controla el formato de presentación
usado por Parse::Eyapp::Node::str :
0
la representación es compacta.
$Parse::Eyapp::Node::LINESEP
está a 4.
Véase la página
para un ejemplo con $INDENT
a 2 y
$Parse::Eyapp::Node::LINESEP
a 4.
our $STRSEP = ','
Separador de nodos en un término. Por defecto es la coma.
our $DELIMITER = '['
Delimitador de presentación de la información proveída por el método
info
. Por defecto los delimitadores son corchetes. Puede elegirse
uno cualquiera de la lista:
'[', '{', '(', '<'si se define como la cadena vacía o
undef
no se usarán delimitadores.
our $FOOTNOTE_HEADER = "\n---------------------------\n"
Delimitador para las notas a pie de página.
our $FOOTNOTE_SEP = ")\n"
Separador de la etiqueta/número de la nota al pie
our $FOOTNOTE_LEFT = '^{'
, our $FOOTNOTE_RIGHT = '}'
Definen el texto que rodea al número de referencia en el nodo.
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 declaredy 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 } };
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.