Sei sulla pagina 1di 9

REINGENIERÍA DE UN COMPILADOR EDUCATIVO

CGPI 20070913

Autores:
Isaac Andrés Canales Martínez
microbenjager@aim.com
Michel Ruiz Tejeida
minamrg@aol.com

Coautores:
MC Sergio Fuenlabrada Velázquez
fuensergio@yahoo.com.mx

Instituto Politécnico Nacional


Unidad Profesional Interdisciplinaria de Ingeniería y Ciencias Sociales y Administrativas
Av. Té 950, Col. Granjas México, CP. 08100,
Teléfono (55) 5624-2000 extensiones 70355 y 70365.

Como estudiantes dentro del área de informática una correcto funcionamiento, considerando los requisitos
de las características que se nos atribuye es la del problema, y evitar la inestabilidad. Todas estas
solución de problemas mediante el uso de recursos metodologías y procesos que se deben de seguir, es
computacionales; sin embargo la creación de una lo que se conoce como Ingeniería de Software.
solución con las características mencionadas
requiere de cierto grado de conocimiento y habilidad Formalmente la Ingeniería de Software se define
que, finalmente nos indicará la eficiencia de la como “la aplicación de un enfoque sistemático,
disciplinado y cuantificable hacia el desarrollo,
solución propuesta.
operación y mantenimiento del software.”
¿Cómo sabemos si nuestra solución es
Lo anterior se refiere al proceso de creación del
eficiente?
sistema computacional modelando y adaptándolo a
Para aquellos que desarrollan sistemas que utilicen las necesidades del usuario, siguiendo estándares
un equipo de cómputo1, es un gran reto identificar si de calidad que permitirán la mejor solución posible.
finalmente la solución es la deseada por el usuario y
si ésta cumple las características adecuadas para ¿Qué pasa si el sistema está terminado y no
ser un buen sistema. seguimos los procedimientos adecuados?

Como se sabe, el proceso de creación lleva consigo Al crear aplicaciones para solucionar problemas
una serie de pasos sistematizados y metodológicos; específicos, en ocasiones, se omiten algunos pasos
sin embargo, en la aplicación diaria se pasan por alto al seguir cierta metodología, lo que trae consigo
tareas y actividades que son consideradas inútiles o problemáticas comunes, dentro de las más
innecesarias, que posteriormente se verá reflejado destacadas encontramos: crear características del
en la productividad del mismo. sistema que no resuelven el problema principal,
agregar funciones extras para mejorar la aplicación y
Por todo lo anterior, el desarrollo de un sistema debe hacerla más robusta pero que finalmente no son
seguir normas y metodologías, para asegurar el necesarias, entre otras.
1
Conocido también como Sistema Computacional

1
La solución para determinar si el sistema cumple su La escritura de compiladores comprende los
función la podemos encontrar dentro de la lenguajes de programación, la arquitectura de
Reingeniería de Software, ya que ésta es el proceso computadoras, la teoría de lenguajes, los algoritmos
de revisión de aplicaciones de software con el y la ingeniería de software. Es importante aclarar
propósito de reutilizar el sistema actual. algunas definiciones primordiales antes de
mencionar las herramientas utilizadas; dichas
La Reingeniería de Software utiliza las mismas definiciones se muestran en los siguientes párrafos.
técnicas y principios de la Ingeniería de Software,
con la diferencia de que ahora será un proceso Expresión Regular. Es una expresión que describe
comparativo entre lo que se debió haber hecho y lo un conjunto de cadenas sin enumerar sus
que existe actualmente, para con ello identificar las elementos. Las expresiones regulares son
fallas y puntos débiles del sistema, que permitirá simplemente fórmulas cuyo propósito es representar
posteriormente corregir la aplicación y evitar iniciar cada una de ellas un lenguaje. Así, el lenguaje de
un nuevo proyecto, lo que ahorrará tiempo y reducirá una expresión regular es simplemente el lenguaje
costos. que ella representa.

Podríamos explicar detalladamente cada una de Autómata Finito. Un autómata finito se puede
estas metodologías, sin embargo, nuestro propósito representar diagramáticamente mediante un grafo
se centra en la aplicación de lo que se ha venido dirigido etiquetado, llamado grafo de transiciones, en
explicando a un sistema terminado. el que los nodos son los estados y las aristas
etiquetadas representan la función de transición, ver
Los autores, siendo estudiantes de la carrera de la figura 2.
Ingeniería en Informática de la UPIICSA, llevaron a
cabo el desarrollo de un compilador, para la materia
de Compiladores que se cursa en el 4º semestre de
dicha carrera; es necesario mencionar que el
producto fue realizado sin la aplicación de una
metodología de Ingeniería de Software.

Compilador Fig. 2. Un autómata finito en su representación


gráfica.
Un compilador es un programa que lee un programa
escrito en un lenguaje (lenguaje fuente), y lo traduce
a un programa equivalente en otro lenguaje El autómata finito también tiene una representación
(lenguaje objeto) como lo muestra la figura 1. Como matemática formada por una 5-tupla (S, Σ, δ, so, F)
parte importante de este proceso de traducción, el donde.
compilador informa a su usuario de la presencia de - S es el conjunto de estados
errores en el programa fuente. - Σ es el alfabeto utilizado
- δ es el conjunto de las funciones de transición
- so es el estado inicial

Tabla de Símbolos. Es una estructura de datos que


contiene un registro por cada lexema (componente
Fig. 1. Diagrama representativo de un compilador. del lenguaje), y se utiliza para reunir información
sobre los distintos atributos que posee cada lexema
(ver figura 5).

2
JFlex. Es un generador de analizadores léxicos para
Java, escrito en Java. JFlex fue diseñado para
trabajar en conjunto con CUP (generador de
Analizadores Sintácticos LALR). Para su
construcción requieres de la definición del lenguaje
por medio de expresiones regulares, que
posteriormente son convertidas de forma automática
a autómatas, para la generación de los lexemas que
serán utilizados por el analizador sintáctico.

CUP. Generador de analizadores sintácticos para


Java, escrito en Java. Como se mencionó
Figura 3. Como todo compilador iniciamos leyendo
previamente, tiene gran compatibilidad con JFlex.
un programa en código fuente.
CUP genera analizadores sintácticos del tipo LALR
(lookahead Left-to-Right), que se definen por medio El código fuente debe tener la característica
de un archivo externo, utilizando gramáticas. exclusiva de estar enfocado al paradigma de
programación estructurada y no en la programación
Descripción del compilador.
orientada a objetos.
Hasta el momento los resultados arrojados por el
El código fuente del compilador se almacena en un
compilador presentan un avance significativo, se ha
archivo que tiene por nombre el seleccionado por el
llegado a la etapa de generación de código
programador, con una extensión .rot soportada por la
intermedio (código de tres direcciones) que
interfaz gráfica del mismo; en donde se puede
posteriormente se transformará al código
modificar libremente y compilarlo de forma sencilla y
ensamblador.
rápida presionando tan solo un botón.
A continuación explicaremos a detalle el proceso de
Análisis Léxico. Es la primer fase del compilador; su
compilación realizado por el proyecto en cuestión.
función es la de identificar cada uno de los
Código Fuente. El compilador lee el programa a caracteres del código fuente, para generar como
partir de un código fuente de alto nivel, la sintaxis de salida los componentes léxicos que utilizará el
éste es muy semejante al utilizado en lenguajes de analizador sintáctico. El analizador léxico interactúa
programación como C o Java; dentro de lo que se con la tabla de símbolos, de tal forma que es el que
puede destacar: algunas de las palabras reservadas se encarga de llenarla y definir los atributos de cada
de ambos lenguajes, la estructura de funciones, lexema (ver figura 4).
asignaciones y operadores lógicos y aritméticos (ver
figura 3).

3
Analizador Sintáctico LALR. Es la parte del
compilador que agrupa los componentes léxicos de
un programa fuente, en frases que el compilador
utiliza para sintetizar la salida. Este tipo de
analizadores utiliza funciones y algoritmos para la
generación de tablas de análisis sintáctico, que
posteriormente determinan si una entrada pertenece
o no a una gramática. El resultado del análisis
sintáctico se muestra en la figura 6.

Figura 4. Resultado del código analizado por el


analizador léxico.

Durante toda la fase de compilación se realizan las


pruebas pertinentes para la detección de errores; en
la fase de análisis léxico los errores que pueden
ocurrir es el declarar dentro del código fuente algún
carácter que no pertenezca al lenguaje, este puede Figura 6. Ejemplo de un árbol de análisis sintáctico.
ser un signo de puntuación o algún carácter especial. Analizador Semántico. Etapa del compilador que
revisa el programa fuente para tratar de encontrar
errores semánticos y reúne la información sobre
tipos para la fase posterior de generación de código
(esto gracias a la tabla de símbolos ver la figura 5).
Una parte importante, es la verificación de tipos, aquí
es donde el compilador verifica si cada operador
tiene operandos permitidos por la especificación del
lenguaje.

Generación de código intermedio. Después de los


análisis sintáctico y semántico, algunos compiladores
generan una representación intermedia explícita del
programa fuente. Se puede considerar
representación intermedia como un programa para
máquina abstracta. En la figura 7 se muestra un
ejemplo de código intermedio.

Figura 5. Al realizar el análisis léxico actualizamos la


tabla de símbolos del compilador.

4
Figura 9. Utilizando únicamente los registros 1 y 2, la
traducción del código optimizado puede convertirse en
un código ensamblador eficiente.

Detección e información de errores. Cada fase


puede encontrar errores. Sin embargo, después de
detectar un error, se debe tratar de alguna forma ese
error, para poder continuar la compilación,
permitiendo la detección de más errores en el
programa fuente. Un compilador que se detiene
cuando encuentra el primer error, no resulta tan útil
como debiera, ya que se comportaría como un
traductor.
Figura 7. Finalmente obtenemos el código de tres
direcciones. Proceso de Reingeniería

Optimización de código. Esta fase tiene el propósito Como en toda metodología de creación de sistemas
de mejorar el código intermedio, de modo que resulte es de vital importancia identificar la factibilidad y así
un código máquina más rápido de ejecutar. saber si continuamos con el siguiente paso o
debemos cambiar de estrategia de solución, de igual
forma en la reingeniería de software debemos estar
seguros al aplicar el proceso o si debemos realizar
un plan de acción alternativo.
Figura 8. La optimización de código mejora la forma
de realizar los cálculos reduciendo el mismo código a Inicialmente lo más conveniente es comprobar que el
solo dos direcciones. sistema actual requiere del proceso de reingeniería,
lo cual se lleva a cabo identificando si el software
Generación de código. La fase final de un compilador
cumple adecuadamente los requerimientos para los
es la generación de código objeto, que por lo general
que fue creado. El siguiente paso es el de
consiste en código ensamblador (ver figura 9). Las
asegurarse que el sistema requiere necesariamente
posiciones de memoria se seleccionan para cada
ser modificado, con lo que obtenemos los puntos
una de las variables usadas por el programa.
débiles y zonas críticas. Resulta conveniente
Después, cada una de las instrucciones intermedias
basarse en la documentación del sistema para
se traduce a una secuencia de instrucciones de
entender su funcionamiento y poder realizar una
máquina que ejecuta la misma tarea. Finalmente
evaluación adecuada de los cambios que deberán
hemos concluido con todas las fases que forman un
realizarse.
compilador, sin embargo existe un procedimiento
que se realiza de forma implícito durante todo el Una vez que se ha determinado que el sistema
proceso de compilación que es la detección y realmente requiere de una reingeniería, se debe
manejo de errores. tener en cuenta que el trabajo de ésta será menor al

5
de la creación de uno nuevo, pero que finalmente el Implementación del analizador semántico y verificación
de tipos de acuerdo a los resultados del analizador
precio será alto.
sintáctico.
Generación de código.
Al realizar la reingeniería del compilador se basó el
desarrollo en un modelo que describe Tabla 1. Requerimientos del compilador
detalladamente lo mencionado; en donde cada
actividad realiza una mejora progresiva y que de Tomando en cuenta los requerimientos es necesario
acuerdo al diagrama presentado a continuación, analizar las funciones que fueron establecidas para
cada una de éstas puede repetirse en otras cumplirlos y así verificar que solo existan funciones
ocasiones con la particularidad de que el ciclo puede dedicadas a dicho propósito, esta actividad recibe el
terminar después de cualquiera de estas actividades. nombre de Ingeniería Inversa, la cual será tratada
El proceso de reingeniería se muestra gráficamente más adelante.
en la figura 10. Reestructuración de documentos.

Análisis de Uno de los aspectos más importantes en los ciclos


Inventario.
de vida de sistemas es la documentación, en donde
Reconstrucci se localizará los aspectos técnicos del sistema,
Ingeniería
directa.
ón de
Documentos.
desde el análisis de los requerimientos hasta la
especificación del proceso de implementación.

De tal forma, es conveniente examinar la


documentación actual y compararla con las
Reestructura
ción de
Ingeniería características y funciones del sistema, con el
inversa.
datos.
propósito de conocer si la documentación realmente
Reestructura describe lo que el software hace, y saber si ésta
ción de
código. debe actualizarse.

Desgraciadamente el compilador que aquí se trata


Figura 10. Modelo de proceso de reingeniería de
no cuenta con documentación alguna, ya que éste
software.
no fue creado siguiendo los lineamientos de la
Requerimientos. Inicialmente todo sistema ingeniería de software.
computacional tiene una lista de requerimientos que
El desarrollo del compilador, fue la etapa que utilizó
dieron origen a su creación, del cual es conveniente
la mayoría del tiempo destinado, lo cual llevó a la
analizar para comprobar que cada función realizada
ausencia de documentación.
fue diseñada exclusivamente para resolverlo.
Creación de un lenguaje. Los lineamientos de la Reingeniería señalan que hay
Realizar las gramáticas regulares al lenguaje creado. varias opciones para llevar a cabo la reestructuración
Identificación de las palabras reservadas del lenguaje. de documentos, una de esas alternativas es la de
Definir los operadores lógicos, aritméticos y
relacionales. volver a documentar por completo.
Lectura de código fuente desde un archivo de texto o
entrada del teclado. Esta opción de reestructuración indica el hecho de
Creación de la tabla de símbolos y la función de que es necesario partir de cero, es decir, suponiendo
actualización.
Desarrollar el analizador léxico en base al lenguaje que no hay documentación existente, caso que se
propuesto. presenta en el compilador aquí expuesto, y se
Creación del analizador sintáctico a partir del código sugiere documentar un mínimo esencial.
generado por el analizador léxico.

6
El proceso elegido, al aplicarlo al compilador, dio Reestructuración de código.
como resultado la obtención de documentos que
indican las funciones de cada clase, variables, La lógica de programación es diferente dependiendo
funciones y procedimientos, todo lo anterior aplicado del programador, ya que se puede llegar a la misma
al código; en lo referente a la parte del análisis, se solución de diferentes formas, pero esto no significa
definieron y documentaron los requerimientos, que todas sean las mejores, por eso se recomienda
diseño, palabras reservadas, operadores y establecer estándares en el código, ya sea que las
variables comiencen siempre de alguna forma, que
componentes del lenguaje.
las funciones o procedimientos tenga nombres
Ingeniería Inversa. coherentes de acuerdo a lo que hacen, u otros
patrones.
Cuando existe un sistema informático al cual se le
aplica un proceso de reingeniería, es necesario Si no se han fijado lineamentos o estándares en el
regresar a la etapa de diseño incluso si no hay código, el proceso de mantenimiento será algo
documentación, esto es para analizar posibles realmente complicado, por consecuente, la
errores de análisis y posteriormente hacer las reingeniería debe tocar este importante punto y
debidas correcciones; la ingeniería inversa permite hacer algo al respecto.
realizar lo anterior.
La reestructuración de código tiene como objetivo
La realización de una ingeniería inversa, consiste en identificar partes del código fuente que violen el
“desmembrar” el sistema existente y posteriormente funcionamiento natural de las estructuras de control
estudiar y analizar detalladamente cada uno de esos o que no cumplan con lo establecido por la
miembros o partes resultantes, para saber cómo se programación estructurada u orientada a objetos,
obtiene el resultado, cómo se realiza el proceso o para posteriormente corregir esos errores, poner a
simplemente para saber porque el código está prueba el nuevo código, y finalmente documentar los
estructurado de cierta forma. cambios realizados.

Es muy importante tener un criterio y grado de El proceso de reestructuración de código del


abstracción muy amplia, para poder pensar como lo compilador, permitió identificar ciertas funciones y
hizo el equipo de desarrollo del sistema estudiado; procedimientos que realizaban su tarea de forma
en caso de que el proceso de ingeniería inversa sea correcta, pero no óptima.
realizado por aquellos que desarrollaron el sistema,
las cosas se simplifican bastante. En el caso Algunas partes del código que se encontraron como
concreto del compilador, el lector podrá darse cuenta defectuosas, resultaron ser aquellas donde se
que el proceso de reingeniería se llevó a cabo por realizaban procesos de traducción al código de tres
direcciones y procesos de análisis del archivo fuente;
los mismos desarrolladores.
dichos defectos no permitían que el proceso de
La ingeniería inversa aplicada al sistema tratado, no compilación se realice de forma correcta, lo que
fue un proceso muy laborioso, ya que sólo hubo daba como resultado una salida incorrecta o
optimización de ciertas partes en la lógica del código, incompleta al usuario del sistema informático.
eliminación de algunas variables o simplemente la
verificación de que los resultados que arroja el Reestructuración de datos.
compilador los hiciera como se planeó desde un Como se mencionó anteriormente, se puede llegar a
principio. una solución de diferentes formas, aunque
primeramente se pueda pensar en los ciclos de

7
ejecución, también existen variaciones en las lleva a cabo de forma satisfactoria la re-compilación
estructuras y tipos de datos utilizados para llegar a del nuevo código.
esa solución.
Ingeniería Directa.
La utilización de ciertos tipos de datos y la definición
y/o implementación de estructuras de control, es de La ingeniería de software tiene la finalidad de crear
vital importancia para el óptimo desempeño y sistemas computacionales de calidad, cubriendo
utilización de recursos de un programa, ya que se estándares y facilitando el análisis de los procesos y
puede desperdiciar memoria si se utiliza un tipo de resultados que debe arrojar.
dato en vez de otro o se puede complicar la La ingeniería directa se refiere a la aplicación de las
resolución del problema al no utilizar una estructura técnicas de ingeniería de software, pero en una
de datos correcta. forma menos compleja, es decir, aplicar un proceso
Si se detectan problemas de definición de datos, es de análisis y diseño a lo que se obtuvo en las etapas
necesario analizar el porqué no es buena esa anteriores de reingeniería, tomando en cuenta sólo
implementación y seleccionar otro tipo o estructura aquellas partes donde existieron cambios.
de dato, y al igual que el proceso de reingeniería Al aplicar la ingeniería directa, se pretende añadir
anterior “Reestructuración de código”, poner a funciones que sirvan para la mejora del sistema en
prueba el nuevo código, y finalmente documentar los forma modular e incluso en forma global.
cambios realizados.
El compilador aquí descrito pasó por esta etapa de
Java fue el lenguaje de programación utilizado para reingeniería, y los resultados obtenidos fueron muy
desarrollar el compilador, por consecuente se utilizó notorios.
la orientación a objetos, y es por ello que casi todo
dentro del desarrollo de esta herramienta informática Primeramente, el proceso de ingeniería directa
está declarado en clases. permitió establecer un diseño de interfaz gráfica, ya
que la primera versión del compilador se ejecutaba
Las estructuras de datos que se utilizaron en el en línea de comandos, lo que puede ser difícil de
código fuente son muy básicas, arreglos y listas utilizar para algunas personas.
enlazadas por mencionar algunas, y los tipos de
datos también son tipos básicos, como String2, Una vez que se tenía el diseño de la interfaz,
enteros y caracteres. también se tomó la decisión de que el compilador
debería integrar un editor de código, ya que como se
Es importante mencionar que la reestructuración de mencionó antes, al ser la interfaz línea de comandos,
datos brinda el soporte para que la aplicación tenga sólo se podían compilar archivos que ya estuvieran
un largo plazo de vida, esto se debe al avance que previamente capturados en otro editor de texto.
van teniendo los lenguajes de programación, porque
en algunos desaparecen ciertos tipos de datos, no Al principio de este escrito se abordaron las
dan soporte a algunas funciones como en el caso consideraciones teóricas del compilador, como son,
que ocurre entre los compiladores de C estándar y tabla de símbolos, análisis léxico, análisis sintáctico,
los desarrollados por Borland o Microsoft, y en Java entre otros; todas estas etapas de compilación
el hecho de que desaparecen funciones conforme se generan un resultado, y al aplicar la ingeniería
actualiza la versión de su máquina virtual o directa, se decidió mostrar de forma gráfica al
simplemente al dar mantenimiento al código no se usuario todos los resultados de cada uno de los
procesos de compilación, ya que la primera versión
2
Cadena de caracteres

8
solo mostraba el producto final, que es el código de 3 El proceso de reingeniería se puede aplicar tanto a
direcciones, como el mostrado en la figura 7. grandes o pequeños, simples o complejos sistemas
informáticos.
Finalmente, el usuario del compilador es capaz de
modificar, crear y abrir sus códigos en el entorno
gráfico, y compilar dichos archivos fuente con sólo
dar clic en un botón.
Referencias.

[1] Pressman, R., (2006). Ingeniería de software


Conclusión
(Sexta edición). (Ojeda, R., Morales, I., Yägue,
La ingeniería de software es una herramienta que se V., Sánchez, S.) Madrid, España: McGraw-Hill.
debe aplicar en el desarrollo de sistemas
computacionales actuales tanto a los dirigidos al [2] V. Aho, A., Sethi, R., & D. Ulman, J. (1998).
usuario como el llamado software de base, debido a Compiladores (Primera edición ed.). (P. Flores
que en estos días, la demanda de la manipulación y Suárez, & P. Botella i López, Trads.) Naucalpan
control de información es bastante grande, y se debe de Juárez, Estado de México, México: Addison
contar con herramientas de tecnologías de Wesley Longman.
información que nos brinden seguridad y facilidad de [3] Kelley, D. (1995). Teoría de autómatas y
uso. lenguajes formales. (L. D. Platas, Trans.)
Un problema actual que se presenta dentro de las Ciudad de México, Distrito Federal, México:
organizaciones, es el hecho de contar con un Prentice-Hall.
sistema informático que haya sido desarrollado sin [4] GNU General Public License. (2004, November
haber aplicado ingeniería de software, ya que dichos 7). JFlex. Retrieved July 24, 2005, from The Fast
sistemas pueden no tener la productividad deseada Scanner Generator for Java:
o requerida. http://jflex.de/index.html visitada septiembre
2007
La solución al problema anterior, es la aplicación de
la reingeniería de software, que es el proceso por [5] Scott Hudson, F. F. (1999, July 24). CUP. (C. S.
medio del cual el sistema pasará a ser un producto Ananian, Editor) Retrieved from Parser
con una mejor funcionalidad, mejor desempeño y Generator for Java:
fiabilidad, así como mejorar y facilitar el http://www2.cs.tum.edu/projects/cup/ visitada
mantenimiento del mismo. septiembre 2007

El proceso de reingeniería se lleva a cabo, al igual


que la ingeniería de software, por etapas, entre las
cuales figuran: Reestructuración de documentos,
Ingeniería Inversa, Reestructuración de código,
Reestructuración de datos e Ingeniería Directa.

Cada etapa cumple una función específica dentro de


la reingeniería, ya sea que se orienten a la
documentación del sistema, a la optimización de
código o a la realización de un nuevo análisis.

Potrebbero piacerti anche