Eyapp
provee un conjunto de
módulos que permiten la manipulación y transformación
del AST. La formas mas usual de hacerlo es escribir
el programa de transformaciones árbol en un fichero
separado. El tipo .trg
se asume por defecto.
El ejemplo que sigue trabaja en cooperación
con el programa Eyapp presentado en la sección
8.11
página 8.11.
El programa árbol sustituye nodos producto por un número potencia de
dos por nodos unarios de desplazamiento a izquierda. De este modo
facilitamos la tarea de la generación de un código mas eficiente:
pl@nereida:~/LEyapp/examples$ cat -n Shift.trg 1 # File: Shift.trg 2 { 3 sub log2 { 4 my $n = shift; 5 return log($n)/log(2); 6 } 7 8 my $power; 9 } 10 mult2shift: TIMES($e, NUM($m)) 11 and { $power = log2($m->{attr}); (1 << $power) == $m->{attr} } => { 12 $_[0]->delete(1); 13 $_[0]->{shift} = $power; 14 $_[0]->type('SHIFTLEFT'); 15 }Obsérvese que la variable léxica
$power
es visible en la definición
de la transformación mult2shift
.
Compilamos el programa de transformaciones usando el guión treereg :
nereida:~/src/perl/YappWithDefaultAction/examples> treereg Shift nereida:~/src/perl/YappWithDefaultAction/examples> ls -ltr | tail -1 -rw-rw---- 1 pl users 1405 2006-11-06 14:09 Shift.pmComo se ve, la compilación produce un módulo que
Shift.pm
que contiene el código de los
analizadores.
El código generado por la versión 0.2 de treereg es el siguiente:
pl@nereida:~/LEyapp/examples$ cat -n Shift.pm 1 package Shift; 2 3 # This module has been generated using Parse::Eyapp::Treereg 4 # from file Shift.trg. Don't modify it. 5 # Change Shift.trg instead. 6 # Copyright (c) Casiano Rodriguez-Leon 2006. Universidad de La Laguna. 7 # You may use it and distribute it under the terms of either 8 # the GNU General Public License or the Artistic License, 9 # as specified in the Perl README file. 10 11 use strict; 12 use warnings; 13 use Carp; 14 use Parse::Eyapp::_TreeregexpSupport qw(until_first_match checknumchildren); 15 16 our @all = ( our $mult2shift, ) = Parse::Eyapp::YATW->buildpatterns(mult2shift => \&mult2shift, ); 17 18 #line 2 "Shift.trg" 19 20 sub log2 { 21 my $n = shift; 22 return log($n)/log(2); 23 } 24 25 my $power; 26 27 28 sub mult2shift { 29 my $mult2shift = $_[3]; # reference to the YATW pattern object 30 my $e; 31 my $NUM; 32 my $TIMES; 33 my $m; 34 35 { 36 my $child_index = 0; 37 38 return 0 unless (ref($TIMES = $_[$child_index]) eq 'TIMES'); 39 return 0 unless defined($e = $TIMES->child(0+$child_index)); 40 return 0 unless (ref($NUM = $TIMES->child(1+$child_index)) eq 'NUM'); 41 return 0 unless defined($m = $NUM->child(0+$child_index)); 42 return 0 unless do 43 #line 10 "Shift.trg" 44 { $power = log2($m->{attr}); (1 << $power) == $m->{attr} }; 45 46 } # end block of child_index 47 #line 11 "Shift.trg" 48 { 49 $_[0]->delete(1); 50 $_[0]->{shift} = $power; 51 $_[0]->type('SHIFTLEFT'); 52 } 53 54 } # end of mult2shift 55 56 57 1;
El programa de análisis se limita a cargar los dos módulos generados,
crear el analizador, llamar al método Run
para crear el árbol y proceder a las sustituciones mediante la llamada
$t->s(@Shift::all)
:
pl@nereida:~/LEyapp/examples$ cat -n useruleandshift.pl 1 #!/usr/bin/perl -w 2 use strict; 3 use Rule5; 4 use Parse::Eyapp::Base qw(insert_function); 5 use Shift; 6 7 sub SHIFTLEFT::info { $_[0]{shift} } 8 insert_function('TERMINAL::info', \&TERMINAL::attr); 9 10 my $parser = new Rule5(); 11 my $t = $parser->Run; 12 print "***********\n",$t->str,"\n"; 13 $t->s(@Shift::all); 14 print "***********\n",$t->str,"\n";Cuando alimentamos el programa con la entrada
a=b*32
obtenemos la
siguiente salida:
pl@nereida:~/LEyapp/examples$ useruleandshift.pl a=b*32 *********** ASSIGN(TERMINAL[a],TIMES(VAR(TERMINAL[b]),NUM(TERMINAL[32]))) *********** ASSIGN(TERMINAL[a],SHIFTLEFT[5](VAR(TERMINAL[b])))