Análisis Léxico: detecta entradas como tokens ilegales, es decir, el trabajo
principal que realiza es detectar símbolos preventivos de entrada que no forman parte de nuestro idioma. Análisis Sintáctico: detecta entradas con árboles de análisis mal formados, es decir, determina si un programa esta bien formado o no, o si es un programa valido, también detecta todas las oraciones en el idioma que están mal formados o que no tienen una cadena de análisis. Árbol de expresiones: son los que representan el código de nivel de lenguaje en forma de datos, y los datos se almacenan en una estructura con forma de árbol. Manejo de errores: cuando los errores son encontrados en las distintas fases de análisis se envían a un módulo denominado manejo de errores. También puede ser un subprograma al que se le invoca enviándole el código de error y de ahí se encarga de escribir un mensaje con el error correspondiente. Análisis Semántico: detecta todos los posibles errores restantes en un programa, también comprueba si la semántica del programa que se esta compilando cumple los requisitos del lenguaje fuente. Operaciones semánticas: acceder a la tabla de símbolos, chequeo de tipos, generar código intermedio, generar errores cuando se producen y da lugar a los métodos de compilación dirigidos por sintaxis. Alcance de un identificador o variable: sucede de una función y no de bloques como if, while, switch, entre otros, como lenguajes en java o c/c++, en otras palabras, si se define una variable se podrá utilizar en toda la función en cuestión y no solamente en el bloque definido. Utilidad tabla de símbolos en el análisis semántico: lo usan tanto el léxico y sintáctico, para introducir información y el generador de código intermedio, la fase de optimización y la de generación de código los utilizan para generar código necesario. Tipo de dato en un lenguaje de programación: es la propiedad de un valor que determina su dominio, que operaciones se le pueden aplicar y como es representado internamente por la computadora. Tipado estático de datos: se define el tipo de dato, obligando a que no pueda haber errores con los tipos de datos, algunos lenguajes que usan este tipo de programación son: C++, Java, C, Pascal, C#. Tipado dinámico de datos: nos da la facilidad de no definir los tipos al declarar una variable, los lenguajes que usan este tipado son: Perl, Lisp, Python, PHP, JavaScript. AST (Árbol de Sintaxis Abstracta): es una estructura sintáctica hecho para representar las funciones que se producen dentro de un programa. Se basa en el código fuente de la programación. Chequeo de tipos: se encarga de verificar que una expresión sea del mismo tipo de la variable a la que es asignada y verifica que cuando una función o procedimiento son llamados estos deben corresponder a la cantidad de parámetros cuando la función o procedimiento fue declarado.
Análisis Léxico FRONT END Análisis Sintáctico Análisis Semántico
Generación de código INT
BACK END Optimización de código Generación de código objeto (.com, .exe, .jar, .sh, .bin, .apk)
FRONT END: es la parte del compilador encargada de analizar y comprobar la
validez del código fuente y en base a ella crear los valores de la tabla de símbolos. BACK END: parte en la cual es generado el código máquina, el cual es creado de acuerdo a lo analizado en el FRONT END, en pocas palabras es donde se traduce ese lenguaje intermedio a ensamblador. Lenguaje intermedio: son aquellos que no generan código máquina, si no que mediante un lenguaje intermedio BYTECODE generado, pasa posteriormente a un compilador para realizar el archivo objeto o lenguaje máquina. Son empleados con el fin de obtener optimización y portabilidad a las aplicaciones. Código objeto: consiste en código de máquina relocalizable a código ensamblador. Las posiciones de memoria se seleccionan para cada una de las variables usadas por el programa. Después, cada una de las instrucciones intermedias se traduce a una secuencia de instrucciones de máquina que ejecuta la misma tarea. Archivo .obj: son archivos intermedios generados por el compilador antes de crear un ejecutable. El archivo de objeto consiste de una tabla de símbolos y el código C compilado en código de máquina. Archivo .class: contiene código BYTECODE en su forma binaria. Habitualmente los archivos class se empaquetan y comprimen en archivos jar. Archivo ejecutable: consisten en instrucciones que han sido traducidos a partir de su código fuente original a código máquina, también llamado lenguaje de máquina o código objeto a través de la utilización de un programa especializado llamado compilado. BYTECODE: es el formato binario de código ejecutable por la maquina virtual de java, el BYTECODE recibe su nombre porque usualmente cada código de operación tiene una longitud de un byte. Cada instrucción tiene un código de operación entre 0 y 25s. seguido de parámetros tales como los registros o las direcciones de memoria. MSIL en .NET: ahora conocido como CIL, es un lenguaje ensamblador orientado a objetos y está basado en pilas. Los lenguajes principales en .NET son C#, Visual Basic .NET, C++/CLI y J#. APIREST: es un conjunto de reglas y especificaciones que las aplicaciones pueden seguir para comunicarse entre ellas. El uso de una API es el mecanismo más útil para conectar dos softwares entre sí. Notación de 3 direcciones: es un lenguaje usado por compiladores optimizadores para ayudar en las transformaciones de mejora de código. Cada instrucción TAC tiene a lo sumo tres operandos y es típicamente una combinación de asignación y operador binario. Optimización: puede referirse a la forma de mejorar o cambiar una acción realizada, esto con la finalidad de mejorar, buscar una mayor eficiencia o eficacia. Optimización local: La optimización local se realiza sobre módulos del programa, principalmente sobre un bloque básico la cual es un fragmento de código que solamente tiene una única entrada y salida. Entre las optimizaciones locales se encuentran: Folding, propagación de constantes, la reducción de potencia y reducción de subexpresiones comunes. Optimización global: La optimización global comienza a partir del análisis del grafo del flujo de ejecución, espeto permite una propagación de constantes fuera del bloque básico, eliminación del código no utilizado y una mejor asignación de los registros. Se presenta con respecto a todo el código, es considerada de las más lenta ya que mejora el desempeño general de todo tipo de programa. Optimización de ciclos: La mayoría de las optimizaciones de ciclos tratan de encontrar los elementos que no deben repetirse en un ciclo, por lo cual la optimización de ciclos es importante por la parte del rendimiento de un programa ya que estas realizan acciones repetitivas y si estas acciones están mal realizadas el problema puede hacerse N veces más grande. Entre algunos ejemplos podemos decir que sería la expansión de bucles mejor conocido como loop unrolling, la reducción de frecuencia o la eliminación de variables de inducción. Optimización de mirilla: Consiste en estructurar de manera eficiente el flujo del programa, como sería las instrucciones de bifurcación como son las decisiones, ciclos y saltos de rutinas. Lo que tiene de objetivo la optimización de mirilla es tener los saltos la más de cerca de las llamadas, siendo el salto lo más pequeño posible. tipo de optimización consiste en estructurar de manera eficiente el flujo del programa como son, las instrucciones, decisiones, ciclos y saltos. Costo/optimización: se refiere al costo que de igual forma se optimiza para tener una o más respuestas para determinar la configuración de los factores que sea factible o conveniente desde el punto de vista económico y produzca valores aceptables para las respuestas. Medidas que se pueden aplicar para mejorar el código de un programa: • Realizar correcciones en el código. • Revisar la Eficiencia, la cantidad de código y de recursos. • Reusabilidad, reutilizar código. • Implementar métricas en el proceso. • Métricas de complejidad.