Fondamenti dell`informatica

Transcript

Fondamenti dell`informatica
Fondamenti dell’informatica
Teoria dei linguaggi formali
Rosario Culmone
[email protected]
4/4/2008
UNICAM - p. 1/42
Linguaggi
▲
▲
▲
▲
4/4/2008
Definizione di grammatica di Chomsky
Derivazione di stringhe e generazione di linguaggi
Classi di grammatiche e di linguaggi
Linguaggi di tipo 0, 1, 2, 3
UNICAM - p. 2/42
Modi per definire un linguaggio
metodo di costruzione delle stringhe del linguaggi basato sul
concetto di riscrittura
generativo
riconoscitivo
algebrico
4/4/2008
automa
espressioni regolari
UNICAM - p. 3/42
Grammatiche di Chomsky
Sono definite come G = hVT , VN , P, Si
▲ VT simboli terminali
▲ VN simboli non terminali, detti anche variabili o categorie sintattiche
▲ P produzioni
▲ S simbolo non terminale iniziale detto assioma S ∈ VN o seme del processo
generativo
Sia V = VT ∪ VN , una regola di produzione α → β, in cui α ∈ V ∗ VN V ∗ e
β ∈ V ∗ . Il significato è che α può essere rimpiazzato con β
Ad esempio aC → baB
4/4/2008
UNICAM - p. 4/42
Riscrittura
Forma sintetica delle produzioni: se si ha α → β1 , . . . , α → βn si può scrivere
α → β1 | · · · | βn
Tra due stringhe φ e ψ esiste una derivazione diretta, indicata con φ =⇒ ψ, se
esistono α ∈ V ∗ VN V ∗ e β, γ, δ ∈ V ∗ tali che φ = γαδ, ψ = γβδ e α → β ∈ P .
Ad esempio AbbaBcB =⇒ AbbbCcB applicando la produzione aB → bC
Ripetendo la derivazione diretta si ha una derivazione
∗
Tra due stringhe φ e ψ esiste una derivazione, indicata con φ =⇒ ψ, se
esistono n ≥ 1 stringhe α1 , . . . , αn derivabili direttamente l’una dall’altra tali che
φ = α1 e ψ = αn
Ad esempio: se si hanno le seguenti produzioni aB → bC, C → dC si ha:
∗
AbbaBcB =⇒ AbbbddCcB dato che
AbbaBcB =⇒ AbbbCcB =⇒ AbbbdCcB =⇒ AbbbddCcB
4/4/2008
UNICAM - p. 5/42
Forma di frase
Data una grammatica G = hVN , VT , P, Si una forma di frase è una qualunque
∗
stringa x tale che x ∈ V ∗ e S =⇒ x ovvero qualsiasi stringa derivabile
dall’assioma
Il linguaggio generato da G è costituito da sole forme di frase composte solo da
∗
terminali, ovvero L(G) = {x | S =⇒ x ∧ x ∈ VT∗ }
4/4/2008
UNICAM - p. 6/42
an bn cn
Esempio: G = h{a, b, c}, {S, A, B, C}, P, Si
1 S → aSBC 4 aB → ab 7 cC → cc
2 S → aBC
5 bB → bb
3 CB → BC
6 bC → bc
Ad esempio per generare la stringa aabbcc
1
2
3
4
5
6
S =⇒ aSBC =⇒ aaBCBC =⇒ aaBBCC =⇒ aabBCC =⇒ aabbCC =⇒
7
aabbcC =⇒ aabbcc
4/4/2008
UNICAM - p. 7/42
Grammatiche equivalenti
Due grammatiche G1 e G2 si dicono equivalenti se L(G1 ) = L(G2 )
Esempio date le grammatiche
G1 = h{a, b}, {S, A}, P, Si con P = {S → aA | b, A → aS}
G2 = h{a, b}, {S, A}, P, Si con P = {S → Ab | b, A → aAa | aa}
sono equivalenti perché generano entrambe il linguaggio
L = {an b | n/2 = 0, n > 0}. Ad esempio la stringa aaaab può essere generata:
Con G1
S =⇒ aA =⇒ aaS =⇒ aaaA =⇒ aaaaS =⇒ aaaab
Con G2
S =⇒ Ab =⇒ aAab =⇒ aaaab
4/4/2008
UNICAM - p. 8/42
Categorie di linguaggi
Le grammatiche di Chomsky si possono classificare in base alla potenza
espressiva. Le limitazioni si basano su regole delle produzioni.
▲ tipo 0, non limitate
▲ tipo 1, contestuali (context sensitive)
▲ tipo 2, non contestuali (context free)
▲ tipo 3, regolari
4/4/2008
UNICAM - p. 9/42
Tipo 0
Sono basate sulle produzioni generali senza restrizioni:
α → β, α ∈ V ∗ VN V ∗ , β ∈ V ∗
I linguaggi di tipo 0 sono i linguaggi generati da grammatiche di tipo 0.
Esempio il linguaggio L = {an bn | b ≥ 0} è di tipo 0 in quanto generabile dalla
grammatica con produzioni:
S
→ aAbX | ǫ
aB → aaAb
bX → b
A
→ ǫ
Con queste grammatiche possono esistere infinite derivazioni per la stessa
stringa del linguaggio generabile. Inoltre tali grammatiche si indicano anche
come non monotone in quanto permettono la diminuzione della dimensione
della forma di frase applicando le produzioni.
4/4/2008
UNICAM - p. 10/42
Tipo 1
Sono basate su produzioni del tipo:
α → β, α ∈ V ∗ VN V ∗ , β ∈ V + con |α| ≤ |β|
I linguaggi di tipo 1 sono i linguaggi generati da grammatiche di tipo 1
Esempio il linguaggio L = {an bn cn | n ≥ 1} è di tipo 1 in quanto generabile
dalla grammatica con produzioni:
S
→ aSBC | aBC bB → bb
CB → BC
bC → bc
aB
→ ab
cC → cc
Le produzioni di tipo 1 non riducono la lunghezza delle forme di frase
(monotone)
Il linguaggio L = {an bn | n ≥ 1} è di tipo 1 in quanto può essere generabile
dalla grammatica con produzioni:
S
→ aAB | ab
aA → aaAB
B
→ b
4/4/2008
UNICAM - p. 11/42
Tipo 2
Sono basate su produzioni del tipo:
A → β, A ∈ VN , β ∈ V +
I linguaggi di tipo 2 sono i linguaggi generati da grammatiche di tipo 2
Esempio il linguaggio L = {an bn | n ≥ 1} è di tipo 2 in quanto generabile dalla
grammatica con produzioni:
S → aSb | ab
4/4/2008
UNICAM - p. 12/42
Tipo 3
Sono basate su produzioni del tipo:
A → a | bB con A, B ∈ VN , a, b ∈ VT
I linguaggi di tipo 3 sono i linguaggi generati da grammatiche di tipo 3
Esempio il linguaggio L = {abn | n ≥ 1} è di tipo 3 in quanto generabile dalla
grammatica con produzioni:
S → aB
B → bB | b
Le grammatiche di tipo 3 si chiamano anche grammatiche regolari e possono
essere descritte in modo algebrico con espressioni regolari
4/4/2008
UNICAM - p. 13/42
Contesto delle grammatiche di tipo 1
Nella definizione originali di contesto, Chomsky intendeva la seguente regola
Se α → γ
con α = φ1 Aφ2 e γ = φ1 βφ2 e con A ∈ VN , β ∈ V + , φ1 , φ2 ∈ V ∗ (contesto)
Ad esempio nella grammatica per il linguaggio L = {an bn v n | n ≥ 1} le
produzioni:
aB → ab, bB → bb, bC → bc, cC → cc
▲ Le produzioni contestuali si Chomsky sono di tipo 1
▲ Le produzioni di tipo 1 possono essere facilmente strasformate in produzioni
contestuali
La produzione CB → BC che non ha contesto può essere trasformata in
produzioni contestuali:
CB → CX
CX → BX
BX → BC
4/4/2008
UNICAM - p. 14/42
Grammatiche context free
Sono caso particolare delle produzioni di tipo contestuale dove φ1 , φ2
(contesto) sono entrambe nulle
4/4/2008
UNICAM - p. 15/42
Tipo 3
Sono basate su produzioni del tipo:
A → aB oppure A → a con A, B ∈ VN , a ∈ VT
I linguaggi di tipo 3 sono i linguaggi generati da grammatiche di tipo 3
Esempio il linguaggio L = {an b | n ≥ 0} è di tipo 3 in quanto è generato dalla
grammatica con le produzioni:
S → aS | b
4/4/2008
UNICAM - p. 16/42
Linguaggio stretto
Un linguaggio è strettamente di tipo n se esiste una grammatica di tipo n che lo
genera e non esiste nessuna grammatica di tipo m > n che lo genera.
Il linguaggio L = {an bn | n ≥ 0} è generato da una grammatica di tipo 2 e non
è generabile con nessuna grammatica di tipo 3
Il linguaggio L = {an bn cn | n ≥ 0} è generato da una grammatica di tipo 1 e
non è generabile con nessuna grammatica di tipo 2 o 3
4/4/2008
UNICAM - p. 17/42
Relazioni
T IPO 0
T IPO 1
{an bn cn }
{an bn }
T IPO 2
T IPO 3
{an b}
4/4/2008
UNICAM - p. 18/42
Riconoscitori
Ogni tipo di linguaggio ha il suo specifico riconoscitore.
tipo 0
Macchina di Turing
L’automa più potente che conosciamo. Ogni modello di calcolo o
automa può essere simulato da questo tipo di automa
Tipo 1 Automa limitato linearmente
Simile alla Macchina di Turing ma con con lunghezza del nastro
proporzionale all’elemento da riconoscere
tipo 2
Automa a pila non deterministico
Automa a stati finiti con capacità di memorizzare stati intermedi
nel riconoscimento di un elemento del linguaggio
tipo 3
Automa a stati finiti deterministico o non deterministico
Automa nella forma più semplice, numero finito di stati e nessuna
capacità di memorizzazione
4/4/2008
UNICAM - p. 19/42
Automa a pila
Un automa a pila o automa push-down o stack automata è una macchina
astratta adatta a riconoscere ed accettare quei linguaggi che nelle
grammatiche formali sono detti di tipo 2, non contestuali o context-free. Il nome
di tale macchina deriva dal fatto che come memoria di lavoro utilizza una
struttura dati detta stack.
La pila o stack è un tipo di dato astratto su cui è possibile invocare solo tre
operazioni, push, pop ed empty. La pila realizza il comportamento LIFO (Last
In First Out).
s.push(e) inserisce l’elemento e in cima alla pila s
▲ x = s.pop() estrae dalla testa un elemento e lo pone in x
▲ s.empty() produce true o f alse se la pila non possiede alcun elemento o ne
possiede almeno uno
Valgono le seguenti proprietà: e = s.push(e).pop() e
s.push(e).push(l) 6= s.push(l).push(e)
▲
4/4/2008
UNICAM - p. 20/42
Automa a pila non deterministico
Un automa a pila non deterministico M = hΣ, Γ, Z0 , Q, q0 , F, δi, dove:
Σ
è l’alfabeto di input
Γ
è l’alfabeto dei simboli della pila
Z0 è il carattere (appartenente a Γ) iniziale della pila
Q
è un insieme finito e non vuoto di stati
q0 (appartenente a Q) è lo stato iniziale
F
è un sottoinsieme di Q contenente gli stati finali
δ
è la funzione di transizione (parziale) δ : Q(Σ ∪ {ǫ}) × Γ → P (Q × Γ∗ )
P è un sottoinsieme dell’insieme delle parti di Q × Γ∗ ovvero di uno stato e una
stringa di simboli della pila
4/4/2008
UNICAM - p. 21/42
Funzione di transizione
Ad esempio se lo stato corrente è q1 e lo stato della pila e dell’input è il
seguente
q1
A
Z0
a
b
b
La funzione di transizione potrebbe essere:
δ(q1 , a, A) = {(q2 , BA), (q3 , ǫ)}
In modo non deterministico l’automa si pone nel suo successivo stato q2 o q3 e
la pila sarà
B
A
Z0
4/4/2008
o
Z0
UNICAM - p. 22/42
Lettura dell’input
Se nell’alfabeto dell’input è presente ǫ allora l’automa può cambiare stato
senza spostare la testina:
δ(qi , ǫ, A) = {(qj , BA), (qh , ǫ)}
Il secondo valore della coppia (stato, carattere della pila) ovvero il carattere da
porre in cima alla pila sostituisce quello considerato dalla funzione di
transizione. Quindi con (qj , BA) il carattere sulla pila A viene sostituito con BA
mentre con la seconda coppia viene sostituito con ǫ ovvero il carattere A in
cima alla pila viene cancellato.
Operativamente l’automa quando applica la funzione di transizione effettua una
operazione di pop() e successivamente una operazione di push(N ). Quindi è
possibile effettuare anche un push(ǫ)
4/4/2008
UNICAM - p. 23/42
Esempio di automa a pila
Vediamo come esempio l’automa a pila M che riconosce il linguaggio
L = {an bn | n > 0}. L’automa potrebbe essere (accettazione per stato finale):
M = h{a, b}, {Z0 , A0 , A}, Z0 , {q0 , q1 , q2 }, q0 , {q2 }, δi
La funzione di transizione può essere rappresentata con una tabella, ha tre
input e due output.
Z0
a
b
q0
q1
q2
4/4/2008
q0 , A
A0
A
a
b
a
b
q0 , AA0
q2 , A0
q2 , A0
q0 , AA
q1 , ǫ
q1 , ǫ
UNICAM - p. 24/42
Esempio di accettazione
Verifichiamo che l’automa a pila precedentemente definito accetti la stringa
aaabbb. La tabella evidenzia i cambi di stato e lo stato della pila durante la
computazione
Input
a
a
a
b
b
b
4/4/2008
Stato/prima → dopo
q0 → q 0
q0 → q 0
q0 → q 0
q0 → q1
q1 → q1
q1 → q2
P ila/prima → dopo
Z0 → A
A → AA0
AA0 → AAA0
AAA0 → AA0
AA0 → A0
A0 → A0
UNICAM - p. 25/42
Automa a pila deterministico
Un automa a pila deterministico è un automa a pila M = hΣ, Γ, Z0 , Q, q0 , F, δi,
tale che per ogni carattere a ∈ Σ, per ogni stato Z ∈ Γ e per ogni stato q ∈ Q:
|δ(q, a, Z)| + |δ(q, ǫ, Z)| < 2
4/4/2008
UNICAM - p. 26/42
Configurazione di un automa a pila
Dato un automa a pilaM = hΣ, Γ, Z0 , Q, q0 , F, δi si dice configurazione di M
una tripla hq, x, γi, dove
▲ q ∈ Q, q è lo stato corrente dell’automa
▲ x ∈ Σ∗ , x è la stringa ancora da leggere come input
▲ γ ∈ Γ∗ , γ è la situazione corrente della pila
Esiste una transizione dalla configurazione hq, x, γi alla configurazione
hq ′ , x′ , γ ′ i e scriveremo h, q, x, γi → h, q ′ , x′ , γ ′ i se vale:
▲ x = ax′ ∧ γ = Zη ∧ γ ′ = ξη ∧ (q ′ , ξ) ∈ δ(q, a, Z)
▲ x = x′ ∧ γ = Zη ∧ γ ′ = ξη ∧ (q ′ , ξ) ∈ δ(q, ǫ, Z) nel caso si cambi stato e pila
senza leggere nulla
Esiste una computazione da ci a ck se esiste una sequenza di configurazioni
c0 , c1 , . . . , cn tali che c0 = ci e cn = ck e pr ogni i < n si ha che ci → ci+1
4/4/2008
UNICAM - p. 27/42
Linguaggio accettato da automa a pila
Un linguaggio riconosciuto da un automa a pila può essere accettato in due
modi:
▲ Accettazione per pila vuota. Una stringa è accettata da un automa a pila M
se e solo se al termine della scansione della stringa la pila è vuota, quindi
∗
L(M ) = {x | hq0 , x, Z0 i → hq, ǫ, ǫi}
▲
Accettazione per stato finale.
Una stringa è accetata da un automa a pila M se e solo se al termine della
scansione della stringa l’automa si trova in uno stato finale, quindi
∗
L(M ) = {x | hq0 , x, Z0 i → hq, ǫ, γi q ∈ F, γ ∈ Γ∗ }
Le due modalità sono equivalenti
4/4/2008
UNICAM - p. 28/42
Esempio di accettazione per pila vuota
Lo stesso linguaggio dell’esempio precedente L = {an bn | n > 0} ma con
accettazione per pila vuota
La tabella di transizione
Z0
a
b
q0
q1
4/4/2008
q0 , A
A
a
b
q0 , AA
q1 , ǫ
q1 , ǫ
UNICAM - p. 29/42
Esempio di computazione
Verifichiamo che l’automa a pila precedentemente definito accetti la stringa
aaabbb. La tabella evidenzia i cambi di stato e lo stato della pila durante la
computazione
Input
a
a
a
b
b
b
4/4/2008
Stato/prima → dopo
q0 → q 0
q0 → q 0
q0 → q 0
q0 → q1
q1 → q1
q1 → q1
P ila/prima → dopo
Z0 → A
A → AA
AA → AAA
AAA → AA
AA → A
A→ǫ
UNICAM - p. 30/42
Forme normali per grammatiche libera da
contesto
La forma delle produzioni della grammatiche libera da contesto è normalmente
A → β ma possiamo imporre delle regole con cui si scrivono le produzioni.
Queste regole vanno sotto il nome di forme normali
▲ Forma Normale di Chomsky. Ogni produzione può presentarsi solo nelle
seguenti forme: A → BC o A → a
▲ Forma Normale di Greibach. Ogni produzione può presentarsi nella forma
A → aβ dove β ∈ VN∗ . Notare che β può essere anche ǫ
La FNG è simile alle grammatiche regolari. Infatti una grammatica regolare ha
la forma di A → a oppure A → aB. Il vincolo rilassato è che a differenza delle
grammatiche regolari sono permessi più non terminali a destra del simbolo
terminale.
4/4/2008
UNICAM - p. 31/42
Uso della FNG
Il motivo di esprimere in forma normale le produzioni ha diversi scopi
▲ permette di costruire l’automa a pila che riconosce il linguaggi
▲ permette di caratterizzare i linguaggi analizzabili in modo efficiente
Bisogna definire il metodo per trasformare qualsiasi produzione di una
grammatica libera da contesto in produzioni in FNG.
4/4/2008
UNICAM - p. 32/42
Traformazione in FNG [1]
Chiamiamo A − produzioni tutte le produzioni del tipo A → β1 | β2 | · · · | βn
Operazione di sostituzione.
Data una grammatica G le cui produzioni includono A → α1 Bα2 (α1 , α2 ∈ V ∗ ) e
B → β1 | β2 | · · · | βn e non esistono altre B − produzioni allora si possono
riscrivere le produzioni nella forma A → α1 β1 α2 | α1 β2 α2 | · · · | α1 βn α2
4/4/2008
UNICAM - p. 33/42
Traformazione in FNG [2]
Operazione dell’eliminazione della ricorsione sinistra.
Le A − produzioni del tipo A → Aα1 | . . . Aαm | β1 | · · · | βn (nessuna delle βi
inizia con A) possono essere sostituite con le produzioni:
A → β1 B | · · · | βn B | β1 | · · · | βn
B → α1 B | · · · | αn B | α1 | · · · | αm
Ad esempio se si ha A → AaB | b non possiamo applicare nessun tipo di
sostituzione per eliminare la ricosione sinistra. Il metodo, quindi, consiste nel
trasformare la ricorsione sinistra in ricorsione destra e esponendo davanti un
simbolo terminale (come vuole FNG).
La forma A → Aα1 | . . . Aαm | β1 | · · · | βn produce forme di frase del tipo
(β1 | · · · | βn )(α1 | · · · | αm )∗
Quindi la prima produzione A → produce la prima parte della struttura di frase
mentre la seconda B → genera la parte finale (e ricorsiva) della struttura di
frase.
4/4/2008
UNICAM - p. 34/42
Traformazione in FNG [3]
E’ quindi possibile dimostrare che data una grammatica G di tipo 2 tale che
ǫ∈
/ L(G) esiste una grammatica G′ in GNF con L(G) = L(G′ )
La dimostrazione consiste nella concreta creazione di G′ mediante un
algoritmo che alterna, in modo opportuno, sostituzione ed eliminazione della
ricorsione sinstra sino ad ottenere una grammatica equivalente in FNG
4/4/2008
UNICAM - p. 35/42
Linguaggi liberi da contesto e automi a
pila
Se L(G) è un linguaggio libero da contesto esiste un automa a pila M tale che
L(M ) = N (M )
Data una grammatica G = hΣ, VN , S, P i costruiamo un automa a pila che
riconosce il linguaggio generato da G ovvero L(G).
L’automa a pila è definito nel seguente modo M = hΣ, Γ, Z0 , Q, q0 , F, δi dove
▲ Σ, l’alfabeto dell’automa coincide con i simboli terminali della grammatica
▲ Γ = VN , ovvero l’alfabeto della pila coincide con i simboli non terminali della
grammatica
▲ Z0 = S, ovvero il simbolo iniziale sulla pila coincide con il simboli non
terminale della grammatica (assioma)
▲ Q = {q}, l’automa ha un solo stato
▲ q0 = q, ovvero lo stato iniziale coincide con l’unico stato dell’automa
▲ F = ∅, l’automa non ha stati finali perché accetta per pila vuota
4/4/2008
UNICAM - p. 36/42
Funzione di transizione
Se G contiene le produzioni A → aγ1 | · · · | aγn con γi ∈ VN∗
allora si ha
δ(q, a, A) = {(q, γ1 ), . . . , (q, γn )}
Ad esempio data la grammatica che genera il linguaggio an bn (forma GNF)
S
A
B
→
→
→
aSA | aA | bSB | bB
a
b
S
q
4/4/2008
A
a
b
a
q, SA
q, A
q, SB
q, B
q, ǫ
B
b
a
b
q, ǫ
UNICAM - p. 37/42
Dalla grammatica all’automa e viceversa
∗
Per dimostrare l’equivalenza bisogna dimostrare che hq, x, Si → hq, ǫ, ǫi se e
∗
solo se S =⇒ x
Piu in generale considerando anche una situazione intermedia si dovrà avere
∗
∗
che hq, xu, Si → hq, u, γi se e solo se S =⇒ xγ ovvero se l’automa è andato
avanti sino ad accettare x allora la grammatica avrà prodotto x e deve ancora
riscrivere γ, lo stesso γ che si trova ancora sulla pila dell’automa
Se un linguaggio è accettato da un automa a pila M mediante pila vuota,
esiste una grammatica non contestuale G che lo genera, tale cioè che
L(G) = N (M ). Pertanto i linguaggi liberi da contesto coincidono con i linguaggi
riconosciuti da automi a pila non deterministici
4/4/2008
UNICAM - p. 38/42
Esempio
Si consideri la stringa abba e vediamo come si evolve la generazione della
stringa con la grammatica e parallelamente con l’automa
S =⇒ aSA =⇒ abBA =⇒ abbA =⇒ a
La pila dell’automa avrà il seguente andamento
S
4/4/2008
S
A
B
A
A
UNICAM - p. 39/42
Compilatori e interpreti
L’analisi sintattica (Parsing) di una stringa consiste nel ricostruire l’albero di
derivazione per poter:
▲ comprendere la struttura della stringa
▲ verificare la sua correttezza sintattica
L’analisi sintattica è una fase fondamentale nella traduzione di un programma
da un linguaggio ad un altro. Le fasi di un compilatore o interprete sono
▲ Analisi lessicale (Scanning). Individuazione dei "tokens" ovvero oggetti
sintattici indivisibili
▲ Analisi sintattica (Parsing). Individuazione degli alberi di derivazione
▲ Analisi semantica. Generazione del codice intermedio o oggetto
▲ Ottimizzazione. Ottimizzazione del codice generato
4/4/2008
UNICAM - p. 40/42
Strumenti per la generazione di linguaggi
Lo studio dei linguaggi ha permesso di produrre numerosi strumenti per la
generazione di compilatori e interpreti. Ad esempio:
▲ Analisi lessicale. Lex, flex
▲ Analisi sintattica. Yacc, JavaCC,
▲ Analisi semantica. JavaCC, Coco/R
4/4/2008
UNICAM - p. 41/42
Oltre i linguaggi
Le grammatiche Context-free non sono limitate alle applicazioni matematiche
(linguaggi "formali"). La grammatica del Lojban, è un linguaggio artificiale con
un immenso potere espressivo, è context-free, e non ambiguo. Recentemente
si è pensato che una classe poetica chiamata Venpa del Tamil è guidata da
una grammatica context-free.
4/4/2008
UNICAM - p. 42/42