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 '>'