27
UNIVERSIDAD ESTATAL A DISTANCIA VICERRECTORÍA ACADÉMICA ESCUELA CIENCIAS EXACTAS Y NATURALES CÁTEDRA TECNOLOGÍA DE SISTEMAS

Introducción a los compiladores - Parte 2

  • Upload
    uned

  • View
    57

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Introducción a los compiladores - Parte 2

UNIVERSIDAD ESTATAL A DISTANCIAVICERRECTORÍA ACADÉMICA

ESCUELA CIENCIAS EXACTAS Y NATURALESCÁTEDRA TECNOLOGÍA DE SISTEMAS

Page 2: Introducción a los compiladores - Parte 2

OBJETIVOS

Identificar las diferencias entre la sintaxis y la semántica.

Adquirir los conocimientos sobre los métodos de análisis sintácticos.

Aplicar los métodos de análisis sintácticos y su utilización en un programa de lenguaje.

Asociar la información con una construcción del lenguaje para utilizar técnicas de traducción.

Analizar la sintaxis de un lenguaje de programación.

Page 3: Introducción a los compiladores - Parte 2

REPASANDO SOBRE ANÁLISIS LÉXICO

En la presentación anterior conversamos que el compilador lee un archivo de entrada para posteriormente convertir cada instrucción del código de dicho archivo para poder ir identificando tokens y lexemas que por medio de patrones definidos se lograba. Se desecha la información que no era necesaria para el compilador, tal como espacios en blanco, salto de líneas, comentarios etc. Y la función primordial de la tabla de símbolo a modo de un soporte para poder ir formando el compilador, etc.

Page 4: Introducción a los compiladores - Parte 2

ANÁLISIS SINTÁCTICO (PARSING)

sintaxis: es parte de la gramática de una oración e indica que las palabras o elementos queconforman una oración están en un orden correcto.

Si transferimos ese concepto a la computación sería como las reglas o las normas quebrindan las secuencias correctas de un lenguaje de programación. Así, antes de iniciar con lasintaxis, debemos saber que la gramática en informática señala la estructura jerárquica delos programas, la cual se integrará por los siguientes aspectos:

1. Símbolos elementales o terminales. 2. Símbolos variables o no terminales.

Page 5: Introducción a los compiladores - Parte 2
Page 6: Introducción a los compiladores - Parte 2

Por lo anterior el análisis sintáctico, son reglas que indican la

estructura de un programa bien formado.

En java, por ejemplo, un programa se compone de bloques, un bloque de proposiciones, una proposición de expresiones, una expresión de componentes léxicos y así sucesivamente.

Se puede describir la sintaxis de las construcciones por gramáticas independientes del contexto o notación:

prop while (expr) prop

prop if (expr) else prop

Page 7: Introducción a los compiladores - Parte 2

EJEMPLO WHILE

(while)|([a-zA-Z]+)|([>|<|=]+)|([0-9]+)|([(|)]+)|([{|}]+)|(;)

while (num<=100){

println(num);num=num +1;

}

https://sekthdroid.wordpress.com/2013/02/08/parsing-tokenizing-y-formatting-en-java/http://www.ocpsoft.org/opensource/guide-to-regular-expressions-in-java-part-1/

Page 8: Introducción a los compiladores - Parte 2

Una gramática independiente del contexto tiene cuatro

componentes: ejemplo if expr else expr

Un conjunto de componentes léxicos, denominados símbolos terminales. (Ej. if y else).

Un conjunto de no terminales. (Ej. expr y prop )

Un conjunto de producciones, en el que cada producción consta de un no terminal, llamado lado

izquierdo de la producción, una flecha que se puede leer como puede tener la forma, y una

secuencia de componentes léxicos y no terminales, o ambos, llamado lado derecho de la

producción.

La denominación de uno de los no terminales como símbolo inicial.

Page 9: Introducción a los compiladores - Parte 2

ANÁLISIS SEMÁNTICO• Se basa en el árbol semántico y la información de la tabla de símbolos para

comprobar que lo que se está escribiendo es congruente con el lenguaje de programación.

• La fase de análisis semántico revisa el programa fuente para tratar de encontrar errores semánticos y reúne la información sobre los tipos para la fase posterior de generación de código.

• En ella se utiliza la estructura jerárquica determinada por la clase de análisis sintáctico para identificar los operadores y operandos de expresiones y proposiciones

Sintáctico Semántico

Page 10: Introducción a los compiladores - Parte 2

MANEJO DE LOS ERRORES

• Los errores léxicos incluyen la escritura incorrecta de los identificadores, las palabras clave o losoperadores; por ejemplo, el uso de un identificador tamanioElipce en vez de tamanioElipse, y la omisiónde comillas alrededor del texto que se debe interpretar como una cadena.

• Los errores sintácticos incluyen la colocación incorrecta de los signos de punto y coma, además dellaves adicionales o faltantes; es decir, “{” o “}”. Como otro ejemplo, en C o Java, la aparición de unainstrucción case sin una instrucción switch que la encierre es un error sintáctico (sin embargo, por logeneral, esta situación la acepta el analizador sintáctico y se atrapa más adelante en el procesamiento,cuando el compilador intenta generar código)

• Los errores semánticos incluyen los conflictos de tipos entre los operadores y los operandos. Unejemplo es una instrucción return en un método de Java, con el tipo de resultado void.

• Los errores lógicos pueden ser cualquier cosa, desde un razonamiento incorrecto del programador en eluso (en un programa en C) del operador de asignación =, en vez del operador de comparación ==. Elprograma que contenga = puede estar bien formado; sin embargo, tal vez no refleje la intención delprogramador.

Page 11: Introducción a los compiladores - Parte 2

ESTRATEGIAS PARA RECUPERARSE DE LOS ERRORES

• Recuperación en modo de pánico: un identificador mal escrito corregirlo.

• Recuperación a nivel de frase: por ejemplo, una coma (,) corregirlo por un punto y coma (;)

• Producciones de errores: anticipar los errores.

• Corrección global: validar por medio técnicas de arboles sintácticos los tokens y hacer las correcciones necesarias para que funcione.

Page 12: Introducción a los compiladores - Parte 2

COMPARACIÓN ENTRE ANÁLISIS LÉXICO Y ANÁLISIS SINTÁCTICO

• La sencillez en el diseño es la consideración más importante: La separación del análisis léxico y el análisis sintáctico a menudo nos permite simplificar por lo menos una de estas tareas. Por ejemplo, un analizador sintáctico que tuviera que manejar los comentarios y el espacio en blanco como unidades sintácticas sería mucho más complejo que uno que asumiera que el analizador léxico ya ha eliminado los comentarios y el espacio en blanco. Si vamos a diseñar un nuevo lenguaje, la separación de las cuestiones léxicas y sintácticas puede llevar a un diseño más limpio del lenguaje en general.

• Se mejora la eficiencia del compilador: Un analizador léxico separado nos permite aplicar técnicas especializadas que sirven sólo para la tarea léxica, no para el trabajo del análisis sintáctico. Además, las técnicas de búfer especializadas para leer caracteres de entrada pueden agilizar la velocidad del compilador en forma considerable.

• Se mejora la portabilidad del compilador: Las peculiaridades específicas de los dispositivos de entrada pueden restringirse al analizador léxico.

Page 13: Introducción a los compiladores - Parte 2

DIAGRAMAS DE TRANSICIONES DE ESTADOS

inicio*

0 1 2

letra otro

Return (ObtenerToken() / InstalarID() )

letra o dígito

Diagrama de transiciones para identificadores y palabras clave por ejemplo abc123z

Convertir los patrones en diagramas de flujo estilizados, conversión de patrones de expresiones regulares a diagramas de transiciones para su verificación de palabras reservadas o identificadores, los tokens o componentes lexicos deben ser revisados con ello.

Page 14: Introducción a los compiladores - Parte 2

AUTÓMATAS FINITOS

• Es un diagrama de transiciones generalizado.

• Un autómata finito puede ser determinista o no determinista, donde no determinista significa que en un estado se puede dar el caso de tener más de una transición para el mismo símbolo de entrada.

Page 15: Introducción a los compiladores - Parte 2

AUTÓMATA FINITO NO DETERMINISTA:

Significa que en un estado se puede dar el caso de tener más de una transición para el mismo símbolo de entrada

Un autómata finito no determinista (AFN) es un modelo matemático formado por:

• Un conjunto de estados

• Un conjunto de símbolos de entrada (el alfabeto de símbolos de entrada)

• Una función de transición "mueve" que transforma pares estado - símbolo en conjuntos de estados

• Un estado Q0 que se considera el estado de inicio

• Un conjunto de estados F considerados como estado de aceptación o finales

Ejemplo: 00101

Page 16: Introducción a los compiladores - Parte 2

Inicio b ba

q0 q1 q2q3

a

b

Un autómata finito no determinista para (a b) * abb

Page 17: Introducción a los compiladores - Parte 2

AUTÓMATA FINITO DETERMINISTA

• Un autómata finito determinista (AFD) es un caso especial de un AFN en el cual:

• Ningún estado tiene una transición , es decir, una transición con la entrada de conjunto vacío.

• Para cada estado s y cada símbolo de entrada a, hay a lo sumo una arista etiquetada a que sale de S.

Page 18: Introducción a los compiladores - Parte 2

a

Inicio b ba

0 1 2 3

a

b

Un autómata finito determinista (AFD) para (a | b) * abb

a

b

0-1-2-1-2-30-1-2-3

Page 19: Introducción a los compiladores - Parte 2

SECUENCIAS AUTÓMATA FINITO DETERMINISTA

Muestre la secuencia de movimientos en el siguiente AFD para las cadenas:1 – aabc2 – bbc3 – cabb4 – abbbc5 – aaaac

1. La secuencia es 0 – 1 – 1 – 3

2. La secuencia es 0 – 2 – 2 - 3

3. La secuencia 0 – 1 – 1 – 2 - 3

4. La secuencia es 0 – 1 – 2 – 2 -2 – 3

5. La secuencia es 0 – 1 – 1 – 1 – 1 - 3

Page 20: Introducción a los compiladores - Parte 2

ÁRBOLES SINTÁCTICOS

Un árbol de análisis sintáctico es un árbol con las propiedades siguientes:

La raíz está etiquetada con el símbolo inicial

Cada hoja esta etiquetada con un componente léxico o con E.

Cada nodo interior está etiquetado con un no terminal.

A

X Y Z

Árbol de análisis sintáctico para A XYZ

Page 21: Introducción a los compiladores - Parte 2

Hay varias tareas que se pueden realizar durante el análisis sintáctico:

Recoger información sobre distintos componentes léxicos en la tabla de símbolos

Realizar la verificación de tipo y otras clases de análisis semántico

Generar código intermedio

Page 22: Introducción a los compiladores - Parte 2

Análisis sintáctico descendente.

La construcción descendente de un árbol de análisis sintáctico se hace empezando por la raíz, etiquetada

con el no terminal inicial, y realizando de forma repetida los dos pasos siguientes:

En el nodo n, etiquetado con el no terminal A, selecciónese una de las producciones para A y constrúyase

los hijos de n para los símbolos del lado derecho de la producción.

Encuéntrese el siguiente nodo en el que ha de construirse un subárbol.

Por ejemplo la expresión Entrada: num*num+num

Gramática: E ::= E + T | T T ::= T * F | F F ::= num

(E: expresión, T: término, F: factor)

Page 23: Introducción a los compiladores - Parte 2

REGLAS DE PRODUCCIÓN SINTÁCTICA

Podemos construir una gramática para expresiones aritméticas a partir de una tabla que muestre la asociatividad y la precedencia de los operadores

asociativo por la izquierda: + −

asociativo por la derecha: * /

Creamos dos no terminales llamadas expr y term para los dos niveles de precedencia, y un no terminal adicional llamado factor para generar unidades básicas en las expresiones. Las unidades básicas en las expresiones son dígitos y expresiones entre paréntesis. factor → dígito | ( expr )

los operadores binarios, * y /, que tienen la mayor precedencia. Como estos operadores asocian por la izquierda, las producciones son similares a las de las listas que asocian por la izquierda.

De manera similar, expr genera listas de términos separados por los operadores aditivos:

Por lo tanto, la gramática resultante es:

Page 24: Introducción a los compiladores - Parte 2

Análisis sintáctico ascendente.Este método intenta construir un árbol de análisis sintáctico para una cadena de entrada que comienza por las

hojas (el fondo) y avanza hacia la raíz.

Por ejemplo la expresión Entrada: num*num+num

Gramática: E ::= E + T | T T ::= T * F | F F ::= num

(E: expresión, T: término, F: factor)

Page 25: Introducción a los compiladores - Parte 2

Analizadores sintácticos LR

Este diagrama consiste en una entrada, una salida, una pila, un programa controlador y una tabla de análisis sintáctico que tiene dos partes (ACCION y el ir_A). El programa controlador es igual para todos los analizadores sintácticos LR; sólo la tabla de análisis sintáctico cambia de un analizador sintáctico a otro. El programa de análisis sintáctico lee caracteres de un búfer de entrada, uno a la vez. En donde un analizador sintáctico de desplazamiento-reducción desplazaría a un símbolo, un analizador sintáctico LR desplaza a un estado. Cada estado sintetiza la información contenida en la pila, debajo de éste.

Page 26: Introducción a los compiladores - Parte 2

CONCLUSIÓN ANÁLISIS SINTÁCTICO

• En esta etapa, se identifican las estructuras más grandes del programa, proposiciones, declaraciones, expresiones, etc., utilizando los esquemas léxicos producidos por el analizador léxico.

• El análisis sintáctico por lo regular alterna con el análisis semántico.

• Primero el analizador sintáctico identifica una secuencia de elementos léxicos que forman una unidad de sintaxis tal como una expresión. Se llama entonces al analizador de semántica para procesar esta unidad.

Page 27: Introducción a los compiladores - Parte 2

FIN