Sintaxis
abstracta y concreta: un punto de partida útil
para considerar la traducción de una cadena de entrada es un árbol de sintaxis
abstracta, donde cada nodo representa un operador, y los hijos de ese nodo, los
operandos. Por contraste, un árbol de análisis sintáctico se denomina árbol de
sintaxis concreta, y la gramática subyacente, sintaxis concreta del lenguaje.
Los arboles de sintaxis abstracta, o simplemente arboles sintácticos difieren
de los arboles de análisis sintáctico en que las distinciones superficiales de
forma, sin importancia en la traducción, no aparecen en los arboles
sintácticos.
Ejemplo:
El árbol sintáctico para
9-5+2 se muestra a continuación, dado que + y – tiene el mismo nivel de
precedencia, y los operadores con igual nivel de precedencia, se evalúan de
izquierda a derecha, el árbol presenta 9-5 agrupado como una buexpresion.
ejemplo propuesto: 8+3-5-2
Si no se ha definido el orden de
evaluación de los operandos la
siguiente optimización es válida
B=2*A+(A=c*d);
Pasar
a
A=c*d;
B=A*3;
Adaptación
del esquema de traducción: la técnica para la
eliminación de la recursividad por la izquierda, se puede aplicar también a
producciones que contengan acciones semánticas.
Cuando las acciones
semánticas se intercalan en las producciones, se trasladan junto con la
transformación. Aquí se hace A= expr, α=+ termino {print (‘+’)}, ϐ=- termino
{print(‘-‘)} y y=termino, esta
traducción traduce esta transformación:
Expr -> termino resto
Resto -> termino
{print(‘+)} resto|-termino{print(‘-‘)} resto| €
Termino ->0
{print(‘0’)}
Termino ->1
{print(‘1’)}
……
Termino ->9
{print(‘9’)}
Procedimiento
para los no terminales: la
función parea, es la contraparte en C del código ejemplo para aparear un
componente léxico con el símbolo de preanalisis y avanzar por la entrada.
Puesto que cada componente léxico es un solo carácter en este lenguaje, parea
puede hacerse comparando y leyendo caracteres.
Las funciones para los no
terminales imitan a los lados derechos de las producciones.
Por ejemplo, la
producción expr -> termino resto se aplica para las llamadas a termino() y
resto () en la función expr().
Simplificación
del traductor: Ciertas llamadas
recursivas de pueden remplazar por iteraciones. Cuando la ultima proposición
ejecutada en el cuerpo de un procedimiento es una llamada recursiva al mismo
procedimiento, se dice que la llamada es recursiva por el final. Por ejemplo las
llamadas de resto() al final de la cuarta y séptima línea de la función resto ()
son recursivas por el final, por que el control fluye hacia el final del cuerpo
de la función después de cada una de esas llamadas.
Se puede imprimir mayor
velocidad a un programa remlazando la recursión por el final con una
construcción de iteración. Para un procedimiento sin parámetros, una llamada
recursiva por el final simplemente se puede remplazar por un salto al inicio
del procedimiento.
El código de resto se
puede rescribir como:
Mientras el símbolo de pre
análisis sea un signo mas o menos, el procedimiento resto parea el signo, llama
a termino para que paree un digito, y repite el proceso.
0 comentarios:
Publicar un comentario