Análisis Sintáctico Ascendente y Descendente
Análisis Sintáctico Ascendente y Descendente
Análisis Sintáctico Ascendente y Descendente
L
A.E.I.R.N.N.R
Ingeniería en sistemas
Con retroceso
Pretende buscar en el árbol universal a la sentencia a reconocer; cuando lo
encuentre, el camino que lo separa de la raíz nos da el árbol sintáctico. Ahora bien,
es posible que la sentencia sea errónea y que no se encuentre como hoja del árbol lo
que, unido a que es muy probable que el árbol sea infinito, nos lleva a la necesidad
de proponer un enunciado que nos indique cuándo se debe cancelar la búsqueda
porque se da por infructuosa.
Con funciones recursivas
No todo diagrama de sintaxis es susceptible de ser convertido tan fácilmente en
función recursiva; concretamente, en aquellos nudos del diagrama en los que el
flujo puede seguir por varios caminos, la decisión sobre cuál seguir se ha hecho en
base al siguiente token de la entrada, de manera que dicho token actúa como
discriminante.
De gramáticas LL(1).
Se basa en un autómata de reconocimiento en forma de tabla, denominada tabla de
chequeo de sintaxis. Dicha tabla posee como eje de ordenadas a los no terminales
de la gramática, y como abcisas a los terminales (incluido en pseudotoken EOF). El
contenido de cada casilla interior (que se corresponde con la columna de un
terminal y la fila de un no terminal) contiene, o bien una regla de producción, o bien
está vacía, lo que se interpreta como un rechazo de la cadena a reconocer.
En general, podemos decir que una gramática LL(1) es aquélla en la que es
suficiente con examinar sólo un símbolo a la entrada, para saber qué regla aplicar,
partiendo del axioma inicial y realizando derivaciones a izquierda. Toda gramática
reconocible mediante el método de los diagramas de sintaxis siguiendo el
procedimiento visto en el punto anterior es LL(1).
El método consiste en seguir un algoritmo partiendo de:
Ϡ La cadena a reconocer, junto con un apuntador, que nos indica cual
es el token de pre-búsqueda actual; denotaremos por a dicho token.
Ϡ Una pila de símbolos (terminales y no terminales); denotaremos por
X la cima de esta pila.
Ϡ Una tabla de chequeo de sintaxis asociada de forma unívoca a una
gramática.
Ejemplo:
Utilizaremos la gramática simple, G1 (T1, N1, P1, S1) que define los enteros no negativos
(ENN)
T1 = {0,1,2,3,4,5,6,7,8,9}
N1 = {DIGITO, ENN}
DIGITO à 0|1|2|3|4|5|6|7|8|9|
S1 = {ENN}
Queremos analizar la frase 123. en un principio solo conocemos la raíz del árbol y la frase
que debe analizarse.
ENN 1 2 3
Por último el árbol de análisis sintáctico queda completo con la producción DIGITO à 3.
Podemos ver que el árbol crece de arriba abajo a medida que se lee la frase de entrada de
izquierda a derecha.
Con retroceso
Este intenta probar todas las posibles operaciones (reducciones y desplazamientos)
mediante un método de fuerza bruta, hasta llegar al árbol sintáctico, o bien agotar
todas las opciones, en cuyo caso la cadena se rechaza.
De gramáticas LR(1)
En este epígrafe se introducirá una técnica eficiente de análisis sintáctico
ascendente que se puede utilizar para procesar una amplia clase de gramáticas
de contexto libre. La técnica se denomina análisis sintáctico LR(k). La abreviatura
LR obedece a que la cadena de entrada es examinada de izquierda a derecha (en
inglés, Left-to-right), mientras que la “R” indica que el proceso proporciona el árbol
sintáctico mediante la secuencia de derivaciones a derecha (en inglés, Rightmost
derivation) en orden inverso. Por último, la “k” hace referencia al número de tokens
de pre-búsqueda utilizados para tomar las decisiones sobre si reducir o desplazar.
Cuando se omite, se asume que k, es 1.
El análisis LR es atractivo por varias razones.
Ϡ Pueden reconocer la inmensa mayoría de los lenguajes de programación que
puedan ser generados mediante gramáticas de contexto-libre.
Ϡ El método de funcionamiento de estos analizadores posee la ventaja de
localizar un error sintáctico casi en el mismo instante en que se produce con
lo que se adquiere una gran eficiencia de tiempo de compilación frente a
procedimientos menos adecuados como puedan ser los de retroceso.
Además, los mensajes de error indican con precisión la fuente del error.
Tanto si hay retroceso como si no, en un momento dado, la cadena de entrada estará
dividida en dos partes, denominadas β y α.
β: representa el trozo de la cadena de entrada (secuencia de tokens) por consumir: â 0 T .
Coincidirá siempre con algún trozo de la parte derecha de * la cadena de entrada. Como
puede suponerse, inicialmente â coincide con la cadena a reconocer al completo (incluido el
EOF del final).
α: coincidirá siempre con el resto de la cadena de entrada, trozo al que se habrán aplicado
algunas reglas de producción en sentido inverso: á 0 (NcT) .
Ejemplo:
El análisis sintáctico ascendente usando otra vez la gramática G1 y la frase 123. de nuevo,
solo sabemos cuál es la raíz del árbol de análisis sintáctico y la frase que debemos de
analizar. En el primer paso se encuentran la reducción 1 ß DIGITO y se obtiene el inicio del
árbol sintáctico.
Entonces se aplica la reducción DIGITO ß ENN para continuar con el árbol de análisis
sintáctico:
A partir de este ejemplo podemos ver que comenzamos con las hojas del árbol sintáctico y
asciende hacia la raíz.
Referencias: