Fases del compilador con ejemplo

Tabla de contenido:

Anonim

¿Cuáles son las fases del diseño del compilador?

El compilador opera en varias fases, cada fase transforma el programa fuente de una representación a otra. Cada fase toma entradas de su etapa anterior y alimenta su salida a la siguiente fase del compilador.

Hay 6 fases en un compilador. Cada una de esta fase ayuda a convertir el lenguaje de alto nivel en el código de máquina. Las fases de un compilador son:

  1. Análisis léxico
  2. Análisis de sintaxis
  3. Análisis semántico
  4. Generador de código intermedio
  5. Optimizador de código
  6. Generador de códigos
Fases del compilador

Todas estas fases convierten el código fuente dividiéndolo en tokens, creando árboles de análisis y optimizando el código fuente en diferentes fases.

En este tutorial, aprenderá:

  • ¿Cuáles son las fases del diseño del compilador?
  • Fase 1: Análisis léxico
  • Fase 2: Análisis de sintaxis
  • Fase 3: Análisis semántico
  • Fase 4: Generación de código intermedio
  • Fase 5: Optimización de código
  • Fase 6: Generación de código
  • Gestión de tablas de símbolos
  • Rutina de manejo de errores:

Fase 1: Análisis léxico

El análisis léxico es la primera fase en la que el compilador escanea el código fuente. Este proceso puede ser de izquierda a derecha, carácter por carácter, y agrupar estos personajes en fichas.

Aquí, el flujo de caracteres del programa fuente se agrupa en secuencias significativas identificando los tokens. Hace la entrada de los tickets correspondientes en la tabla de símbolos y pasa ese token a la siguiente fase.

Las principales funciones de esta fase son:

  • Identificar las unidades léxicas en un código fuente.
  • Clasifique las unidades léxicas en clases como constantes, palabras reservadas e introdúzcalas en diferentes tablas. Ignorará los comentarios en el programa fuente.
  • Identificar el token que no forma parte del idioma.

Ejemplo :

x = y + 10

Tokens

X identificador
= Operador de asignación
Y identificador
+ Operador de suma
10 Número

Fase 2: Análisis de sintaxis

El análisis de sintaxis se trata de descubrir la estructura en el código. Determina si un texto sigue o no el formato esperado. El objetivo principal de esta fase es asegurarse de que el código fuente escrito por el programador sea correcto o no.

El análisis de sintaxis se basa en las reglas basadas en el lenguaje de programación específico mediante la construcción del árbol de análisis con la ayuda de tokens. También determina la estructura del idioma de origen y la gramática o sintaxis del idioma.

A continuación, se muestra una lista de las tareas realizadas en esta fase:

  • Obtener tokens del analizador léxico
  • Comprueba si la expresión es sintácticamente correcta o no
  • Informar todos los errores de sintaxis
  • Construya una estructura jerárquica que se conoce como árbol de análisis

Ejemplo

Cualquier identificador / número es una expresión

Si x es un identificador e y + 10 es una expresión, entonces x = y + 10 es una declaración.

Considere el árbol de análisis para el siguiente ejemplo

(a+b)*c

En Parse Tree

  • Nodo interior: registro con un operador archivado y dos archivos para niños
  • Hoja: registros con 2 / más campos; uno para el token y otra información sobre el token
  • Asegúrese de que los componentes del programa encajen de manera significativa
  • Recopila información de tipos y comprueba la compatibilidad de tipos
  • Los operandos de verificación están permitidos por el idioma de origen

Fase 3: Análisis semántico

El análisis semántico verifica la consistencia semántica del código. Utiliza el árbol de sintaxis de la fase anterior junto con la tabla de símbolos para verificar que el código fuente dado sea semánticamente coherente. También comprueba si el código transmite un significado apropiado.

Semantic Analyzer comprobará si hay discrepancias de tipos, operandos incompatibles, una función llamada con argumentos incorrectos, una variable no declarada, etc.

Las funciones de la fase de análisis semántico son:

  • Le ayuda a almacenar la información de tipo recopilada y guardarla en una tabla de símbolos o árbol de sintaxis
  • Le permite realizar la verificación de tipos
  • En el caso de falta de coincidencia de tipos, donde no hay reglas de corrección de tipos exactas que satisfagan la operación deseada, se muestra un error semántico.
  • Recopila información de tipos y comprueba la compatibilidad de tipos
  • Comprueba si el idioma de origen permite los operandos o no

Ejemplo

float x = 20.2;float y = x*30;

En el código anterior, el analizador semántico encasillará el entero 30 para que flote 30.0 antes de la multiplicación.

Fase 4: Generación de código intermedio

Una vez que finaliza la fase de análisis semántico, el compilador genera código intermedio para la máquina de destino. Representa un programa para alguna máquina abstracta.

El código intermedio se encuentra entre el lenguaje de alto nivel y el nivel de máquina. Este código intermedio debe generarse de tal manera que sea fácil de traducir al código de la máquina de destino.

Funciones de generación de código intermedio:

  • Debe generarse a partir de la representación semántica del programa fuente.
  • Contiene los valores calculados durante el proceso de traducción.
  • Le ayuda a traducir el código intermedio al idioma de destino
  • Le permite mantener el orden de precedencia del idioma de origen
  • Contiene el número correcto de operandos de la instrucción.

Ejemplo

Por ejemplo,

total = count + rate * 5

El código intermedio con la ayuda del método de código de dirección es:

t1 := int_to_float(5)t2 := rate * t1t3 := count + t2total := t3

Fase 5: Optimización de código

La siguiente fase de es la optimización del código o el código intermedio. Esta fase elimina la línea de código innecesaria y organiza la secuencia de declaraciones para acelerar la ejecución del programa sin desperdiciar recursos. El objetivo principal de esta fase es mejorar el código intermedio para generar un código que se ejecute más rápido y ocupe menos espacio.

Las principales funciones de esta fase son:

  • Le ayuda a establecer un equilibrio entre la velocidad de ejecución y la de compilación.
  • Mejora el tiempo de ejecución del programa de destino.
  • Genera código optimizado aún en representación intermedia
  • Eliminar el código inalcanzable y deshacerse de las variables no utilizadas
  • Eliminar declaraciones que no se modifican del ciclo

Ejemplo:

Considere el siguiente código

a = intofloat(10)b = c * ad = e + bf = d

Puede llegar a ser

b =c * 10.0f = e+b

Fase 6: Generación de código

La generación de código es la última y última fase de un compilador. Obtiene entradas de las fases de optimización del código y, como resultado, produce el código de la página o el código objeto. El objetivo de esta fase es asignar almacenamiento y generar código de máquina reubicable.

También asigna ubicaciones de memoria para la variable. Las instrucciones del código intermedio se convierten en instrucciones de máquina. Esta fase convierte el código optimizado o intermedio en el idioma de destino.

El idioma de destino es el código máquina. Por lo tanto, todas las ubicaciones y registros de la memoria también se seleccionan y asignan durante esta fase. El código generado por esta fase se ejecuta para tomar entradas y generar salidas esperadas.

Ejemplo:

a = b + 60.0

Posiblemente se traduciría a registros.

MOVF a, R1MULF #60.0, R2ADDF R1, R2

Gestión de tablas de símbolos

Una tabla de símbolos contiene un registro para cada identificador con campos para los atributos del identificador. Este componente facilita al compilador buscar el registro del identificador y recuperarlo rápidamente. La tabla de símbolos también le ayuda a gestionar el alcance. La tabla de símbolos y el controlador de errores interactúan con todas las fases y la tabla de símbolos se actualiza en consecuencia.

Rutina de manejo de errores:

En el proceso de diseño del compilador, pueden producirse errores en todas las fases que se indican a continuación:

  • Analizador léxico: tokens mal escritos
  • Analizador de sintaxis: faltan paréntesis
  • Generador de código intermedio: operandos no coincidentes para un operador
  • Optimizador de código: cuando no se puede acceder a la declaración
  • Generador de código: declaraciones inalcanzables
  • Tablas de símbolos: error de varios identificadores declarados

Los errores más comunes son la secuencia de caracteres no válida en el escaneo, las secuencias de token no válidas en el tipo, el error de alcance y el análisis sintáctico en el análisis semántico.

El error se puede encontrar en cualquiera de las fases anteriores. Después de encontrar errores, la fase debe ocuparse de los errores para continuar con el proceso de compilación. Estos errores deben informarse al controlador de errores que maneja el error para realizar el proceso de compilación. Generalmente, los errores se informan en forma de mensaje.

Resumen

  • El compilador opera en varias fases, cada fase transforma el programa fuente de una representación a otra
  • Seis fases del diseño del compilador son 1) Análisis léxico 2) Análisis de sintaxis 3) Análisis semántico 4) Generador de código intermedio 5) Optimizador de código 6) Generador de código
  • El análisis léxico es la primera fase en la que el compilador escanea el código fuente
  • El análisis de sintaxis se trata de descubrir la estructura en el texto
  • El análisis semántico verifica la consistencia semántica del código.
  • Una vez que finaliza la fase de análisis semántico, el compilador genera código intermedio para la máquina de destino
  • La fase de optimización de código elimina la línea de código innecesaria y organiza la secuencia de declaraciones
  • La fase de generación de código obtiene entradas de la fase de optimización del código y produce el código de página o el código objeto como resultado
  • Una tabla de símbolos contiene un registro para cada identificador con campos para los atributos del identificador
  • La rutina de manejo de errores maneja errores e informes durante muchas fases