Scaricare la presentazione
La presentazione è in caricamento. Aspetta per favore
PubblicatoGeronima Neri Modificato 8 anni fa
1
Compilatore Programma sorgente Compilatore Programma ‘oggetto’ Statistiche Informazioni debugger Listing Messaggi errore Cross reference
2
Source lang. Compilatore Target lang. Obiettivo : emettere velocemente codice per una macchina target, corretto ed efficiente Velocemente veloce generazione di codice veloce (retargetting) Corretto preservare la semantica del linguaggio sorgente Efficiente in esecuzione
3
Soluzione : dividire il compilatore in due blocchi principali source program Front End Back End Analisi Sintesi target program Rappresentazione intermedia Isolare le dipendenze dal linguaggio sorgente nel Front End (analisi lessicale, sintattica e semantica) Isolare nel Back End le dipendenze dalla macchina target (generazione ed ottomizzazione del codice)
4
Analizzatore Lessicale Analizzatore Sintattico Preparazione alla Generazione del codice Generatore di codice TABELLETABELLE Analisi Sintesi L’Analisi Semantica è dispersa in tutte le fasi
5
Problema degli M x N traduttori CPascalFortranBasic i38668020Z8000 Cobol CPascalFortranBasicCobol i38668020Z8000 Linguaggio intermedio m = 5 n = 3 5 * 3 = 15 traduttori m + n = 5 + 3 = 8 traduttori
6
Esempio di traduzione IA = B + C * DELTA + DELTA * C si riconoscono le diverse unità del testo si classificano le diverse unità del testo si crea la tabella dei simboli si trasforma il linguaggio sorgente in un linguaggio di tokens (id,P 1 ) = (id,P 2 ) + (id,P 3 ) * (id,P 4 ) + (id,P 4 ) * (id,P 3 ) B IA C DELTA P 2 P 1 P 3 P 4 Tabella dei simboli
7
(id,P 1 ) = (id,P 2 ) + (id,P 3 ) * (id,P 4 ) + (id,P 4 ) * (id,P 3 ) ALBERO SINTATTICO
8
Albero derivante dalla grammatica: id = + | - | * | / | id | cost | ( ) Anche per l’analisi semantica e per la traduzione si utilizza l’albero sintattico
9
Lessico Insieme delle parole chiave del linguaggio, degli identificatori, delle costanti e dei commenti IF ‘I’ ‘F’ i simboli lessicali IF, DO, WHILE, … DO ‘D’ ‘O’ appaiono come terminali [ | ] * lettera cifra lettera Commento stringa_senza_graffa_chiusa Stringa_senza_graffa_chiusa ( - ‘ ’) *
10
Analisi lessicale Produzioni Regole di produzione Codici Costante ( 0 | 1 | ….|9 ) [0 | 1 | ….|9 ] * 2 Identif. ( A | B | …| Z) [ 0 | 1 | …| 9 | A | B|…Z]* 1 Espon. ‘*’ ‘*’ 6 Più ‘+’ 3 Per ‘*’ 7
11
Analisi lessicale Automa a stati finiti q0q0 q1q1 q2q2 q3q3 q4q4 þ 0,1,..9 þ A, B,..Z 0,1,…9 A,B,…Z + - = þ * * þ 21345672134567
12
Grafi sintattici + - - + * / cost var )( Espr ( | + | - ) term (( + | - ) term ) * Fatt cost | var | (espr) espr Term fatt (( * | / ) fatt ) * fatt term
13
ANALISI SINTATTICA Grammatiche ambigue (dannose perchè non è chiaro il significato della frase) Metodi per togliere l’ambiguità: Cambio della grammatica Aggiunta di regole per disambiguare
14
Esempio if then else if then if E1 then S1 else if E2 then S2 else S3 if then else E1 S1 if then else E2 S2 S3
15
Esempio di ambiguità If E1 then if E2 then S1 else S2 (ambigua perchè ci sono 2 possibili alberi sintattici) 1) if then else E1 S2 if then E2 S1
16
Esempio di ambiguità 2) If then E1 if then else E1 S1 S2
17
Esempio di soluzione: “closest match” (si lega l’else all’if-then annidato più vicino) if E1 then if E2 then S1 else S2 if then E1 if else E2 S1 S2
18
1. E - - > E + T 2. E - - > T 3. T - - > T * F 4. T - - > F 5. F - - > (E) 6. F - - > id id + id * id E E + T T T * F F F id id id
19
Derivazione sinistra 1 2 4 6 3 4 E - - > E + T - - > T + T - - > F + T - - > id + T - - > id + T * F - - > E E E E E E + T E + T E + T E + T E + T T T T T T * F F F F id id
20
6 6 - - > id + F * F - - > id + id * F - - > id + id * id E E E E + T E + T E + T T T * F T T * F T T * F F F F F id F id id id id id id Derivazione sinistra
21
ANALISI SINTATTICA verifica se X appartiene a L(G) TOP DOWN Il parser inizia l’analisi dal nodo radice corrispondente allo “start symbol” e ricorsivamente discende sui sottoalberi tracciando l’intero albero sintattico BOTTOM UP Il parser parte dai nodi foglia (terminali) e si costruiscono i sottoalberi dal basso verso l’alto fine ad arrivare all’intero albero sintattico
22
ANALISI SINTATTICA DETERMINISTICA Ad ogni passo dell’analisi esiste sempre una sola scelta possibile NON DETERMINISTICA E’ possibile arrivare a situazioni in cui più scelte sono possibili. Si procede per tentativi ed in caso di insuccesso occorre tornare sui propri passi e tentare strade alternative
23
BACKTRACKING Ritornare al punto in cui è stata compiuta l’ultima scelta che aveva alternative valide possibili, disfare tutte le azioni compiute fino a quel punto (cancellare l’albero tracciato fino a quel punto) e continuare scegliendo una delle rimanenti alternative. Nei casi pratici ciò è usualmente non accettabile perchè associate all’analisi sintattica ci sono altre azioni “semantiche” (aggiornamento delle tabelle dei simboli ecc.) ed è troppo costoso farle più di una volta. Si fanno perciò solo analisi deterministiche.
24
Metodo ricorsivo discendente Ad ogni non terminale è associato un sottoprogramma eventualmente ricorsivo. S - - > c A d ; A - - > a b; A - - > a Procedure A(); begin if scan() = ‘a’ then begin if scan() = ‘b’ then return (true) end; else return(false); end; Procedure S(); begin if scan() = ‘c’ then begin if A() then if scan() = ‘d’ then return(true); end; return(false); end;
25
Analisi ricorsivo discendente Impedita dalla ricorsione a sinistra: A - - > A α E - - > E + T E - - > T T - - > T * F T - - > F F - - > (E) F - - > id Procedure E(); begin if E() then …… Va in loop
26
Trasformazione della grammatica E - - > E + T E - - > T E’ = = > E’ - - > + T E’ E - - > T E’ - - > ε T - - > T * F T - - > F T’ = = > T’ - - > * F T’ T - - > F T’ - - > ε F - - > (E) = = > F - - > id
27
Programma di analisi procedure E(); begin T(); EPRIME(); end; Procedure EPRIME(); begin if scan() = ‘+’ then begin T(); EPRIME(), end; procedure T(); begin F(); TPRIME(); end; Procedure TPRIME(); begin if scan() = ‘*’ then begin F(); TPRIME(); end;
28
Programma di analisi Procedure F(); begin if scan() = id then return (‘OK’) else if scan() = ‘(‘ then begin E(); if scan() = ‘)’ then ERROR(); end; else ERROR(); end;
29
Altri impedimenti Prefissi comuni nelle parti destre di diverse produzioni per lo stesso non terminale - - > if then else - - > if then - - > else - - > ε
30
Regola generale per la fattorizzazione sinistra A - - > α β A - - > α A’ diventano A’ - - > β A - - > α γ A’ - - > γ Analisi ricorsivo discendente: Facile scrittura delle procedure dell’analizzatore sintattico Possibile solo se il linguaggio implementativo permette la ricorsione ed essa è realizzata in modo efficiente
31
Analisi TOP -DOWN Top Down deterministico si dice PREDITTIVO se e solo se: per ogni non terminale si può prevedere la corretta riduzione. Il Parser, per decidere come procedere, usa il non terminale corrente ed il prossimo token (LOOK AHEAD = prospezione) Se la prospezione ha lunghezza pari ad 1, l’analisi si dice LL(1) (Look ahead, Left to right) Il Pascal è LL(1).
32
Analisi BOTTOM UP Analisi ascendente a spostamento e riduzione : LR(k) Partendo dalla stringa da analizzare, si procede da sinistra a destra e quando si trova una sottostringa corrispondente ad una parte destra di una produzione si fa una riduzione. S 0 - - > S # a c b # S - - > a S b S S # S - - > c S 0
33
Analisi BOTTOM UP Si usano le stesse regole della grammatica ( produzioni) ma in senso riduttivo, cioè da destra a sinistra. Si chiama parte riducibile (HANDLE) la porzione di una stringa, composta da terminali e non terminali, che è parte destra di una regola di produzione e può essere ridotta al non terminale della parte sinistra della regola stessa.
34
Esempio di analisi BOTTOM UP S - - > a A B e A - - > A b c | b B - - > d 1.a b b c d e(A - - > b) 2. a A b c d e(A - - > A b c) 3. a A d e(B - - > d) 4. a A B e(S - - > a A B e) 5. S Nel passaggio 2-3 si poteva scegliere la regola A - - > b ma …. la frase a A b c d e non è riducibile perchè da S non e’ possibile derivare a A A c d e, cioè S -/ - > a A A c d e PROBLEMA CHIAVE E’ LA DETERMINAZIONE DELLA PARTE RIDUCIBILE (HANDLE)
35
ANALISI ASCENDENTE LR(k) A SPOSTAMENTO E RIDUZIONE repeat leggi simbolo dal buffer di input sposta simbolo al top dello stack while top dello stack <> handle aggiungi simbolo allo stack endwhile riduci stringa al top dello stack elimina simboli ridotti dallo stack aggiungi al top dello stack il simbolo ridotto until top dello stack = simbolo distintivo or buffer di input = vuoto if top dello stack = simbolo distintivo and buffer di input = vuoto then exit(‘successo’) else exit (‘errore’) endif
36
Esempio (1) E - - > E + T(2)E - - > T (3)T - - > T * F (4)T - - > F (5)F - - > (E) (6)F - - > id id + id * id stack input azione --------------------------------------------------------------------------------------------------- 1.# id + id * id # sposta 2.# id + id * id # riduce con (6) 3.# F + id * id # riduce con (4) 4.# T + id * id # riduce con (2) 5.# E + id * id # sposta 6.# E + id * id # sposta 7.# E + id * id # riduce con (6) 8.# E + F * id # riduce con (4) 9.# E + T * id # sposta 10.# E + T * id # sposta 11.# E + T * id # riduce con (6) 12.# E + T * F # riduce con (3) 13.# E + T # riduce con (1) 14.# E # accetta
37
ANALISI SINTATTICA GUIDATA DA TABELLE LR: Analizzatore sintattico governato da tabella che, in funzione del prossimo simbolo in input e del contenuto al top dello stack, esegue una mossa di spostamento o di riduzione. Una grammatica è detta LR se la tabella non ha elementi che indicano contemporaneamente spostamenti e riduzioni. Esistono strumenti che verificano automaticamente se la grammatica è LR e ne costruiscono la tabella dell’analizzatore sintattico ascendente. Es. LEX, YACC in UNIX
38
Schema di un parser LR guidato da tabella a 1 …. ………a n ………... a k # input S m.. output. S 0 # tabella stack azione goto LR parser
39
AZIONEGOTO STATOid+*()#ETF 0S 5S 4123 1S 6accept 2r2S 7r2 3r4 4S 5S 4823 5r6 6S 5S 493 7S 5S 410 8S 6S 11 9r1S 7r1 10 11 r3 r5 r3 r5 r3 r5
40
STACKINPUT (1)0id* + # (2)0id5* + # (3)0F3*id+ # (4)0T2*id+ # (5)0T2*7id+ # (6)0T“*7id5+ # (7)0T2*7F10+id# (8)0T2+id# (9)0E1+id# (10)0E1+6id# (11)0E1+6id5# (12)0E1+6F3# (13)0E1+6T9# (14)0E1#
41
Algoritmo di base per parser LR(1) token = next_token() Loop s = top_stack if action[s,token] = “shift s i ” then push token push s i token = next_token() else if action[s,token] =“reduce A - - >β” then pop 2* length(β ) symbols s = top stack push A push result of goto[s,A] else if action[s,token] =“accept” then return else error endloop
42
TRATTAMENTO DEGLI ERRORI -rilevamento dell’errore e diagnosi -rimedio all’errore -ripresa dell’analisi -Criteri di merito: -segnalare l’errore al più presto possibile -saltare meno testo possibile prima di riprendere l’analisi Gli analizzatori LL(1) e LR(1) rilevano un errore quandoil token corrente non può essere parte di un programma corretto (grammatica); Trattamento: -Fermarsi al primo errore -Fare error recovery, cioè superare l’errore e riprendere l’analisi
43
Rimedio agli errori Diverse tecniche: Cancellazione (metodo del “panico”) –Salta i simboli fino a che è possibile la ripresa dell’analisi; ricerca di un simbolo sicuro in grado di far sincronizzare il parser. E’ la forma più semplice di error recovery Sostituzione –Cerca di sostituire un simbolo con un altro (ipoteticamente più probabile); continua con il simbolo successivo a quello errato Inserimento –Cerca di inserire simboli che possono permettere la continuazione dell’analisi
44
ANALISI SEMANTICA Verifica che ogni elemento del programma (operatori ed operandi) sia usato nel contesto in cui può apparire in base alla specifiche del linguaggio (restrizioni rispetto alla grammatica libera dal contesto) Controlli di tipo statico (alla compilazione :compile time): Controllo sulla congruenza tra operandi di tipo diverso Controllo sul flusso del programma (errata uscita o entrata in strutture di controllo) Controllo di unicità ( ridefinizione delle variabili, labels di “case ripetute, ecc.) Le strutture di lavoro per l’analisi semantica sono: La tavola dei simboli L’albero sintattico generato dall’analizzatore sintattico
45
Esempio di analisi semantica x := y dichiarata? visibile? variabile? variabile? funzione? costante? tipo? tipo? # parametri? tipo? assegnabile? tipo? compatibile? in range? valore?
46
Gestione dello “scope” var a : real; var b : integer; a:= a + b; var a: integer, a:= a + b;
47
Visibilità delle variabili (struttura delle tabelle dei simboli) a ( real)indirizzo --------- ------------ b (integer)indirizzo ------------------- ----------------- a (integer)indirizzo ----------------
48
CODICI (LINGUAGGI) INTERMEDI 1)Alberi sintattici a:= b + c ---- - - -> := a + b c 2)Statements a 3 indirizzi a := b op c Quadruple oparg1arg2ris +bct1 :=t1a
49
CODICI (LINGUAGGI) INTERMEDI 3)Statements a 2 indirizzi triple 4)Notazione polacca prefissa := a + b c postfissa a b c + := oparg1arg2 +bc(0) :=a(0)(1)
50
Quadruple A := - B * ( C + D) T1 := - B T2 := C + D T3 := T1 * T2 A := T3 OPARG1ARG2RIS (0)MinusB-T1 (1)+CDT2 (2)*T1T2T3 (3):=T3-A
51
Triple A := - B * ( C + D) A[I] := B A := B[I] OPARG1ARG2 (0)minusB- (1)+CD (2)*(0)(1) (3):=(2)A OPARG1ARG2 (0)[]AI (1):=B(0) OPARG!ARG2 (0)[]BI (1):=(0)A
52
Notazione polacca postfissa (eseguibile o interpretabile direttamente) L’operatore segue gli operandi x + y ----->x y + x + y * z----->x y z * + (a + b) * (x + y)----->a b + x y + *
53
Interpretazione di una forma polacca postfissa Var γ : pila di valori (interi) cursimb : elemento dell’espressione val : valore (intero) Begin repeat leggi pross. elemento in cursimb if cursimb = operando then push(γ, cursimb) else pop operandi di cursimb ed applicalo ad essi cursimb = val:=cursimb(op1,…., opn); push (γ, val) endif until fine espressione scrivi (top (γ)) End
54
Valutazione della espressione (3 + 2) * (7 – 3) - - - > 3 2 + 7 3 - * pilainput 3 2 + 7 3 - * 5 7 3 - * 5 4 * 20
55
Linguaggio intermedio per istruzioni di controllo if a < b then a:=1 else b:= 1; ge abl1 assign1-a ramo then jpl2-- defl1-- ramo else assign1-b defl2--
56
Produzione codice intermedio: diretta da sintassi produzioniazione di traduzione ------------------------------------------------------------------------------------------ S - - > id := ES.ptr = mknode(ASSIGN, BINARY, mknode(NAME, id), E.ptr) E - - > E1 + E2E.ptr = mknode(ADD, E1.ptr, E2.ptr) E - - > E1 * E2E.ptr = mknode(MUL, E1.ptr, E2.ptr) E - - > - E1E.ptr = mknode(MINUS, E1.ptr) E - - > (E1)E.ptr = E1.ptr E - - > idE.ptr = mknode(NAME, id)
57
Esempio: semplice calcolatrice produzioniazioni semantiche ------------------------------------------------------------------------------------------ S - - > Eprint(E_val) E - - > T + - EE_val = T_val +- E_val E - - > TE_val = T_val T - - > F */ TT_val = F_val */T_val T - - > FT_val = F_val F - - > (E)F_val = E_val F - - > numF_val = num.value
58
Generazione del codice INPUT al generatore di codice: formato intermedio – albero sintattico –istruzioni a 3 indirizzi –notazione polacca OUTPUT del generatore di codice: 1.linguaggio macchina assoluto 2.linguaggio macchina rilocabile 3.linguaggio assembler sorgente 2. Maggiore flessibilità: compilazione separata + link a librerie 3. Maggiore semplicità: allocazione della memoria, risoluzione dei salti, gestione del formato rilocabile lasciata all’assemblatore
59
Tecniche di generazione del codice 1. Macro Espansione 2. “Ad hoc” 3. Pattern matching 2. Famiglia di algoritmi ritagliati sul tipo di architettura target: prive di presupposti formali e/o di possibilità di automatizzazione
60
Macro espansione Assumendo come input delle quadruple e come output assembler per un processore dotato di registri. ADD ($1, $2, $3) isMOV$1, R0 ADD$2, R0 MOVR0, $3ASSIGN($1, nil, $3) endisMOV$1, R0 MUL ($1, $2, $3)MOVR0, $3 isMOV$1, R0end MUL$2, R0 MOVR0, $3) end
61
Esempio di macro espansione Istruzione sorgente:a:= b + c * d Produce le seguenti quadruple e codice assembler: MOVc, R0 *cdt1MULd, R0 +bt1t2MOVR0, t1 :=t2-aMOVb, R0 ADDt1, R0 MOVR0, t2 MOVt2, R0 MOVR0, a
62
Pattern matching si usano patterns srutturati ad albero che descrivono istruzioni e forme intermedie ad albero; si selezionano le istruzioni scomponendo l’input in singoli patterns; si procede top-down con tecnica simile all’analisi sintattica. L’algoritmo è simile all’analisi guidata da sintassi: ogni volta che si riconosce un pattern lo si riscrive (come se fosse una regola sintattica) e come azione corrispondente si emette codice.
63
Esempio di pattern matching A := B + C * D := A + * B C D Libreria di patterns mem < - - :=[mov reg, mem] mem reg reg < - - +[add mem, reg] mem reg reg < - - *[mov mem1, reg mem1 mem2 mul mem2, reg] Seleziona il pattern 1 Chiede match sul figlio destro Seleziona pattern 2 Chiede match sul figlio destro Seleziona pattern 3 Emissione codice 3 Riscrittira del’albero Emissione codice 2 Riscrittura dell’albero Emissione codice 1 1 2 3
Presentazioni simili
© 2024 SlidePlayer.it Inc.
All rights reserved.