Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Gramáticas
Ejemplo:
O S P
S A T
P V
A el
A un
T niño
T perro
V corre
V camina
Gramáticas
T niño
•S V es la variable de inicio.
•T={a,b}
S aSb •V={S}
•S=S
S •P={SaSb, S}
S aSb ab
Una derivación es la obtención de una palabra u a
partir de una palabra v, ambas pertenecientes a
(V+T)*, aplicando una regla de producción:
a VF transparencia previa.
a B bB
B
Ba
b Ir derivando la palabra corresponde
a ir cambiando de estado interno (la
variable), y escribiendo.
Gramáticas regulares)
•SaT
•TSb
•S
Más ejemplos:
S SS | ( S ) |
donde T={(,)}, V={S}. ¿Lenguaje?
S (S) ()
S (S) (SS) ((S)S) ((S)(S)) (()(S)) (()())
Más ejemplos:
S aSa | bSb |
donde T={a,b}, V={S}. ¿Lenguaje?
Ejercicios:
G 1: G2:
S XaaX S XY
X aX | bX | X aX | bX | a
Y Ya | Yb | a
SXX
XaXb |
GLC "prototípicas"
SaSb | X
XbXa |
GLC, un ejemplo más complejo
10010011010010110
inicio parte central final
00110100
A B C D
Cantidad de 0’s:
A: , ó termina en 1 •la misma a cada lado
C: , ó comienza con 1 •al menos uno
GLC, un ejemplo más complejo
10010011010010110
inicio parte central final
A B C S → ABC
A → | U1
00110100 U → 0U | 1U |
C → | 1U
D
B → 0B0 | 0D0
Cantidad de 0’s: D → 1U1 | 1
•la misma a cada lado
•al menos uno
Derivaciones y árboles
S XY
X aaX |
Y Yb |
S XY aaXY aaXYb aaaaXYb aaaaXb aaaab
X Y S XY aaXY
aaaaXY aaaaY
aaaaYb aaaab
a a X Y b
SR aaaab :
a a X S XY XYb
Xb aaXb
aaaaXb aaaab
Derivaciones y árboles
S
•En la raíz va S.
X Y
•En las hojas, terminales o .
a a X Y b •Las derivaciones extremas,
L y R, corresponden a
a a X hacer recorridos del árbol
en pre-orden y post-orden,
respectivamente.
E E + E | (E) | V
E Vx|y|z E
E + E E + E
x+y+z
V E + E E + E V
x V V V V z
y z x y
T o t a l = p r e c i o + i v a ; Analizador
léxico
asignación
Parser
Total := Expresión
id + id
precio iva
E E + E | EE | (E) | V
E Vx|y|z E
E E E + E
V E + E xy+z E E V
x V V V V z
y z x y
S La mayoría de los
lenguajes lo resuelven
if b then S else S
asignando el else al if
más cercano.
if b then S a
a
S
if b then S
if b then S else S
a a
GLC: ambigüedad
E E + E | EE | (E) | V
Vx|y|z
•Genera lo mismo, pero
obliga al árbol a
ET|E+T reconocer la prioridad
TF|TF de la multiplicación.
F (E) | V •Java o C++ aplican algo
Vx|y|z análogo para resolver
los else ambiguos.
GLC: ambigüedad
L {a nb nc m } {a nb mc m }
S S1 | S2 S1 S1c | A S 2 aS 2 | B
A aAb | B bBc |
Ergo:
S → aSb | bSaSb | T
T→S|
S aSb aaSbb
abSaSbb ... Problema:
aTb
bSaSb baSbaSb ¿Cuándo
...
parar?
T S ...
GLC: simplificación
Ejemplo:
S a | Xb | aYa •Eliminamos X
XY| •A partir de SXb se agrega
Yb|X Sb, pues X es anulable.
•A partir de SaYa se agrega
Anulables: X e Y. Saa, pues Y es anulable,
S a | Xb | aYa | b | aa
XY
Yb|X
Eliminación de producciones nulas
Otro ejemplo:
S aMb S aMb
Sustituimos
M aMb M S ab
M M aMb
M ab
Anulables: M
Eliminación de producciones unitarias
Ejemplo: S aX | Yb
XS
Y bY | b | X
•Como X * S, se agregan XaX , XYb
•Como Y * X... No se agrega nada.
•Como Y * S, se agregan YaX , YYb
•Finalmente, eliminamos las producciones unitarias
XS y YX.
S aX | Yb
X aX | Yb
Y bY | b | aX | Yb
Eliminación de variables inútiles
S aSb SX
S X aX Y es inútil: no
SX X hay forma de que
aparezca en una
X aX Y bX derivación!
S uXv w
•Si esto nunca ocurre, es inútil.
S aS | A | C U={a,b}
Aa U={a,b,A}
U={a,b,A,S}
B aa
U={a,b,A,S,B}
C aCb
Eliminación de variables inútiles
S aS | A | C U={a,b} S aS | A
Aa U={a,b,A}
U={a,b,A,S}
Aa
B aa
U={a,b,A,S,B} B aa
C aCb
Eliminación de variables inútiles
S aS | A
Generamos
Aa grafo de
dependencia S A B
B aa
B no es alcanzable
Es inútil. S aS | A
Aa
Eliminación de variables inútiles
Simplificación de gramáticas:
S AS S AS
Está en FNC
S a S AAS
A SA A SA
No está en FNC
Ab A aa
Forma Normal de Chomsky (FNC)
Y listo.
S AV1
•Llevar GLC a la forma normal de V1 BTa
Chomsky es relativamente fácil. A TaV2
V2 TaTb
•Tener la GLC en FNC sirve para varias
cosas, prácticas y teóricas. B ATc
Ta a
•La más importante: para parsear en Tb b
tiempo polinomial en |w|.
Tc c
CYK
A BB k\j 1 2 3 4 5
Aa 1 a a b b b
B AB 2 aa ab bb bb
Bb
3 aab abb bbb
aabbb
5 aabbb
S AB
CYK
A BB
Aa
a a b b b
B AB
A A B B B
Bb
aa ab bb bb
aabbb
S AB
CYK
A BB
Aa
a a b b b
B AB
A A B B B
Bb
aa ab bb bb
S,B A A
aab abb bbb
Variables que
generan las
subpalabras de aabb abbb
largo 2
aabbb
S AB
CYK
A BB
a a b b b
Aa
A A B B B
B AB
Bb aa ab bb bb
S,B A A
aab abb bbb
Variables que S,B A S,B
generan las
subpalabras aabb abbb
de largo 5 (o A S,B
sea, w)
aabbb
S,B
CYK
Input
Estados Pila
PDA
PDA
PDA (Autómatas de pila)
No determinismo:
•Los PDA que veremos, salvo que se indique lo
contrario, son no deterministas : hay transiciones ,
puede haber más de una transición para una misma
situación, etc...
Lenguaje reconocido:
•El lenguaje reconocido por el PDA será el conjunto
de palabras para las cuales existe una secuencia de
transiciones que concluye con la palabra leída
completa, y en estado de aceptación.
•Es decir, igual que en AFND+.
PDA (Autómatas de pila)
saco de guardo en
leo del
la pila la pila
•En el grafo de input
transiciones se anota
lo que se saca y
guarda en la pila. q1 a, b c q2
a, b c
q1 q2
input
a a
pila
b tope c
h Reemplaza h
e e
$ $
a, c
q1 q2
input
a a
pila c
b tope b
h Guarda h
e ("push")
e
$ $
a,b
q1 q2
input
a a
pila
b tope
h Saca h
e ("pop")
e
$ $
q1 a, q2
input
a a
pila
b tope b
h Sin cambio h
e e
$ $
PDA (Autómatas de pila)
q2
a, b c
q1 q1 ,b c q2
a, b c q3
No determinismo Transición
PDA (Autómatas de pila)
M = ( Q, , q0, F )
: Q({})({}) 2Q({})
PDA, ejemplo
a, a b, a
q0 , q b, a q , $ $ q
1 2 3
PDA, ejemplo
Input
a a a b b b
$
Pila
estado a, a b, a
actual
q0 , q b, a q , $ $ q
1 2 3
PDA, ejemplo
Input
a a a b b b
$
Pila
a, a b, a
q0 , q1 b, a q2 , $ $ q3
PDA, ejemplo
Input
a a a b b b a
$
Pila
a, a b, a
q0 , q1 b, a q2 , $ $ q3
PDA, ejemplo
Input a
a a a b b b a
$
Pila
a, a b, a
q0 , q1 b, a q2 , $ $ q3
PDA, ejemplo a
Input
a
a a a b b b a
$
Pila
a, a b, a
q0 , q1 b, a q2 , $ $ q3
PDA, ejemplo a
Input
a
a a a b b b a
$
Pila
a, a b, a
q0 , q1 b, a q2 , $ $ q3
PDA, ejemplo
Input a
a a a b b b a
$
Pila
a, a b, a
q0 , q1 b, a q2 , $ $ q3
PDA, ejemplo
Input
a a a b b b a
$
Pila
a, a b, a
q0 , q1 b, a q2 , $ $ q3
PDA, ejemplo
Input
a a a b b b
$
Pila
a, a b, a
acepta
q0 , q1 b, a q2 , $ $ q3
PDA, ejemplo
L {a b : n 0}
n n
a, a b, a
q0 , q1 b, a q2 , $ $ q3
PDA, otro ejemplo
L( M ) {ww } R
a, a a, a
b, b b, b
q0 , q1 , $ $ q2
PDA, otro ejemplo
Input
a b b a
$
Pila
a, a a, a
b, b b, b
q0 , q1 , $ $ q2
PDA, otro ejemplo
Input
a b b a a
$
Pila
a, a a, a
b, b b, b
q0 , q1 , $ $ q2
PDA, otro ejemplo
Input
b
a b b a a
$
Pila
a, a a, a
b, b b, b
q0 , q1 , $ $ q2
PDA, otro ejemplo
Input
b
a b b a a
$
Pila
a, a a, a
b, b b, b
q0 , q1 , $ $ q2
PDA, otro ejemplo
Input
b
a b b a a
$
Pila
a, a a, a
b, b b, b
q0 , q1 , $ $ q2
PDA, otro ejemplo
Input
a b b a a
$
Pila
a, a a, a
b, b b, b
q0 , , $ $ q2
q1
PDA, otro ejemplo
Input
a b b a
$
Pila
a, a a, a
b, b b, b
acepta
q0 , q1 , $ $ q2
Un ejemplo más:
Vimos que la gramática de abajo
genera el lenguaje L={w{0,1}*: w tiene D
2 bloques de 0’s del mismo tamaño}
[transparencia 23]
10010011010010110
Ejemplos de strings en L: 01011, 001011001,
A B C
10010101001
Ejemplos de strings fuera de L: 01001000, A, parte inicial: ,
01111 o termina en 1
S → ABC
B, parte central: zona
A → | U1 D, rodeada por
U → 0U | 1U | bloques de 1 o más 0’s.
C → | 1U C, parte final: ,
o comienza con 1
B → 0B0 | 0D0
D → 1U1 | 1 D, centro del centro:
parte y termina con 1.
Un ejemplo más:
He aquí un PDA que reconoce ese
mismo lenguaje:
B
A 0, /
1, / 0, / 0
, / 1, / 0, / 0 D
q0 q1 q2 q3
1, /
, / 0, /
0, / 1, / q4
1, /
1, /
1, $ / $ 1, /
q6 q5
C 0, 0 /
q7 , $ / $
Guardando strings
String guardado
Permitiremos ahora
guardar strings en la
pila: q1 a, b w q2
a,b cda
q1 q2
c string
pila d guardado
b tope Guarda a
h “cda” h
e e
$ $
Guardando strings
a,b cda
q1 q2
es equivalente a tener
L( M ) {w : na nb }
a, $ 0$ b, $ 1$
a, 0 00 b, 1 11
a, 1 b, 0
q1
, $ $ q2
Input
a b b b a a
$
a, $ 0$ b, $ 1$
Pila
a, 0 00 b, 1 11
a, 1 b, 0
q1
, $ $ q2
Input
a b b b a a
0
$
a, $ 0$ b, $ 1$
Pila
a, 0 00 b, 1 11
a, 1 b, 0
q1
, $ $ q2
Input
a b b b a a
0
$
a, $ 0$ b, $ 1$
Pila
a, 0 00 b, 1 11
a, 1 b, 0
q1
, $ $ q2
Input
a b b b a a
1
$
a, $ 0$ b, $ 1$
Pila
a, 0 00 b, 1 11
a, 1 b, 0
q1
, $ $ q2
Input
a b b b a a 1
1
$
a, $ 0$ b, $ 1$
Pila
a, 0 00 b, 1 11
a, 1 b, 0
q1
, $ $ q2
Input
a b b b a a 1
1
$
a, $ 0$ b, $ 1$
Pila
a, 0 00 b, 1 11
a, 1 b, 0
q1
, $ $ q2
Input
a b b b a a
1
$
a, $ 0$ b, $ 1$
Pila
a, 0 00 b, 1 11
a, 1 b, 0
q1
, $ $ q2
Input
a b b b a a
$
a, $ 0$ b, $ 1$
Pila
a, 0 00 b, 1 11
a, 1 b, 0
acepta
q1
, $ $ q2
•Idea: este PDA guarda en la pila sólo lo que está en
exceso, respecto a na=nb.
a, $ 0$ b, $ 1$
a, 0 00 b, 1 11
a, 1 b, 0
q1
, $ $ q2
PDA: descripción instantánea
(q,w,v)
q Q, el
v , el contenido
estado actual
w , lo que falta actual del stack
por leer en el input
PDA: descripción instantánea
Descripción
instantánea
(q1, bbb, aaa$)
a
Instante 4: Input a
a a a b b b a
$
Pila
a, a b, a
q0 , q1 b, a q2 , $ $ q3
PDA: descripción instantánea
Descripción
instantánea
(q2 , bb, aa$)
a
Instante 5: Input a
a a a b b b a
$
Pila
a, a b, a
q0 , q1 b, a q2 , $ $ q3
PDA: descripción instantánea
Escribimos (q1,bbb,aaa$)(q2,bb,aa$)
y el cómputo completo será
(q0,aaabbb,$)
(q1,aaabbb,$)
(q1,aabbb,a$)
(q1,abbb,aa$)
(q1,bbb,aaa$) •Abreviando podemos decir que
(q2,bb,aa$) (q0,aaabbb,$) (q3,,$)
(q2,b,a$)
(q2,,$) •A veces se pone * para
(q3,,$) especificar que se refiere a
más de un paso.
Lenguaje por estado de aceptación
$ $
, $/
, $/Z0$
, $/
, $/
PDA y GLC
S S Nótese que:
aSa a S a
•Lo que va
aaSaa aa S aa
quedando a la
aaYZaa aa Y Zaa
izquierda se
aabYZaa aab Y Zaa
“congela”, y no se
aabbYZaa aabb Y Zaa
vuelve a mirar.
aabbZaa aabb Z aa
aabbcZaa aabbc Z aa •Lo que está a la
aabbcYaa aabbc Y aa derecha es una
aabbcbYaa aabbcb Y aa pila!
aabbcbaa aabbcb aa
GLC PDA
Para cada
Para cada
producción , p q a, a aT
pq en P
q0 , S q1 ,$ $
q2
GLC PDA
Idea:
•Lo que está en la pila es lo que falta “procesar”.
•Si vemos ahí un terminal, significa que lo generó
nuestro último reemplazo. Por lo tanto, tiene que
tenerlo el input.
•Si es una variable, la tenemos que reemplazar por
alguna de sus producciones.
, p q a, a
q0 , S q1 ,$ $
q2
GLC PDA
Ejemplo: derivación izquierda (q0,abcba,$)
S (q1,abcba,S$)
(a la idem), y cómputo en el
aSa (q1,abcba,aSa$)
PDA (a la derecha).
aYZa (q1,bcba,Sa$)
Gramática: (q1,bcba,YZa$)
abYZa (q1,bcba,bYZa$)
abZa S aSa | YZ (q1,cba,YZa$)
abcZa Y bY | (q1,cba,Za$)
abcYa Z cZ | Y (q1,cba,cZa$)
abcbYa (q1,ba,Za$)
, Y (q1,ba,Ya$)
abcba (q1,ba,bYa$)
, S aSa , Z cZ
a, a (q1,a,Ya$)
, S YZ , Z Y b, b (q1,a,a$)
, Y bY c, c (q1,,$)
(q2,,$)
q0 , S q1 ,$ $
q2
PDA GLC
p a, X Y q
donde la a, la X y/o la Y pueden eventualmente ser .
p a, X Y q
•En la gramática que se define, los terminales serán
(el alfabeto de entrada del PDA).
V = {S} Q({})Q
PDA GLC
p a, X Y q
Las reglas de producción se definen con la intención
de que [pXq] produzca exactamente el conjunto de
palabras que, leídas en el PDA, pueden llevarnos desde
el estado p hasta el estado q, sacando una X de la pila
(y sin meternos más abajo):
p a, X Y q
[pXq] * w (p, w, X) * (q, , )
gramática pda
p a, X Y q r
A continuación, para cada transición como la de
arriba, se agregan las reglas de producción
{anbn:n0}
a, a b, a
q0 a, a q1 b, a q2 , $ $ q3
{w=u uR : u{a,b}* }
Idea:
Idea:
•En la derivación, alguna variable R debe aparecer en la
producción a partir de si misma.
•Eso permite bombear: en lugar de producir Rx la
segunda vez que aparece, volvemos a hacer Rvxy, y así
tantas veces como queramos.
Lema de bombeo para LLC
B B
S b S b
A B A B
a B b b
a B b b
S b
b
A B
a B b b
Lema de bombeo para LLC
•Tomemos w=ambmcm.
¡Contradicción!
Warning:
Entonces:
•V = V1 V2 {S}
•T = T1 T2
•S una variable nueva
•P = P1 P2 {S S1|S2}
Propiedades de clausura
De manera similar,
•V = V1 V2 {S}
•T = T1 T2
•S una variable nueva
•P = P1 P2 {S S1S2}
Propiedades de clausura
•V = V1 {S}
•T = T1
•S una variable nueva
•P = P1 {S S S1 | }
Propiedades de clausura
Contraejemplo:
L1 L2 = {anbncn: n0}
no lo es.
Propiedades de clausura
Demostración:
Idea de la demostración:
•Consideramos M=(Q, , q0, F) un PDA que
reconoce L1, y M'=(Q', ', q'0, F') un AFD que
reconoce L3.
•Construimos un PDA con estados QQ', que
simulará simultáneamente M y M' sobre un mismo
input.
•Aceptamos la palabra si al final tanto M como M'
aceptan.
Propiedades de clausura
Aplicaciones de eso:
Aplicaciones de eso:
2) Probemos que
L={w{a,b,c}*: |w|a=|w|b=|w|c}
no es de libre contexto.
Problema de membresía:
Respuesta:
Problema de vacuidad:
Respuesta:
Problema de finitud:
Respuesta:
Problema de finitud:
S AB
A C
A aCb | a
B bB | bb S
C cBS B
Problema de igualdad:
Respuesta:
Respuesta: al procesar...
•Lenguajes de programación.
•Lenguajes de marcas ("ML")
•Lenguajes humanos (casi, casi)
Ventajas:
•La forma (CSS) y el contenido (HTML) se
especifican por separado.
•La marcación semántica permite lectura vía
software.
Marcado semántico
<H1>Hot Cop</H1>
información.
<li>Written: 1978
<li>Artist: Village People
</ul>
Y el DTD es...
una gramática de libre contexto.
Forma:
<!DOCTYPE nombre-del-DTD [
lista de definiciones de elementos
]>
Definición de elemento:
Base:
Operadores:
| unión
, concatenación
* clausura de Kleene: 0 o más ocurrencias
+ clausura positiva: 1 o más ocurrencias
? opcional: 0 o 1 ocurrencias
DTD
Ejemplo DTD:
<!DOCTYPE PcSpecs [
<!ELEMENT PCS (PC*)>
<!ELEMENT PC (MODEL, PRICE, PROC, RAM, DISK+)>
<!ELEMENT MODEL (#PCDATA)>
<!ELEMENT PRICE (#PCDATA)>
<!ELEMENT PROC (MANF, MODEL, SPEED)>
<!ELEMENT MANF (#PCDATA)>
<!ELEMENT SPEED (#PCDATA)>
<!ELEMENT RAM (#PCDATA)>
<!ELEMENT DISK (HARDDISK | CD | DVD )>
<!ELEMENT HARDDISK (MANF, MODEL, SIZE)>
<!ELEMENT SIZE (#PCDATA)>
<!ELEMENT CD (SPEED)>
<!ELEMENT DVD (SPEED)>
]>
DTD
<PCS>
<PC>
Fragmento de un XML
<MODEL>4560</MODEL> según ese DTD
<PRICE>$2295</PRICE>
<PROCESSOR>
<MANF>Intel</MANF>
<MODEL>Pentium</MODEL>
<SPEED>4Ghz</SPEED>
</PROCESSOR>
<RAM>8192</RAM>
<DISK>
<HARDDISK>
<MANF>Maxtor</MANF>
<MODEL>Diamond</MODEL>
<SIZE>2000Gb</SIZE>
</HARDDISK>
</DISK>
<DISK><CD><SPEED>32x</SPEED></CD></DISK>
</PC>
<PC> ….. </PC>
</PCS>
XML
Moralejas:
T o t a l = p r e c i o + i v a ; Análisis léxico
("lexer")
asignación
Análisis
Expresión sintáctico
Total :=
("parser")
id + id
Análisis semántico
(chequeo de tipos, etc)
precio iva
Generación de
código
Parseo y compiladores
Dos aproximaciones:
Top down:
•Partimos de la raíz del árbol de derivación (S)
•Tomamos una regla de producción, e intentamos
calzarla con el input.
•Si en algún momento no podemos avanzar, nos
devolvemos por la rama y probamos otra cosa
(backtracking).
Bottom up:
•Vamos procesando las hojas, creciendo hacia la raíz.
•A medida que leemos el input, los posibles árboles
se codifican en un estado interno.
Parseo y compiladores
Casos problemáticos:
Lenguajes
Lenguajes
regulares
YACC
La parte que
ER + código GLC + código uno tiene que
hacer
LEX YACC
•http://www.giaa.inf.uc3m.es/docencia/II/PL2/herra
mientas/YACC.pdf
•http://epaperpress.com/lexandyacc/
•http://dinosaur.compilertools.net/