Monografias.com > Sin categoría
Descargar Imprimir Comentar Ver trabajos relacionados

Compiladores (página 2)




Enviado por superhacker77



Partes: 1, 2

5. Forma de examinar de un compilador

En la compilación hay dos partes: Análisis y Síntesis.
La parte del análisis divide al programa fuente
en sus elementos componentes y crea una representación
intermedia. De las dos partes, la síntesis
es la que requiere la técnica más
especializada.
Durante el análisis se determina las operaciones que
implica el programa fuente y
se registra en una estructura
jerárquica llamada árbol. A menudo, se usa una
clase especial de árbol llamado árbol
sintáctico, donde cada nodo representa una
operación y los hijos de un nodo son los argumentos de la
operación. Por ejemplo, en la figura 5 se muestra un
árbol sintáctico para una proposición de
asignación.

Figura 5. Árbol sintáctico para
posición := inicial + velocidad *
60

6. Como se sintetiza el
código
objeto un compilador estándar, teórica y
gráficamente generación de
código

En esta parte el código
intermedio optimizado es traducido a una secuencia de
instrucciones en ensamblador o
en el código de máquina del procesador que
nos interese. Por ejemplo, la sentencia
A:=B+C se convertirá en:
LOAD B
ADD C
STORE A
suponiendo que estas instrucciones existan de esta forma en el
ordenador de que se trate. Una conversión tan directa
produce generalmente un programa objeto que contiene muchas
cargas (loads) y almacenamientos (stores) redundantes, y que
utiliza los recursos de la
máquina de forma ineficiente. Existen técnicas
para mejorar esto, pero son complejas. Una, por ejemplo, es
tratar de utilizar al máximo los registros de
acceso rápido que tenga la máquina. Así, en
el procesador 8086
tenemos los registros
internos AX, BX, CX, DX, etc. y podemos utilizarlos en vez de
direcciones de memoria.

Tabla De Símbolos
Un compilador necesita guardar y usar la información de los objetos que se va
encontrando en el texto fuente,
como variables,
etiquetas, declaraciones de tipos, etc. Esta información se almacena en una estructura de
datos interna conocida como tabla de símbolos. El
compilador debe desarrollar una serie de funciones
relativas a la manipulación de esta tabla como insertar un
nuevo elemento en ella, consultar la información
relacionada con un símbolo, borrar un elemento, etc. Como
se tiene que acceder mucho a la tabla de símbolos los
accesos deben ser lo más rápidos posible para que
la compilación sea eficiente.

Manejo de errores
Es una de las misiones más importantes de un compilador,
aunque, al mismo tiempo, es lo que
más dificulta su realización. Donde más se
utiliza es en las etapas de análisis sintáctico y
semántico, aunque los errores se pueden descubrir en
cualquier fase de un compilador. Es una tarea difícil, por
dos motivos:

  • A veces unos errores ocultan otros.
  • A veces un error provoca una avalancha de muchos
    errores que se solucionan con el primero.

Es conveniente un buen manejo de errores, y que el
compilador detecte todos los errores que tiene el programa y no
se pare en el primero que encuentre. Hay, pues, dos criterios a
seguir a la hora de manejar errores:

  • Pararse al detectar el primer error.
  • Detectar todos los errores de una
    pasada.

En el caso de un compilador interactivo (dentro de un
entorno de desarrollo
integrado, como Turbo-Pascal o Borland
C++) no importa que se pare en el primer error detectado, debido
a la rapidez y facilidad para la corrección de
errores.

7. Árboles
sintácticos para representar como sintetiza el
código objeto un compilador

Figura 6.- Generación de
código.

figura 7.- Código en ensamblador
para la figura 6.

8. Herramientas
que muestran tipos de análisis de programas
fuente

Muchas herramientas
de software que
manipulan porgraas fuente realizan primero algún tipo de
análisis. Algunos ejemplos de tales herramientas
son:

  1. Editores de estructuras: un editor de estructuras toma como entrada uan secuencia de
    ordenes para construir un programa fuente. El editor de
    estructuras no sólo realiza las funciones de
    creación y modificación de textos de un editor
    de textos ordinario, sino que también analiza el
    texto del
    programa imponiendo al programa fuente una estructura
    jerárquica apropiada. De esa manera, el editor de
    estructuras puede realizar tareas adicionales útiles
    para la preparación de programas.
    Por ejemplo, puede comprobar si la entrada está
    formada correctamente, puede proporcionar palabras clave de
    manera automática y puede saltar desde un begin o un
    paréntesis izquierdo hasta su correspondiente end o
    paréntesis derecho. Además, la salida de tal
    editor suele ser similar a la salida de la fase del
    análisis de un compilador.
  2. Impresoras estéticas: Una impresora
    estética analiza un programa y lo
    imprime de forma que la estructura del programa resulte
    claramente visible. Por ejemplo, los comentarios pueden
    aparecer con un tipo de letra especial, y las proposiciones
    pueden aparecer con una indentación proporcional a la
    profundidad de su anidamiento en la
    organización jerárquica de las
    proposiciones.
  3. Verificadores estáticos: Un verificador
    estático lee un programa, lo analiza e intenta
    descubrir errores potenciales sin ejecutar el programa. La
    parte del análisis es similar a la que se encuentra en
    los compiladores de optimación. Así
    un verificador estático puede detectar si hay partes
    de un programa que nunca se podrán ejecutar o si
    cierta variable se usa antes de ser definida. Además,
    puede detectar errores de lógica como intentar utilizar una
    variable real como apuntador, empleando las técnicas de verificación de
    tipos.
  4. Intérpretes: En lugar de producir un
    programa objeto como resultado de una traducción, un
    interprete realiza las operaciones
    que implica el programa fuente. Para una proposición
    de asignación, por ejemplo, un intérprete
    podría construir un árbol como el de la figura
    5, y después efectuar las operaciones de los nodos
    conforme "recorre" el árbol. En la raíz
    descubriría que tiene que realizar una
    asignación, y llamaría a una rutina para
    evaluar la expresión de la derecha y después
    almacenaría el valor
    resultante en la localidad de memoria
    asignada con el identificador posición. En el hijo
    derecho de la raíz, la rutina descubriría que
    tiene que calcular la suma de dos expresiones. Se
    llamaría a si misma de manera recursiva para calcular
    el valor de
    la variable inicial.

9. Diagrama de
análisis de un programa fuente, definiendo cada una de sus
partes

Al principio de la historia de los compiladores, el
tamaño del programa ejecutable era un recurso
crítico, así como la memoria que
utilizaba el compilador para sus datos, por lo que
lo frecuente era que cada fase leyera un fichero escrito por la
fase anterior y produjera un nuevo fichero con el resultado de
las transformaciones realizadas en dicha fase. Esta
técnica (inevitable en aquellos tiempos) hacía que
el compilador realizara muchas pasadas sobre el programa fuente.
En los últimos años el tamaño del fichero
ejecutable de un compilador es relativamente pequeño
comparado con el de otros programas del sistema, y
además (gracias a los sistemas de
memoria
virtual) normalmente no tienen problemas de
memoria para compilar un programa medio. Por estos motivos, y
dado que escribir y leer un fichero de tamaño similar o
mayor que el del programa fuente en cada fase es una
pérdida considerable de tiempo (incluso
en los sistemas
modernos), la tendencia actual es la de reducir el número
de ficheros que se leen o escriben y por tanto reducir el
número de pasadas, incluso el de aquéllas que se
realizan en memoria, sin escribir ni leer nada del disco.
Las fases se agrupan en dos partes o etapas: front end (las fases
de análisis) y back end (las fases de generación y
optimización de código). Estas dos etapas se
comunican mediante una representación intermedia (generada
por el front end), que puede ser una representación de la
sintaxis del programa (un árbol sintáctico
abstracto) o bien puede ser un programa en un lenguaje
intermedio. El front end depende del lenguaje
fuente y casi siempre es independiente (o debe serlo) de la
máquina objeto para la que se va a generar código;
el back end depende del lenguaje objeto y debe ser independiente
del lenguaje fuente (excepto quizá para algún tipo
de optimización).

Análisis Léxico
El analizador léxico, también conocido como
scanner, lee
los caracteres uno a uno desde la entrada y va formando grupos de
caracteres con alguna relación entre sí (tokens),
que constituirán la entrada para la siguiente etapa del
compilador. Cada token representa una secuencia de caracteres que
son tratados como una
única entidad. Por ejemplo, en Pascal un token
es la palabra reservada BEGIN, en C: WHILE, etc.
Hay dos tipos de tokens: tiras específicas, tales como
palabras reservadas (if, while, begin, etc.), el punto y coma, la
asignación, los operadores aritméticos o
lógicos, etc.; tiras no específicas, como
identificadores, constantes o etiquetas. Se considera que un
token tiene dos partes componentes: el tipo de token y su valor.
Las tiras específicas sólo tienen tipo (lo que
representan), mientras que las tiras no específicas tienen
tipo y valor. Por ejemplo, si "Contador" es un identificador, el
tipo de token será identificador y su valor será la
cadena "Contador".
El Analizador Léxico es la etapa del compilador que va a
permitir saber si es un lenguaje de formato libre o no.
Frecuentemente va unido al analizador sintáctico en la
misma pasada, funcionando entonces como una subrutina de este
último. Ya que es el que va leyendo los caracteres del
programa, ignorará aquellos elementos innecesarios para la
siguiente fase, como los tabuladores, comentarios, espacios en
blanco, etc.

Figura 8.- Análisis léxico.

Análisis Sintáctico
El analizador sintáctico, también llamado parser,
recibe como entrada los tokens que le pasa el Analizador
Léxico (el analizador sintáctico no maneja
directamente caracteres) y comprueba si esos tokens van llegando
en el orden correcto (orden permitido por el lenguaje).
La salida "teórica" de la fase de análisis
sintáctico sería un árbol
sintáctico.
Así pues, sus funciones son:

  • Aceptar lo que es válido
    sintácticamente y rechazar lo que no lo es.
  • Hacer explícito el orden jerárquico que
    tienen los operadores en el lenguaje
    de que se trate. Por ejemplo, la cadena A/B*C es interpretada
    como (A/B)*C en FORTRAN y comoA/(B*C) en APL.
  • Guiar el proceso de
    traducción (traducción dirigida por la
    sintaxis).

Análisis Semántico
El análisis semántico es posterior al
sintáctico y mucho más difícil de formalizar
que éste. Se trata de determinar el tipo de los resultados
intermedios, comprobar que los argumentos que tiene un operador
pertenecen al conjunto de los operadores posibles, y si son
compatibles entre sí, etc. En definitiva,
comprobará que el significado de lo que se va leyendo es
válido.
La salida "teórica" de la fase de análisis
semántico sería un árbol semántico.
Consiste en un árbol sintáctico en el que cada una
de sus ramas ha adquirido el significado que debe tener. En el
caso de los operadores polimórficos (un único
símbolo con varios significados), el análisis
semántico determina cuál es el aplicable. Por
ejemplo, consideremos la siguiente sentencia de
asignación:
A := B + C
En Pascal, el signo "+" sirve para sumar enteros y reales,
concatenar cadenas de caracteres y unir conjuntos. El
análisis semántico debe comprobar que B y C sean de
un tipo común o compatible y que se les pueda aplicar
dicho operador. Si B y C son enteros o reales los sumará,
si son cadenas las concatenará y si son conjuntos
calculará su unión.
Ejemplo
VAR
ch : CHAR; (* Un identificador no se puede utilizar si *)
ent: INTEGER; (* previamente no se ha definido. *)

ch := ent + 1; (* En Pascal no es válido, en C sí.
*)

Análisis Léxico: Devuelve la secuencia de
tokens: id asig id suma numero ptocoma
Análisis Sintáctico: Orden de los tokens
válido
Análisis Semántico: Tipo de variables
asignadas incorrecta

Estructura del programa fuente
Programa fuente
Programa objeto en lenguaje ensamblador
Código de máquina relocalizable
Código de máquina absoluto
Figura 9.- Sistema para
procesamiento de un lenguaje

 

Figura 10.- Árbol de análisis
sintáctico para posición := inicial + velocidad *
60.

10.
Conclusiones

Este trabajo servirá mucho en el momento de la
creación de un compilador, ya que en él se detallan
todas y cada una de las partes que involucran a este.
Primeramente investigue que existen distintos tipos de
compiladores, me gustaria crear un compilador de
optimación, ya que pienso que es muy útil a la hora
de crear un algoritmo o
programa. La función de
un compiladores es leer un programa escrito es un lenguaje, en
este caso el lenguaje fuente, y lo traduce a un programa
equivalente en otro lenguaje, el lenguaje objeto. Me parece
fascinante que nosotros podamos crear un compilador en seis meses
(en un curso), cuando en los años 50, ya que en aquellos
tiempos se tardaron hasta 18 años trabajando en un
compilador.
Por otro lado, comprendí que un compilador, requiere de
una sintaxis y lenguajes específicos, ya que, al igual que
el lenguaje humano, si no lo escribimos correctamente el
compilador no hará lo que deseamos. Y que en la
compilación hay dos partes: Análisis y
Síntesis. La parte del análisis divide al programa
fuente en sus elementos componentes y crea una
representación intermedia.
Aprendí que las herramientas que muestran tipos de
análisis de programas fuente, son muy útiles al
momento de crear un programa al codificar un algoritmo, ya
que estas herramientas nos ayudan formateando el texto,
corrigiendo errores, dando tips; para que nosotros como
programadores seamos más eficientes al momento de crear
alguna aplicación.
También he notado como todas nuestras materias se va
complementando y enlazando, por ejemplo, en matemáticas discretas vimos la
representación de árboles, los cuales usamos aquí.
Igualmente en estructura de
datos I, vimos métodos de
ordenamiento que las gramáticas de los compiladores usan.
Por lo tanto, no parece tan complicado crear un compilador,
sólo se necesitan los conocimientos adecuados y dedicarle
su tiempo para tener éxito.

11.
Bibliografía

  • Compiladores, Principios,
    técnicas y herramientas, Alfred V. Aho, Ravi Sethi,
    Jeffrey D. Ullman. Addison – Wesley
    iberoamericana.
  • http://www.dlsi.ua.es/docencia/asignaturas/comp1/comp1.html
  • http://www.cps.unizar.es/~ezpeleta/COMPI
  • http://www.ii.uam.es/~alfonsec
  • Compiladores: Conceptos Fundamentales. B. Teufel, S.
    Schmidt, T. Teufel. Addison Wesley Iberoamericana.

Ceballos Carmona Miguel Ángel, 25 años
Estudiante universitario del ITESI, en Irapuato, Gto.
Trabajo para la materia
Lenguajes y autómatas. Creado en Febrero del 2002.
Palabras clave para Búsqueda: compiladores, lenguajes y
autómatas, análisis léxico, análisis
sintáctico, análisis semántico,
árboles sintácticos, Compilador cruzado, Compilador
con montador, autocompilador, metacompilador, descompilador,
código objeto.

 

 

 

Autor:

Miguel Ángel

Partes: 1, 2
 Página anterior Volver al principio del trabajoPágina siguiente 

Nota al lector: es posible que esta página no contenga todos los componentes del trabajo original (pies de página, avanzadas formulas matemáticas, esquemas o tablas complejas, etc.). Recuerde que para ver el trabajo en su versión original completa, puede descargarlo desde el menú superior.

Todos los documentos disponibles en este sitio expresan los puntos de vista de sus respectivos autores y no de Monografias.com. El objetivo de Monografias.com es poner el conocimiento a disposición de toda su comunidad. Queda bajo la responsabilidad de cada lector el eventual uso que se le de a esta información. Asimismo, es obligatoria la cita del autor del contenido y de Monografias.com como fuentes de información.

Categorias
Newsletter