Comments
Description
Transcript
Cosa è un linguaggio?
Teoria dei linguaggi Cosa è un linguaggio? Alfabeto = insieme di simboli (caratteri ascii) Stringa insieme finito di simboli di un alfabeto ε e la stringa vuota (talvolta denotata da λ) |s| rappresenta la lunghezza di una stringa. Linguaggio un insieme di stringhe ∅, l’insieme vuoto è un linguaggio {ε} è il linguaggio contenente la sola stringa vuota L’insieme di tutti I possibile ptogrammi C è un linguaggio L’insieme di tutti I possibili identificatori in un linguaggio è un linguaggio 1 Terminologia Dato un alfabeto T = {a, b} su di esso si possono definire infiniti linguaggi L1 = {a, aa, ab, aab} L2 = {a,b} L3 = linguaggio contenente lo stesso numero di a e di b Definizioni Cardinalità di un linguaggio = numero di stringhe appartenenti al linguaggio Frase = stringa appartenente al linguaggio Linguaggio infinito = linguaggio con cardinalità infinita Linguaggio finito = linguaggio con cardinalità finita Linguaggio vuoto Φ = linguaggio con cardinalità 0 stringa vuota = ε oppure λ 2 Operazioni su stringhe Concatenamento x=a y = bc x ·y = abc sε =s εs=s Sottostringhe x = bc Riflessione x = ab y = ba Potenza m-esima sn = s s s .. s ( n times) s0 = ε x=a x4 = aaaa y = ab y3 = ababab Operazioni su i linguaggi Concatenamento L1 = {a, b} L2 = {c, d} L = L1 ·L2 = = {xy | x ∈ L1, y ∈ L2} = = {ac, ad, bc, bd} Unione L1 = {a, b} L2 = {c, d} L = L1 ∪ L2= = {x ∈ L1 ∪ L2} = = {a, b, c, d} Potenza m-esima Lm = Lm-1 ·L L0 = Φ Esempio L = {a, b} L3 = L2 ·L = {aa, ab, ba, bb} ·{a, b} = = {aaa, aba, baa, bba, aab, abb, bab, bbb} 3 Linguaggio universale Definiamo linguaggio universale (monoide libero) su un alfabeto T l’insieme di tutte le stringhe di tale alfabeto Il linguaggio universale si può definire come limite dell’elevamento a potenza L* = stella di Kleene = ∪n=0Ln = L0 ∪ L1 ∪ L2 ∪…. ∝ Positive Closure L+ = ∪n=1Ln = L1 ∪ L2 ∪…. Esempi di Linguaggi L1 = {a,b,c,d} L2 = {1,2} L1L2 = {a1,a2,b1,b2,c1,c2,d1,d2} L1 ∪ L2 = {a,b,c,d,1,2} L13 = tutte le stringhe di lunghezza 3 (con a,b,c,d} L1* = tutte le stringhe con a,b,c,d e la stringa vuota L1+ = non include la stringa vuota 4 Grammatiche Per descrivere un linguaggio sia esso un linguaggio naturale o un linguaggio di programmazione è necessario definire un insieme di regole a cui deve sottostare ogni frase del linguaggio per essere corretta. Tali regole devono specificare tutte o solo le stringhe appartenenti al linguaggio Per fare ciò è necessario quindi introdurre: una grammatica: cioè una specifica formale di tutte le strutture di frase (o frasi) consentite un algoritmo di riconoscimento: cioè un metodo per analizzare le frasi e determinare la loro struttura Grammatiche generative Una Grammatica generativa può essere pensata come un insieme di regole che generano tutte e sole le frasi del linguaggio Noam Chomsky ha definito quattro classi di “complessità” per le grammatiche generative Chomsky Hierarchy. 5 The Chomsky Hierarchy Tipo 0 - Grammatiche generali - Macchina di Turing Tipo1 - Grammatiche Dipendenti dal Contesto Tipo 2 - Grammatiche non contestuali - Automi a Pila Tipo 3 - Grammatiche regolari - Automi a stati finiti Tipo 0 Tipo 1 Tipo 2 Tipo 3 Grammatiche generative Una grammatica generativa G è espressa come una quadrupla G=(V, Σ, P, S), dove: V è l’insieme dei non terminali o variabile (nel seguito utilizzeremo le lettere maiscule) Σ è l’insieme finito di terminali (utilizzaremo le lettere minuscole) P è l’insieme finito delle produzioni o regole nella forma α→β S è un simbolo speciale appartenente all’insieme dei non terminali V chiamato assioma Normalmente V ∩ Σ = ∅. Ogni simbolo della grammatica è un elemento di V ∪ Σ. 6 Grammatiche regolare (tipo 3) Una grammatica regolare (RG) è denotata da G = (V, Σ, P,S), dove V è l’ insieme dei non terminali, Σ è l’insieme dei terminali, S è un non-terminale chiamato assioma, P è un insieme finito di produzioni, con ogni produzione nella forma A →β, con: A ∈ V e β ∈ (V ∪ Σ)*. ∀ produzione in una grammatica regolare regolare le produzioni possono consistere in produzioni come le seguenti A → aB, B → b (grammatiche lineari destre) oppure B → Ab, A → a (grammatiche lineari sinistre) Generalmenre, le lettere greche minuscole denotano stringhe in (V ∪ Σ)*. Esempio di grammatica V = {S} Σ = {a, b} P = {S → ε (stringa vuota) S → abS S = {S} Stringhe appartenenti al linguaggio: S → abS → ab S → abS → ababS → abab 7 Nelle grammatiche di tipo 3, il solo non terminale nella parte destra (RHS) della produzione sempre si trova alla fine della regola (o alternativamente all’inizio) Le grammatiche di tipo 3 sono molto restrittive (non si possono utilizzare per la sintassi dei linguaggi di programmazione) ma i loro riconoscitori sono molto efficenti. Cosa è un linguaggio regolare? Sono tutti e soli i linguaggi che si possono generare con grammatiche generative di tipo 3 Un linguaggio che può essere espresso mediante le operazioni di concatenamento, unione e stella di Kleene applicate un numero finito di volte a linguaggi unitari e al linguaggio vuoto Ogni linguaggio finito è regolare 8 Automi a stati finiti Un riconoscitore per un linguaggio è un programma che prende iuna stringa x e risponde “si” se x è una frase del linguaggio, “no” altrimenti. Chiameremo Automa a stati finiti il riconoscitore per il linguaggi regolari Un automa a stati finiti può essere deterministico (DFA o DFSA) o non deterministico (NFA o NFSA) Sia DFA che NFA riconoscono I linguaggi regolari deterministico – piu’ veloce, ma talvonta poco compatto non-deterministico – piu’ lento, ma piu compatto Per la costruzione degli analizzatori lessicali si utilizzano automi deterministici. Finite state automata (FSA) Un FSA ha: un insieme finito di stati un insieme di transizioni (o mosse) da uno stato ad un altro stato etichettato da caratteri di Σ uno stato speciale chiamato stato iniziale S0 un insieme di stati finali o di accettazione (stringa valida) 9 Gli automi a stati finiti sono rappresentati graficamente da un digramma di transizioni. Iniziamo dallo stato iniziale Il carattere di input a genera una transizione dallo stato corrente ad uno altro stato se esiste una mossa dallo stato corrente etichettata con il carattere di input Se non esiste una mossa etichetata con il carattere di unput la stringa è valida se lo stato è di accettazione (stato finale) Esempio (a b (c)+ )+. Non-Deterministic Finite Automaton (NFA) Un automa a stati finiti non-deterministico (NFA) è un modelllo matematico che consiste di: S – un insieme di stati Σ - un insieme di simboli di input (alfabeto) mosse – una funzione che data una coppia stato-simbolo restituisce uno stato, cioè Mossa : S x Σ → S s0 - uno stato iniziale, s0 ∈ S F – un insieme di stati finali F ⊆ S In un NFA sono consentite ε-mosse. In altre parole, esistono transizioni che non consumano simboli due mosse che da uno stato per effetto dello stesso simbolo portano a due stati diversi Un NFA accetta una stringa x, se e solo se esiste un cammino dallo stato iniziale ad uno stato finale tale ogni arco sia etichettato coni simboli in x 10 Costruzione del riconoscitore di un FSA lettera = a .. z, A..Z cifra = 0..9 Del è un qualsiasi carattere diverso da a..z e 0..9 lettera | cifra 0 lettera | _ 1 2 Del a..z 0..9 - del FINALI 0 1 Error 1 Error NO 1 1 1 Error 2 NO 2 Error Error Error Error SI 11 NFA (Esempio) 0 rappresenta lo stato iniziale s0 {2} è l’insieme degli stati finali F Σ = {a,b} S = {0,1,2} a La funzione di transizione e descritta a b dalla tabella 0 1 2 start a b b 0 {0,1} {0} Grafo di transizione di un NFA 1 _ {2} 2 _ _ Il linguaggio riconosciuto da questo NFA è (a | b) * a b Esempio: commenti C++ 12 Espressioni regolari Una espressione regolare puo essere: ε (la stringa vuota) e denota il linguaggio {ε} ∀ simbolo terminale a, a è una espressione regolare se R è una espressione regolare R* è una espressione regolare (R* è chiamate stella di kleene o chiusura di R). Per esempio: (ab)* genera: ε, ab, abab, etc. se R è una espressione regolare R+ è una espressione regolare. Per esempio: (ab)+ genera: ab, abab, etc. se R e S sono espressioni regolari, R ∪ S (oppure R|S) è una espressione regolare che si comporta come R o S se R e S sono espressioni regolari, R · S (oppure RS) è una espressione regolare che descrive la concatenazione di R seguito da S [a-z] è una abbreviazione per denotes a|b|c|..|z Espressioni regolare Espressioni regolai sopra un alfabeto Σ Espressione reg. Linguaggio ε {ε} a∈ Σ {a} L(r1) ∪ L(r2) (r1) | (r2) (r1) (r2) L(r1) L(r2) (L(r))* (r)* (r) L(r) (r)+ = (r)(r)* (r)? = (r) | ε 13 Esempi (c|d|e)(a|b) rappresenta il linguaggio L = {ca, cb, da, db, ea, eb} (a|b)*c(a|b)* rappresenta l’insieme di stringhe con zero o piu “a” seguite da “c”, seguite da zero o piu “b” (a b (c)+ )+ 14 Espressioni regolari Le parentesi possono essere omesse nelle espressioni regolare utilizzando le regole di precedenza * concatenation | ab*|c means highest next lowest (a(b)*)|(c) Esempi Σ = {0,1} 0|1 => {0,1} (0|1)(0|1) => {00,01,10,11} 0* => {ε ,0,00,000,0000,....} (0|1)* => tutte le stringhe con 0 e 1, compresa la stringa vuota Definizioni Regolari LA scrittura di espressioni regolari per alcuni linguaggi può essere complessa perche le espressioni regolari che lo descrivono possono essere complesse, In questo caso si usano le definizioni regolari”. Noi possiamo attribuire dei nomi come simboli per la definizione di altre espressioni regolari. Una definizione regolare è una sequenza di definizioni nella forma: d1 → r 1 d2 → r 2 . dn → r n dove di è un nome e ri è una espressione regolare sui simboli Σ∪{d1,d2,...,di-1} 15 Definizioni regolari Esempio: Identificatori in C lettera → A | B | ... | Z | a | b | ... | z cifra → 0 | 1 | ... | 9 identificatore → lettera (lettera | cifra ) * SE noi scriviamo direttamente l’espressione regolare avremo (A|...|Z|a|...|z) ( (A|...|Z|a|...|z) | (0|...|9) ) * Esempio: Numeri interi senza segno cifra → 0 | 1 | ... | 9 cifra → cifra + opt-fraction → ( . cifra ) ? opt-exponent → ( E (+|-)? cifra ) ? unsigned-num → cifra opt-fraction opt-exponent Proprieta’ algebriche Assioma Descrizione r |s = s|r | e’ commutativo r |(s|t) = r |(s|t) | è associativo (rs)t = r (st) La concatenazione è associativa La concatenazione gode della prorprietà distributiva su | ε è l’elemento neutro per la concatenazione r (s|t) = rs|rt (s|t)r = sr |tr εr = r rε = r r* = ( r |ε)* r** = r* * è idenpotente 16 Grammatiche regolari - Automi a stati finiti (FSA) Esiste una corrispondenza biunivoca tra grammatiche regolari ed FSA Esempio Espressione regolare : a*·b·c* Grammatica regolare: V = {S, A, C} T = {a, b, c} P={ S→A A → aA A → bC C → cC C → ε} S = {S} a c P0 b P1 17 Esempio V = {S} T = {a, b} P = {S → ε S → abS S = {S} a P0 P1 b Esempio Grammatica per il linguaggio dei numeri interi V = {S,D} 0,1,2,3,…9 T = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} P = {S → D P0 P1 0,1,2,3…9 S →DS D →0|1|2|3|4|5|6|7|8|9} S = {S} Grammatica per il linguaggio dei numeri interi (non sono accettati numeri come 04) V = {S,D} 1,2,3,…9 T = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} P = {S → D P0 P1 S →0 0,1,2,3…9 S →DS D →1|2|3|4|5|6|7|8|9} P2 0 S = {S} 18 Esempio Esempio V = {S} T = {a, b} P = {S → ε S → abS S = {S} Il seguente FSA riconosce a*b* a non anbn b P0 b P1 La ricorsione è necessaria per modellare anbn (Cioè non è un FSA Le grammatiche regolari sono troppo restrittive per i linguaggi di programmazione e pertanto non sono sufficienti per la costruzione dei compilatori Per esempio, le grammatiche regolari non possono generare il linguaggio anbn con n ≥ 1 (Nota che tale linguaggio corrisponde al Begin e End dei linguaggi di a programmazione) Esistono altri tipi di grammatiche generative che possono generare tale linguaggio. 19 Espressioni regolari - Grammatica regolare Esiste una corrispondenza biunivoca tra linguaggio regolare ed espressione regolare Esempio Espressione regolare : a*·b·c* Regular Grammar: V = {S, A, C} T = {a, b, c} P={ S→A A → aA A → bC C → cC C → ε} S = {S} Grammatiche regolari - Automi a stati finiti (FSA) FSA(Q, T, δ, q0, F) Dove Q = insieme degli stati T insieme di simboli terminali δ insieme delle transizioni, q0 = stato iniziali, F = insieme stati finali G(V, T, P, S) Algoritmo di costruzione V=Q S = q0 ∀ q ∈ Q, ∀ a ∈ T se ∃ una transizione etichettata con a da q a r ∈ Q allora esiste in P la produzione q → a r ∀ q ∈ F, ∃ una produzione q → ε 20 Esempio Q = {A, B, C} a T = {a, b, c, d} F = {B, C} A q0 = A A = δ(A,a), B = δ(A,b), C = δ(B,c), C = δ(C,d), A = δ(C,b) d c b B C b V = {A, B, C} T = {a, b, c, d} B → ε, C → ε A → a A, A → a B, B → c C, C → d C, C → b A S=A Esempio Linea di commento che inizia con “//” a termina con “eol” V = {S, A, C} T = {/, c, e} P={ S → // A A→ cA A → e} E = // c* e P2 P1 c e e = eol c = qualsiasi carattere P0 P1 21 Conversione di una espressione regolare in un Automa a stati finiti La conversione di una espressione regolare in un NFA produce un NFA tale che ogni stato ho solo uno o due successori ed ha un unico stato finale Un espressione regolare può essere convertito in un NFA automaticamente utilizzando le regole di Thomson’s. Queste regole sono semplici e sistematiche Non è detto che sia uil metodo più efficente per effettuare la conversione Garantisceh che il risultante NFA abbia uno stato iniziale e uno stato finale. Forme base Per ε, si costruisce il seguente NFA start ε i f Per a in T, si costruisce il seguente NFA start i a f 22 Recursive Rules Detti N(s) e N(t) gli NFA for s and t. NFA N(s|t): N(s) ε ε start i f ε ε N(t) Recursive Rules NFA N(st): start i N(s) N(t) f 23 Recursive Rules NFA N(s*) ε start ε i ε N(s) f ε NFA N((s)) = N(s) Thomson’s Construction (Example - (a|b) * a ) a: b: a a ε (a | b) b ε ε ε b ε (a|b) * ε ε a ε ε ε b ε ε (a|b) *a ε ε ε a ε ε ε b a ε ε 24 Chiusura La ε chiusura di uno stato è l’insieme degli stati che include: Lo stato stesso, Gli stati che possono essere raggiunti dallo stato attraverso una serie di ε mosse Per calcolare la ε -chiusura di un insieme s: Aggiungere s alla ε -chiusura Se t appartiene alla ε-chiusura(s) e esiste una ε mossa da t a u, aggiungere u alla chiusura e continuare fino a quando possibile Funzione chiusura void close(NFASet S) { while (x in S and x →λy and y notin S) { S = S U {y} } } 25 Costruzione di un DSA da un NFA Eliminazione delle epsilon mosse N (Q, T, δ, q0, F) automa con epsilon mosse N’ (Q, T, δ’, q0, F’) automa senza epsilon mosse con F’ = F ∪ q0 se ε-chiusura(q0) contiene uno stato di F F’ = F altrimenti per ogni a in T esiste δ’(q,a) se esiste δ(q,a) oppure esiste uno stato p tale che δ(p,a), p= δ(q, ε) Costruzione di un DSA da un NFA Eliminazione delle transizioni non deterministiche N (Q, T, δ, q0, F) automa non deterministico senza epsilon mosse M (Q’, T, δ’, q’0, F’) automa deterministico dove Q’ = 2Q F’ = {p ∈ Q’ | p contiene uno stato appartenente a F} q’0 = [q0 ] ∀ p ∈ Q’ e ∀ a ∈ T δ’(p,a) = {s | s ∈ δ(q,a) ∩ F ≠ ∅} 26 Esempio a ε a 2 1 5 a a b 3 4 b Esempio a a a 2 1 a 5 a a b 3 b 4 27 Esempio a a a 2 1 a 5 a a b 3 4 b Esempio [2,3,4] a a [2] [1] [5] a b a [4,5] b [2,4] a b 28 Uno stato S è finale (o accettante) nel DS se contiene uno stato finale in NFA Lo stato iniziale e ε-closure({s0} Conversione di un NFA in un DFA Inserire ε-closure({s0}) come stato non marcato in DS while (c’è uno stato non marcato S1 in DS) do { marcare S1 per ogni simbolo di ingresso a do { S2 Í ε-closure(move(S1,a)) if (S2 ∉ DS) aggiungere S2 in DS come stato non marcato transfunc[S1,a] Í S2 } } DFA MakeDeterministic(NFA N) { DFA D; NFASet T D.StartState = { N.StartState } close(D.StartState) D.States = { D.StartState } while (è possibile aggiungere stati/transizioni){ ∀ S in D.States and c in Σ T = {y in N.States : x→c y per qualche x in S} close(T); if (T notin D.States) { D.States = D.States U {T} D.Trans = D.Trans U {S →c T} }} D.AcceptingStates = { S in D.States : uno stato di accettazione di N in S} } 29 Esempio di conversione di un NFA in un DFA 2 ε 0 ε a 3 ε 1 6 ε ε 7 a 8 ε 4 b 5 ε Esempio di conversione di un NFA in un DFA S0 = ε-closure({0}) = {0,1,2,4,7} S0 in DS come stato non marcato ⇓ marcare S0 ε-closure(move(S0,a)) = ε-closure({3,8}) = {1,2,3,4,6,7,8} = S1 ε-closure(move(S0,b)) = ε-closure({5}) = {1,2,4,5,6,7} = S2 transfunc[S0,b] Í S2 transfunc[S0,a] Í S1 ⇓ marcare S1 ε-closure(move(S1,a)) = ε-closure({3,8}) = {1,2,3,4,6,7,8} = S1 ε-closure(move(S1,b)) = ε-closure({5}) = {1,2,4,5,6,7} = S2 transfunc[S1,a] Í S1 transfunc[S1,b] Í S2 ⇓ marcare S2 ε-closure(move(S2,a)) = ε-closure({3,8}) = {1,2,3,4,6,7,8} = S1 ε-closure(move(S2,b)) = ε-closure({5}) = {1,2,4,5,6,7} = S2 transfunc[S2,a] Í S1 transfunc[S2,b] Í S2 S1 in DS S2 in DS 30 Esempio di conversione di un NFA in un DFA S0 è lo stato iniziale dato che 0 membro di S0={0,1,2,4,7} S1 è lo stato di accettazione (stato finale) del DFA dato che 8 appartiene a S1 = {1,2,3,4,6,7,8} a S1 a S0 a b b S2 b Esempio 31 Conversione di una Espressione Regolare direttamente in un DFAs E’ possibile convertire direttamente una espressione 1. 2. 3. 4. regolare in un DFA (senza creare prima un NFA). Concatenare l’espressione con un simbolo speciale #. r Î (r)# “espressione regolare aumentata” Creare un albero sintattico della “espressione regolare aumentata” In tale albero sintattico tutti gli elementi del vocabolario (più # e ε) sono delle foglie dell’albero Numerare con “position number” tutti gli elementi del vocabolario (più # e ε) Regular Expression Î DFA (cont.) (a|b) * a Î (a|b) * a # • • | a 1 b 2 Albero sintattico di (a|b) * a # # 4 a 3 * “espressione regolare aumentata” • Ogni simbolo e numerato (positions) • Ogni simbolo è una foglia • inner nodes sono operatori 32 followpos Definiamo la funzione followpos followpos(i) -- è l’insime di posizioni che seguono una posizione I nella stringa generata dall’espressione regolare aumentata Esempio, ( a | b) * a # 1 2 3 4 followpos(1) = {1,2,3} followpos(2) = {1,2,3} followpos(3) = {4} followpos(4) = {} firstpos, lastpos, nullable Per valutare followpos, noi abbiamo bisogno di tre funzioni che sono definite per I nodi dell’albero firstpos(n) -- l’insieme di posizioni del first simbolo della stringa generata dalla subexpression di radice n. lastpos(n) -- l’insieme di posizioni del last simbolo della stringa generata dalla subexpression di radice n. nullable(n) -- true se la stringa vuota appartine alla subexpression di radice n, false altrimenti 33 Come valutare firstpos, lastpos, nullable n nullable( n) firstpos(n) lastpos(n) foglia ε true Φ Φ Foglia i false {i} {i} c2 nullable(c1) or nullable(c2) firstpos(c1) ∪ firstpos(c2) lastpos(c1) ∪ lastpos(c2) c2 nullable(c1) and nullable(c2) if (nullable(c1)) firstpos(c1)∪firstpos(c 2) else firstpos(c1) if (nullable(c2)) lastpos(c1) ∪ lastpos(c2) else lastpos(c2) firstpos(c1) lastpos(c1) | c1 • c1 * c true Come valutare followpos Due regole per calcolare la funzione followpos: 1. Se n un concatenation-node (•)con figlio sinistro c1 e figlio destro c2, e i ∈ lastpos(c1), allora firstpos(c2) ⊆ followpos(i). 2. Se n è un star-node (*), e i ∈ lastpos(n), allora firstpos(n) ⊆ followpos(i). Se firstpos e lastpos sono stati calcolati per ogni nodo, followpos può essere calcolato con una visita depth-first dell’albero sintattico. 34 Example -- ( a | b) * a # green – firstpos blue – lastpos {1,2,3} • {4} {1,2,3}• {3} {4}# {4} 4 {1,2}*{1,2}{3}a{3} 3 {1,2} {1,2} | {1} a {1} {2}b {2} 2 1 followpos(1) = {1,2,3} followpos(2) = {1,2,3} followpos(3) = {4} followpos(4) = {} • Dopo aver calcolato followpos possiamo creare il DFA per l’espressione regolare. Algoritmo (RE Î DFA) Creare l’albero sintattico di (r) # Calcolare le funzioni followpos, firstpos, lastpos, nullable Porre firstpos(root) in S (S è l’insieme degli stati del DFA) come stato non marcato. while (∃ s ∈ S non marcato) { s for each simbolo a { s’ Í followpos(s1) ∪ ... ∪ followpos(sn) let s1,...,sn posizioni in s e simboli per quelle posizioni sono a move(s,a) Í s’ if (s’ non e vuoto e non in S put s’ into S come stato non marcato. the start state of DFA is firstpos(root) the accepting states of DFA are all states containing the position of # 35 Esempio -- ( a | b) * a # followpos(1)={1,2,3} followpos(3)={4} followpos(2)={1,2,3} followpos(4)={} S1=firstpos(root)={1,2,3} ⇓ marcare S1 a: followpos(1) ∪ followpos(3)={1,2,3,4}=S2 b: followpos(2)={1,2,3}=S1 ⇓ marcare S2 a: followpos(1) ∪ followpos(3)={1,2,3,4}=S2 b: followpos(2)={1,2,3}=S1 move(S1,a)=S2 move(S1,b)=S1 move(S2,a)=S2 move(S2,b)=S1 b S1 start state: S1 accepting states: {S2} a a S2 b Example -- ( a | ε) b c* # followpos(1)={2} followpos(2)={3,4} followpos(3)={3,4} followpos(4)={} S1=firstpos(root)={1,2} ⇓ marcare S1 a: followpos(1)={2}=S2 move(S1,a)=S2 b: followpos(2)={3,4}=S3 move(S1,b)=S3 ⇓ marcare S2 b: followpos(2)={3,4}=S3 ⇓ marcare S3 c: followpos(3)={3,4}=S3 S2 move(S2,b)=S3 a b S1 move(S3,c)=S3 b S3 c start state: S1 accepting states: {S3} 36 Minimizzare il numero di stati per un DFA Dividere gli stati in due insiemi: G1 : insiemi di stati finali G2 : insieme di stati non finali states Per ogni nuovo gruppo G Partizionare G in sottogruppo take che gli stati s1 e s2 sono nello stesso gruppo iff per tutti I simboli di input a, gli stati s1 e s2 hanno transizioni a stati nello stesso gruppo. Lo stato iniziale del DFA minimizzato è il gruppo contenente lo stato inziale del DFA originale. GLi stati finiale del DFA minimizzato sono I gruppi contenente gli stati finiali del DFA originale. Esempio si minimizzazione a 1 G1 = {2} G2 = {1,3} 2 a b b a G2 cannot be partitioned because 3 move(1,a)=2 move(3,a)=2 b move(1,b)=3 move(2,b)=3 So, the minimized DFA (with minimum states) b {1,3} a a {2} b 37 Minimizing DFA – Esempio a a 1 2 a Groups: 4 b a b 3 {1,2,3} {1,2} b {4} {3} no more partitioning b So, the minimized DFA a b 1->2 2->2 3->4 1->3 2->3 3->3 b a {3} b a {1,2} a b {4} Esempi di espressioni regolari 1. letter(letter|digit)* 2. digits = digit digit* opt_frac = . digits | ε opt_exp = (E(+|-| ε) digits | ε num = digits opt_frac opt_exp 38