Está en la página 1de 23

Implementación

de métodos
computacionales

Primer período
Entendiendo
a los lenguajes de programación…

Análisis sintáctico e
integración de
conocimientos

IMECO – Primer período

Ing. Román Martínez M


Estructura de un Compilador

ANALISIS SINTESIS
Análisis de Análisis de Generación Generación
Programa Análisis Optimización Programa
Léxico sintaxis de código de código
fuente semántico de código objeto
(Scanner) (Parser) intermedio objeto

Lista de tokens Árbol sintáctico Árbol sintáctico Código intermedio Código optimizado
validado

Descompone el código fuente para Transforma a los elementos reconocidos


verificar el uso correcto del lenguaje del lenguaje en el código objeto
Analizador de SINTAXIS (Parser)

• Verifica que la secuencia de tokens cumpla con el orden definido


por la gramática del lenguaje.
• Se forman frases gramaticales (estatutos) en forma de árbol
sintáctico.
• La gramática debe de ser LIBRE DE CONTEXTO para poder
reconocer las estructuras típicas de un lenguaje de
programación.
main()

Ejemplo { //programa que no hace nada


int a;
a = a * 2;
}

Lista de Tokens: programa


PR_main (5)
Paréntesis_abierto (12) main ( ) { estatutos }
Paréntesis_cerrado (13)
Llave_abierta (18)
PR_int(4)
estatuto ; estatuto ;
identificador (20, dirX)
Puntoycoma (33)
identificador (20, dirX)
PARSER
Op= (67) int id expresión
identificador (20,dirX)
Op* (58)
Cte_entera (25, dirZ) id = expresión
Puntoycoma (33)
Llave_cerrada (19)
id * cte_entera
¿Cómo se construye un Analizador de Sintaxis?

• Diseñar la gramática del lenguaje y quitarle ambigüedades.


Un diagrama de sintaxis puede facilitar el diseño.
• Implementar por medio de algún método:
• Descenso recursivo
• Predictivo
• LR (require autómatas de pila)

• Utilizar un generador automático de parser: Yacc, Bison, Javacc


• Gramática LR -> AEF de pila -> Método LR
El método de
Descenso recursivo

• Consiste en programar un módulo por cada símbolo No Terminal de


la gramática a reconocer.

• La programación del módulo se basa en la secuencia de la


producción del No Terminal, incluyendo :
• La verificación de la presencia de un símbolo terminal en la entrada (con un if).
• La llamada al módulo del símbolo No terminal correspondiente (incluso
recursivamente si se requiere).
void A()
Ejemplo { if (token == ’a’)
{ token = dame_token();
B();
if (token == ’a’ ) cout << “Entrada exitosa”;
else cout << “Error, esperaba ‘a’”;
}
else
Gramática: cout << “Error, esperaba ‘a’”;
No Terminales: {A, B} }

Terminales: {a, b, c} void B()


{ if (token ==’b’)
Producciones: { token = dame_token();
A ::= a B a B();
if (token == ’b’) token = dame_token();
B ::= b B b else cout << “Error, esperaba ‘b’”;
B ::= c }
else
if (token == ’c’) token = dame_token();
else cout << “Error, esperaba ‘b’ o ‘c’”;
}
Características del método de
Descenso Recursivo (DR)

• Fácil y rápido de implementar.


• Fácil de marcar los errores, pero difícil de recuperarse de ellos.
• Requiere que la gramática no tenga ambigüedades:

• No debe haber producciones con recursividad izquierda: A ::= Aa | b


Regla de conversión: A ::= bA’ A’ ::= aA’ | e

• No debe haber producciones con factores comunes: A ::= aA | a


Regla de conversión: A ::= aA’ A’ ::= A | e

• Sólo para gramáticas LL.


EJEMPLO
Eliminación de ambigüedades para DR

Ambigüedad por recursividad izquierda Regla de conversión:


a A ::= bA’
A ::= Aa | b
EXP ::= EXP op EXP A’ ::= aA’ | e
EXP ::= ( EXP )
EXP ::= cte b Gramática transformada SIN ambigüedades:
b
EXP ->b cte EXP1
EXP -> ( EXP ) EXP1
EXP1 -> op EXP EXP1
a
EXP1 -> e
char t;
//Declaracion de prototipos para tener recursividad mutua
void exp();

EJEMPLO
void exp1();
void exp()
{ if (t == '0') //reconoce cte.
{ t = getch(); cout<<t;
exp1(); }
else
if (t == '(') //reconoce (
{ t = getch(); cout<<t;
exp();
if (t == ')') //reconoce )
{ t = getch(); cout<<t;

EXP -> cte EXP1


exp1();
}
else

EXP -> ( EXP ) EXP1


{ cout<<"Se esperaba )"<<endl;
exit(0); }
}

EXP1 -> op EXP EXP1


else
{ cout << "ERROR, esperaba cte o ("<<endl;
exit(0); }

EXP1 -> e }
void exp1()
{ if (t == '+') //reconoce operador
{ t = getch(); cout<<t;
exp();
exp1(); }
}
main()
{ t = getch(); cout<<t;
exp();
PARSER if (t == 13)
cout << "Entrada aceptada"<<endl;
else
cout << "Expresion mal construida"<<endl;
}
EJERCICIOS

1. Modifica el programa del Parser 2. Modifica el programa del Parser


para que sea capaz de reconocer para que sea capaz de reconocer al
tanto a los paréntesis como a los operador de negativo (signo –)
corchetes como agrupadores de unario.
subexpresiones.
• Ejemplos de expresiones válidas: • Ejemplos de expresiones válidas:
• [0] • -0
• (0+0)+[0+0] • 0+-0
• (0+[0+0]) • -(0+0)
• [(0+0)+0] • (-0+0)+0+-0
• [(([(0+0)])+0)]
• ---0
Automatización de la generación de un
Scanner o un Parser

Herramientas como Lex o Flex reciben


como entrada las expresiones regulares
y generan el scanner

METALENGUAJES

Herramientas como Yacc, Bison o


Javacc reciben como entrada la
gramática BNF y generan el parser
M1 | M2

Algoritmo de
Thompson
Conversión de una M1 M2

expresión regular
en un AFN

M 1*
Conversión de un AFN en AFD

• Generar una nueva tabla de transiciones, agrupando los estados a los que
se transiciona con cada símbolo, y uniendo estados de transiciones
épsilon.
• Cada grupo de estados que se forme, representa un nuevo estado del
autómata convertido, y deberá incorporarse a la tabla.
• Renombrar los grupos de estados formados, que pasan a ser los estados
del AFD equivalente.
• Los grupos de estados que contengan a un estado aceptor del AFN,
pasan a ser estados aceptores del nuevo AFD.
Ejemplo
Tabla de transiciones con estados agrupados
AFN Estado a b
A {q0} - B {q1, q2}
B {q1, q2} C {q0, q3} -
C {q0, q3} - D{q0, q1, q2}
D{q0, q1, q2} C {q0, q3} B {q1, q2}

AFD
b a b
A B C D
a
b
Recordando… Jerarquía de Chomsky
Relación con herramientas para describir los lenguajes

Recursivamente
enumerables Máquinas de Turing

Sensibles al contexto Lenguajes


de programación
Libres de contexto Gramáticas
SINTAXIS Autómatas de pila

Regulares LÉXICO Expresiones regulares


Autómatas de estados finitos
Gramáticas

Léxico = Sintaxis de bajo nivel


Autómatas de pila
Pushdown automata

ENTRADA
• Autómata finito que utiliza una pila
(stack) como memoria para recordar
información y tomar decisiones en el
proceso que se modela.
• Las transiciones del autómata se
realizan con el dato de entrada y con
el dato que hay en el tope de la pila,
tomando acción sobre la misma.
• Permiten representar lenguajes
libres de contexto en donde hay
control o balanceo de elementos.
Descripción de los lenguajes de la
jerarquía de Chomsky con Gramáticas formales

• Las gramáticas formales que hemos utilizado se utilizan para describir


lenguajes libres de contexto.
L → xxLzz
• Todas las producciones representan la derivación de un No Terminal con una L → xyz
secuencia de terminales o no terminales.
L→e
• Las gramáticas formales que definen lenguajes regulares se
restringen al sólo permitir que las producciones tengan una secuencia
de uno o dos símbolos. R → aR R → Ra
• Si la producción es con un solo símbolo debe ser terminal.
• Si es con dos símbolos, uno debe ser terminal y el otro No Terminal en
R→a R→e
cualquier orden.

• Las gramáticas formales para definir lenguajes sensitivos al S → abc | aSBc


contexto tienen producciones cuyo lado izquierdo no es sólo de un
No Terminal, sino que es acompañado por los terminales que
cB → Bc
contextualizan la derivación de ese No Terminal. bB → bb
Ejemplo: Derivación en un LSC

Gramática: S S
S → abc | aSBc → abc → aSBc
cB → Bc → aaSBcBc
bB → bb → aaabcBcBc
S
→ aaabBccBc
→ aSBc
→ aaabbccBc
→ aabcBc
→ aaabbcBcc
→ aabBcc
→ aaabbBccc
Conclusión: → aabbcc
La gramática reconoce el lenguaje
→ aaabbbccc
anbncn para n>0
Máquinas de Turing

Autómata finito con memoria infinita (cinta) sobre


la cual puede moverse en ambos sentidos,
leer y escribir según transiciones.

Modelo conceptual de cualquier proceso computable.


Turing
Teoría de la computación
https://www.youtube.com/watch?v=iaXLDz_UeYY
https://www.youtube.com/watch?v=v5rPVciWAvw

¿Qué es computable?
¿Qué has aprendido en estas primeras 5 semanas del curso?

¿Qué se ha transformado en tí?


¿Ves, piensas, haces algo de diferente?

¿Qué podemos hacer mejor para el siguiente período?

Si quieres triunfar, no te quedes mirando la escalera…


Empieza a subir escalón por escalón, hasta que llegues arriba…

También podría gustarte