Вы находитесь на странице: 1из 78

LENGUAJES Y COMPILADORES

Analisis Sintactico Descendente

Profesor: Carlos A. Ruiz De La Cruz Melo


Correo: zorroculto69@hotmail.com
INTRODUCCION
 El parser, o analizador sintáctico, obtiene una
cadena de tokens del analizador lexicográfico(scanner)
y verifica que esta secuencia pueda ser generada por la
gramática del lenguaje fuente

PROGRAMA FUENTE

ANALIZADOR
LEXICO
Dame el siguiente
siguiente
token
token ANALIZADOR
SINTACTICO
INTRODUCCION
 La sintaxis suele especificarse a traves de una G.L.C.

 Se genera lógicamente un árbol de análisis (parse


tree). Físicamente en la práctica nunca se construyen
porque ocuparían mucho espacio, en su lugar se usan
como alternativa, pilas.

 El parser avisará de los errores de una forma


inteligible y capaz de recuperarse de aquellos errores
para continuar procesando el resto de la entrada
METODOS A UTILIZAR

Métodos de análisis universales

 CocKe-Younger-Kasami
 Earley
 Métodos ascendentes(botton-up) y descendentes
(top-down)
BOTTON-UP Y TOP-DOWN

 Los analizadores top-down


construyen el árbol de análisis
sintáctico desde el símbolo inicial
hasta describir la frase a reconocer,
mientras que los botton-up
comienzan por la frase a reconocer
subiendo hasta el símbolo inicial

 En ambos casos la cadena de entrada


se analiza de izquierda a derecha.
BOTTON-UP Y TOP-DOWN

Para una G=( Vn, Vt, P, S )

Análisis
S
Análisis
Descendente Ascendente
SVn , w  Vt*
(Top-down) (Botton-up)

w
CONDICIONES PARA UN TOP-DOWN
Las producciones de la G.L.C deben cumplir los
siguientes requisitos:

1. No debe existir recursividad por la


izquierda

2. Conocer el conjunto PRIMERO (First) de


cada Vn
CONDICION PARA UN CONJUNTO
FIRST
Para producciones de la forma

A  1 /2 /…. /n

A Vn , i ( Vn Vt )*

Escoger la producción correcta requiere


que todos los símbolos iniciales de
los i sean diferentes, si son
diferentes es lo que se conoce como
conjunto PRIMERO o First.
ANALISIS TOP-DOWN
Ejemplo 1
G=( Vn , Vt, P, S)
Vn={ S, I, C} Vt = { while, if, else, do, {, }, ; }
P={ S  do { I }while C;
S  while C { I }
S  if C { I} else { I }
:
}
Observación

PRIMERO (S)= { do, while, if }


Al reconocer una frase

do{ a=0; }while(k>2);


TIPOS DE TOP-DOWN

Existen los métodos siguientes:

 Análisis Descendente Recursivo (ADR)


 Análisis Descendente Predictivo, no
recursivo (ADP)
ADR
 A cada Vn se le asocia un procedimiento

 Los procedimientos procesan la entrada.

 La llamada recursiva de los procedimientos genera el árbol de


análisis sintáctico.

 También se cuenta con procedimientos auxiliares para tratamiento de


error y representación del scanner.
ADR
Ejemplo 2

G=( Vn, Vt, P, S )


Vn = { S, A1, A2 }

Da lugar a los siguientes procedimientos:

Procedimiento S
Procedimiento A1
Procedimiento A2
Procedimientos
Procedimiento ERROR
adicionales
Procedimiento Léxico
ADR
Un procedimiento opera del siguiente modo

 Usa la producción A  con AVn, (Vn Vt)* si el


símbolo de entrada que se esta examinando pertenece
a PRIMERO(A)
 El procedimiento implementa el lado derecho de la
producción:

 Un Vn da lugar a que se invoque un procedimiento


 Un Vt que se lee y esta de acuerdo con la
gramática provoca la lectura del siguiente
símbolo.
ADR
Ejemplo 3
Se generará el ADR a partir de la
siguiente gramática

G=(Vn, Vt, P, E )
Vn={ E, T, F } Vt = { id, *, +, (, ) }
P= {
E  E+T / T
T  T*F / F
F  ( E ) / id A  A  ,   ( Vn  Vt ) * , A  V
}
A  A’ A , A’  Vn
A’  A’ |  a ,   ( Vn  Vt )
ADR
Se buscará primero eliminar la recursividad
G=(Vn, Vt, P, E )
Vn={ E, T, F } Vt = { id, *, +, (, ) }
P= {
E  TR A  A  ,   ( Vn  Vt ) * , A  V
R  +TR / 
A  A’ A , A’  Vn
T  FG
G  *FG /  A’  A’ |  a ,   ( Vn  Vt )
F  ( E ) / id
}
ADR
Tenemos tres procedimientos adicionales

 Uno para el léxico llamado léxico


 Otro para avisar de errores llamado error
 Y para verificar el patrón especificado por la
gramática denominado igual
ADR
E  TR
Procedimiento E( )
T()
R() R  +TR / 
finE

ProcedimientoR()
si( e = ‘+’) entonces T  FG
igual(‘+’)
Procedimiento F()
T() G  *FG /  case e
R()
finsi ‘(’ :igual(‘(’)
finR E()
F  ( E ) / id igual(‘)’)
ProcedimientoT( ) ‘id’ :igual(‘id’)
F() otro
G() error()
ProcedimientoG()
finT fin-case
si( e = ‘*’ ) entonces
igual(‘*’) finF
F()
G()
finsi
finG
ANALISIS DE UNA
SECUENCIA CON ADR
El final de cadena se
indica por un carácter $

Secuencia a ser
id * id $ analizada

Programa principal
que llama al
Programa principal
analizador léxico y
eLexico() luego al analizador
E() sintáctico (E)
finprincipal

id * id $

Primer símbolo a ser


procesado
ADR
Procedimiento E() ProcedimientoG() ProcedimientoIgual(t)
T() si( e = ‘*’ ) si e = t
R() igual(‘*’) e  lexico()
finE F() sino
G() error()
finsi Fin Igual
finG
ProcedimientoR()
si( e = ‘+’)
igual(‘+’) Procedimiento F()
T() case e
R()
‘(’ :igual(‘(’)
finsi
E()
finR
igual(‘)’)
‘id’ :igual(‘id’)

ProcedimientoT()
otro
error()
id * id $
F() fin-case
G() finF
finT
ADR
Procedimiento E() ProcedimientoG() ProcedimientoIgual(t)
T() si( e = ‘*’ ) si e = t
R() igual(‘*’) e  lexico()
finE F() sino
G() error()
finsi Fin Igual
finG
ProcedimientoR()
si( e = ‘+’)
igual(‘+’)
T() Procedimiento F()
R() case e
finsi ‘(’ :igual(‘(’)
finR E()
igual(‘)’)

ProcedimientoT()
‘id’ :igual(‘id’)
otro
id * id $
F() error()
G() fin-case
finT finF
ADR
Procedimiento E() ProcedimientoG() ProcedimientoIgual(t)
T() si( e = ‘*’ ) si e = t
R() igual(‘*’) e  lexico()
finE F() sino
G() error()
finsi Fin Igual
finG
ProcedimientoR()
si( e = ‘+’)
igual(‘+’)
T() Procedimiento F()
R() case e
finsi ‘(’ :igual(‘(’)
finR E()
igual(‘)’)

ProcedimientoT()
‘id’ :igual(‘id’)
otro
id * id $
F() error()
G() fin-case
finT finF
ADR
Procedimiento E() ProcedimientoG() ProcedimientoIgual(t)
T() si( e = ‘*’ ) si e = t
R() igual(‘*’) e  lexico()
finE F() sino
G() error()
finsi Fin Igual
finG
ProcedimientoR()
si( e = ‘+’)
igual(‘+’)
T() Procedimiento F()
R() case e
finsi ‘(’ :igual(‘(’)
finR E()
igual(‘)’)

ProcedimientoT()
‘id’ :igual(‘id’)
otro
id * id $
F() error()
G() fin-case
finT finF
ADR
Procedimiento E() ProcedimientoG() ProcedimientoIgual(t)
T() si( e = ‘*’ ) si e = t
R() igual(‘*’) e  lexico()
finE F() sino
G() error()
finsi Fin Igual
finG
ProcedimientoR()
si( e = ‘+’)
igual(‘+’)
T() Procedimiento F()
R() case e
finsi ‘(’ :igual(‘(’)
finR E()
igual(‘)’)

ProcedimientoT()
‘id’ :igual(‘id’)
otro
id * id $
F() error()
G() fin-case
finT finF
ADR
Procedimiento E() ProcedimientoG() ProcedimientoIgual(t)
T() si( e = ‘*’ ) si e = t
R() igual(‘*’) e  lexico()
finE F() sino
G() error()
finsi Fin Igual
finG
ProcedimientoR()
si( e = ‘+’)
igual(‘+’)
T() Procedimiento F()
R() case e
finsi ‘(’ :igual(‘(’)
finR E()
igual(‘)’)

ProcedimientoT()
‘id’ :igual(‘id’)
otro
id * id $
F() error()
G() fin-case
finT finF
ADR
Procedimiento E() ProcedimientoG() ProcedimientoIgual(t)
T() si( e = ‘*’ ) si e = t
R() igual(‘*’) e  lexico()
finE F() sino
G() error()
finsi Fin Igual
finG
ProcedimientoR()
si( e = ‘+’)
igual(‘+’)
T() Procedimiento F()
R() case e
finsi ‘(’ :igual(‘(’)
finR E()
igual(‘)’)

ProcedimientoT()
‘id’ :igual(‘id’)
otro
id * id $
F() error()
G() fin-case
finT finF
ADR
Procedimiento E() ProcedimientoG() ProcedimientoIgual(t)
T() si( e = ‘*’ ) si e = t
R() igual(‘*’) e  lexico()
finE F() sino
G() error()
finsi Fin Igual
finG
ProcedimientoR()
si( e = ‘+’)
igual(‘+’)
T() Procedimiento F()
R() case e
finsi ‘(’ :igual(‘(’)
finR E()
igual(‘)’)

ProcedimientoT()
‘id’ :igual(‘id’)
otro
id * id $
F() error()
G() fin-case
finT finF
ADR
Procedimiento E() ProcedimientoG() ProcedimientoIgual(t)
T() si( e = ‘*’ ) si e = t
R() igual(‘*’) e  lexico()
finE F() sino
G() error()
finsi Fin Igual
finG
ProcedimientoR()
si( e = ‘+’)
igual(‘+’)
T() Procedimiento F()
R() case e
finsi ‘(’ :igual(‘(’)
finR E()
igual(‘)’)

ProcedimientoT()
‘id’ :igual(‘id’)
otro
id * id $
F() error()
G() fin-case
finT finF
ADR
Procedimiento E() ProcedimientoG() ProcedimientoIgual(t)
T() si( e = ‘*’ ) si e = t
R() igual(‘*’) e  lexico()
finE F() sino
G() error()
finsi Fin Igual
finG
ProcedimientoR()
si( e = ‘+’)
igual(‘+’)
T() Procedimiento F()
R() case e
finsi ‘(’ :igual(‘(’)
finR E()
igual(‘)’)

ProcedimientoT()
‘id’ :igual(‘id’)
otro
id * id $
F() error()
G() fin-case
finT finF
ADR
Procedimiento E() ProcedimientoG() ProcedimientoIgual(t)
T() si( e = ‘*’ ) si e = t
R() igual(‘*’) e  lexico()
finE F() sino
G() error()
finsi Fin Igual
finG
ProcedimientoR()
si( e = ‘+’)
igual(‘+’)
T() Procedimiento F()
R() case e
finsi ‘(’ :igual(‘(’)
finR E()
igual(‘)’)

ProcedimientoT()
‘id’ :igual(‘id’)
otro
id * id $
F() error()
G() fin-case
finT finF
ADR
Procedimiento E() ProcedimientoG() ProcedimientoIgual(t)
T() si( e = ‘*’ ) si e = t
R() igual(‘*’) e  lexico()
finE F() sino
G() error()
finsi Fin Igual
finG
ProcedimientoR()
si( e = ‘+’)
igual(‘+’)
T() Procedimiento F()
R() case e
finsi ‘(’ :igual(‘(’)
finR E()
igual(‘)’)

ProcedimientoT()
‘id’ :igual(‘id’)
otro
id * id $
F() error()
G() fin-case
finT finF
ADR
Procedimiento E() ProcedimientoG() ProcedimientoIgual(t)
T() si( e = ‘*’ ) si e = t
R() igual(‘*’) e  lexico()
finE F() sino
G() error()
finsi Fin Igual
finG
ProcedimientoR()
si( e = ‘+’)
igual(‘+’)
T() Procedimiento F()
R() case e
finsi ‘(’ :igual(‘(’)
finR E()
igual(‘)’)

ProcedimientoT()
‘id’ :igual(‘id’)
otro
id * id $
F() error()
G() fin-case
finT finF
ADR
Procedimiento E() ProcedimientoG() ProcedimientoIgual(t)
T() si( e = ‘*’ ) si e = t
R() igual(‘*’) e  lexico()
finE F() sino
G() error()
finsi Fin Igual
finG
ProcedimientoR()
si( e = ‘+’)
igual(‘+’)
T() Procedimiento F()
R() case e
finsi ‘(’ :igual(‘(’)
finR E()
igual(‘)’)

ProcedimientoT()
‘id’ :igual(‘id’)
otro
id * id $
F() error()
G() fin-case
finT finF
ADR
Procedimiento E() ProcedimientoG() ProcedimientoIgual(t)
T() si( e = ‘*’ ) si e = t
R() igual(‘*’) e  lexico()
finE F() sino
G() error()
finsi Fin Igual
finG
ProcedimientoR()
si( e = ‘+’)
igual(‘+’)
T() Procedimiento F()
R() case e
finsi ‘(’ :igual(‘(’)
finR E()
igual(‘)’)

ProcedimientoT()
‘id’ :igual(‘id’)
otro
id * id $
F() error()
G() fin-case
finT finF
ADR
Procedimiento E() ProcedimientoG() ProcedimientoIgual(t)
T() si( e = ‘*’ ) si e = t
R() igual(‘*’) e  lexico()
finE F() sino
G() error()
finsi Fin Igual
finG
ProcedimientoR()
si( e = ‘+’)
igual(‘+’)
T() Procedimiento F()
R() case e
finsi ‘(’ :igual(‘(’)
finR E()
igual(‘)’)

ProcedimientoT()
‘id’ :igual(‘id’)
otro
id * id $
F() error()
G() fin-case
finT finF
ADR
Procedimiento E() ProcedimientoG() ProcedimientoIgual(t)
T() si( e = ‘*’ ) si e = t
R() igual(‘*’) e  lexico()
finE F() sino
G() error()
finsi Fin Igual
finG
ProcedimientoR()
si( e = ‘+’)
igual(‘+’)
T() Procedimiento F()
R() case e
finsi ‘(’ :igual(‘(’)
finR E()
igual(‘)’)

ProcedimientoT()
‘id’ :igual(‘id’)
otro
id * id $
F() error()
G() fin-case
finT finF
ADR ProcedimientoG()
si( e = ‘*’ )
ProcedimientoIgual(t)
si e = t
igual(‘*’) e  lexico()
Procedimiento E() F() sino
T() G() error()
R() finsi Fin Igual
finE finG

ProcedimientoR()
Programa principal
si( e = ‘+’)
igual(‘+’) eLexico()
T() E()
R()
finsi Procedimiento F() finprincipal
finR case e
‘(’ :igual(‘(’)
E()

ProcedimientoT()
igual(‘)’)
‘id’ :igual(‘id’)
id * id $
F()
otro
G()
error()
finT
fin-case
finF
TERMINO EL
RECONOCIMIENTO
IMPLEMENTACION DEL ADR
#define cmp strcmp // reemplaza la función COMPARA
#define esn isdigit // reemplaza la función ES DÍGITO
#define esl isalpha // reemplaza la función ES LETRA
class AS{
char cad[100];
int p;
char *lex;
public:
// métodos que implican los Vn de la gramática G
void E(); void T(); void R(); void G(); void F();
void I(char *); // verifica el patrón de la gramática G
char *L(); // implementa el analizador léxico
void leer(); // captura una frase del lenguaje
void W(); // avisa de algun error
AS(){ p=0;} // puntero a cada símbolo de la frase
};
SCANNER DEL ADR
char *AS::L(){ // analizador léxico
char *t; int k=0,s=0;
t = new char[20];
for(int i=p; i<strlen(cad); i++)
if(cad[i]!=' '){ // caracter blanco formará un nuevo lexema
if( p==i && esl(cad[i])) s=1; // si es identificador
if(s){
if(esl(cad[i]) || esn(cad[i])); // si es letra o dígito
else return "sos"; // si no es lexema conocido
}
t[k]=cad[i];
k++;
}
else { p=i+1; break; } // apunta al próximo componente léxico
t[k]='\0';
if(s) return "id"; // retorna un identificador
else return t; // retorna otro tipo de lexema
}
METODOS DEL ADR
void AS::leer(){
cout<<"\n leer cadena: ";gets(cad);
lex=L(); Es el programa
E(); leido en una
} cadena

void AS::I(char *m){ //igual


if(!cmp(m,lex)) lex=L(); Verifica el
else W(); patrón
} especificado por
la gramática

void AS::W(){
cout<<"\n error";
getch(); exit(0); }
Avisa de algun
error
METODOS DEL ADR
void AS::E(){ T(); R(); }

E TR

void AS::R(){
if (!cmp(lex,"+")){
I("+");
T(); R+TR / 
R();
}
}

void AS::T(){ F(); G(); } T  FG


METODOS DEL ADR
void AS::G(){
if( !cmp(lex,"*")){
I("*");
F(); G *FG / 
G();
}
}

void AS::F(){
if(!cmp("(",lex)){ I("("); E(); I(")");
}
else if (!cmp(lex,"id")) I("id");
F ( E ) / id
else W();
}
main() {
AS p;
p.leer();
cout<<"\n perfecto";
getch();
}
DETALLE DE UN ADR
1. Para producciones de la forma A  1 / 2 /… / n

Si entrada PRIMERO(1) entonces


Procedimiento 1
sino Si entrada PRIMERO(2)
………
sino Si entrada PRIMERO(n) entonces
Procedimiento n
sino
error
finsi
……..
finsi
finsi

A  1 / 2 /… / n
DETALLE DE UN ADR
2. Para producciones A  1 2 … n

Procedimiento 1
Procedimiento 2
……………..
Procedimiento n
A  1 2 … n
3. Para producciones A   A / 

si entrada PRIMERO()
Procedimiento 
Procedimiento A
finsi
AA/

DETALLE DE UN ADR
4. Para producciones A  

Procedimiento 
A
5. Para producciones A   / 
si entrada PRIMERO() A/
Procedimiento 
Finsi

6. Para producciones A  a, a  Vt
si entrada = a
entrada lexico()
sino
error
A  a, a  Vt
finsi
ANALIZADOR DESCENDENTE
PREDICTIVO (ADP)
 Es un analizador sintáctico que no es recursivo

 Condición exigible es que a partir del siguiente


token de entrada, sea posible determinar que
regla aplicar lo cual se logra mediante una tabla.

 La recursividad se evita mediante una pila

 Un analizador descendente predictivo dirigido


por tabla y que usa pila es el método que se
basa en gramáticas LL(k)
ADP
Frase de entrada
i+i* i
$
pila
E ANALIZADOR
SALIDA
$ SINTACTICO

TABLA DE ANALISIS
SINTACTICO (TAS)
CONSTRUCCION DE UN ADP
I. Hallar los conjuntos PRIMERO y SIGUIENTE

II. La construcción de la tabla de análisis


sintáctico (TAS) usando la información de los
conjuntos PRIMERO y SIGUIENTE
I.HALLAR LOS CONJUNTOS
PRIMERO
PRIMERO(α) donde α(VtVn)*, son los terminales que
pueden comenzar una forma de frase derivable de α. Dada
G=(Vn, Vt, P, S), se calcula PRIMERO(X) aplicando las
siguientes reglas:

1. Si XVt  PRIMERO(X) es { X}
2. Si X  P  se adiciona  a PRIMERO(X)
3. Si X Vn y XY1 Y2 … Yk  P  colocar aVt en
PRIMERO(X) si, para alguna i , a esta en PRIMERO(Yi ) y 
esta en todos los PRIMERO(Y1),…, PRIMERO(Yi -1) osea Y1 …
Yi -1 * 
I.HALLAR LOS CONJUNTOS
Ejemplo 4
Encontrar los conjuntos PRIMEROS de los Vn
Dada G=(Vn, Vt, P, S)
TABLA I
Vn ={S, A, B} Vt ={ a,b,c}
P={ SIMBOLO PRIMERO

S ABc S a, b, c
A a, 
A a /
B b, 
B b /
}
I.HALLAR LOS CONJUNTOS
SIGUIENTE

SIGUIENTE(A) para AVn es el conjunto de terminales que pueden


aparecer inmediatamente a la derecha de A.
Dada G=(Vn, Vt, P, S), se calcula SIGUIENTE(A) aplicando las
siguientes reglas:

 Colocar $ en SIGUIENTE(S) si S es símbolo inicial y $ es el


delimitador.
 De AB, colocar todo PRIMERO() en SIGUIENTE(B)
excepto 
 De AB o AB donde PRIMERO()  colocar todo
de SIGUIENTE(A) en SIGUIENTE(B).
I.HALLAR LOS CONJUNTOS
Ejemplo 5
Encontrar los conjuntos SIGUIENTES de los Vn
Dada G=(Vn, Vt, P, S)
Vn ={S, A, B} Vt ={ a,b,c} TABLA II
P={ SIMBOLO SIGUIENTE

S ABc S $
A b, c
A a /
B c
B b /
}

 Colocar $ en SIGUIENTE(S) si S es símbolo inicial y $ es el


delimitador.
 De AB, colocar todo PRIMERO() en SIGUIENTE(B)
excepto 
 De AB o AB donde PRIMERO()  colocar todo
de SIGUIENTE(A) en SIGUIENTE(B).
II. TAS
ALGORITMO

ENTRADA: una gramática G


SALIDA : tabla de análisis sintáctico M

1.  A donde α(Vt Vn)* se dan los pasos 2 y 3


2.  a PRIMERO(), se adiciona A a M[ A, a]
3. Si PRIMERO(), adicionese A a M[ A, b ], b Vt de
SIGUIENTE(A), si PRIMERO() y $SIGUIENTE(A),
adicionese A a M[ A, $]
TABLA DE ANALISIS SINTACTICO
DEL ADP
SIMBOLO PRIMERO SIGUIENTE
Dada G=(Vn, Vt, P, S) S a, b, c $
Vn ={S, A, B} Vt ={ a,b,c} A a,  b, c
P={ B b,  c

S ABc
A a /
B b /
} TAS
Vn TABLA DE SIMBOLOS
a b c
S S ABc S ABc S ABc

A A a A A

B B b B
ALGORITMO DE ANALISIS
Sim apunta al primer componente léxico de w$
Repetir
Sea X símbolo de la cima de la pila y a el símbolo apuntado por sim
si X Vt o $
si X = a
sacar X de la pila y avanzar sim
sino error
finsi
sino si M[ X, a] = X Y1 Y2 … Yk
sacar X de pila y meter Yk Yk-1 … Y1 con Yi en la cima
sino entrada
error
finsi
finsi X A
Hasta X = $
a. . . . . .$
:
pila : Sim
$
Vn TABLA DE SIMBOLOS
a b c
S S ABc S ABc S ABc RECONOCIMIENTO

A A a A A

B B b B

No PILA ENTRADA SALIDA


1 $S abc$ S ABc
2 $ cBA abc$ A a

TAS
3 $ cBa abc$
4 $ cB bc$ B b
5 $ cb bc$
6 $c c$

ANALISIS DEL ADP


7 $ $ SE ACEPTA
ADP
Ejemplo 6
Se generará el ADP a partir de la siguiente gramática

G=(Vn, Vt, P, E )
Vn={ E, T, F } Vt = { id, *, +, (, ) }
P= {
E  E+T / T
T  T*F / F
F  ( E ) / id
}
ADP
G=(Vn, Vt, P, E )
Vn={ E, T, F } Vt = { id, *, +, (, ) }
P= {
E  E+T / T
T  T*F / F
F  ( E ) / id
}

Se buscará primero eliminar la recursividad


G=(Vn, Vt, P, E )
Vn={ E, T, F } Vt = { id, *, +, (, ) }
P= {
E  TR
R  +TR / 
T  FG
G  *FG / 
F  ( E ) / id
}
CONJUNTOS PRIMERO Y SIGUIENTE
DEL ADP
 Colocar $ en SIGUIENTE(S) si S es símbolo inicial y $ es el
delimitador.
 De AB, colocar todo PRIMERO() en SIGUIENTE(B)
excepto 
 De AB o AB donde PRIMERO()  colocar todo
de SIGUIENTE(A) en SIGUIENTE(B).

G=(Vn, Vt, P, E )
TABLA III
Vn={ E, T, F } Vt = { id, *, +, (, ) } SIMBOLO PRIMERO SIGUIENTE
P= { E ( , id ),$
E  TR R +, ),$
R  +TR /  T ( , id +, ) , $
T  FG G *, +, ) , $
G  *FG /  F ( , id *, +, ) , $
F  ( E ) / id
}
TABLA DE ANALISIS SINTACTICO
DEL ADP
SIMBOLO PRIMERO SIGUIENTE
G=(Vn, Vt, P, E )
E ( , id ),$
Vn={ E, T, F } Vt = { id, *, +, (, ) } R +, ),$
P= {
T ( , id +, ) , $
E  TR
G *, +, ) , $
R  +TR / 
F ( , id *, +, ) , $
T  FG
G  *FG / 
F  ( E ) / id
} TAS
Vn SIMBOLOS DE ENTRADA
id + * ( ) $
E ETR ETR
R R+TR R R
T TFG TFG
G G G*FG G G
F Fid F(E)
Vn SIMBOLOS DE ENTRADA

id + * ( ) $
E ETR ETR

R R+TR R R RECONOCIMIENTO


T TFG TFG
G G G*FG G G
F Fid F(E)

No PILA ENTRADA SALIDA


1 $E id * id $ E  TR
2 $ RT id * id $ T  FG

TAS
3 $ RGF id * id $ F  id
4 $ RG id id * id $
5 $ RG * id $ G * FG
6 $ RGF* * id $

ANALISIS DEL ADP


7 $ RGF id $ F  id
8 $ RG id id $
9 $ RG $ G 
10 $R $ R 
11 $ $ SE ACEPTA
GRAMATICAS LL(K)
Una gramática es LL(k) si la tabla
construida tiene una única producción
en la interseción de una columna(Vt) y
una fila (Vn)

LL(K)
LL(K)
Lectura de los Número de símbolos
símbolos de entrada tomados en cada
de izquierda a lectura
derecha

Las derivaciones son por la


izquierda

Los casos en el ejemplo5 y ejemplo6, son


ejemplos de una gramática LL
CONDICION DE ERROR DE UN ADP
Ejemplos usando la tabla IV
 M[R,+] = R+TR es correcto
 M[R,*] , si se diera indicaría error, así que la
gramática no sería LL
PROPIEDADES DESEABLES EN UN
PARSER

 Determinar la acción reconociendo unos pocos


tokens de entrada
 Como máximo un k preestablecido
 En la práctica suele ser k=1

 No necesitar marcha atras (backtracking)

 No ocupar mucha memoria


IMPLEMENTACION TAS M
Vn SIMBOLOS DE ENTRADA
import java.io.*;
class TABLA{ id + * ( ) $
String M[][]= new String[6][7]; E ETR ETR
String produccion="";
R R+TR R R
T TFG TFG
G G G*FG G G
F Fid F(E)
TABLA(){ // se inicializa la tabla
for(int i=0; i<6; i++)
for(int j=0; j<7; j++)
M[i][j]=" ";// primero se llena de blancos
M[0][1]="i";M[0][2]="+"; M[0][3]="*";
M[0][4]="("; M[0][5]=")";M[0][6]="$";

M[1][0]="E";M[1][1]="RT";M[1][4]="RT";
M[2][0]="R";M[2][2]="RT+";M[2][5]="&";M[2][6]="&";
M[3][0]="T";M[3][1]="GF"; M[3][4]="GF";
M[4][0]="G";M[4][2]="&";M[4][3]="GF*";M[4][5]="&";M[4][6]="&";
M[5][0]="F";M[5][1]="i";M[5][4]=")E(";
}
IMPLEMENTACION id
PILA
G
boolean Terminal(String car){ R
for(int i=1; i< 7; i++)
if(M[0][i].equals(car)) return true;
return false;
$ fondo
}

String RetProduccion(){ return produccion; } Vn SIMBOLO DE


id
E ETR
boolean ExisteInterseccion(String XX,String ae){
int i,x=0,y=0; R R+TR
for(i=1; i< 7; i++)
if(M[0][i].equals(ae)) x=i;

for(i=1; i< 6; i++)


if(M[i][0].equals(XX)) y=i;
if(x ==0 || y == 0 ) return false;
else if( M[y][x].equals(" ")) return false;
else{ produccion=M[y][x]; return true;}

}
} // FIN DE CLASE TABLA
IMPLEMENTACION
class PARSER{
TABLA t=new TABLA();
String pila[]=new String[100];
String ae; //guarda un simbolo de la cadena de entrada
int i; // indice de la pila
String cad; // guarda la cadena de entrada
int p; // posicion de un simbolo de la cadena de entrada a leer
int pos;
static String leer(String m){
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String cadena="";
System.out.println(m);
try{ cadena=br.readLine(); }
catch(IOException ioe) { }
return cadena;
}

b*(a+ b)
IMPLEMENTACION pos

int RetPos(){ return pos; }

b *( a + b ) $
String Lexico(){ // regresa un lexema
char caracter;
String tira=""; //int k=0;
boolean sw=false;
for(int i=p; i<cad.length(); i++)
if(cad.charAt(i)!=' '){
tira=tira+cad.charAt(i); // se rellena otra cadena
pos=i+1;
break;
}
caracter=tira.charAt(0);
if(Character.isLetter(caracter))
tira="i";
i * ( i + i )
return tira.trim();
}

void lectura(){ // lee la cadena de entrada


cad=leer("LEER CADENA: ");
cad=cad+" $";
sintactico(); // se llama al analizador
}
IMPLEMENTACION pos

void mover(int pos){ p=pos; }


b *( a + b ) $
PARSER(){ pila[0]="$"; pila[1]="E"; i=2; p=0; } E
i=2
$
void Empilar(String produccion){// mete en la pila
String t;
for(int j=0; j<produccion.length(); j++){ T GF
t="";
t=t+produccion.charAt(j);
pila[i]=t; i++; PILA
} T
}
R
void error(){
System.out.println(" error de sintaxis");
$ fondo
System.exit(0);
}
IMPLEMENTACION pos

String RetCad(){
String temp=""; int j,k=0;
b *( a + b ) $
for(j=p; j<cad.length(); j++){
temp=temp+cad.charAt(j); }
return temp;
}

String RetPila(){
String CadPila="";
a+b)$
for(int j=0; j<i; j++) CadPila=CadPila+pila[j];
return CadPila;
}

PILA
T
R $RT
$ fondo
IMPLEMENTACION
void sintactico(){ // analizador sintactico
String XX; String produccion=""; int pos=0;
do{
// se copian las cadenas retornadas en "ae" y "XX"
ae=Lexico(); XX=pila[i-1];
pos=RetPos();
if( t.Terminal(XX)) // retorna 1 si XX es terminal, sino 0
if(XX.equals(ae)) {
i=i-1; // se descuenta un simbolo de la pila
mover(pos); // se lee la cadena de entrada desde
// la posicion "pos"
}
else { System.out.println("1"); error();}
else
if (t.ExisteInterseccion(XX,ae)){
produccion=t.RetProduccion();
System.out.println("| "+RetPila()+" | "+RetCad()+" | "+XX+"-->"+produccion);
i = i -1; // se descuenta un simbolo de la pila
// si la produccion es & no se mete en la pila
if(!produccion.equals("&")) Empilar(produccion);
}
else {System.out.println("2");error();}
}while(!XX.equals("$"));
}
IMPLEMENTACION
public static void main(String arg[]){
PARSER p=new PARSER();
p.lectura();
System.out.println("\n analisis correcto");
}
} // FIN DE PARSER

LEER CADENA:
a*b
| $E | a * b $ | E-->RT
| $RT | a * b $ | T-->GF
| $RGF | a * b $ | F-->i
| $RG | * b $ | G-->GF*
| $RGF | b $ | F-->i
| $RG | $ | G-->&
| $R | $ | R-->&

analisis correcto

Process completed.
ADP
Ejemplo 7

A partir del siguiente ejemplo de código del lenguaje


WHILE, generar un ADP y pruébelo para alguna secuencia
del lenguaje. El lenguaje no debe aceptar el programa vacío
y el argumento de cada while debe ser solo un identificador

Un programa ejemplo del lenguaje WHILE

while a {
while b { }
while c { }
}
while d { }
ADP G=(Vn, Vt, S, P)
Vn={ S, W, A}
Vt={while, {, }, id }
Gramática Se elimina la
P={
ambigüedad SWK
G=(Vn, Vt, S, P) KS / 
Vn={ S, W, A} AS/ 
Vt={while, {, }, id } Wwhile id { A}
P={
SWS / W }
AS/ 
Wwhile id { A}

} G=(Vn, Vt, S, P)
Vn={ S, W, A}
Vt={while, {, }, id }
P={ Se eliminan
SWA producciones
AS/  redundantes
Wwhile id { A} la

}
CONJUNTOS
G=(Vn, Vt, S, P)
Vn={ S, W, A}
Vt={while, {, }, id }
P={
SWA
AS/ 
Wwhile id { A}

Vn PRIMERO SIGUIENTE
S while $ R1
W while $, while R3, R2
A while,  $, } R3, R2
TABLA DE ANALISIS
SINTACTICO
CONJUNTOS
G=(Vn, Vt, S, P)
Vn={ S, W, A} Vn PRIMERO SIGUIENTE
Vt={while, {, }, id } S while $
P={
SWA
AS/  W while $, while
Wwhile id { A} A while,  $, }

TAS
Vn while $ }
S SWA
W Wwhile id { A}
A AS A A
PRUEBA DEL ANALIZADOR
G=(Vn, Vt, S, P)
Vn={ S, W, A}
Vt={while, {, }, id } S
P={
SWA
AS/  WA
Wwhile id { A}

}
while id { A} 
while b { while c{ } }
S

WA

while id { A} 
PRUEBA DEL ANALIZADOR

G=(Vn, Vt, S, P)
Vn={ S, W, A} PILA SECUENCIA PRODUCCION
Vt={while, {, }, id } $S while b{while c{}} $ SWA

P={ $AW while b{while c{}} $ Wwhile id {A}

SWA $A}A{id while while b{while c{}} $

AS/  $A}A{id b{while c{}} $

Wwhile id { A} $A}A{ {while c{}} $


$A}A while c{}} $ AS

} $A}S while c{}} $ SWA

G es LL $A}AW
$A}A}A{id while
while c{}} $
while c{}} $
Wwhile id {A}

TAS
$A}A}A{id c{}} $
Vn while $ } $A}A}A{ {}} $
$A}A}A }} $ A
S SWA
$A}A} }} $
W Wwhile id { A}
$A}A }$ A
A AS A A $A} }$
$A $ A

$ $ SE ACEPTA
LABORATORIO

Escriba un ADR para reconocer clases en C++. Por


ejemplo

class Auto{ };
class B: public V{ int x; int m(float a); };
:
Luego impleméntelo en C++ o en java

Observación:

Puede utilizar el programa ejemplo.


Utilice lexemas de 1 o mas caracteres

Enviar a zorroculto69@Hotmail.com

Вам также может понравиться