lunes, 22 de junio de 2009

EXAMEN DE COMPILADORES


ANÁLISIS SEMÁNTICO


Se ocupa de analizar si la sentencia tiene algún significado. Se pueden encontrar sentencias que son sintácticamente correctas pero que no se pueden ejecutar porque carecen de sentido. Busca errores semánticos. Reúne información de tipos. Identifica operadores y operandos.

La habilidad para analizar un programa, razonando acerca de sus propiedades, es una de las tareas más importantes en el diseño de software y en la manipulación de programas. El análisis de flujo de datos, es decir, el proceso de recoger información sobre la forma en que el programa usa las variables y las estructuras de datos (sin necesidad de ejecutarlo) juega un papel fundamental en el diseño de programas que, a su vez, transforman programas (como compiladores, intérpretes, sistemas de comprobación de tipos, etc).

Una aproximación interesante para el análisis de los lenguajes de alto nivel consiste en considerar el análisis del programa como un tipo de pseudo evaluación, es decir, un proceso que imita la ejecución del programa.

El análisis semántico utiliza como entrada el árbol sintáctico detectado por el análisis sintáctico para comprobar restricciones de tipo y otras limitaciones semánticas y preparar la generación de código.

En compiladores de un solo paso, las llamadas a las rutinas semánticas se realizan directamente desde el analizador sintáctico y son dichas rutinas las que llaman al generador de código. El instrumento más utilizado para conseguirlo es la gramática de atributos.

CHEQUEOS DINAMICOS: Hace referencia a aspectos que sólo pueden ser conocidos en tiempo de ejecución.

CHEQUEOS ESTATICOS: Hace referencia a aspectos que pueden ser controlados en tiempo de compilación.

Se dividen en:

Chequeos de Control de Flujo

v El control de flujo del programa es sensitivo al contexto.

Ejemplos:

  • Declaración de una variable debe ser visible al usarla (en scope).
  • Declaración de una variable debe estar antes de usarla.
  • Cada camino de salida (exit path) retorna un valor del tipo correcto.

Chequeos de Unicidad

  • Uso (y mal uso) de identificadores

Ejemplos:

  • Ningún identificador puede ser usado para dos definiciones diferentes en el mismo scope.

Chequeos de Tipo

  • Los chequeos semánticos más extensos

Ejemplos:

  • Que el número de argumentos haga match con el número de parámetros formales y que los tipos correspondientes sean equivalentes.
  • Si se llama como expresión, debe retornar un tipo.
  • Cada acceso a una variable debe hacer match con la declaración (arreglo, estructura, etc.)

Chequeos Dinámicos

  • v Chequeos de límites de arreglos
  • v Chequeo de referencia del Null Pointer

Propagación de atributos

Sea la expresión

int a,b,c;

a/(b+c^2)

El árbol sintáctico es:

     /
      ---------
      |       |
      a       +
          ---------
          |       |
          b       ^
              ---------
              |       |
              c       2
 

Análisis semántico de programas

Considere:

if x==y then z=1; else z=2;

El diagrama es:


  • Una vez que se entendió la estructura, se analiza el significado.
  • Los compiladores realizan un análisis limitado para detectar inconsistencias.
  • Algunos realizan un mayor análisis para mejorar el rendimiento del programa.


COMPILADORES E INTÉRPRETES

1. En el cuadro siguiente escriba dos tareas para cada analizador:

2. Transformar las siguientes expresiones a notación postfija y prefijo.

a. a * b % c – d * a – d % e

En notación Postfija: a b c % * d a * d e % - -

En notación Prefija: * a b % c * - d a % - d e

b. (a + c) – (d * e) / x % y

En notación Postfija: a c + d e * x y % / -

En notación Prefija: + a c *- d e / % x y

c. (h – i – j * k) % m / x / y

En notación Postfija: h i j k * - - m x y / / %

En notación Prefija: - h i * - j k % / m x / y

3. Dado el árbol de derivación, obtener la expresión en notación infija, postfija y prefija.




En notación infija: ( a * b % c – d ) * ( h – f % e) Depende de cómo se le interpreta el árbol.

En notación Postfija: a b c % * d – h f e % - *

En notación Prefija: * * a b % - c d – h f % e

4. Señale dos ventajas de la generación de código intermedio

1. El código objeto es abstraído para una maquina virtual. Esta abstracción ayuda a separar operaciones de alto y bajo nivel y realizaciones dependientes de la maquina.

2. La generación de código y el asignamiento de registros temporales son separados de las RUTINAS SEMANTICAS, las cuales solo trabajan con la abstracción presentada por la representación intermedia. Las dependencias del código objeto son aisladas de las rutinas de generación de código.

5. Explique con un ejemplo la optimización de código.

  • Reprentaciones de código para extraer información
  • Condiciones que se han de cumplir.
  • El código optimizado se ha de comportar igual que el código de partida excepto por ser más rápido o ocupar menos espacio.
  • Hay que buscar transformaciones que no modifiquen el comportamiento del código según el comportamiento definido para el lenguaje de programación.

6. Señale el proceso de compilación de un programa en C#.

Proceso de una operación matemática.

int A=0;

int B=0;

int C=0;

int R=0;

R=A*B+C;

El proceso de compilación realiza primero un análisis del programa fuente para producir la sintaxis del programa objeto. Para ello utiliza diversas tablas.

Para obedecer a estas funciones las estructuras deben obedecer a reglas muy rígidas, puesto que las ambigüedades no podrían ser dilucidas por la maquina. De ahí la importancia de los lenguajes formales y de los autómatas en relación con los lenguajes evolucionados y los compiladores; pues las tareas esenciales del compilador son la evaluación sintáctica y la evaluación semántica.

El explorador (scanner) o analizador lexicográfico tiene como misión indagar sobre los caracteres del programa fuente y generar los símbolos del programa para pasarlo a los analizadores sintáctico y semántico.

El programa fuente se representa internamente de muy diversas formas de muy diversas formas: arboles, lista de cuartetos, etc.

LA EVALUACION SINTACTICA

ANALISIS LEXICOGRAFICO

El programa fuente es para el analizador lexicográfico una secuencia de caracteres que necesita reconocer y de la cual debe eliminar los caracteres inútiles (comentarios, espacios, etc.) y transformarla en una secuencia de elementos o términos que servirá de entrada a la fase de análisis sintáctico.

La tarea de distinguir los diferentes símbolos es lo que constituye el léxico.

A* B+C

A Es un identificador

* Es un operador

Normalmente, en un lenguaje se tienen los siguientes grupos de caracteres

  • Constantes
  • Identificadores
  • Operadores (aritméticos, relacionales, lógicos, etc.)
  • Palabras calve ( IF, GOTO, WHILE, etc.)
  • Delimitadores (^{, “, ( etc.)

Cada uno de los grupos anteriores forma un tokens (unidad léxica) distinta; y a cada tokens se le asocia una tabla donde se reflejan todos los caracteres pertenecientes al mismo.

El léxico de un lenguaje es el conjunto de tokens distintos que lo forman.

Al conjunto de reglas que permite escribir correctamente un lenguaje se le llama sintaxis del lenguaje.

7. Generar CI para el código siguiente:

If x>10 and Not(y<0)>

A+=2

B+=1

End if

for (i=0; i<10;>

x += i;

}