next up previous contents index PLPL moodlepserratamodulosperlmonksperldocapuntes LHPgoogleetsiiullpcgull
Sig: Práctica: Declaraciones Automáticas Sup: La Estructura de los Ant: Práctica: Arbol de Análisis Err: Si hallas una errata ...

Análisis Semántico

Hay quien dice que el análisis semántico es la determinación de aquellas propiedades que, siendo dependientes del contexto, pueden ser computadas estáticamente en tiempo de compilación para cualquier programa correcto. Entre estas propiedades están: la comprobación de que las variables son declaradas, la compatibilidad de tipos en las expresiones, el correcto uso de las llamadas a función asi como el ámbito y visibilidad de las variables. La fase de análisis semántico puede verse como una fase de ``adornado'' o ``etiquetado'' del AAA, en la cual los atributos de los nodos del AAA son computados.

Aunque la veamos como una fase separada del análisis sintáctico, puede en numerosas ocasiones llevarse a cabo al mismo tiempo que se construye el árbol. Así lo hacemos en este ejemplo: incrustamos la acción semántica en la correspondiente rutina de análisis sintáctico. Así, en la rutina term, una vez que hemos obtenido los dos operandos, comprobamos que son de tipo numérico llamando (línea 8) a

Semantic::Analysis::check_type_numeric_operator:

Observe como aparece un nuevo atributo TYPE decorando el nodo creado (línea 9):

 1 sub term() {
 2   my ($t, $t2);
 3 
 4   $t = factor;
 5   if ($lookahead eq '*') {
 6     match('*');
 7     $t2 = term;
 8     my $type = Semantic::Analysis::check_type_numeric_operator($t, $t2, '*');
 9     $t = TIMES->new( LEFT => $t, RIGHT => $t2, TYPE => $type);
10   }
11   return $t;
12 }

En el manejo de errores de tipo, un tipo especial $err_type es usado para indicar un error de tipo:

  sub check_type_numeric_operator {
    my ($op1, $op2, $operator) = @_;

    my $type = numeric_compatibility($op1, $op2, $operator);
    if ($type == $err_type) {
      Error::fatal("Operandos incompatibles para el operador $operator") 
    }
    else {
      return $type;
    }
  }
La subrutina numeric_compatibility comprueba que los dos operandos son de tipo numérico y devuelve el correspondiente tipo. Si ha ocurrido un error de tipo, intenta encontrar un tipo conveniente para el operando:

  sub numeric_compatibility {
    my ($op1, $op2, $operator) = @_;

    if (($op1->TYPE == $op2->TYPE) and is_numeric($op1->TYPE)) {
      return $op1->TYPE; # correct
    }
    ... # código de recuperación de errores de tipo
  }

  sub is_numeric {
    my $type = shift;

    return ($type == $int_type); # añadir long, float, double, etc.
  }

Es parte del análisis semántico la declaración de tipos:

sub declaration() {
  my ($t, $class, @il);

  if (($lookahead eq 'INT') or ($lookahead eq 'STRING')) {
    $class = $lookahead;
    $t = &type();
    @il = &idlist();
    &Semantic::Analysis::set_types($t, @il);
    &Address::Assignment::compute_address($t, @il);
    return $class->new(TYPE => $t, IDLIST => \@il);
  }
  else {
    Error::fatal('Se esperaba un tipo');
  }
}
Para ello se utiliza una tabla de símbolos que es un hash %symbol_table indexado en los identificadores del programa:

sub set_types {
  my $type = shift;
  my @vars = @_;

  foreach my $var (@vars) {
    if (!exists($symbol_table{$id})) { $symbol_table{$var}->{TYPE} = $type; }
    else { Error::error("$id declarado dos veces en el mismo ámbito"); }
  }
}

Cada vez que aparece una variable en el código, bien en un factor o en una asignación, comprobamos que ha sido declarada:

sub factor() {
  my ($e, $id, $str, $num);

  if ($lookahead eq 'NUM') { ... }
  elsif ($lookahead eq 'ID') {
    $id = $value;
    match('ID');
    my $type = Semantic::Analysis::check_declared($id);
    return ID->new( VAL => $id, TYPE => $type);
  }
  elsif ($lookahead eq 'STR') { ... }
  elsif ($lookahead eq '(') { ... }
  else { Error::fatal("Se esperaba (, NUM o ID"); }
}

La función check_declared devuelve el atributo TYPE de la correspondiente entrada en la tabla de símbolos.

sub check_declared {
  my $id = shift;

  if (!exists($symbol_table{$id})) {
    Error::error("$id no ha sido declarado!");
    # auto-declaración de la variable a err_type
    Semantic::Analysis::set_types($err_type, ($id));
  }
  return $symbol_table{$id}->{TYPE};
}



Subsecciones
next up previous contents index PLPL moodlepserratamodulosperlmonksperldocapuntes LHPgoogleetsiiullpcgull
Sig: Práctica: Declaraciones Automáticas Sup: La Estructura de los Ant: Práctica: Arbol de Análisis Err: Si hallas una errata ...
Casiano Rodríguez León
2013-03-05