Resultado del Análisis de Ámbito

Como se ha comentado en la sección 5.5 el volcado de los AST con Data::Dumper es insuficiente. Para la visualización utilizaremos el método str presentado en la sección 5.8.

Código de Apoyo a la Visualización

Sigue el código de apoyo a la visualización:

pl@nereida:~/Lbook/code/Simple-Scope/lib/Simple$ sed -ne '845,$p' Scope.eyp | cat -n
 1  ############## Debugging and Display
 2  sub show_trees {
 3   my ($t) = @_;
 4
 5   print Dumper $t if $debug > 1;
 6   $Parse::Eyapp::Node::INDENT = 2;
 7   $Data::Dumper::Indent = 1;
 8   print $t->str."\n";
 9  }
10
11  $Parse::Eyapp::Node::INDENT = 1;
12  sub TERMINAL::info {
13    my @a = join ':', @{$_[0]->{attr}};
14    return "@a"
15  }
16
17  sub PROGRAM::footnote {
18    return "Types:\n"
19           .Dumper($_[0]->{types}).
20           "Symbol Table of the Main Program:\n"
21           .Dumper($_[0]->{symboltable})
22  }
23
24  sub FUNCTION::info {
25    return $_[0]->{function_name}[0]
26  }
27
28  sub FUNCTION::footnote {
29    my $text = '';
30    $text .= "Symbol Table of $_[0]->{function_name}[0]\n" if $_[0]->type eq 'FUNCTION';
31    $text .= "Symbol Table of block at line $_[0]->{line}\n" if $_[0]->type eq 'BLOCK';
32    $text .= Dumper($_[0]->{symboltable});
33    return $text;
34  }
35
36  sub BLOCK::info {
37    my $info = "$_[0]->{line}:$_[0]->{depth}";
38    my $fatherblock = $_[0]->{fatherblock};
39      $info .= ":".$fatherblock->info
40    if defined($fatherblock) and UNIVERSAL::can($fatherblock, 'info');
41    return $info;
42  }
43
44  *BLOCK::footnote = \&FUNCTION::footnote;
45
46  sub VAR::info {
47    return $_[0]->{type} if defined $_[0]->{type};
48    return "No declarado!";
49  }
50
51  *FUNCTIONCALL::info = *VARARRAY::info = \&VAR::info;

Un Ejemplo con Errores de Ámbito

Utilizando este código obtenemos una descripción completa y concisa del árbol anotado. Si hay errores de ámbito se mostrarán.

pl@nereida:~/Lbook/code/Simple-Scope/script$ usescope.pl prueba27.c 2

   1 int a,b;
   2
   3 int f(char c) {
   4  a[2] = 4;
   5  {
   6    int d;
   7    d = a + b;
   8  }
   9  c = d * 2;
  10  return g(c);
  11 }
Identifier d not declared at line 9
Identifier g not declared at line 10

Mostrando el Resultado del Análisis de Ámbito

Si no hay errores se obtiene un listado enumerado del programa fuente, el árbol, la tabla de tipos y las tablas de símbolos:

pl@nereida:~/Lbook/code/Simple-Scope/script$  usescope.pl prueba25.c 2

   1 int a[20],b,e[10];
   2
   3 g() {}
   4
   5 int f(char c) {
   6 char d;
   7  c = 'X';
   8  e[b] = 'A'+c;
   9  {
  10    int d;
  11    d = d + b;
  12  }
  13  c = d * 2;
  14  return c;
  15 }
  16
  17
PROGRAM^{0}(
  FUNCTION[g]^{1},
  FUNCTION[f]^{2}(
    ASSIGN(
      VAR[CHAR](
        TERMINAL[c:7]
      ),
      CHARCONSTANT(
        TERMINAL['X':7]
      )
    ) # ASSIGN,
    ASSIGN(
      VARARRAY[A_10(INT)](
        TERMINAL[e:8],
        INDEXSPEC(
          VAR[INT](
            TERMINAL[b:8]
          )
        ) # INDEXSPEC
      ) # VARARRAY,
      PLUS(
        CHARCONSTANT(
          TERMINAL['A':8]
        ),
        VAR[CHAR](
          TERMINAL[c:8]
        )
      ) # PLUS
    ) # ASSIGN,
    BLOCK[9:3:f]^{3}(
      ASSIGN(
        VAR[INT](
          TERMINAL[d:11]
        ),
        PLUS(
          VAR[INT](
            TERMINAL[d:11]
          ),
          VAR[INT](
            TERMINAL[b:11]
          )
        ) # PLUS
      ) # ASSIGN
    ) # BLOCK,
    ASSIGN(
      VAR[CHAR](
        TERMINAL[c:13]
      ),
      TIMES(
        VAR[CHAR](
          TERMINAL[d:13]
        ),
        INUM(
          TERMINAL[2:13]
        )
      ) # TIMES
    ) # ASSIGN,
    RETURN(
      VAR[CHAR](
        TERMINAL[c:14]
      )
    ) # RETURN
  ) # FUNCTION
) # PROGRAM
---------------------------
0)
Types:
$VAR1 = {
  'A_10(INT)' => bless( {
    'children' => [
      bless( {
        'children' => []
      }, 'INT' )
    ]
  }, 'A_10' ),
  'F(X_1(CHAR),INT)' => bless( {
    'children' => [
      bless( {
        'children' => [
          bless( {
            'children' => []
          }, 'CHAR' )
        ]
      }, 'X_1' ),
      $VAR1->{'A_10(INT)'}{'children'}[0]
    ]
  }, 'F' ),
  'CHAR' => $VAR1->{'F(X_1(CHAR),INT)'}{'children'}[0]{'children'}[0],
  'VOID' => bless( {
    'children' => []
  }, 'VOID' ),
  'INT' => $VAR1->{'A_10(INT)'}{'children'}[0],
  'A_20(INT)' => bless( {
    'children' => [
      $VAR1->{'A_10(INT)'}{'children'}[0]
    ]
  }, 'A_20' ),
  'F(X_0(),INT)' => bless( {
    'children' => [
      bless( {
        'children' => []
      }, 'X_0' ),
      $VAR1->{'A_10(INT)'}{'children'}[0]
    ]
  }, 'F' )
};
Symbol Table of the Main Program:
$VAR1 = {
  'e' => {
    'type' => 'A_10(INT)',
    'line' => 1
  },
  'a' => {
    'type' => 'A_20(INT)',
    'line' => 1
  },
  'b' => {
    'type' => 'INT',
    'line' => 1
  },
  'g' => {
    'type' => 'F(X_0(),INT)',
    'line' => 3
  },
  'f' => {
    'type' => 'F(X_1(CHAR),INT)',
    'line' => 5
  }
};

---------------------------
1)
Symbol Table of g
$VAR1 = {};

---------------------------
2)
Symbol Table of f
$VAR1 = {
  'c' => {
    'type' => 'CHAR',
    'param' => 1,
    'line' => 5
  },
  'd' => {
    'type' => 'CHAR',
    'line' => 6
  }
};

---------------------------
3)
Symbol Table of block at line 9
$VAR1 = {
  'd' => {
    'type' => 'INT',
    'line' => 10
  }
};

pl@nereida:~/Lbook/code/Simple-Scope/script$

Observe como se anotan las referencias a pie de árbol usando la notación ^{#}. La salida se completa con las notas a pie de árbol.



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