Este documento presenta los objetivos y contenidos de una cátedra sobre análisis sintáctico. Explica la diferencia entre sintaxis y semántica, y los métodos de análisis sintáctico como gramáticas independientes del contexto y producciones. También cubre autómatas finitos, árboles sintácticos, análisis ascendente y descendente, y analizadores LR. El propósito es que los estudiantes adquieran conocimientos sobre estas técnicas y puedan aplicar métodos de análisis
Topografía 1 Nivelación y Carretera en la Ingenierías
Análisis sintáctico lenguajes programación
1. UNIVERSIDAD ESTATAL A DISTANCIA
VICERRECTORÍA ACADÉMICA
ESCUELA CIENCIAS EXACTAS Y NATURALES
CÁTEDRA TECNOLOGÍA DE SISTEMAS
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.
3. 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.
4. ANÁLISIS SINTÁCTICO (PARSING)
sintaxis: es parte de la gramática de una oración e indica que las palabras o elementos que
conforman 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 que
brindan las secuencias correctas de un lenguaje de programación. Así, antes de iniciar con la
sintaxis, debemos saber que la gramática en informática señala la estructura jerárquica de
los programas, la cual se integrará por los siguientes aspectos:
1. Símbolos elementales o terminales.
2. Símbolos variables o no terminales.
5.
6. 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
8. 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.
9. 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
10. MANEJO DE LOS ERRORES
• Los errores léxicos incluyen la escritura incorrecta de los identificadores, las palabras clave o los
operadores; por ejemplo, el uso de un identificador tamanioElipce en vez de tamanioElipse, y la omisión
de 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 de
llaves adicionales o faltantes; es decir, “{” o “}”. Como otro ejemplo, en C o Java, la aparición de una
instrucción case sin una instrucción switch que la encierre es un error sintáctico (sin embargo, por lo
general, 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. Un
ejemplo 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 el
uso (en un programa en C) del operador de asignación =, en vez del operador de comparación ==. El
programa que contenga = puede estar bien formado; sin embargo, tal vez no refleje la intención del
programador.
11. 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.
12. 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.
13. 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.
14. 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.
15. 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
16. Inicio b ba
q0 q1 q2
q3
a
b
Un autómata finito no determinista para (a b) * abb
17. 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.
18. 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-3
0-1-2-3
19. SECUENCIAS AUTÓMATA FINITO DETERMINISTA
Muestre la secuencia de movimientos en el siguiente AFD para las cadenas:
1 – aabc
2 – bbc
3 – cabb
4 – abbbc
5 – 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
20. Á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
21. 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
22. 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)
23. 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:
24. 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)
25. 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.
26. 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.