Está en la página 1de 52

Tema 4.

Gramticas y Anlisis Sintctico


PARSER

Leccin 11,12,13
Gramticas Libres del Contexto

Compiladores (05/02/15 04:50)

- 4.1 -

Definicin de Gramtica
Una gramtica G es una tupla (T,N,I,P)
donde:

T conjunto de smbolos terminales.


N conjunto de smbolos no terminales.
Ismbolo inicial.
P conjunto de producciones.

Una produccin es de la forma


(T|N)+ (T|N)*
L={x T*| I * x} es el lenguaje

generado por la gramtica G.


es un paso de derivacin
si P

representa la aplicacin iterada de


*pasos de derivacin.
Notacin:
Letras maysculas representan smbolos no
terminales.
Letras minsculas representan smbolos
terminales.

Compiladores (05/02/15 04:50)

- 4.2 -

Ejemplo de Gramtica
La gramtica G=(N,T,I,P) donde,
N={I,A,B}
T={x,(,),+,-,*,/}
P={
II+I
II-I
IA
AA*A
AA/A
A(I)
Ax

Secuencias generadas por G:

x, x*x
x*x+x
x*(x/x)
x-x+x*x/x

Compiladores (05/02/15 04:50)

- 4.3 -

Pasos de Generacin
Secuencia: x*x+x

I+I

x*A+A

A+I
x*x+A

A*A+I

A*A+A

x*x+x

Arbol sintctico:
I

A
A *
x

Compiladores (05/02/15 04:50)

I
A

- 4.4 -

Clasificacin de las Gramticas


Regulares
Producciones:
N
N

Analizador: autmata finito determinista.


Complejidad del anlisis: lineal

Libres del Contexto


Producciones:
N

Analizador: autmata con pila.


Complejidad del anlisis: lineal

Dependientes del Contexto


Producciones:
, donde (T|N)* y ||

Complejidad del anlisis: exponencial

Generales
Complejidad del anlisis: no se puede con
memoria finita.

Compiladores (05/02/15 04:50)

- 4.5 -

Gramticas de los Lenguajes de


Programacin
Un lenguaje de programacin se puede
generar con una gramtica dependiente del
contexto.
Las declaraciones provocan la necesidad de
analizar el contexto.
No utilizaremos estas gramticas por la
complejidad temporal de su analizador.

Solucin:
Utilizar una gramtica libre del contexto
que tiene una complejidad lineal y dejar las
caractersticas del lenguaje dependientes
del contexto para el anlisis semntico.

Compiladores (05/02/15 04:50)

- 4.6 -

Notacin BNF Extendida


Regla BNF:
no terminal ::= expresin BNF

Terminal:
Forma nica: secuencia de caracteres que
lo forma.
Ej. if, +, then, for

Forma variable: nombre que lo identifica.


Ej. identificador, numero, string, carcter, literal

No Terminal: nombre entre < y >


Ej. <programa>, <lista de argumentos>,
<expresin>, <instruccin>

Secuencia vaca:
Operadores:

Unin: |
Secuencia:
Opcional: [ |
Repeticin: {}= | | | |...

Compiladores (05/02/15 04:50)

- 4.7 -

Ejemplo
Gramtica simplificada de la declaracin
de una variable en C.
<dec>::=<tipo> <var> {, <var>};
<tipo>::=[signed|unsigned] (int|char)
<var>::={*} identificador {[ nmero ]}
Smbolos terminales: signed, unsigned, int,
char, identificador, nmero, [, ], ,
Smbolos no terminales: <dec>, <tipo>,
<var>
Smbolo inicial: <dec>
Secuencias vlidas:
int a,**b[3][4];
unsigned char *p;
signed char str[100];

Compiladores (05/02/15 04:50)

- 4.8 -

Estructura Sintctica de un Lenguaje y su


Gramtica
Gramtica de expresiones aritmticas de
nmeros y variables. Operaciones: +,-, *, /,
- (cambio de signo), parntesis.
<expresin>::=[-]<operando>
{(+|-|*|/) [-]<operando>}
<operando>::=(<expresin>) |
identificador | nmero
Secuencias valida: a+10*30/(-bd+2)
Arbol sintctico generado para a+b*c
<expresin>
<operando> +

<operando>

* <operando>

identificador

identificador

identificador

Este rbol sintctico no representa el orden


en que se han de realizar + y *.
Compiladores (05/02/15 04:50)

- 4.9 -

Prioridad de las Operaciones y el Arbol


Sintctico
Nueva gramtica:
<expresin>::=<trmino>{(+|-) <trmino>}
<trmino>::=<factor>{(*|/) <factor>}
<factor>::=[-](( <expresin> ) |
identificador | nmero)
Arbol sintctico generado para a+b*c
<expresin>
<trmino>

<factor>

<factor>

identificado

<trmino>

identificador

<factor>
identificador

En este rbol cada operador se agrupa con


sus operandos y las operaciones ms
prioritarias estn ms abajo.

Compiladores (05/02/15 04:50)

- 4.10 -

Asociatividad y el Arbol Sintctico


Operacin asociativa:
abc = abc) = (ab)c Ej. +, *
Operacin asociativa por la izquierda:
abc = (ab)c

Ej. -, /

<operacin>::=<operando>{<operando>}
<operacin>
<operando> <operando> <operando>
Operacin asociativa por la derecha:
abc = abc)

Ej. = (asignacin)

<operacin>::=<operando>[<operacin>]
<operacin>
<operando>

<operacin>
<operando>

Compiladores (05/02/15 04:50)

<operando>

- 4.11 -

Ambigedad Gramatical
Una gramtica es ambigua si puede generar
una secuencia de smbolos con dos rboles
sintcticos diferentes.
Ejemplo: <a> ::= <a> (+ | *) <a> | nmero
Secuencia: 1*2+3
Arboles sintcticos generados:
<a>
<a>

<a>
<a>

nmero <a> + <a>


nmero nmero

<a> + <a>
<a> * <a> nmero
nmero nmero

Una gramtica no se puede utilizar para la


realizacin de un compilador por que no
especifica la estructura sintctica del
lenguaje.
Compiladores (05/02/15 04:50)

- 4.12 -

Diagramas Sintcticos
No Terminal

Diagrama sintctico de un
smbolo no terminal

No Terminal

Smbolo no terminal

Terminal

Smbolo Terminal

Ejemplo: <sumas>::= nmero {+ nmero}

sumas
nmero

nmero

Compiladores (05/02/15 04:50)

- 4.13 -

Ejemplo
Diagramas sintcticos para expresiones
aritmticas.
expresin

trmino
+
trmino

trmino

factor
*
factor
/
-

factor

identificador

factor

nmero
(

Compiladores (05/02/15 04:50)

expresin

- 4.14 -

Paso de BNF a Diagramas Sintcticos


A cada smbolo no terminal le corresponde una nica regla.
Por cada regla se crea un nico diagrama sintctico.
<no terminal>::= expresin BNF

Aplicar las siguientes reglas de conversin para pasar de la expresin BNF a su


diagrama sintctico.

No terminal

Diagrama sintctico
de la expresin BNF

<no terminal>

No Terminal

Terminal

Terminal

Compiladores (05/02/15 04:50)

- 4.15 -

Paso de BNF a Diagramas Sintcticos


n
Diag. sint.
de

Diag. sint.
de

Diag. sint.
de n

n
Diag. sint.
de
Diag. sint.
de

Diag. sint.
de n

Compiladores (05/02/15 04:50)

- 4.16 -

Paso de BNF a Diagramas Sintcticos

Diag. sint.
de

Diag. sint.
de

Compiladores (05/02/15 04:50)

- 4.17 -

Ejemplo de Paso de BNF a Diagrama


Sintctico
Gramtica de instrucciones PASCAL
simplificada:
<instruccin>::=
if <condicin> then <instruccin>
[else <instruccin>]

instruccin

Diagrama sintctico de
if <condicin> then <instruccin>
[else <instruccin>]

Compiladores (05/02/15 04:50)

- 4.18 -

Ejemplo de Paso de BNF a Diagrama


Sintctico
Diagrama sintctico de
if <condicin> then <instruccin> [else <instruccin>]

instruccin

Diag.

Diag.

Diag.

if

<condicin>

then

Diag.
<instruccin>

Diag.
[else <instruccin>]

Diag. if

if

Diag. then

then

Diag. <condicin>

condicin

Diag. <instruccin>

instruccin

Compiladores (05/02/15 04:50)

- 4.19 -

Ejemplo de Paso de BNF a Diagrama


Sintctico
Diag. [else <instruccin>]

Diag. sint. de

else <instruccin>

Diag. else <instruccin>

Diag.

Diag.

else

<instruccin>

Diag. else

else

Diag. <instruccin>

instruccin

instruccin

if

condicin

else
Compiladores (05/02/15 04:50)

then

instruccin

instruccin
- 4.20 -

Gramtica LL(1) Simple


Un parser para gramticas libres de
contexto debe utilizar Backtracking
Reducir las gramticas utilizables a
aquellas que permitan un reconocimiento
determinista, en base al primer smbolo
terminal de la secuencia.
Una gramtica LL(1) simple es aquella
gramtica libre de contexto sin reglas y
para cada smbolo A N las alternativas
para A empiezan con un smbolo terminal
distinto.
A a11| a22 ... | ann , ai aj para i j y ai
T para 1 i n

Compiladores (05/02/15 04:50)

- 4.21 -

Ejemplo de Gramticas LL(1) Simple


Ejemplo:
S aS
S bA
A d
A ccA

Reconocer:
aabccd

Compiladores (05/02/15 04:50)

- 4.22 -

Conjunto de Primeros de una Secuencia de


Terminales y no Terminales
Primeros: concepto

T+ Primero() = { x | x... y x T}

Gramtica LL(1) sin reglas es:


una gramtica libre de contexto en la que para todas
las reglas de la forma A 1| 2 ... | n , los
conjuntos Primero(1), Primero(2),..., Primero(n)
son disjuntos.

Primero(i) Primero(j) = i j

Ejemplo:
S ABe
SC
A dB
A aS
A c
B AS
Bb
Cb

Compiladores (05/02/15 04:50)

Primero(S) = {a,b,c,d}
Primero(A) = {a,c,d}

Primero(B) = {a,b,c,d}
Primero(C) = {b}

- 4.23 -

Gramticas LL(1) con reglas


Primeros: concepto (T|N)+

*
Primero() = { | ...
y T}

Siguientes: concepto N
*
Siguiente() = { | S
Primero() y
S es el smbolo inicial y
T}

Gramtica LL(1) con reglas es una


gramtica libre de contexto en la que para
cada par de reglas de la forma A y A
se cumple que:
Primero(Siguiente(A))
Primero(Siguiente(A)) =
O lo que es lo mismo, para todas las reglas
de la forma A 1| 2 ... | n :
Primero(i) Primero(j) = i j
y si i , entonces
*
Primero(
j) Siguiente() = j1..n

Compiladores (05/02/15 04:50)

- 4.24 -

Clculo del Conjunto de Smbolos


Anulables
Un smbolo N es anulable si y solo si
*
Clculo del conjunto de Smbolos
Anulables:
Anulables0={N| A }
Repetir
Anulablesn+1=Anulablesn
{BN| A12 ...m y
im iAnulablesn}
Hasta que Anulablesn==Anulablesn+1

Compiladores (05/02/15 04:50)

- 4.25 -

Ejemplo: Clculo del Conjunto de


Smbolos Anulables
Gramtica:
IDIa
IvI
Af

B+I

CAB
DCA

Aplicacin del Algoritmo


Anulables0={A,B}
Anulables1={A,B,C}
Anulables2={A,B,C,D}

Compiladores (05/02/15 04:50)

- 4.26 -

Clculo del Conjunto de Primeros


de los no Terminales
A
Si AAnulables entonces P0(A)={
sino P0(A)=
Repetir produccin A de G
Pn+1(A)= Pn(A) PrimerosDe
Hasta que APn(A)== Pn+1(A)
PrimerosDe(}
PrimerosDe(a)={a}
PrimerosDe(A)= AN
si Pn(A) entonces

,aT

(Pn(A)-{})PrimerosDe()
sino Pn(A)

Compiladores (05/02/15 04:50)

- 4.27 -

Ejemplo de Clculo de Primeros


Gramtica:
I
TFC
B+TB|-TB|
Fx
C*FC|/FC|
Anulables={B,C}

Clculo del conjunto de primeros


P(I)


2
3 {x}
4 {x}

P(T) P(B)
{} {}
{}
{x}
{x} {}
{x} {}
{x} {}

Compiladores (05/02/15 04:50)

P(F) P(C)
{}
{x} {}
{x} {}
{x} {}

- 4.28 -

Clculo del Conjunto de Siguientes


A
Si A es el inicial entonces S0(A)={
sino S0(A)=
Repetir produccin A B de G
Sn+1(B)= Sn(B) PrimerosDe
si PrimerosDe) entonces
Sn(A)
sino
Hasta que ASn(A)== Sn+1(A)

Compiladores (05/02/15 04:50)

- 4.29 -

Ejemplo de Clculo de Siguientes


Gramtica:
I
TFC
B+TB|-TB|
Fx
C*FC|/FC|

Primeros
P(I)
{x}

P(T) P(B)
{x} {}

P(F) P(C)
{x} {}

Clculo del conjunto de siguientes

S(I) S(T)
S(B) S(F)
S(C)
{}
{} {} {} {}
{} {} {} {} {}
{} {} {} {} {}

Compiladores (05/02/15 04:50)

- 4.30 -

Clculo de Primeros y Siguientes en BNF


Primeros:
P(n)=P()
P(n)=P()P()P(n)
P([])=P()P()
P({})=P()P()
P() en <A>::= ... es S(<A>)
Siguientes

S( A )

P()

X : A

Problema:
Estas definiciones generan recursividades
infinitas que tras su estudio se pueden eliminar

Compiladores (05/02/15 04:50)

- 4.31 -

Analizador Sintctico Dirigido por Tabla


Simbolo Terminal t;
Parser(n) {
if (prediccin[t,n]==E) error();
p=Producciones[prediccin[t,n]];
while (p!=NULL) {
if (p->symT)
if (t==p->sym) t=leer_smbolo();
else error();
else Parser(p->sym);
p=p->siguiente;
}
}

Producciones[P]: tabla donde los smbolos


de cada produccin forman una lista
encadenada
sym

siguiente

prediccin[T,N]: tabla que dado un


smbolo no terminal y el terminal ledo
especifica que produccin hay que aplicar.

Compiladores (05/02/15 04:50)

- 4.32 -

Ejemplo: Analizador Sintctico Dirigido


por Tabla
Gramtica
I
TFC
B+TB|-TB|
Fx
C*FC|/FC|

Tabla de Producciones
1

5
6

Compiladores (05/02/15 04:50)

- 4.33 -

Ejemplo: Analizador Sintctico Dirigido


por Tabla
Clculo de la tabla de prediccin
prediccin[t,n]=E si no hay ninguna
produccin de n cuyos primeros contengan
t.
prediccin[t,n]=al nmero de produccin
de n tal que t pertenezca a sus primeros

Tabla de prediccin

No terminales

Terminales
+

Compiladores (05/02/15 04:50)

- 4.34 -

Construccin de un Parser a Partir de los


Diagramas Sintcticos (I)
Programa principal
Smbolo SLA; /* Smbolo ledo */
main() {
SLA=leer_smbolo();
Inicial();
if (SLA!=) Error();
}

Compiladores (05/02/15 04:50)

- 4.35 -

Construccin de un Parser a Partir de los


Diagramas Sintcticos (II)
No terminal
Diagrama sintctico
del No terminal

noterminal ( ) {
Parser[Diagrama sintctico]
};
Diag. sint.
de

Diag. sint.
de

Diag. sint.
de n

{
Parser[
Parser[
...
Parser[n
}
Compiladores (05/02/15 04:50)

- 4.36 -

Construccin de un Parser a Partir de los


Diagramas Sintcticos (III)
Diag. sint.
de
Diag. sint.
de

Diag. sint.
de n

switch (SLA) {
case ( Primero()) : Parser[] break;
case (Primero()) : Parser[] break;
...
case (Primero(n)) : Parser[n] break;
default: error();
}

Compiladores (05/02/15 04:50)

- 4.37 -

Construccin de un Parser a Partir de los


Diagramas Sintcticos (VI)

Diag. sint.
de

while (SLAPrimero() )
Parser[

No Terminal

Noterminal( );
Terminal

if (SLA == Terminal) leer_smbolo();


else error()

Compiladores (05/02/15 04:50)

- 4.38 -

Construccin de un Parser a Partir de la


Descripcin BNF (I)
Programa principal
Simbolo SLA; /* Simbolo leido */
main() {
SLA=leer_smbolo();
Inicial();
if (SLA!=) Error();
}
<no terminal>::= expresin BNF
no_terminal ( ) {
Parser[expresin BNF]
};

Compiladores (05/02/15 04:50)

- 4.39 -

Construccin de un Parser a Partir de la


Descripcin BNF (II)
Parser[n]
{
Parser[
Parser[
...
Parser[n
}

Parser[n]
switch (SLA) {
case ( Primero()) : Parser[] break;
case (Primero()) : Parser[] break;
...
case (Primero(n)) : Parser[n] break;
default: error();
}

Compiladores (05/02/15 04:50)

- 4.40 -

Construccin de un Parser a partir de la


descripcin BNF (III)
Parser[{}]
while (SLAPrimero() )
Parser[
Parser[<no terminal>]
Noterminal( );
Parser[ Terminal]
if (SLA== Terminal) leer_smbolo();
else error();

Compiladores (05/02/15 04:50)

- 4.41 -

Tratamiento de los Errores en Anlisis


Descendente
Tratamiento de errores:
Detectar slo el primero
Detectar el mximo (razonable)
Sincronizar despus del error
Prever errores tpicos y cambiar la
gramtica a otra que los acepte dando
warnings.
Corregir el error: Decidir cual ha sido el
error y reconstruir el programa fuente
eliminando dicho error

Consideraciones:
No se pueden solucionar correctamente
todos los casos.
Hay que considerar la psicologa del
programador.
Como mnimo tratar correctamente los
errores ms comunes.
Minimizar:
Error no detectados
Falsas alarmas

Compiladores (05/02/15 04:50)

- 4.42 -

Sincronizacin Despus de Error


Despus de un error se leen smbolos hasta
encontrar uno que pertenezca al conjunto
de sincronizacin
Saltar smbolos hasta encontrar uno
correcto y continuar (se supone que era
cdigo adicional errneo)
Saltar smbolos hasta encontrar uno
correcto como siguiente del smbolo no
terminal que se est analizando y retornar
para continuar con ese smbolo siguiente
(se supone que falta un trozo y se continua
en un nivel superior)

El conjunto de sincronizacin se puede


formar a partir del clculo de los smbolos
que pueden seguir a un momento dado del
anlisis sintctico.
Acumular los smbolos de estructuras
mayores en el conjunto de sincronizacin.

Compiladores (05/02/15 04:50)

- 4.43 -

Correccin de Errores
Despus de un error aadir o quitar
smbolos hasta poder continuar el anlisis
sintctico.
Aadir: ir hacia delante dentro de la
gramtica.
Quitar: ir hacia atrs dentro de la
gramtica.

En el caso que varias correcciones sean


vlidas se seleccionar la de menor peso.
Ponderacin de la secuencia:
A cada insercin de un smbolo se le asocia
un peso segn lo fcil que sea dejarselo.
A cada eliminacin de un smbolo se le
asocia un peso segn lo fcil que sea
ponerlo de ms.

Compiladores (05/02/15 04:50)

- 4.44 -

Tema 4. Anlisis Sintctico Ascendente


(Bottom-Up)

Lecciones 17,18

Compiladores (05/02/15 04:50)

- 4.45 -

Anlisis Sintctico Ascendente


(Bottom-Up)
Un analizador sintctico ascendente
construye el rbol sintctico de abajo a
arriba, por lo tanto
parte de los smbolos terminales que agrupan
o reducen en smbolos no terminales

Ejemplo
Gramtica
II+I | I-IA
AA*A | A/A(I) |num

Expresin 1+2*3
Derivacin: I => I+I => num+I => num+A =>
num+A*A => num+num*A => num+num*num
La reduccin de smbolos supone ir de derecha a
izquierda en los pasos de derivacin
1 + 2 * 3
num+num*num

A
I
Compiladores (05/02/15 04:50)

- 4.46 -

Gramticas LR(k)
El conjunto de las gramticas LR(k) es el
conjunto de las gramticas libres del
contexto no ambiguas
El conjunto de las gramticas LR(k)
contiene las gramticas LL(k).
k es el nmero de smbolos que hay que
considerar hacia delante antes de que el
analizador sintctico realice una accin.
Solo se consideran las gramticas LR(0) y
LR(1) ya que para k>1 el anlisis tiende ha
ser demasiado costoso.

Familias de gramticas
demasiado costoso

LR(k)
LR(1)

equivalentes
por transformacin

LALR(1)
SLR(1)
demasiado simple
Compiladores (05/02/15 04:50)

LL(1)

LR(0)
- 4.47 -

Bases del Anlisis Sintctico con


Gramticas LR(k) (I)
Derivacin de ms a la derecha (rightmost
derivation) de una secuencia de smbolos
X es
I => 1 => 2 => 1 =>...=> m = X
donde para todo i [1..m-1]
Bt => t, i= Bt, BP,

t T*

Como ha de actuar el analizador de una


gramtica LR(k)
es una secuencia de smbolos terminales
y no terminales donde se han realizado
todas las reducciones posibles.
es la nueva reduccin que podemos
realizar y la sustituimos por el smbolo no
terminal B que la genera
t es el resto de smbolos de la secuencia
que faltan por procesar.
La decisin de que reduccin se ha de
realizar se toma en base a y a los k
primeros smbolos de t si la gramtica es
LR(k).

Compiladores (05/02/15 04:50)

- 4.48 -

Bases del Anlisis Sintctico con


Gramticas LR(k) (II)
Knuth demostr que se pueden reconocer
los prefijos vlidos mediante un
autmata finito.
hay que considerar que el nmero de
prefijos puede ser infinito.
Una vez reconocido el prefijo y ledos los
k primeros smbolos de t hay una nica
reduccin vlida a aplicar.

Como es un parser LR
Es una mquina con
como entrada la secuencia a analizar
una pila
un mecanismo de control finito formado
por:
estados de lectura
Lee un smbolo, lo pone en la pila y salta a
un nuevo estado

estados reductores no es necesario


sustituyen la secuencia que encuentra en
la pila por B.

un estado inicial

Compiladores (05/02/15 04:50)

- 4.49 -

Gramtica LR(0)
Gramtica

Estado reductor

SE#
ET | E+T | E - T
Ti | (E)

T
+

EE+T

SE#

Estado de lectura

Ti

EE-T

T
2

ET

Compiladores (05/02/15 04:50)

T
(

10

11

T(E)

- 4.50 -

Trazado
Secuencia: i-(i+i)#
Paso

Pila

Entrada Prefijo

Grupo

i-(i+i)#

0 i3

-(i+i)#

0 T2

-(i+i)#

0 E1

-(i+i)#

0 E1 -7

(i+i)#

E-

0 E1 -7 (4

i+i)#

E-(

0 E1 -7 (4 i3

+i)#

E-(i

0 E1 -7 (4 T2

+i)#

E-(T

0 E1 -7 (4 E10

+i)#

E-(E

0 E1 -7 (4 E10 +6

i)#

E-(E+

10

0 E1 -7 (4 E10 +6 i3

)#

E-(E+i

11

0 E1 -7 (4 E10 +6 T8

)#

E-(E+T E+T

12

0 E1 -7 (4 E10

)#

E-(E

E+T

13

0 E1 -7 (4 E10 )11

E-(E)

(E)

14

0 E1 -7 T9

E-T

E-T

15

0 E1

16

0 E1 #5

17

E#
Aceptado

Compiladores (05/02/15 04:50)

- 4.51 -

Gramticas no LR(0)
Gramtica LR(0)
SE#
ET | E+T | E - T
Ti | (E)

Gramtica No LR(0)
S E#
E E - T
ET
T F ^ T
TF
F (E)
Fi

Para aplicar una de estas


dos reducciones hay que
leer el siguiente smbolo

Gramticas SLR(1), LR(1), LALR(1):


Se decide cual es el estado siguiente de una
reduccin a partir del estado de la pila y el
smbolo ledo hacia delante
Los tres tipos de gramticas se diferencian
en el tratamiento del smbolo ledo hacia
delante.

Compiladores (05/02/15 04:50)

- 4.52 -

También podría gustarte