Implementazione di Linguaggi 2

Slides:



Advertisements
Presentazioni simili
Training On Line - CONP. 2 Richiesta Da Menu: Conferimenti ad inizio anno termico > Agosto > Pluriennali > Nuova Richiesta Si accede alla pagina di Richiesta.
Advertisements

Dipartimento di Ingegneria Idraulica e Ambientale - Universita di Pavia 1 Caduta non guidata di un corpo rettangolare in un serbatoio Velocità e rotazione.
Presente e futuro della religiosità nel nord est DIFFERENZE TRA GENERAZIONI figli e padri italo de sandre 1ids.
MONITORAGGIO MATEMATICA V A Alunni 26 Presenti 23 Quesiti 44 Risposte totali 650 Risultato medio 28,3 media 64,2%
1 MeDeC - Centro Demoscopico Metropolitano Provincia di Bologna - per Valutazione su alcuni servizi erogati nel.
TAV.1 Foto n.1 Foto n.2 SCALINATA DI ACCESSO ALL’EREMO DI SANTA CATERINA DEL SASSO DALLA CORTE DELLE CASCINE DEL QUIQUIO Foto n.3 Foto n.4.
1 Pregnana Milanese Assessorato alle Risorse Economiche Bilancio Preventivo P R O P O S T A.
Sintassi (prima parte)
Traduttore diretto dalla sintassi (seconda parte)
Traduzione guidata dalla sintassi
1 Implementazione di Linguaggi 2 PARTE 5 Implementazione di Linguaggi 2 PARTE 5 Massimo Ancona DISI Università di Genova Testo: A.V. Aho, R. Sethi, J.D.Ullman.
Type Checking (1° parte)
Generazione di Codice Intermedio
Algoritmi e Programmazione
Frontespizio Economia Monetaria Anno Accademico
1 Linguaggi di Programmazione - elementi Corso di Laurea in Informatica (AA 2005/2006) Gabriella Pasi e Carla Simone
Lez. 3 - Gli Indici di VARIABILITA’
Programmazione Procedurale in Linguaggio C++
1 Istruzioni, algoritmi, linguaggi. 2 Algoritmo per il calcolo delle radici reali di unequazione di 2 o grado Data lequazione ax 2 +bx+c=0, quali sono.
Implementazione dell algortimo di Viterbi attraverso la soluzione del problema di cammino mi- nimo tramite software specifico. Università degli studi di.
Reaching Definitions. Tino CortesiTecniche di Analisi di Programmi 2 Reaching definitions Dato un punto del programma, quali sono i comandi di assegnamento.
Ordini Parziali - Reticoli
Esercitazioni su circuiti combinatori
Algoritmi e Strutture Dati Capitolo 2 Modelli di calcolo e metodologie di analisi.
Informatica di base A.A. 2003/2004 Algoritmi e programmi
Programmazione 1 9CFU – TANTE ore
ELEZIONI REGIONALI 2010 PRIMI RISULTATI E SCENARI 14 aprile 2010.
Canale A. Prof.Ciapetti AA2003/04
Ufficio Studi UNIONCAMERE TOSCANA 1 Presentazione di Riccardo Perugi Ufficio Studi UNIONCAMERE TOSCANA Firenze, 19 dicembre 2000.
Test di ipotesi X variabile casuale con funzione di densità (probabilità) f(x; q) q Q parametro incognito. Test Statistico: regola che sulla base di un.
1 Sistemi Digitali. 2 Definizione Analog Waveform Time Voltage (V) 0 5 Digital Waveform Time Voltage (V)
1 Implementazione di Linguaggi 2 Implementazione di Linguaggi 2 Federico Bernardi Type checking 2° parte Type checking 2° parte - Equivalenza di type expressions.
1 Implementazione di Linguaggi 2 Massimo Ancona DISI Università di Genova Testo: A.V. Aho, R. Sethi, J.D.Ullman Compilers Principles,Techniques and Tools,
Master universitario di II livello in Ingegneria delle Infrastrutture e dei Sistemi Ferroviari Anno Accademico 2012/2013 Cultura dimpresa, valutazione.
La partita è molto combattuta perché le due squadre tentano di vincere fino all'ultimo minuto. Era l'ultima giornata del campionato e il risultato era.
MP/RU 1 Dicembre 2011 ALLEGATO TECNICO Evoluzioni organizzative: organico a tendere - ricollocazioni - Orari TSC.
Unità Didattica 2 I Linguaggi di Programmazione
mosaic manipola oggetti primitivi (ruota e unisci) regole:
Cos’è un problema?.
Gli italiani e il marketing di relazione: promozioni, direct marketing, digital marketing UNA RICERCA QUANTITATIVA SVOLTA DA ASTRA RICERCHE PER ASSOCOMUNICAZIONE.
INSIEMI NUMERABILI L’analisi matematica introduce il concetto di insieme numerabile come insieme i cui elementi possono essere “contati” ossia che possiede.
LINGUAGGI DI PROGRAMMAZIONE
CHARGE PUMP Principio di Funzionamento
Settimana: 3-7 marzo Orariolunedimartedi Mercoledi 5 Giovedi 6 Venerdi lezione intro alla fis mod DR lezione intro alla fis mod DR.
Velocità ed accelerazione
Q UESTIONI ETICHE E BIOETICHE DELLA DIFESA DELLA VITA NELL AGIRE SANITARIO 1 Casa di Cura Villa San Giuseppe Ascoli Piceno 12 e 13 dicembre 2011.
Q UESTIONI ETICHE E BIOETICHE DELLA DIFESA DELLA VITA NELL AGIRE SANITARIO 1 Casa di Cura Villa San Giuseppe Ascoli Piceno 12 e 13 dicembre 2011.
1 Negozi Nuove idee realizzate per. 2 Negozi 3 4.
ORDINE DI CHIAMATA a 1minuto e 2 minuti PRINCIPALI TEMPI DELLA COMPETIZIONE ORDINE DI CHIAMATA a 1minuto e 2 minuti PRINCIPALI TEMPI DELLA COMPETIZIONE.
ISTITUTO COMPRENSIVO “G. BATTAGLINI” MARTINA FRANCA (TA)
Lo sviluppo del software e i linguaggi di programmazione
LE SAI LE TABELLINE? Mettiti alla prova!.
Un trucchetto di Moltiplicazione per il calcolo mentale
1 Ly-LAB Sistema di gestione dei dati analitici di laboratorio.
Grammatiche, Linguaggio e Automi R. Basili TAL - a.a
Esempi risolti mediante immagini (e con excel)
NO WASTE Progetto continuità scuola primaria scuola secondaria Salorno a.s. 2013_
Numeri Interi senza segno
I chicchi di riso e la sfida al Bramino
Mercato del lavoro e condizione giovanile: la crisi si acuisce
Il numero più grande Accademia dei Lincei
TRASFORMATA DI FOURIER
Corso di Laurea Ingegneria Informatica Fondamenti di Informatica
A.P. cat. B - 1 Per chi vuole: Libro di testo D.P. Curtis, K. Foley, K. Sen, C. Morin Informatica di base 2° edizione Mc Graw-Hill Companies.
IL GIOCO DEL PORTIERE CASISTICA. Caso n. 1 Il portiere nella seguente azione NON commette infrazioni.
Grammatiche Grammatiche libere da contesto Grammatiche regolari
Grammatiche non contestuali (1)
Linguaggi e Grammatiche Alfabeto : insieme non vuoto di elementi detti simboli A = { a, b, c } Stringa : sequenza di simboli di un alfabeto ab abc abcab.
Linguaggi, stringhe e alfabeti. Linguaggi e grammatiche Un linguaggio è un sistema di comunicazione tra persone che permette di trasmettere informazioni.
Parsing ricorsivo discendente Il parsing ricorsivo discendente (recursive descent parsing) è un metodo di tipo top-down che può essere facilmente codificato.
Transcript della presentazione:

Implementazione di Linguaggi 2 Massimo Ancona Testo: A.V. Aho, R. Sethi, J.D.Ullman Compilers Principles,Techniques and Tools, Addison Wesley

Diagramma del processo di compilazione

Strumenti associati al compilatore: il Linker

Contesto/ambiente di un cmp Programming Environment Un ambiente grafico interattivo per lo sviluppo, il testing e la manutenzione dei programmi: integra e gestisce gli strumenti e i meccanismi seguenti Strumenti e meccanismi correlati ai compilatori Sistemi per le compilazioni separate Sistemi per il controllo delle versioni Meccanismi per le ricompilazioni efficienti Macroprocessori e Preprocessori Linker loader Interpreti debugger profiler

Processo Di Compilazione Nella sua forma piu' astratta il processo di compilazione e' descritto nella figura seguente: il compiler e' una funzione che mappa un programma in linguaggio sorgente in un programma equivalente in linguaggio oggetto.

Fasi e Passi (Passate) Sono due concetti ortogonali: Le fasi denotano trasformazioni sul programma eseguite da tutti i compilatori. I passi si riferiscono al numero di processi successivi, in cui e' suddiviso un compilatore (il loro numero dipende in parte dal linguaggio). Il compilatore in una passata, legge il codice sorgente o una sua forma intermedia equivalente, raffinando il processo di treduzione e producendo una nuova rappresentazione intermedia, fino ad arrivare al codice target, nell’ultima passata.

Fasi Di Compilazione Una fase denota il tipo di operazione effettuata. Fasi e passate sono concetti ortogonali anche se una struttura canonica del compilatore tende ad incapsulare una (o piu') fasi, in una specifica passata. La divisione piu' grossolana prevede due fasi: analisi e sintesi. Con la prima il programma sorgente viene suddiviso nelle parti costituenti ottenendone una rappresentazione intermedia. Nella seconda si costruisce il programma target nel linguaggio oggetto.

Analisi e Sintesi Strumenti che eseguono l’analisi dell’input Editori di testo, Formattatori e Sistemi Ipertestuali (HTML, XML, PDF, TEX) Silicon Compilers (sintetizzatori di circuiti e componenti Hardware) Query Interpreters Motori di Ricerca e strumenti correlati

Analisi e Sintesi Analisi e Sintesi Analisi divide il pgm sorgente nelle parti costituenti creando una rappresentazione intermedia. Sintesi costruisce il programma oggetto dalla rappresentazione intermedia.

Dettaglio Delle Fasi ELenco completo delle possibili fasi di compilazione: Concettualmente un compilatore opera in fasi, e ogni fase trasforma il programma sorgente da una rappresentazione ad un’altra. Questa è una tipica DECOMPOSIZIONE di un compilatore. Le fasi sulla ragruppate sulla sinistra “lessicale sintattica e semantica” rappresentano la porzione di analisi del compilatore, mentre le restanti tre fasi sulla destra rappresentano la sintesi del compilatore, in cui viene effettivamente costruito il codice oggetto partendo dalla rappresentazione intermedia.

Rappresentazioni Intermedie sorgente primo := base + 53 * delta; out lessicale id[1] op= id[2] op+ ci=53 op* id[3] out sintattico op= id[1] op+ id[2] op* 53 id[3]

Rappresentazioni Intermedie (e Finali) out semantica op= id[1] op+ id[2] op* float id[3] 53 Il risultato della fase lessicale viene detto parse tree, ma una rappresentazione interna più comune è data dal SYNTAX TREE. Che è una rappresentazione compressa del parse tree in cui gli operatori a

Rappresentazioni Intermedie codice intermedio tmp1 = float(53) tmp2 = id[3] op* tmp1 tmp3 = id[2] op+ tmp2 id[1] = tmp3 Ottimizzazione di codice (intermedio) tmp1 = id[3] op* 53.00 id[1] = id[2] op+ tmp1 Dopo la fase di analisi alcuni compilatori generano una rappresentazione intermedia esplicita del sorgente. Questa rappresentazione intermedia deve avere 2 caratteristiche: Essere facile da produrre E facile da tradurre nel codice oggetto. Il codice intermedio può avere varie forme – la rappresentazione utilizzata qui è detta THREE ADDRESS CODE. Consiste di una serie di istruzioni, ognuna delle quali ha al più tre operandi. La fase di ottimizzazione del codice cerca di migliorare il codice intermedio per renderlo di più veloce esecuzione. Di solito nel codice intermedio viene generata 1 istruzione per ogni operatore presente della rappresentazione ad albero dopo l’analisi semantica

Rappresentazione Finale codice macchina: movf id3, rf2 mulf #53.00, rf2 movf id[2], rf1 addf rf2, rf1 movf rf1, id[1] Supponiamo di utilizzare solamente due registri rf1 e rf2. L’ultima fase del compilatore è la generazione del codice target, assembly. Per prima cosa viene selezionata una locazione di memoria per ogni variabile utilizza nel programma, ogni istruzione intermedia viene tradotta in una sequenza di istruzioni macchina che compiano lo stesso task. Un aspetto cruciale è l’ASSEGNAMENTO DELLE VARIABILI AI REGISTRI. Il primo operando di ogni istruzione specifica il sorgente ed il secondo la destinazione, la F presente in ogni istruzione indica che stiamo lavorando con numeri floating-point.

Tipi di Compilatori Vi sono diversi tipi di compilatori Ad un sol passo Multi-passo Load_and_go Debugging Optimizing Compiler-Interpreter Effettuano una sola passata sul codice sorgente. Eseguono più passate del codice sorgete o del albero sintattico I compilatori load-and-go traducono in codice sorgente in istruzioni macchina che vengono direttamente memorizzate nella memoria del computer, una volta tradotto il programma è eseguito.

Introduzione alla Compilazione Un compilatore in due passate

Le fasi di analisi del sorgente Analisi Lessicale. I caratteri del codice sorgente vengono letti left-to-right e raggruppati in Token. Analisi Sintattica. I caratteri o token sono raggruppati in frasi grammaticali. Analisi Semantica. Vengono effettuati controlli per trovare errori semantici e raccogliere informazioni per la generazione di codice.

Le fasi di analisi del sorgente Analisi Lessicale. Token Source Program Lexical analyzer Parser Get next Token La fase di analisi lessicale è la prima fase del compilatore, il compito principale è leggere i caratteri in input e produrre in output una serie di token che il parser utilizzerà per l’analisi sintattica. Come compito secondario: Toglie i commenti dal programma sorgente Toglie i caratteri degli spazi bianchi, tab e new line Può tenere traccia del numero di linee, in questo modo il numero di linea può essere associato ai messaggi di errore. Alcune volte l’analizzatore lessicale ha anche il compito di copiare il programma sorgente con gli errori marcati Alcuni analizzatori lessicali sono suddivisi in due fasi a cascata: prima fase detta scanning e seconda fase analisi lessicale. Symbol Table

Le fasi di analisi del sorgente Analisi Lessicale. Eseguita dallo Scanner Ad esempio l’istruzione: alpha:=beta+gamma*100; viene codificata nei seguenti TOKEN: <ID:’alpha’><OP::=><ID:’beta’><OP:><ID:’gamma’><OP:><VAL:’100’> Gli spazi ridondanti, i fine linea ecc. che separano i token vengono eliminati.

Le fasi di analisi del sorgente Analisi Sintattica. Ogni linguaggio di programmazione ha delle regole che descrivono la struttura sintattica di un programma ben formato. La sintassi di un linguaggio di programmazione può essere descritta da una grammatica libera da contesto

Le fasi di analisi del sorgente Analisi Sintattica. Token Source Program Lexical analyzer Parser Parse Tree Get next Token Nel nostro modello, il parser ottiene in input una sequenza di token dall’analizzatore lessicale, e verifica che tale sequenza di token possa essere generata dalla grammatica del linguaggio sorgente. Symbol Table

Le fasi di analisi del sorgente Analisi Sintattica. Eseguita dal Parser Agisce dopo l’analisi lessicale. Raggruppa i token in frasi grammaticali che si rappresentano con un parse tree. Parse tree di: alpha := beta + gamma * 100 (<:=>) <EXP:ID> <EXP: > <ID:’alpha’> <EXP:ID> <EXP: > <ID:’beta’> <EXP:ID> <EXP:VAL> <ID:’gamma’> <VAL:’100’>

Le fasi di analisi del sorgente Analisi Semantica. Controlla il codice sorgente alla ricerca di errori semantici e raccoglie informazioni sui tipi per la fase di generazione di codice Type checking è la componente più importate di questa fase: Controlla che gli operatori abbiano operandi permessi dalla specifica del linguaggio.

Relazione tra le Fasi La suddivisione tra analisi lessicale e sintattica è piuttosto arbitraria (come per le altre fasi della compilazione); Uno dei metodi usati per discriminarle si basa sulla ricorsione: i costrutti descrivibili senza ricorsione si assegnano all’analisi lessicale; quelli sostanzialmente ricorsivi a quella sintattica.

Sintassi Formale dei Linguaggi di Programmazione La si specifica tramite: diagrammi sintattici; equazioni BNF EBNF; grammatiche non contestuali (context free) Tutte forme sostanzialmente equivalenti. La sintassi dei linguaggi di programmazione viene in generale specificata mediante DIAGRAMMI SINTATTICI o EQUAZIONI BNF, o tramite GRAMMATICHE LIBERE DA CONTESTO.

Grammatiche Libere da Contesto (CFG) Le Context Free Grammar sono una notazione per specificare la sintassi di un linguaggio. Una CFG ha 4 componenti: Un insieme di token, detti simboli terminali Un insieme di non-terminali Un insieme di produzioni, dove ogni produzione consiste di un non-terminale (left side), una freccia e una sequenza di token e/o non-terminali (right side) L’indicazione di un non-terminale come simbolo iniziale I token o simboli terminali sono ad esempio le parole chiave del linguaggio. I non-terminali sono di variabili sintattiche che denotano un insieme di stringhe. Le produzioni specificano il modo in cui i terminali ed i non-terminali possono essere combinati per formate stringhe.

Grammatiche Libere da Contesto Esempio Vediamo un esempio di produzioni che definiscono semplici espressioni aritmetiche: expr  expr op expr expr  ( expr ) expr  id op  + op  - op  * op  / op   Simboli terminali: id + - * /  ( ( Simboli non-terminali: expr op Simbolo iniziale: expr

Grammatiche Libere da Contesto Esempio Scrivere la grammatica context free per esprimere zero o più volte il simbolo (terminale) thing. List  List  thing List List  List  thing List  List List List  List  List thing

Grammatiche Libere da Contesto (CFG): Definizione Formale Alfabeto T () : è un insieme finito non vuoto, e gli elementi di T () vengono chiamati simboli o caratteri. Useremo le lettere V, T, N,  per indicare alfabeti

Grammatiche Libere da Contesto (CFG): Definizione Formale Parola di lunghezza k0, su un alfabeto T: è una sequenza finita w=x1x2…xk di elementi di T, k, denotata anche k=|w| è detta lunghezza di w, e la parola di lunghezza zero, detta parola vuota, e’ indicata .

Grammatiche Libere da Contesto (CFG): Definizione Formale L’insieme delle parole su T (linguaggio), indicato con T* monoide: con legge di composizione concatenazione di parole Date w1,w2T, w1= x1x2…xk, w2= y1y2…yl w= w1.w2= x1x2…xky1y2…yl, di lunghezza k+l, è detta concatenazione di w1 e w2. Il monoide (T*,.) è detto monoide libero su T.

Parentesi Algebrica: Monoide Un monoide è un insieme M munito di una singola operazione binaria, chiamata prodotto, che ad ogni coppia di elementi a, b di M associa un elemento ab, rispettando i seguenti assiomi: per ogni a, b appartenenti a M, il loro prodotto ab appartiene ancora a M, vale a dire, M è chiuso rispetto al prodotto. Il prodotto è associativo: dati a, b, c appartenenti a M, vale (ab)c = a(bc). Esiste in M un (unico) elemento neutro e tale che ae = ea = a.

Grammatiche Libere da Contesto (CFG): Definizione Formale Una CFG formalmente è una quadrupla G=(N,T,P,S) con NT= e V=NT, dove: T è un alfabeto di simboli terminali di G. N è un alfabeto di simboli non-terminali di G. P è un insieme finito di produzioni di G. SN è detto simbolo iniziale di G.

Grammatiche Libere da Contesto (CFG): Definizione Formale Notazione utilizzata per le produzioni NV*: a,b,c,…,+,-,…,0,1,…,(,[,{,… indicano elementi di T (= terminali) A,B,C,… indicano elementi di N (= non-terminali) U,V,X,Y,Z indicano elementi di V=TN u,v,x,y, indicano elementi di T*(= stringhe di terminali) ,,,…, indicano elementi di V* (= stringhe di simboli grammaticali) =(A,)NV* è indicata da A

Linguaggi Context Free Linguaggio generato da G: L(G)=wT*| S * w Un linguaggio L  T* è libero da contesto se esiste G=(N,T,P,S) CFG tale che L=L(G)

A   (Derivazione) Forme Sentenziali Data G=(N,T,P,S) una forma sentenziale di G è definita ricorsivamente, come segue: S è una forma sentenziale di G, se A è una forma sentenziale di G e A è una produzione di G allora  è una forma sentenziale di G. La relazione tra A e  al punto precedente viene indicata: A   (Derivazione)

Derivazioni Dirette e Non A   esprime che  deriva direttamente da A o che A genera direttamente . Le notazioni * + indicano rispettivamente la chiusura transitiva-riflessiva e transitiva di   *  denota che = oppure  i i=1..n =1  2  …  n =  e n>0.  +  denota che =1  2  …  n =  e n>0. Idea di base: le produzioni di una grammatica possono essere viste come REGOLE DI RISCRITTURA in cui il NON-TERMINALE a sinistra viene rimpiazzato dalla stringa della parte destra della produzione.

Derivazioni - Esercizio La stringa – ( id + id ) è una sentenza della grammatica G? E  - E  - ( E )  - ( E + E )  - ( id + E )  - ( id + id ) G: E  E + E E  E * E E  ( E ) E  - E E  id E * - ( id + id )

Derivazioni canoniche Una derivazione  * e’ detta canonica destra e indicata  rm* , se ad ogni passo di derivazione si espande il simbolo non-terminale più a destra.  rm*  se  i si ha i=iAixi, i+1=iixi, Ai i, =1  2  …  n =  i=1,…,n

Derivazioni canoniche Una derivazione  * e’ detta canonica sinistra e indicata  lm* , se ad ogni passo di derivazione si espande il simbolo non-terminale più a sinistra.  lm*  se  i si ha i=xiAi i, i+1=xii i, Ai i, =1  2  …  n =  i=1,…,n

Derivazioni Canoniche Esempio Non-terminali terminali G=({E,T,P}, {(,),a,b,c,*,+,-}, P, E) P={EE +T |E -T |T, T T *P |P, P  (E ) | a | b | c} Data (a-b) – c la derivazione: E  E -T  T -T  P -T  (E )-T  (E - T )-T  (T - T )-T  (P - T )-T  (a - T )-T  (a - P )-T  (a - b )-T  (a - b )-P  (a - b ) - c È canonica sinistra.

Esempio Sia G=({E,T,P}, {(,),a,b,c,*,+,-}, P, E) dove P={EE+T | E-T | T, T T*P | P, P  (E) | a | b |c} La derivazione: E E-T  E-P  E-c T-c P-c (E)-c  (E-T)-c (E-P)-c (E-b)-c (T-b)-T (P-b)-c  (a-b)-c è canonica destra, confrontandola con la canonica sinistra: E E-T  T-T P-T (E)-T  (E-T)-T (T-T)-T (P-T)-T (a-T)-T (a-P)-T  (a-b)-T (a-b)-P (a-b)-c Si vede che differiscono solo per l’ordine di applicazione delle produzioni. Entrambe applicano le stesse produzioni alle stesse istanze di non terminali

Parsing Tree Tutte le derivazioni che differiscono solo per l’ordine di applicazione delle produzioni sono sostanzialmente equivalenti e possono essere rappresentate da un’unica derivazione canonica destra, un’ unica derivazione canonica sinistra o da un unico albero etichettato detto Parsing Tree. Il parse tree può essere visto come una rappresentazione grafica della derivazione, che filtra le scelte fatte a riguardo dell’ordine di applicazione delle produzioni.

Parsing Tree - Definizione La radice è etichettata da S Ogni foglia dell’albero è etichettato da  o da un simbolo di T (terminale) Ogni nodo interno è etichettato da un simbolo di N (non terminale) Se A etichetta un nodo interno e X1,X2,…, Xn sono le etichette dei figli, allora AX1X2…Xn  P

Parsing Tree - Esempio Derivazione: - (id + id) E - E ( E ) E + E

Esempio di Parsing Tree Derivazione di: (a – b ) – c Grammatica: EE +T |E -T |T T T *P |P, P  (E ) | a | b | c}

Classificazione di Chomsky È una classificazione dei linguaggi basata sulla complessità delle produzioni delle grammatiche che li generano. I linguaggi di tipo 0 sono generati da grammatiche a struttura di frase. I linguaggi di tipo 1 sono generati da grammatiche dipendenti dal contesto. I linguaggi di tipo 2 sono generati da grammatiche libere dal contesto. I linguaggi di tipo 3 sono generati da grammatiche lineari (o regolari).

Classificazione di Chomsky Grammatiche a struttura di frase. Le produzioni sono del tipo  A    Grammatiche dipendenti dal contesto. Le produzioni sono del tipo  A      dove , V*, AN e V* . Grammatiche libere dal contesto. Le produzioni sono del tipo A, dove V* . Grammatiche lineari (o regolari). Le produzioni sono del tipo AuB oppure Au, dove u  * e A, B  N.

Classificazione di Chomsky Ogni grammatica di tipo n è anche una grammatica di tipo n − 1. Un linguaggio è di tipo n se è generato da una grammatica di tipo n, ma non di tipo n + 1. Esempi: - Linguaggio di tipo 3: L = {ambn : m, n  0}. - Linguaggio di tipo 2: L = {anbn : n  0}. - Linguaggio di tipo 1: L = {anbncn : n  0}. - Linguaggio di tipo 0: L = {an : n è numero primo}.

Grammatiche e Linguaggi Ambigui Una grammatica G è ambigua se:  wL(G) con due parsing tree diversi Un linguaggio è inerentemente ambiguo se per ogni G tale che L=L(G) si ha che G e’ ambigua.

Tecniche per Disambiguare Inserire regole di precedenza per gli operatori. Utilizzare associatività a sinistra o a destra. Manipolare la grammatica.

Grammatica Ambigua Esempio G=({S}, {if, then, else, s, b}, P={S  if b then S | if b then S else S | s}, S) Srm if b then S rm if b then if b then S else S rm if b then if b then S else s rm if b then if b then s else s S rm if b then S else S rm if b then S else s rm if b then if b then S else s rm if b then if b then s else s if b then if b then s else s

Grammatica Ambigua Esempio Grammaticha ambigua: G=({S}, {if, then, else, s, b}, P={S  if b then S | if b then S else S | s}, S) Grammatica disambiguata: G=({S, S1, S2}, {if, then, else, s, b}, P={S  S1, S1  if b then S1 | if b then S2 else S1 | s, S2  if b then S2 else S1 | s},

Grammatica non ambigua con proprietà opportune Nota: la gramamtica è context free, e mostriamo solo le produzioni. Grammatica di espressioni non ambigua con priorità di operatori e associatività cablate EE+T | E-T | T TT*F | T/F | F FP^F | P P (E) | I | N I  a|b|c|d N  0 | 1 | 2 G per espressioni, semplice ma ambigua EEOE|(E)|a|b|c|d O+|-|*|^

Altri esempi di grammatiche G0 di espressioni non ambigua con priorità di operatori e associatività cablate EE+T | E-T | T |-T|+T TT*F | T/F | F F (E) | I | N I  a|b|c|d N  0 | 1 | 2 G1 per espressioni, semplice, non ambigua ma flat EEOT|T|-T|+T T (E)|a|b|c|d|0|1|2 O+|-|*|/

Derivazione canonica di G0 Data a-b*c e G0 abbiamo: ErmE-T rmE-T*F rmE-T*I rmE-T*c rmE-F*c rmE-I*c rmE-b*c rmT-b*c rmF-b*c rmI-b*c rma-b*c EE+T | E-T | T |-T|+T TT*F | T/F | F F (E) | I | N I  a | b | c | d N  0 | 1 | 2

Parse tree (G0) Derivazione Canonica: ErmE-T rmE-T*F rmE-T*I rmE-T*c rmE-F*c rmE-I*c rmE-b*c rmT-b*c rmF-b*c rmI-b*c rma-b*c E E - T T T * F F F I I I c a b

Derivazione canonica di G1 Data a-b*c e G1 abbiamo: ErmEOT rmEOc rmE*c rmEOT*c rmEOb*c rm rmE-b*c rm rmT-b*c rm a-b*c EEOT|T|-T|+T T (E)|a|b|c|d|0|1|2 O+|-|*|/

Parse tree (G1) Derivazione Canonica: ErmEOT rmEOc rmE*c rmEOT*c rmEOb*c rm rmE-b*c rm rmT-b*c rm a-b*c E E O T E O T * c T - b a

Esercizio Studiare G2: EFOT | T FFOT | T |  T(E)| a | b | c | d | 0 | 1 | 2 O+ | - | * | ^

Esempio Documenti HTML XML: DPs B Pd Ps<html> Pd<\html> B  <body>L <\body> LE L | E |  E<div>R<\div> Rrest

Esempio Documenti HTML XML: DPs B Pd Ps<html> Pd<\html> B  <body>L <\body> LE L | E |  E<div>R<\div> Rrest

Esempio Documenti HTML XML: DPs B Pd Ps<html> Pd<\html> B  <body>L <\body> LE L | E |  E<div>R<\div> Rrest

Esempio Documenti HTML XML: DPs L Pd Ps<html> Pd<\html> LE L | E |  E<div>R<\div> Rrest

Operazioni sui Linguaggi Dati due linguaggi L, M  * definiamo prodotto di L e M, indicato LM o L.M, l’insieme: LM ={uv | u L & v M}

Operazioni sui Linguaggi Definiamo chiusura di Kleene di L, indicata con L*, l’operazione: L0={} L1=L Li=LLi-1 i>0 L*=i0 Li L+=i>0 Li

Operazioni sui Linguaggi - Esempi Proprieta’: supponiamo T terminale e vediamo le produzioni di E G0=({E},{t,+,-},P0,E) P0={EE+t | E-t | t|-t|+t} L(G0)={-t,+t,t}({+,-}t)* e G1=({E,O},{t,+,-},P1,E) P1={EEOt|t|-t|+t,O+|-} O+|- L(G1)=L(G0)

Linguaggi - Esempi Esempio di linguaggio inerentemente ambiguo L={aibjck| i=j OR j=k; i,j,k0} SS1S2 | S3S4 S1aS1b | S2  S2 c|  S4bS4c | S3  S3 a|  Esempio di linguaggio non context free. L={anbncn| n>() 0} non e’ un CFL

Syntax Tree (albero sintattico) e Parsing Tree Una delle rappresentazioni intermedie più usate. Più astratto del parsing tree, dipende solo dal linguaggio (non dalla grammatica)

EBNF Usa i simboli metalinguistici “=“ “|” “[“ “]” “{“. “}” “.” “”” […] significa opzionalita’ {…} significa ripetizione: 0 o piu’ volte “(…)” significa raggruppamento “|” indica alternativa “.” termina una produzione I simboli terminali vengono racchiusi tra “ “ Esempio Expression = SimpleExpression [ Relation SimpleExpression ]. Relation = "=" | "<>" | "<" | "<=" | ">" | ">=" | "IN". SimpleExpression = [ "+" | "-" ] Term { AddOperator Term }. AddOperator = "+" | "-" | "OR". Term = Factor { MulOperator Factor }. MulOperator = "*" | "/" | "DIV"| "MOD" | "AND"

EBNF Esempio (Espressioni) Expression = SimpleExpression [ Relation SimpleExpression ]. Relation = "=" | "<>" | "<" | "<=" | ">" | ">=" | "IN". SimpleExpression = [ "+" | "-" ] Term { AddOperator Term }. AddOperator = "+" | "-" | "OR". Term = Factor { MulOperator Factor }. MulOperator = "*" | "/" | "DIV" | "MOD" | "AND"

EBNF Espressioni (cont.) Designator [ ActualParameters ] | "(" Expression ")" | NOT Factor. Set = "[" [ Element { "," Element } ] "]". Element = OrdinalConstant [ ".." OrdinalConstant]. OrdinalConstant= Char | Integer. ActualParameters = ["(" [ ExpressionList ] ")"]. Ident = IdChar { IdChar | Digit }. IdChar = Letter | "_". Number = Integer | Real.

EBNF Espressioni (cont. 2) Integer = Digit { Digit } | Digit { HexDigit } "H". Real = Digit { Digit } "." { Digit } [ ScaleFactor ]. ScaleFactor = "E" [ "+" | "-" ] Digit { Digit }. HexDigit = Digit | "A" | "B" | "C" | "D" | "E" | "F". Digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9". CharConstant = "'" Char "'" | Digit { HexDigit } "X". String = ' { CharN | "''" } '. Char = CharN | "'".