Práctica: Análisis de Tipos en Simple C con Gramáticas Atribuidas

Reescriba el analizador de tipos para Simple C utilizando Language::AttributeGrammars. Repase la sección [*] (Usando Language::AttributeGrammars con Parse::Eyapp).

Es conveniente que las acciones sean aisladas en subrutinas para evitar que Language::AttributeGrammars se confunda. Sigue un ejemplo de como podria hacerse:

pl@nereida:~/doc/casiano/PLBOOK/PLBOOK/code/Simple-AttributeGrammar/lib$ \
                                     sed -ne '585,631p' Trans_Scheme.eyp
  my $attgram = new Language::AttributeGrammar <<'EOG';

# Tipos Basicos
INUM:                   $/.t = { Trans_Scheme::inum }
CHARCONSTANT:           $/.t = { Trans_Scheme::char_constant }
# Variables escalares y arrays
VAR:                    $/.t = { Trans_Scheme::var($/) }
# Expresiones binarias
PLUS:                   $/.t = { Trans_Scheme::bin($<0>.t, $<1>.t, $/) }
MINUS:                  $/.t = { Trans_Scheme::bin($<0>.t, $<1>.t, $/) }
TIMES:                  $/.t = { Trans_Scheme::bin($<0>.t, $<1>.t, $/) }
DIV:                    $/.t = { Trans_Scheme::bin($<0>.t, $<1>.t, $/) }
MOD:                    $/.t = { Trans_Scheme::bin($<0>.t, $<1>.t, $/) }
GT:                     $/.t = { Trans_Scheme::bin($<0>.t, $<1>.t, $/) }
GE:                     $/.t = { Trans_Scheme::bin($<0>.t, $<1>.t, $/) }
LE:                     $/.t = { Trans_Scheme::bin($<0>.t, $<1>.t, $/) }
EQ:                     $/.t = { Trans_Scheme::bin($<0>.t, $<1>.t, $/) }
NE:                     $/.t = { Trans_Scheme::bin($<0>.t, $<1>.t, $/) }
LT:                     $/.t = { Trans_Scheme::bin($<0>.t, $<1>.t, $/) }
AND:                    $/.t = { Trans_Scheme::bin($<0>.t, $<1>.t, $/) }
OR:                     $/.t = { Trans_Scheme::bin($<0>.t, $<1>.t, $/) }
# Sentencias de control
IF:                     $/.t = { Trans_Scheme::condition($<0>.t, $/, $<1>.t) }
IFELSE:                 $/.t = { Trans_Scheme::condition($<0>.t, $/, $<1>.t, $<2>.t) }
WHILE:                  $/.t = { Trans_Scheme::condition($<0>.t, $/, $<1>.t) }
# Asignaciones
ASSIGN:                 $/.t = { Trans_Scheme::assign($<0>.t, $<1>.t, $/) }
PLUSASSIGN:             $/.t = { Trans_Scheme::assign($<0>.t, $<1>.t, $/) }
MINUSASSIGN:            $/.t = { Trans_Scheme::assign($<0>.t, $<1>.t, $/) }
TIMESASSIGN:            $/.t = { Trans_Scheme::assign($<0>.t, $<1>.t, $/) }
DIVASSIGN:              $/.t = { Trans_Scheme::assign($<0>.t, $<1>.t, $/) }
MODASSIGN:              $/.t = { Trans_Scheme::assign($<0>.t, $<1>.t, $/) }
# Llamadas a funciones
FUNCTIONCALL:           $/.t = { Trans_Scheme::functioncall($/) }
# Return
RETURN:                 $/.t = { Trans_Scheme::return($<0>.t, $/) }
# Otros nodos
LABEL:                  $/.t = { Trans_Scheme::void }
GOTO:                   $/.t = { Trans_Scheme::void }
STATEMENTS:             $/.t = { Trans_Scheme::void }
BLOCK:                  $/.t = { Trans_Scheme::void }
BREAK:                  $/.t = { Trans_Scheme::void }
CONTINUE:               $/.t = { Trans_Scheme::void }
FUNCTION:               $/.t = { Trans_Scheme::void }
PROGRAM:                $/.t = { Trans_Scheme::void }

EOG

Las funciones de soporte son similares a las que hemos usado en Trans.trg:

pl@nereida:~/doc/casiano/PLBOOK/PLBOOK/code/Simple-AttributeGrammar/lib$ sed -ne '716,721p' Trans_Scheme.eyp
sub return {
  my ($t, $fathernode) = @_;
  my $child = $fathernode->child(0);
  return $t if ($types->{$fathernode->{returntype}} == $t);
  type_error("Type error in return statement", $fathernode->line);
}

Casiano Rodríguez León
2009-12-09