Comments
Description
Transcript
Grammatiche libere dal contesto
Grammatiche libere dal contesto G = < VN,VT,P,S > VN - Insieme finito di simboli detti Non terminali VT - Insieme finito di simboli detti Terminali ! !! V = VN ! VT, VN "#, VT "#, VN $ VT =# S-. Simbolo distinto o Assioma del Linguaggio !! S % VN P - Insieme di Produzioni o Regole di Riscrittura ! !! P & VN x V* Processo di generazione La Grammatica G con produzioni E 10 1. E ! E + T | E - T | T 2. T ! T * F | T / F | F 3. F ! ( E ) | i E Genera stringhe aritmetiche ! Esempio: la stringa a + b * c è derivata da E T T T F nel seguente modo: E "E + T !! "T +T ! ! " T + T * F! "F+T*F! " i +T * F! " i + T * i! " i +F * i! " i +i * i! pertanto: E "* a + b*c (regola 1) (regola 1) (regola 2) (regola 2) (regola 3) (regola 3) (regola 2) (regola 3) F F a + b * c - E’ conveniente avere un ordine di applicazione delle regole? - L’albero di generazione può essere costruito in modi diversi? - E’ possibile costruire per la medesima stringa alberi di !derivazione diversi? Alberi di derivazione E E 1. E # E + T | E - T | T 2. T # T * F | T / F | F 3. F # ( E ) | i T T T F F F a + Data una grammatica non contestuale G tutte le stringhe s da essa generabili possono essere rappresentate tramite un albero aventi le seguenti proprietà: b * c 1. La radice è etichettata con il simbolo iniziale S 2. Ogni nodo interno è etichettato con un simbolo non terminale ! VN 3. Ogni foglia è etichettata da un simbolo terminale o dalla stringa vuota " 4. Se il nodo K è etichettato con un simbolo non terminale A ed ha k figli etichettati con i simboli !1 ,......., !k allora esiste una produzione della forma A # !1 ,......., !k 5. Se S $* w e w è una stringa di caratteri terminali allora w è rappresentata dalle foglie dell’albero. Parentesi bilanciate La Grammatica G11 genera stringhe di parentesi bilanciate S ! " | SS | (S) due possibili derivazioni sono: S # SS # S (S) # (S) (S) # (S) ( ) # ( ) ( ) S # SS # ( S ) S # ( ) S # ( ) ( S ) # ( ) ( ) S S ( S ! S ) ( S ! ) La Derivazione come classe di equivalenza Data una grammatica G è possibile pervenire alla generazione di una stringa con processi di generazione diverse. Date due generazioni D e D’: D = x1 ! x2 ! ...... ! xn D’ = x’ ! x’ ! ...... ! x’ 1 2 n se si verifica che : 1. " i ! k xi = x’i 2. xk-1 = x’ k-1 = u A v B w con u,v,w # V* e A, B # VN 3. xk = u y v B w, con A $ y # P 4. x’ k = u Av z w, con B$ z # P 5. xk+1 = x’ k+1= u y v z w " si dirà che D precede D’ e si scriverà "" D prec D’ u y v B w !u y v z w . . . . xk-1 = x’ k-1 = u A v B w " " " uAvzw!uyvzw.... Esempio D1 = S ! SS ! (S) S ! ((S)) S ! (( )) S ! (( ))( S) ! (( )) ( ) D2 = S ! SS ! (S) S ! ((S)) S ! ((S )) (S) ! (( ))( S) ! (( )) ( ) ! Pertanto D1 prec D2 D2 = S ! SS ! (S) S ! ((S)) S ! ((S )) (S) ! (( ))( S) ! (( )) ( ) D3 = S ! SS ! (S) S ! ((S)) S! ((S )) (S)! (( S))( ) ! (( )) ( ) pertanto D2 prec D3 Esempio cont. D 4 D 5 D 6 D 7 D 8 = S ! SS ! (S) S ! (S) S ! (S )( ) ! (( S))( ) ! (( )) ( ) = S ! SS ! S (S) ! (S) (S) ! ((S)) (S) ! (( ))( S) ! (( )) ( ) = S ! SS ! S (S) ! (S) (S) ! ((S)) (S) ! (( S))( ) ! (( )) ( ) = S ! SS ! S (S) ! (S) (S) ! (S )( ) ! ((S))( ) ! (( )) ( ) = S ! SS ! S (S) ! S ( ) ! (S )( ) ! ((S))( ) ! (( )) ( ) prec D 1 prec D2 prec D 3 prec D 5 prec D6 leftmost derivation prec prec D 4 D prec prec D 8 7 rightmost derivation Ambiguità S S S D11 = SS ! S S S ! S (S ) S ! S ((S )) S ! S " S (( )) S !S (( )) (S) !S (( )) ( ) ! (( )) ( ) ( S ! Una Grammatica si dice ambigua se medesime stringhe sono generate da alberi sintattici di differente struttura ovvero con due distinte derivazioni left most ( S ( S S ) ! ) ) ! albero alternativo ovvero con due distinte derivazioni right most Per cui si può concludere che la grammatica G11 è una grammatica ambigua S S S ( S ) ( S ) ! ( S ! ) Esempio di Grammatica Ambigua La Grammatica G12 con produzioni !! !! E ! E+E | E- E | E *E | E/E | id id ! a | b | c! è una grammatica ambigua E E E + E E E * E E + I I a * E I I b c E I I a b c Alberi semantici e notazioni polacche un Albero semantico è un albero in cui i nodi interni rappresentano operazioni da effettuarsi sui suoi sottoalberi, mentre i nodi foglia rappresentano operandi Esempio di costruzione E E E + E E E a * + E + b * * c a I a I I b c Primo passo - togliere tutti i simboli intermedi aventi un unico discendente Secondo passo - Sostituire ad ogni simbolo non terminale l’operatore corrispondente b c Alberi semantici e notazioni polacche Esempio di costruzione E E E E * E + I E * + E c a + b * I a b c I b a c Questo albero è stato costruito a partire dalla seconda versione dell’albero sintattico visto in precedenza. Il procedimento è corretto, ma il risultato è, come deve essere diverso in virtù dell’ambiguità della grammatica. Data un’espressione costruita a partire da una grammatica non ambigua è possibile costruire l’albero semantico direttamente tramite opportuni algoritmi. Un tale albero è ovviamente unico. sqrt ! a*b c+d / + * a b c d Alberi semantici e notazioni polacche Attraversando in modo opportuno un albero semantico si può avere una sequenzializzazione delle operazioni scandendo la stringa da sinistra verso destra e collocando gli elementi dentro uno stack. + * a b notazione polacca postfissa o inversa - RPN (Reverse Polish Notation) (visita dell’albero in ordine posticipato, o postordine) + a *b c notazione polacca prefissa (visita dell’albero in ordine anticipato, o preordine) c * ab+* c + a abc*+ *+abc [Se si è a conoscenza dell’arietà delle operazioni coinvolte la notazione polacca ha la caratteristica di rappresentare un’espressione in forma linearizzata senza parentesi.] c b sqrt a b*c d + / sqrt / * a sqrt / * a b + c d + b c d Si leggono i simboli della stringa memorizzando gli operandi nello stack, appena si trova un simbolo di operazione la si effettua e si pone nello stack il risultato. Togliere l’ambiguità Nel caso di grammatica ambigua, se si generano due alberi sintattici diversi, si hanno due alberi semantici diversi, che quindi inducono una semantica diversa per la parola riconosciuta (nel nostro caso un’espressione) Le fonti di ambiguità della Grammatica G dipendono dai seguenti motivi: 12 1. Non viene rispettata la precedenza degli operatori 2. Una sequenza di operatori identici si può raggruppare sia da sinistra che da destra Una versione non ambigua della grammatica G è la seguente grammatica G 12 E ! T! F ! id ! 13 E+T | E- T | T T *F | T/F | F (E) | id a | b | c |..... • Un fattore F rappresenta un’espressione che non si può scomporre rispetto ad un operatore adiacente. Un identificatore o un’espressione parentesizzata è un fattore. • Un termine T rappresenta un’espressione che non si può scomporre rispetto ad un operatore additivo (+, -) adiacente. In sostanza un termine è un prodotto (divisione) di più fattori • Un’ espressione è una qualsiasi composizione di termini tramite operatori additivi (+,-). Ancora sull’ambiguità • Consideriamo il seguente frammento della grammatica del Pascal, scritta secondo la Backus-Naur Form (BNF) <statement> ::= … | <if-statement> | … <if-statement> ::= if <exp> then <statement> [else <statement>] La frase if a then if b then c else d viene derivata mediante due alberi sintattici E S S IS IS E S S IS IS S S if a then if b then c else d E E S S if a then if b then c else d Questo sottolinguaggio del Pascal è ambiguo. I due alberi sintattici inducono scelte semantiche diverse riguardo l’associazione dell’else con gli if. In Pascal si stabilisce, con una regola esterna alla grammatica, che l’else si associa all’if più a destra. Ancora sull’ambiguità • Grammatica non ambigua per lo stesso sottolinguaggio. <statement> ::= <open-statement> | <closed-statement> | <simple-statement> <open-statement> ::= if <exp> then <statement> <open-statement> ::= if <exp> then <closed-statement> else <open-statement> <closed-statement> ::= <simple-statement> <closed-statement> ::= if <exp> then <closed-statement> else <closed-statement> S S OS CS S CS ? CS E E CS CS CS SS SS E E S SS if a then if b then c else d if a then if b then c else d Ancora sull’ambiguità • Si può trasformare una grammatica ambigua in una non ambigua equivalente? Non sempre… • Ci sono linguaggi context-free con la proprietà che ogni grammatica che li genera è ambigua, tali linguaggi sono detti inerentemente ambigui Esempi di linguaggi inerentemente ambigui {an bn cm dm : n ! 1, m !1} ! {an bm cm dn : n ! 1, m !1 } {ai bi c* : i ! 0} ! {a* bi ci : i !0 } • Per molti linguaggi di utilizzo pratico è sempre possibile trovare la grammatica non ambigua equivalente Data la grammatica E Sostituzioni in Alberi di derivazione E 1. E ! E + T | E - T | T 2. T ! T * F | T / F | F 3. F ! ( E ) | i T T abbiamo visto in che modo sia possibile costruire l’albero di derivazione per la stringa a + b*c T F F F a Si osservi come all’interno di un percorso possiamo trovarci in presenza dello stesso simbolo di variabile, radice di un sottoalbero. E’ sempre possibile sostituire il sottoalbero di una variabile con un’altro sottoalbero sempre riferito alla stessa variabile. Quello che si produce è ancora un albero di derivazione di una stringa legale del linguaggio. E E T T F F a F T T + b F * c * c + b Questa proprietà è tipica per le derivazioni dei linguaggi Contex Free. Infatti ogni simbolo non terminale si può sviluppare in modo indipendente dal contesto in cui si trova * c Sostituzioni in Alberi di derivazione Esempio La grammatica S ! 0B | 1A A ! 0 | 0S | 1AA B ! 1 | 1S | 0BB Genera tutte e sole le stringhe che hanno un ugual numero di 0 e di 1 Una possibile derivazione per la stringa 0011 è: S " 0B "00BB " 001B " 0011 Un’altra possibile derivazione è: S " 0B "00BB " 00B1 " 0011 0 0 B 0 S S S B B 1 1 0 B 0 (Si sta parlando di una grammatica ambigua?) B B 1 1 Possiamo ripetere il procedimento indefinitamente ottenendo parole del linguaggio via via crescente B 0 0 B B B 1 B B E’ una caratteristica dei linguaggi Contex-free, che discende dalla proprietà di sostituzione il fatto che la crescita avvenga in maniera costante. Ad esempio se una grammatica genera parole la cui lunghezza cresce in modo esponenziale allora il linguaggio non è libero dal contesto. 1 1 Quindi: S " 0B "00BB " 00B1 " 000BB1 " 000B11 " 000111 Forme Normali A partire da una grammatica Context-free G è sempre possibile costruire una grammatica equivalente G’ ovvero L(G) = L(G’) che abbiano le produzioni in forme particolari, dette forme normali. Le forme normali vengono usate per dimostrare proprietà particolari dei linguaggi piuttosto che per scopi applicativi. Forma normale di Chomsky E’ caratterizzata da regole di due tipi A ! BC dove A, B, C " VN A ! a con a " VT Forma normale di Greibach E’ caratterizzata da regole di un solo tipo A ! a # con a " VT e # " VN* Nel seguito faremo riferimento solo alla forma normale di Chomsky Forma Normale di Chomsky Prima di illustrare la trasformazione occorre effettuare una serie di passaggi preliminari per rendere la grammatica adatta alla trasformazione stessa (forma ridotta). I passaggi effettuati saranno tutti rivolti alla determinazione di grammatiche equivalenti rispetto a quella di partenza, con l’eventuale esclusione del simbolo {!}. 1. A partire da G viene costruita una grammatica G1 di tipo 2 senza !-produzioni che genera L(G) -{!} 2. A partire dalla grammatica G1 si costruisce una grammatica G2 di tipo 2 senza !-produzioni e senza produzioni unitarie. 3. A partire dalla grammatica G2 si costruisce una grammatica G3 di tipo 2 senza !-produzioni, senza produzioni unitarie e senza simboli inutili. 4. La grammatica G4 equivalente alla grammatica di partenza G coincide con G3 se ! " L(G), altrimenti G4 è ricavata da G3 introducendo un nuovo assioma ed un opportuno insieme di produzioni su tale simbolo. Forma Normale di Chomsky 1. Eliminazione delle !-produzioni L’eliminazione delle !-produzioni viene fatta in due step. Nel primo step vengono individuate le variabili (simboli non terminali) annullabili, nel secondo step si effettua l’eliminazione delle !-produzioni. Una variabile (simbolo non terminale) si dice annullabile se questo può generare la stringa vuota. Primo step Es1. S " ACA A " aAa | B | C B " bB | b C " cC | ! Es2 S " AB A " aAA | ! B " bBB | ! Si verifica immediatamente come il simbolo C sia un simbolo annullabile in quanto genera direttamente !. A partire da C si verifica come anche il simbolo A sia annullabile così come il simbolo S. Pertanto i simboli annullabili sono S A C. A partire da A e da B, che sono immediatamente annullabili si ricava l’annullabilità di S. Pertanto i simboli annullabili sono S A B. Forma Normale di Chomsky Eliminazione delle !-produzioni (cont.) A questo punto siamo in grado di effettuare l’eliminazione delle !-produzioni con un procedimento algoritmico che ha l’obiettivo di definire la grammatica equivalente aggiungendo opportune produzioni alla grammatica di partenza. Per ogni produzione della grammatica G del tipo A " X1, X2, ...., Xk, supponiamo che m dei k simboli siano annullabili, allora la grammatica risultante G1 avrà 2m versioni della produzione (con la sola eccezione di quando m=k). Inoltre non verranno riportate le produzioni della forma A " !. Es1. (simboli annullabili S A C) S " ACA A " aAa | B | C B " bB | b C " cC | ! S" A" B" C" ACA |AC | CA | AA |A |C | ! aAa | aa | B | C bB | b cC | c Es2 (simboli annullabili S A B ) S " AB A " aAA | ! B " bBB | ! S " AB | A | B A " aAA | aA | a B " bBB | bB | b L’ !-produzione può comparire direttamente sull’assioma a condizione che questo con compaia alla destra di qualche produzione Forma Normale di Chomsky Osservazioni sull’eliminazione delle !-produzioni Oss. 1- La !-produzione presente in S" A" B" C" ACA |AC | CA | AA |A |C | ! aAa | aa | B | C bB | b cC | c non è significativa se non per la possibilità da parte della grammatica di generare anche la stringa vuota. Infatti il linguaggio L(G) generato dalla grammatica G senza una tale !-produzione è perfettamente equivalente a una grammatica G’ con tale !-produzione. Cioé L(G’) = L(G) # {!}. Oss. 2 - E’ possibile aggiungere direttamente la !-produzione all’assioma del linguaggio come nell’esempio prima visto. Ciò è possibile a condizione che l’assioma non compaia in una parte destra di qualche produzione. Se questa eventualità si verifica è comunque possibile aggiungere la !-produzione al costo dell’inserimento di un simbolo non terminale aggiuntivo, secondo il seguente criterio. Criterio seguito VN’ = VN # { S’} P’ = P # { S’ " !} # { S’ " $ | S " $ % P} Esempio S " aSbA | ab A " cAd | cd S’ " aSbA | ab | ! S " aSbA | ab A " cAd | cd