

Las operaciones binarias
requieren que sus operandos sean de tipo entero.
Si el tipo de alguno de los operandos es CHAR
haremos una conversión explícita al tipo INT
(líneas 17-18):
nereida:~/doc/casiano/PLBOOK/PLBOOK/code/Simple-Types/lib/Simple> sed -ne '66,90p' Trans.trg | cat -n
1 bin: / PLUS
2 |MINUS
3 |TIMES
4 |DIV
5 |MOD
6 |GT
7 |GE
8 |LE
9 |EQ
10 |NE
11 |LT
12 |AND
13 |EXP
14 |OR
15 /($x, $y)
16 => {
17 $x = char2int($_[0], 0);
18 $y = char2int($_[0], 1);
19
20 if (($x->{t} == $INT) and ( $y->{t} == $INT)) {
21 $_[0]->{t} = $INT;
22 return 1;
23 }
24 type_error("Incompatible types with operator '".($_[0]->lexeme)."'", $_[0]->line);
25 }
Obsérve la expresión regular lineal en las líneas 1-15.
La semántica de las expresiones regulares lineales
es modificada ligéramente por Parse::Eyapp::Treeregexp.
Note que no se ha especificado
la opción x . El compilador de expresiones regulares árbol
la insertará por defecto. Tampoco es necesario añadir anclas de frontera
de palabra \b a los identificadores que aparecen en la expresión
regular lineal: de nuevo el compilador de expresiones regulares árbol
las insertará.
Las subrutinas de conversión char2int e int2char se proveen
- junto con la subrutina para emitir mensajes de error - como
código de apoyo a las expresiones árbol. Recuerde que en un programa
Treeregexp puede incluir código Perl en cualquier lugar sin mas que aislarlo
entre llaves. Dicho código será insertado - respetando el orden
de aparición en el fuente
- en el módulo generado por treereg :
pl@nereida:~/doc/casiano/PLBOOK/PLBOOK/code/Simple-Types/lib/Simple$ sed -ne '/^{$/,/^}$/p' Trans.trg | cat -n
1 {
2
3 my $types; # reference to the hash containing the type table
4 my ($INT, $CHAR, $VOID);
5
6 sub type_error {
7 my $msg = shift;
8 my $line = shift;
9 die "Type Error at line $line: $msg\n"
10 }
11
12 sub set_types {
.. .......................
18 }
19
20 sub char2int {
21 my ($node, $i) = @_;
22
23 my $child = $node->child($i);
24 return $child unless $child->{t} == $CHAR;
25
26 my $coherced = Parse::Eyapp::Node->new('CHAR2INT', sub { $_[0]->{t} = $INT });
27 $coherced->children($child); # Substituting $node(..., $child, ...)
28 $node->child($i, $coherced); # by $node(..., CHAR2INT($child), ...)
29
30 return $coherced;
31 }
32
33 sub int2char {
34 my ($node, $i) = @_;
35
36 my $child = $node->child($i);
37 return $child unless $child->{t} == $INT;
38
39 my $coherced = Parse::Eyapp::Node->new('INT2CHAR', sub { $_[0]->{t} = $CHAR });
40 $coherced->children($child); # Substituting $node(..., $child, ... )
41 $node->child($i, $coherced); # by $node(..., INT2CHAR($child), ...)
42
43 return $coherced;
44 }
45
46 }
Si el hijo i-ésimo del nodo $node es de tipo
$CHAR, la línea 26 creará un nuevo nodo.
Mediante el manejador pasado como segundo argumento a Parse::Eyapp::Node->new
se dota al nodo del atributo t, el cual se establece a $INT.
El nuevo nodo se interpone entre padre e hijo (líneas 27 y 28).
De este modo se facilita la labor de la fase posterior
de generación de código, explicitando la necesidad de generar código de conversión.
Si el lenguaje tuviera mas tipos numéricos, FLOAT, DOUBLE etc.
es útil hacer especifico en el tipo del nodo que operación binaria se esta realizando
cambiando el tipo PLUS en PLUSDOUBLE, PLUSINT etc.
según corresponda.
La asignación de tipo a los nodos que se corresponden con expresiones constantes es trivial:
nereida:~/doc/casiano/PLBOOK/PLBOOK/code/Simple-Types/lib/Simple> \
sed -ne '60,61p' Trans.trg | cat -n
1 inum: INUM($x) => { $_[0]->{t} = $INT }
2 charconstant: CHARCONSTANT($x) => { $_[0]->{t} = $CHAR }
pl@nereida:~/Lbook/code/Simple-Types/script$ usetypes.pl prueba18.c 2
1 int c[20][30], d;
2
3 int f(int a, int b) {
4 if (c[2] > 0)
5 return
6 (a+b)*d*c[1][1];
7 }
Type Error at line 4: Incompatible types with operator '>'

