Facultad de Ingeniería de SistemasFacultad de Ingeniería de Sistemas
Lenguajes y Compiladores
Análisis Sintáctico
Parte I
Teoría Lenguajes
1
Parte I
IntroducciónIntroducción
� El analizador sintáctico recibe una secuencia de tokens y decide si la secuencia está correcta o no.
� Los analizadores más usados están basados en un análisis que puede ser descendente o ascendente. Para realizar este análisis se deben construir los árboles sintácticos (derivación).
Teoría Lenguajes2
árboles sintácticos (derivación).� Dificultad: Búsqueda de la regla a aplicar, esto se
efectúa analizando la cadena de entrada de izquierda a derecha.
� Los analizadores sintácticos más eficientes se basan en gramáticas LL y LR.
IntroducciónIntroducción
� Los árboles sintácticos en la práctica son realmente difíciles de construir porque ocuparían mucho espacio. Alternativamente se usan pilas.
� En la Pila se guarda información sobre los nodos del árbol sintáctico relevantes en cada fase del proceso.
Teoría Lenguajes3
árbol sintáctico relevantes en cada fase del proceso.
� Para el caso descendente: en la pila se guardan los nodos no expandidos.
Análisis descendenteAnálisis descendente
� Se basa en gramáticas LL que evitan los bloqueos mutuos.
� Para evitar los bloqueos mutuos será necesario cumplir con la siguiente regla:Para producciones de la forma
A →→→→ αααα αααα αααα . . . αααα
Teoría Lenguajes4
A →→→→ αααα1 αααα2 αααα3 . . . ααααn
Siempre se debe poder escoger la alternativa correcta para la generación del árbol sintáctico.
Intuitivamente, para escoger la alternativa correcta necesitamos que todos los símbolos iniciales de los αisean diferentes (Conjunto First/Primero).
Análisis DescendenteAnálisis Descendente
� Para aplicar los métodos de análisis descendente las gramáticas deben cumplir dos condiciones:� No deben tener recursividad por la izquierda
� Se debe conocer el conjunto First de cada no terminal y deben cumplir las siguientes condiciones:
Teoría Lenguajes5
y deben cumplir las siguientes condiciones:» El conjunto First para un no terminal debe tener un terminal diferente para cada alternativa.
» El conjunto First de dos no terminales deben tener una intersección igual a ΦΦΦΦ.
Análisis Descendente PredictivoAnálisis Descendente Predictivo
� Una forma eficiente de un analizador sintáctico descendente sin retroceso es el denominado Analizador sintáctico predictivo.
� Preliminar:
Dado un símbolo de entrada a y el no terminal A con
Teoría Lenguajes6
Dado un símbolo de entrada a y el no terminal A con la siguiente producción:
A →→→→ αααα1 αααα2 αααα3 . . . ααααn
es necesario conocer la única alternativa que comienza con el símbolo a..
Análisis Descendente PredictivoAnálisis Descendente Predictivo
Ejemplo:comando → if expresión then comando else comando
begin ListaComando endrepeat ListaComados until expresión
Cada alternativa tiene un inicio diferente que permite escoger la opción adecuada, es decir si tenemos el
Teoría Lenguajes7
escoger la opción adecuada, es decir si tenemos el símbolo de entrada repeat debemos usar la tercera alternativa.
� Existen los métodos:� Análisis descendente recursivo (análisis predictivo)� Análisis predictivo no recursivo
Análisis descendente recursivo (ARD)Análisis descendente recursivo (ARD)
� Método descendente en el que se ejecuta un conjunto de métodos recursivos para procesar la entrada.
� A cada no terminal de la gramática se asocia un método.
� La secuencia de métodos llamados durante el procesamiento de la entrada define implícitamente un
Teoría Lenguajes8
procesamiento de la entrada define implícitamente un árbol de análisis sintáctico.
� Adicionalmente se tiene:» Un método de tratamiento de error
» Un método de lectura de un símbolo de entrada (léxico)
Análisis descendente recursivo (ADR)Análisis descendente recursivo (ADR)
� Para una gramática:G = (T, N, P, S)
N = {S, N1, N2, N3}� En la siguiente diapositiva se muestra el esquema de
un analizador sintáctico descendente recursivo.
Teoría Lenguajes9
un analizador sintáctico descendente recursivo.
� En este esquema los métodos se muestran sin parámetros pero considerando que en su mayoría son recursivos, normalmente requieren parámetros.
Esquema para ADREsquema para ADR
Programa Analizador sintácticoMétodo ErrorMétodo LéxicoMétodo SMétodo N1Método N2
Teoría Lenguajes10
Método N2Método N3
Inicio
Léxico
SFin
Tareas de un ADRTareas de un ADR
� Cada método de un analizador descendente recursivo realiza dos tareas:� Decide la producción a usar analizando el símbolo de
entrada. Si el símbolo de entrada pertenece a First(N) entonces se usa la producción con lado derecho N.
Si hay un conflicto entre dos lados derechos entonces en esta gramática no se puede usar
Teoría Lenguajes11
entonces en esta gramática no se puede usar el método descendente recursivo.
� Usa una producción imitando el lado derecho:
»Un no terminal resulta en la llamada al método asociado
»Un terminal coincidente al símbolo de entrada hace que se lea el siguiente componente léxico.
Ejemplo de ADREjemplo de ADR
� Ejemplo de un analizador descendente recursivo.
� Dada la siguiente gramática:
tipo → simple↑↑↑↑ id array [ simple ] of tipo
Teoría Lenguajes12
array [ simple ] of tiposimple → integer
char num punto num
Se tendrían los siguientes métodos:
Ejemplo de ADREjemplo de ADR
Metodo Empareja(t)si Entrada = tentonces Lexico (Entrada)sino Error
fmetodo
Teoría Lenguajes13
fmetodo
Método ErrorEscribir (‘Error de sintáxis’)
fmetodo
Ejemplo de ADREjemplo de ADR
Método Tipocaso Entrada vale‘integer’ , ‘char’ , ‘num’ : simple‘↑↑↑↑’: Empareja(‘↑↑↑↑’) Empareja(‘ id’ )‘array’ : Empareja(‘array’ ) Empareja(‘[‘)
Teoría Lenguajes14
‘array’ : Empareja(‘array’ ) Empareja(‘[‘)simpleEmpareja(‘]’) Empareja(‘of ’)tipo
otro: Errorfmetodo
Ejemplo de ADREjemplo de ADR
Método Simplecaso Entrada vale‘integer’ : Empareja( ‘integer ’)‘char’ : Empareja(‘char’ ) ‘num’ : Empareja(‘num’ )
Teoría Lenguajes15
‘num’ : Empareja(‘num’ )Empareja(‘punto ‘)Empareja(‘num ’)
otro: Errorfmetodo
Especificación de un ADREspecificación de un ADR
� Para especificar un ADR se deben tener en cuenta algunas reglas.
� Para tipo de producción se deberá crear un método con una estructura diferente.
� Es necesario verificar si la producción tiene:
Teoría Lenguajes16
� Es necesario verificar si la producción tiene:� Varias alternativas
� Repetición
� Opcionalidad
� A seguir se presentan las estructuras de los métodos de acuerdo al tipo de producción.
Especificación de un ADREspecificación de un ADR
� Para producciones del tipo: A →→→→ αααα1 αααα2 αααα3 . . . ααααn
si Entrada en Primero( αααα1) entonces Método αααα1
sino si Entrada en Primero( αααα2) entonces Método αααα2
....sino si Entrada en Primero( ααααn) entonces Método ααααn
Teoría Lenguajes17
sino si Entrada en Primero( ααααn) entonces Método ααααn
sino Errorfsi
... fsi
fsi
Especificación de un ADREspecificación de un ADR
� Para Producciones: A → α1 α2 α3 . . . αn
Método αααα1
Método αααα2
Teoría Lenguajes18
Método αααα2
Método αααα3
...Método ααααn
Especificación de un ADREspecificación de un ADR
� Para Producciones: A → α1 A ε
mientras Entrada en Primero( αααα1)hacer
Método αααα1
Teoría Lenguajes19
Método αααα1
fmientras
� Para Producciones: A → α1
Método αααα1
Especificación de un ADREspecificación de un ADR
� Para Producciones: A → α1 ε
si Entrada en Primero( αααα1)entonces Método αααα1
fsi
Teoría Lenguajes20
� Para Producciones: A → t t ∈ T*
Si Entrada = ‘t’ entonces Léxicosino Error
fsi
Uso de Diagramas de transiciónUso de Diagramas de transición
� Se puede realizar un analizador sintáctico predictivo usando diagramas de transiciones.
� El comportamiento para estos diagramas de transiciones es similar al diagrama usado en el léxico, cuando el símbolo usado para la transición es un
Teoría Lenguajes21
cuando el símbolo usado para la transición es un símbolo terminal.
� Tienen un comportamiento especial cuando la transición se produce con un símbolo no terminal
Ejemplo de Diagrama de transiciónEjemplo de Diagrama de transición
� Ejemplo:
tipo → simple ↑↑↑↑ id array [ simple] of tipo
simple1
Teoría Lenguajes22
02
id
4 5 6 7 8
array
[ simple]
of tipo
3
9
Diagrama de transiciónDiagrama de transición
� Características de un diagrama de transición para analizadores sintácticos:� Existe un diagrama para cada no terminal
� Las transiciones están determinadas por un token y no por un símbolo del alfabeto
Teoría Lenguajes23
por un símbolo del alfabeto
� La transición usando un token cambia el estado del autómata
� La transición usando un no terminal A es una llamada al método para A (otro diagrama).
Creación de Diagramas de transiciónCreación de Diagramas de transición
� Eliminar la recursión por la izquierda
� Para cada no terminal A:� Se crea un estado inicial y un estado final
� Para cada producción A → X1 X2 X3 .... Xn se crea un camino del estado inicial al estado final con las aristas
Teoría Lenguajes24
camino del estado inicial al estado final con las aristas etiquetadas con X1, X2 , X3 , .... , Xn
0 1 3 4 n-1X1 X2
X2
Xn
n...
Funcionamiento del Diagrama de transicionesFuncionamiento del Diagrama de transiciones
� Si e es terminal, entonces se cambia al estado t y se
En el diagrama
t
es
Teoría Lenguajes25
� Si e es terminal, entonces se cambia al estado t y se continua con el siguiente símbolo de la entrada
� Si e es un no terminal, el analizador se traslada al estado inicial del diagrama asociado al no terminal e y no mueve la entrada. Cuando llega al estado final de e regresa al estado t.
� Si e = ε, se pasa al estado t sin mover la entrada.
Ejemplo de Diagrama de transicionesEjemplo de Diagrama de transiciones
� Para la gramática
E → T E’
E’ → + TE’εT → FT’
T’ → *FT’ ε
Teoría Lenguajes26
T’ → *FT’ εF → ( E ) id
� Los diagramas de transición correspondientes son:
Ejemplo de Diagrama de transicionesEjemplo de Diagrama de transiciones
0 1T E'
2E
3 4+ T
E' 65
Teoría Lenguajes27
+ T E'
ε
7 8F T'
9T
Ejemplo de Diagrama de transicionesEjemplo de Diagrama de transiciones
10 11* F
T' 1312
T'
ε
Teoría Lenguajes28
14 15( E
F 1716
)
id
Análisis Predictivo no recursivo (APNR)Análisis Predictivo no recursivo (APNR)
� Es posible construir un analizador sintáctico predictivo no recursivo (APNR) manteniendo una pila para no usar la recursividad.
� Estos analizadores buscan la producción a usar dentro de una tabla de análisis sintáctico.
Teoría Lenguajes29
dentro de una tabla de análisis sintáctico.
� También se conocen como analizadores sintácticos dirigidos por tablas.
� Un método descendente dirigido por tablas es el método que se basa en gramáticas LL(1)
Análisis Predictivo no recursivo (APNR)Análisis Predictivo no recursivo (APNR)
a + b $
Salida
Entrada
Pila
Teoría Lenguajes30
Parser predictivo
Tabla M paraParser$
Z
Y
XSalidaPila
Análisis Predictivo no recursivo (APNR)Análisis Predictivo no recursivo (APNR)
� $ es usado:� Como último carácter de entrada
� Como Fondo de la pila
� Inicialmente en la pila está el símbolo inicial sobre el $
Teoría Lenguajes31
$
� M es una matriz cuyo valor indica la producción a usar, es decir M[A, a] = Producción a usar con A no terminal y a
terminal
Acciones del APNRAcciones del APNR
� Dependiendo del elemento de la entrada (a) y el elemento que se encuentre en el tope de la pila (X), el analizador realizará una acción diferente:� Si X = a = $
entonces Fin de análisis sintáctico
Teoría Lenguajes32
entonces Fin de análisis sintáctico
� Si X = a ≠ $
entonces desempilar X y pedir otro token
� Si X ∈ N y M[X, a] = X → Y1 Y2 …Ym , Yi ∈ (N ∪ T) entonces Desempila X Empila Ym … Y2 Y1
� El algoritmo podría ser:
Ejemplo de un APNREjemplo de un APNR
Repetir si X en T entonces si X = a
entonces DesempilarLéxico
sino Error
Teoría Lenguajes33
sino Errorsino si M[X, a] = X →→→→ Y1 Y2 …Ym , Yi
entonces Desempila X Empila Y m... EmpilaY 2 EmpilaY 1
sino Errorhasta (X = $) y (a = $)
Gramáticas LL(1)Gramáticas LL(1)
� Son gramáticas con condiciones especiales que permiten realizar un análisis sintáctico descendente no recursivo conocido con el nombre de parser LL(1).� L se examina la cadena de entrada de izquierda a
derecha
Teoría Lenguajes34
derecha
� L usa la derivación mas a la izquierda
� 1 sólo necesita un símbolo de la entrada
Parser LL(1)Parser LL(1)
� Para la siguiente gramática:
1. E → T E’
2. T → F T'3. F → ( E )
4. F → a
Teoría Lenguajes35
4. F → a 5. E' → + T E’
6. E' → ε7. T' → * F T’
8. T' → ε
Parser LL(1)Parser LL(1)
� Se tiene la matriz M (los números representan el número asociado a la producción)
( a + * ) $
E 1 1
Teoría Lenguajes36
E 1 1
T 2 2
F 3 4
E' 5 6 6
T' 8 7 8 8
Parser LL(1)Parser LL(1)
Pila Entrada Regla usada
E a+a*a M[E,a] = 1
TE' a+a*a M[T,a] = 2
FT'E' a+a*a M[F,a] = 4
Para procesar a + a * a la pila sería
Teoría Lenguajes37
FT'E' a+a*a M[F,a] = 4
aT'E' a+a*a
T'E' +a*a M[T',+] = 8
E' + a*a M[E',+] = 5
+TE' +a *a
TE' a*a M[T,a] = 2
Parser LL(1)Parser LL(1)
FT'E' a*a M[F,a] = 4
aT'E' a*a
T'E' *a M[T',*] = 7
Pila Entrada Regla usada
Teoría Lenguajes38
T'E' *a M[T',*] = 7
*FT'E' *a
FT'E' a M[F,a] = 4
aT'E' a
T'E' ε M[T',$] = 8
E' ε M[E',$] = 6
ε ε
Parser LL(1)Parser LL(1)
� Para construir la matriz M es necesario realizar el cálculo de los :� Conjuntos First
� Conjuntos Follow
� Este tipo de matrices sólo es posible definirla, sin
Teoría Lenguajes39
� Este tipo de matrices sólo es posible definirla, sin ambiguedades para gramáticas LL(1)