2010-04-16 81 views

Respuesta

13

Sí, hay un procedimiento general, consulte p. Ej. wikipedia.

E = TE' 
E'= (e) | +TE' 
T = FT' 
T'= (e) | *FT' 
F = a | b | c 

Cabe mencionar que esto altera la asociatividad de + y * de izquierda a derecha. Es decir, donde antes se analizó a + b + c como (a + b) + c, ahora se analiza como a + (b + c).

Esto no es un problema para la suma y la multiplicación, pero sería un problema para la resta y la división, por ejemplo.

El artículo de Wikipedia tiene más detalles sobre el procedimiento de eliminación de recurrencias a la izquierda y sus complejidades.

+4

Entonces, ¿cómo resolver ese problema?(de invertir la asociatividad) Veo muchas copias (directas o indirectas) de este algoritmo para eliminar la recursión a la izquierda, y siempre escriben la advertencia sobre romper la asociatividad, pero todavía no había visto ninguna solución a ese problema en ninguno de esos artículos . ¿Hay alguna solución? ¿O solo el problema? Y la otra pregunta es: ¿Por qué funciona esto? – SasQ

+2

Lo pregunto porque no he visto ninguna prueba confiable de ese algoritmo. Hubo "pruebas" que demostraron que el lenguaje obtenido de la gramática transformada sigue siendo el mismo, pero para mí hay un ERROR en tales pruebas: una suposición de que si la sintaxis genera el mismo resultado, es lo mismo. Porque NO es! Es un lenguaje completamente diferente, porque tiene un árbol de análisis diferente, por lo que la máquina lo "entiende" de manera diferente. La misma diferencia que entre interpretar "Árbol de sintaxis abstracto" como "Resumen (Árbol de sintaxis)" y "Árbol de sintaxis abstracta": dos cosas diferentes. – SasQ

+1

Lo mismo ocurre con las sintaxis recursivas a la derecha y recursivas a la derecha. Uno es asociativo de izquierda, el otro asociativo de derecha. Y no sé sobre ninguna forma de tener sintaxis recursiva a la izquierda con asociatividad correcta. ¿Tú sabes? – SasQ

2

Como han señalado otros, hay un procedimiento general para reemplazar la recursividad a la izquierda con recursión a la derecha. Las otras respuestas muestran bien cómo usar ese procedimiento general para eliminar la recursividad izquierda en la gramática dada.

Aquí hay una solución que reestructura la gramática dada de una manera específica para esa gramática.

E= T+E|T 
T= F*T|F 
F= a|b|c 
+0

¿De verdad está diciendo que su gramática propuesta es gratuita? Me pregunto porque lo encontré en un curso de Lenguajes formales y se dijo recursivo a la izquierda. –

3

El procedimiento general se encuentra en Wikipedia, por ejemplo. Lo demostraré para E = E+T|T:

E es el no-recursivo izquierdo-no terminal. +T es la secuencia no nula (alfa). T es la secuencia que no comienza con E (beta).

Creamos un nuevo no terminal para el "resto", es decir. la secuencia no nula. Esto maneja la recursión.

E' = epsilon|+TE'

Y modificamos la regla original para utilizar el nuevo no terminal para manejar la recursividad.

E = TE'

1

la producción

E = E+T 
    | T 
T = T*F 
    | F 
F = a|b|c 

va a

E= T ('+' T)* 
T= F ('*' F)* 
F= a|b|c 

Para mantener el mismo procesamiento en el que el puño E disjunta se procesa con A(E,T). la nueva versión usa:

ret = T1; 
while(set.more()) ret = A(ret, set.pop_front().T);