Subido por Alexis León

unidad 5 (81)

Anuncio
.................................................... Ошибка! Закладка не определена.
5.- análisis sintáctico ............................................................................................ 2
5.1 definición y clasificación de gramáticas ....................................................... 2
..................................................................... Ошибка! Закладка не определена.
5.3 árboles de derivación...................................................................................... 4
5.5 diagramas de sintaxis ..................................................................................... 5
5.6 eliminación de la ambigüedad ..................................................................... 12
5.7 tipos de analizadores sintácticos ................................................................ 13
5.- análisis sintáctico
Examen
30
Portafolio
20
Manual de prácticas
30
Propuesta de proyecto
20
100
Competencia especifica
Construye un analizador sintáctico a partir de un lenguaje de programación
5.1 definición y clasificación de gramáticas
Gramática:
La gramática es un ente formal para especificar de una manera finita, el conjunto de
cadenas de símbolos que constituyen un lenguaje.
Una gramática es una cuádrupla:
G= (VT, VN, S, P)
Donde:
VT= {conjunto finito de símbolos terminales}
VN= {conjunto finito de símbolos no terminales}
S= es el símbolo inicial y pertenece a VN
P= {conjunto de producciones o de reglas de derivación}
Todas las cadenas de lenguaje definido por la gramática están formadas con símbolos del
vocabulario terminal VT.
El vocabulario terminal se define por enumeración de los símbolos terminales
Tarea: jerarquía de Chomsky
5.3 árboles de derivación
Árbol de derivación:
Representación gráfica de cómo se deriva una forma sentencial a partir del símbolo noterminal inicial.
Un árbol es un grafo dirigido a cíclico en el cual cada nodo se conecta con un nodo
distinguido, llamado nodo raíz mediante un único camino.
Un nodo N1 se dice descendiente de otro nodo N2 si se puede llegar a N1 a partir de N1 el
nodo raíz no es descendiente de ningún nodo, y los nodos que no tienen descendientes
denominan hojas el resto de los nodos se denominan nodos interiores.
Nodo raíz
Nodos internos
Hojas
Un árbol de derivación tiene las siguientes propiedades:
1.- el nodo raíz esta rotulado como el símbolo distinguido como el símbolo distinguido
(inicial) de la gramática.
2.- cada hoja corresponde a un símbolo terminal o un símbolo no- terminal
3.- cada nodo interior corresponde a un símbolo no- terminal.
5.5 diagramas de sintaxis
Son una forma de representar una gramática libre de contexto.
Representan una alternativa grafica para la forma de Backus- naur (BNF, por sus siglas en
inglés) o la forma extendida de Backus – nar (EBNF).
Consta de una serie de cajas o símbolos geométricos conectados por arcos dirigidos.
1- Cada símbolo terminal se representa por su nombre encerrado en un círculo o en
una caja de bordes circulares
terminal
2- Cada símbolo No terminal se encierra en un rectángulo
No terminal
3- Para producciones que tengan varias alternativas el grafo resultante será del tipo:
Alternativa
Alternativa
Alternativa
4- Producciones que contengan una serie concatenada de símbolos terminales y/o no
terminales
constante
.
.
constante
5- Producciones que tengan cero, una o más repeticiones de un símbolo
digito
Sentencia condicional, usando diagramas sintácticos
letra
letra
letra
if
condición
then
else
sentencia
sentencia
Con grafos o diagrama sintácticas somos capaces de representar la sintaxis de un lenguaje
y podemos utilizarlos en lugar del conjunto de producciones en BNF
Tarea: gramáticas libres del contexto
Ejemplos de diagramas de sintaxis:
Gramáticas:
E: = E + T|
E – T|
E
E
E
:
=
E
+
T
|
T
E
:
=
E
+
T
|
TE
E–
:T
=|
E
+
TE
|
F
E
:E
=–
T
E
+|
T
|
E
FE
E–
:T
=|
E
+
TE
|
n
E
E:
(–=
ETE
:| +
=T
E|
E
+
T
T
E
:
=
E
+
T
|
T: = T * F|
T / F|
F
F: = (E) |
n
FE
E–
: T
=|
E
+E
T
E|
E
: E
=–
ET
+|
T
+
E
:E
=
:
E
=
+
E
T
|+
T
|
E
*
–
E
E
T
:/
|–
=E
: T
E
|
+= E
E
T
|+ E
T
)
|
EE
: –
=T
E
E |–
+ T
T |

Los diagramas de transición son diagramas que representan de forma gráfica las
restricciones de una gramática libre de contexto.
Diagrama para la instrucción de una asignación:
variable
expresión
=
E
:
=
E
+
T
|
Diagrama para la instrucción de una condición:E
–
T
|
Expresión
si
(
numérica
E:
E
E
=
:
Final
si
E
=
+
E
T|
+
Insti.
T
|
E
–
T|
E
–
T
E
|
E
)
E
:
=
E
+
T
|
E
–
T
|
E
entonces
Si no
Insti.
5.6 eliminación de la ambigüedad
Las gramáticas se utilizan para proporcionar la estructura de los archivos, de los programas
y documentos. Sin embargo, no todas las gramáticas proporcionan estructuras unidas.
Cuando una gramática en proporcionar estructuras inicia a veces es posible rediseñar la
gramática para hacer que la estructura sea única para cada cadena. Lamentablemente hay
ocasiones en las que esto no es posible
Ejemplo
E
E
E
+
E
E
*
E
E
E
*
+
E
E
1. E=> e+e=> e+e*e
2. E=> e*e=> e+e*e
La derivación 1 tiene una segunda “E” que es remplazada por E*E. mientras que en la
derivación 2 la primera E es remplazada por E+E, esto genera 2 árboles de derivación
diferentes es decir la primera derivación sugiere que 1+(2*3) = 7 se agrupa a si mientras
que la segunda derivación dice que la expresión se agrupa así (1+2)*3=9.
Por otro lado, la existencia de diferentes derivaciones para una cadena no implica que la
gramática sea defectuosa, por ejemplo.
1. E=> E+E=>1 + E=> a+1 => a+b
2. E=> E+E=>1 + 1=> 1+b => a+b
Sin embargo, no existe ninguna diferencia real entre las estructuras proporcionadas en
estas derivaciones ya que ambas especifican que ay b son identificadores y sus valores
deben sumarse. De hecho, ambas derivaciones dan como resultado el mismo árbol.
E
E
E
+
E
E
+
E
I
E
*
E
I
E
*
A
I
I
A
I
I
A
A
A
A
E
Árboles que dan por resultado a+a*a, lo que demuestra la ambigüedad de la gramática de
expresiones
5.7 tipos de analizadores sintácticos
Ascendente
Se parte de las hojas y se intenta construir el árbol hacia arriba hasta llegar al símbolo inicial
de la gramática
E
E
E
E
E
id
+
id
+
id
5.8 Generación de matriz predictiva (cálculo first y follow)
FIRST:
Si α es cualquier cadena de símbolos gramaticales, se considera FIRST (α) como el conjunto
de terminales que encabezan las cadenas derivadas de α. Si α = * => λ, entonces λ también
está en FIRST (α). Para calcular FIRST(X) para algún símbolo X de la gramática, se aplican las
siguientes reglas hasta que no se pueda añadir nada nuevo al conjunto
FIRST:
Sea G:= (V; ∑; Q0; P) una gramática libre de contexto. Para cada forma sentencia α Є (V U
∑)* y para cada k Є N definiremos la función.
En otras palabras, el operador FIRST k asocia a cada forma sentencia los primeros k símbolos
de cualquier forma terminal alcanzable desde α mediante derivaciones “masa a izquierda".
1. Si X es terminal, entonces FIRST(X) es {X}.
2. Si X es no terminal y existe la producción X → λ, entonces añadir λ a FIRST(X).
3. Si X es no terminal y X → Y1 Y2... . Yk
Es una producción entonces, para todo i (con i variando desde 1 hasta k) tal que Y1 , Y2 ,
..., Yi-1 sean todos no terminales y FIRST(Y1), FIRST(Y2), ..., FIRST(Yi-1) contengan todos λ,
se añaden todos los símbolos no nulos de FIRST(Yi ) a FIRST(X). Finalmente, si λ está en FIRST
(Yj) para j = 1, 2, ..., k (o sea, en todos), entonces se añade λ a FIRST(X). Dicho de otra forma,
lo anterior significa que todos los elementos de FIRST (Y1), excepto λ, pertenecen también
a FIRST(X). Si Y1 no deriva λ, entonces ya ha terminado el cálculo de FIRST(X), pero en caso
contrario, es decir, si Y1= * => λ, entonces todos los elementos de FIRST (Y2) excepto λ
pertenecen también a FIRST(X), y así sucesivamente. Finalmente, si todos los Yi derivan λ,
entonces λ se añade a FIRST(X).
FOLLOW:
Se define FOLLOW(A), para él no terminal A, como el conjunto de terminales a que pueden
aparecer inmediatamente a la derecha de A en alguna forma sentencia, es decir, el conjunto
de terminales a tal que haya una derivación de la forma S= * =>αAaβ para algún α y β. Si A
puede ser el símbolo de más a la derecha en alguna forma sentencia, entonces $ está en
FOLLOW(A).
Para calcular FOLLOW(A) para un símbolo no terminal A, se aplican las siguientes
reglas hasta que no se pueda añadir nada más al conjunto FOLLOW.
1. $ está en FOLLOW(S), siendo S el axioma de G.
2. Si existe una producción A → αBβ, entonces todo lo que esté en FIRST (β), excepto
λ, está en FOLLOW (B).
3. Si existe la producción A → αBβ y FIRST (β) contiene λ (es decir, β= * =>λ), o bien
si existe una producción A → αB, entonces todo lo que esté en FOLLOW(A) está en
FOLLOW (B).
Con las mismas notaciones anteriores, para cada forma sentencia α Є (V U ∑)*
definiremos la función FOLLOWG GK (α) del modo siguiente.
5.9 Manejo de errores sintácticos
Si un compilador tuviera que procesar sólo programas correctos, su diseño e
implementación se simplificarían mucho. Las primeras versiones de los programas suelen
ser incorrectas, y un buen compilador debería ayudar al programador a identificar y localizar
errores. Es más, considerar desde el principio el manejo de errores puede simplificar la
estructura de un compilador y mejorar su respuesta a los errores.
Los errores en la programación pueden ser de los siguientes tipos:

Léxicos: producidos al escribir mal un identificador, una palabra clave o un operador.

Sintácticos: por una expresión aritmética o paréntesis no equilibrados.

Semánticos: como un operador aplicado a un operando incompatible. • Lógicos,
puede ser una llamada infinitamente recursiva.

De corrección: cuando el programa no hace lo que el programador realmente
deseaba.
Errores de corrección no pueden ser detectados por un compilador, ya que en ellos
interviene el concepto abstracto que el programador tiene sobre el programa que
construye, lo cual es desconocido, y probablemente incognoscible, por el compilador. La
detección de errores lógicos implica un esfuerzo computacional muy grande en tanto que
el compilador debe ser capaz de averiguar los distintos flujos que puede seguir un programa
en ejecución lo cual, en muchos casos, no sólo es costoso, sino también imposible. Los
compiladores actuales se centran en el reconocimiento de los tres primeros tipos de
errores. Los errores de sintaxis, que son los que pueden impedir la correcta construcción de
un árbol sintáctico.
El manejo de errores de sintaxis es el más complicado desde el punto de vista de la creación
de compiladores. Nos interesa que cuando el compilador encuentre un error, no cancele
definitivamente la compilación, sino que se recupere y siga buscando errores. Recuperar un
error no quiere decir corregirlo, sino ser capaz de seguir construyendo el árbol sintáctico a
pesar de los errores encontrados. El manejador de errores de un analizador sintáctico debe
tener como objetivos:
Indicar los errores de forma clara y precisa. Debe informar mediante los correspondientes
mensajes del tipo de error y su localización
Recuperarse del error, para poder seguir examinando la entrada
Distinguir entre errores y advertencias. Las advertencias se suelen utilizar para informar
sobre sentencias válidas pero que, por ser poco frecuentes, pueden constituir una fuente
de errores lógicos
No ralentizar significativamente la compilación.
Un buen compilador debe conocer los errores que se pueden producir, con lo que se
consigue simplificar su estructura. Si el propio compilador está preparado para admitir
incluso los errores más frecuentes, entonces se puede mejorar la respuesta ante esos
errores incluso corrigiéndolos.
5.10 Generadores de analizadores sintácticos
YACC
Yacc convierte una gramática independiente del contexto y el código traducido en un
conjunto de tablas para un LR (1) analizador y traductor. La gramática puede ser ambigua;
reglas de prioridad especificados se utilizan para romper las ambigüedades.
El archivo de salida, y.tab.c, debe ser compilado por el compilador C para producir un
programa de yyparse. Este programa debe ser cargado con una función del Analizador
Léxico, yylex (void) (a menudo generada por la lex (1)), con un main (int argc, char * argv [])
del programa, y con la rutina de manejo de errores, yyerror (char *).
Descargar