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