1 / 82

Implementazione di Linguaggi 2 PARTE 2

Implementazione di Linguaggi 2 PARTE 2. Massimo Ancona DISI Università di Genova Testo: A.V. Aho, R. Sethi, J.D.Ullman Compilers Principles,Techniques and Tools, Addison Wesley. Analisi semantica: Traduzione Guidata dalla Sintassi. Si basa sull’associazione di:

kane
Télécharger la présentation

Implementazione di Linguaggi 2 PARTE 2

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

  2. Analisi semantica: Traduzione Guidata dalla Sintassi Si basa sull’associazione di: • attributi semanticialle componenti sintattiche del linguaggio, e di • regole semantiche alle produzioni della grammatica per calcolare i valori degli attributi.

  3. Esempio di traduzione guidata dalla sintassi Esempio: conversione da notazione infissa a postfissa. Formalmente definita da: • se E e’ una variabile allora post(E)=E • E=E1opE2post(E1opE2)=post(E1)post(E2)op • E=(E1) post(E)=post(E1).

  4. Definizione Guidata dalla Sintassi Una DGS (DDS) e’ dafinita da: • definizione di una CFG G=(N,T,P,S) per specificare la struttura sintattica del linguaggio, • associazione di attributi ai simboli di G (elementi di V=NT), • associazione ad ogni elemento di P di un insieme di regole per valutare gli attributi di V=N  T.

  5. Algoritmo di traduzione Guidata dalla Sintassi Per ogni input I: • costruire il parse tree T di I, • per ogni nodo n etichettato da XV si denota X.a il valore dell’attributo a di x in n. Il valore di X.a viene calcolato in base alle regole semantiche per la valutazione di a associate alla produzione di X usata nel nodo n. • Un parse-tree che evidenzi i valori degli attributi e’ detto annotato.

  6. Attributi sintetizzati E’ un attributo il cui valore nel parse tree viene calcolato tramite i vlori degli attributi dei figli in una visita bottom-up dell’albero. Esempio expr expr1+term expr.t:=expr1.t||term.t||’+’ expr expr1-term expr.t:=expr1.t||term.t||’-’ expr term expr.t:=term.t term a|b|c|d. term.t:=‘a’|’b’|’c’|’d’

  7. Analisi e Traduzione expr expr1 + term expr1 - term c term b a expr.t=‘ab-c+’ expr1.t=‘ab-’ + term.t=‘c’ expr1.t=‘a’ - term.t=‘b’ c term.t=‘a’ b a

  8. Schemi di Traduzione Uno schema di traduzione e’ DGS nelle cui produzioni sono inseriti frammenti di codice detti azione semantiche. Le azioni semantiche vengono inserite nelle parti destre delle produzioni e vengono eseguite da un parser esteso quando le incontra. Esempio: rest + term {print(‘+’)} rest1

  9. Schemi di Traduzione Un DGS generalmente non impone un ordine specifico di valutazione degli attributi. Negli esempi piu’ semplici si usa una visita depth-first del parsing tree. proc visit(n: node) begin for each child m of n from-left-to-right do visit(m); eval semantic rules at n end Le traduzioni DGS viste finora sono semplici cioe’ la traduzione delle regole ass. alla parte sinistra di una regola e’ la concatenazione di quelle della relativa parte destra

  10. Parsing Il processo che stabilisce se una stringa di token apprartiene al linguaggio generato da una grammatica G. Per ogni CFG esiste un parser (con back-tracking) di complessita’ O(n3) (in teoria O(n2.7)) che analizza una stringa di n token e costruisce un parse tree di essa. I linguaggi di programmazione hanno algoritmi di complessita’ O(n) che leggono l’input una sola volta da sinistra a destra leggendo “avanti” un solo token per volta, detto look-ahead token

  11. Parsing I parser si dividono in due categorie TOP-DOWN BOTTOM-UP A seconda di come costruiscono il parse tree. I primi costruiscono una derivazione canonica sinistra, i secondi una destra. I primi sono molto popolari perche’ intuitivi e usabili in compiler costruiti a mano. I secondi si applicano a classi di linguaggi piu’ generali.

  12. Parser top-down Metodo (applicato alla G seguente): • typesimple| • ^id| • array[simple] of type • simple  integer | char | num dotdot num A partire dalla radice etichettata dal simbolo iniziale (type) si applicano i seguenti passi: • Nel nodo n etichettato A selezionare una produzione A e costruire da  i figli di n • Determinare il nodo successivo cui associare un sotto albero

  13. Parser top-down Input: ‘ array[num dotodot num] of integer ‘ type array[num dotodot num] of integer array [ simple ] of type type array[num dotodot num] of integer array [ simple ] of type num dotodot num type array[num dotodot num] of integer array [ simple ] of type num dotodot num simple type array[num dotodot num] of integer array [ simple ] of type num dotodot num simple integer

  14. Parser a Discesa Ricorsiva Metodo top-down formato da un insieme di procedure ricorsive. Si associa una procedura ad ogni non terminale della grammatica. Per la G seguente: • typesimple| • ^id| • array[simple] of type • simple integer | char | num dotdot num Si scrive una proc. per type ed una per simple

  15. Parser a Discesa Ricorsiva proc match(t: token); /* scanner*/ begin if lookahead = t then next_token else error; end;

  16. Proc type proc type; /* */ begin if lookahead in {‘integer’,’char,’num’} then simple else if lookahead =‘^’ then begin match(‘^’); match(id) end else if lookahead = ‘array’ then begin match(‘array’); match(‘[‘); simple; match(‘]’); match(‘of’); type end else error end;

  17. Proc simple proc simple; /* */ begin if lookahead =‘integer’ then match(‘integer’) else if lookahead = ‘char’ then match(’char’) else if lookahead =‘num’ then begin match(‘num’);match(‘dotdot’); match(‘num’) end else error end;

  18. Codice completo in Io (1) MODULE PostFix(TABLES); VAR ch: CHAR; PROCEDURE Find; BEGIN DO READ(ch) UNTIL (ch<>' ')AND NOT EOLN END; (* Find*)

  19. Codice completo in Io (2) PROCEDURE Expression; VAR Op: CHAR; PROCEDURE Term; PROCEDURE Factor; BEGIN IF ch='(' THEN Find; Expression; (* ch=) *) ELSE WRITE(ch) FI; Find END; (* Factor *)

  20. Codice completo in Io (3) BEGIN (*Term*) Factor; WHILE ch='*' DO Find; Factor; WRITE('*') OD; END; (*Term*)

  21. Codice completo in Io (4) BEGIN (* Expression*) Term; WHILE (ch='+') OR (CH='-') DO Op:=ch;Find; Term; WRITE(Op) OD; END; (* Expression*)

  22. Codice completo in Io (5) BEGIN (* Main*) Find; DO WRITE(' '); Expression; WRITELN UNTIL Ch='.' END.

  23. Parser Predittivo: teoria Lo sviluppo si basa sulla conoscenza dei primi simboli generabili nella parte destra di una produzione A insieme indicato: FIRSTk()={wT*| |w|<k & *w or |w|=k & xT* *wx} FIRST()=FIRST1() FIRST1()={a T{}|a= & * OR xT* *ax} Se A e A sono due produzioni di G allora esiste un parser a discesa ricorsiva senza backtraking se: FIRST() FIRST()= Le produzioni A richiedono un trattamento speciale

  24. Parser Predittivo: ricorsione sinistra Un parser a discesa ricorsiva puo’ entrare in loop quando incontra una produzione (o un set di produzioni) che originano una ricorsione sinistra. Ad esempio le produzioni: EE+T | E-T | T Sono entrambe ricorsive a sinistra (in E). Questo fa parte di un caso generale AA| In cui =+T (-T)e =T. Questo problema e’ eludibile sostituendo le produzioni precednti con: AR RR|

  25. PARTE APPROFONDITA FINE PARTE DI SURVEY INIZIO LUCIDI DETTAGLIATI

  26. ANALISI LESSICALE

  27. ANALISI LESSICALE

  28. ANALISI LESSICALE • Motivazioni: • Semplificazione progettuale • Efficienza • Portabilita’ • Token pettern lexemi • b2a  • Xyw  letter{(letter|digit)}  ident • Zz23  • Lexemi pattern token

  29. ANALISI LESSICALE • In certi linguaggi l’analisi lessicale non e’ semplice (es. Fortran): • Ammette keyword come identificatori • E’ position dependent • Fa uso troppo libero degli spazi • DO 1 I=1,10 istruzione do (tipo for loop) • DO 1 I=1.10 assegnamento • 100 FORMAT(X7H)=(3-2) ambigua

  30. ATTRIBUTI ASSOCIATI AI TOKEN • Quando piu’ di un lexema soddisfano un pattern lo scanner deve associare attributi ai singoli lexemi per distinguerli: • zx12 ident ‘zx12’ la stringa che identifica uno specifico lexema • 12.45 float ‘12.45 in codice float’ • Se la corrispondenza lexema token e’ 1-1 non occorrono attributi. Esempio • WHILE <---> whiletoken

  31. ERRORI LESSICALI • Pochi errori sono identificabili a questo livello. Il recupero di errori si basa sulla panic rule • Si scartano i caratteri successivi a quello errato finche’ non e’ possibile riconoscere un nuovo token

  32. INSIEMI REGOLARI • Dato un alfabeto T, la famiglia degli insiemi regolari su T e’ la famiglia piu’ piccola di insiemi di T* che: • contiene gli insiemi finiti • e’ chiusa rispetto alle operazioni • unione (), • concatenazione (.) • star (*)

  33. ESPRESSIONI REGOLARI • Una sintassi comoda per esprimere insiemi regolari: •  e’ un’espressione regolare che denota l’insieme  •  e’ un’espressione regolare che denota  • per ogni aT a e’ un’espressione regolare che denota a

  34. ESPRESSIONI REGOLARI • Se p e q sono espressioni regolari che denotano gli insiemi regolari P e Q rispettivamente, allora: • p+q e un’ E.R. che denota l’I.R. PQ (a volte usiamo anche p|q). • pq (o p.q) un’E.R. che denota P.Q • p* e’ un’E.R. che denota P*

  35. ESPRESSIONI REGOLARI ESEMPI • Un identificatore e’ una sequenza di lettere o cifre, la prima delle quali e’ una cifra: • digit=0+1+…+9 • letter = a+b+c+…+x+y+z allora: • ident = letter(digit+letter)* • int = digit(digit)* • espon=(+’E’(‘+’|’-’| )digitdigit)

  36. ESPRESSIONI REGOLARI ESEMPI • int = digit(digit)* • espon=(+’E’(‘+’+’-’+ )int) • float=int(‘.’int)espon

  37. ESPRESSIONI REGOLARI E CFG Definizione Una CFG G=(N,T,P,S) e’ lineare a destra (risp. sinistra) se ogni A ha forma AxB|y A,BN x,yT (rispettivamente ABx|y). Teorema Un sottoinsieme L T* e’ regolare sse esiste CFG G lineare a destra (sinistra) tale che L=L(G).

  38. ESPR. REGOLARI E AUTOMI Definizione Un automa finito non-deterministico e’ una quintupla A=(Q,T,, q0,F) dove: Q e’ un insieme finito detto degli stati T e’ un alfabeto dei simboli in input  e’ la funzione di transizione : QT(Q) dove (Q)=2Q e’ l’insieme delle parti di Q. q0Q e’ detto stato iniziale F e’ l’insieme degli stati finali di accettazione

  39. ESPR. REGOLARI E AUTOMI Spiegazione L’automa opera leggendo sequenzialmente da un nastro in input simboli di T partendo dallo stato iniziale. Ad ogni input A esegue una transizione pilotata da , l’input viene accettato se l’automa termina la lettura in uno stato di F, non accettato se qualunque sequenza di transizioni non porta mai ad uno stato di F. Piu’ esattamente:

  40. ESPR. REGOLARI E AUTOMI Definizione Ogni coppia (q,w)  Q T* e’ detta una configurazione di A. Definizione una mossa di A, denotata ├ o├A e’ definita wT* tra 2 configurazioni da: (q,aw)├A(q’,w)  aT: q’(q,a) Se C e C’ sono configurazioni di A allora: C ├0 C’ sse C=C’; C ├n C’ sse C=C1├ C2 ├ … ├ Cn=C’ C ├*C’ sse n0: C ├n C’

  41. LINGUAGGIO ACCETTATO DA UN AUTOMA DefinizioneL(A)=wT*|(q0,w)├*(q, ) & qF e’ detto linguaggio accettato da A. Teorema Un linguaggio L T* e’ regolare se e solo se esiste un automa A tale che L=L(A). Ne segue che gli insiemi regolari sono caratterizzati equivalentemente da espressioni regolari, automi finiti o grammatiche lineari a destra (sinistra)

  42. DETERMINISMO non DETERMINISMO Definizione Un automa A=(Q,T,, q0,F) e’ detto deterministico se per ogni qQ e aT si ha | (q,a)|1. Inoltre A e’ detto completamente specificato se | (q,a)|=1 Teorema Sia L T* un linguaggio accettato da un automa non deterministico A (L=L(A)) allora esiste un automa deterministico A’ tale che L=L(A’).

  43. DETERMINISMO non DETERMINISMO Definizione Se A=(Q,T,, q0,F) e’ un automa deterministico, si indica (q,a)=q’ in luogo di  (q,a)=q’, l’unico valore associato a (q,a). Essendo gli insiemi regolari definibili sia da espressioni regolari che da automi, usiamo le prime per definire lo scanner e i secondi per implementarlo.

  44. DETERMINISMO non DETERMINISMO Definizione Dato A=(Q,T,, q0,F) automa deterministico, da (q,a)=q’ si deduce che per ogni configurazione C=(q,aw) e’ unico lo stato q’ e la mossa o transizione (q,aw)├(q’,w)=C’ per cui (q,a)=q’. Per questo, gli automi deterministici sono piu’ efficienti di quelli non deterministici e piu’ adatti per implementare scanner.

  45. IMPLEMENTAZIONE DI SCANNER Scanner: costruzione. Si definisce un insieme di espressioni regolari che date in input ad uno ‘scanner constructor’ costruisce un automa finito deterministico ottimizzato che implementa la scanner richiesto. Noi mostrimo i seguenti passaggi: Esp.Reg  NFA  DFA DFA ottimale la costruzione del NFA e’ ridodndante

  46. DA NFA a DFA • Scanner: costruzione. Se L=L(M) per NFA A=(Q,T,, q0,F) allora il DFA equivalente e’ A’=(Q’,T,’, q’0,F’) con: • Q’=(Q)=2Q • q0’=q0, •  SQ ’(S,a)=p| qS: p(q,a)= • (S,a) • F’=S Q | SF

  47. DA NFA a DFA NFADFA: e’ facile mostrare che: A(S,w)├iA’(S’,)  S’={p|qS: (q,w)├iA (p, )}

  48. DIAGRAMMI DI TRANSIZIONE E’ un flowchart stilizzato di un analizzatore lessicale. Permette di tener traccia dei caratteri letti dallo scanner. Si possono avere diagrammi deterministici e non. Grafo di transizione e’ un grafo orientato con vertici etichettati da sinboli di Q e gli archi etichettati da simboli in T. I diagrammi di transizione modellano DFA i

  49. DIAGRAMMI DI TRANSIZIONE Diagramma di transizione: flowchart stilizzato di un analizzatore lessicale. Permette di tener traccia dei caratteri letti dallo scanner. Si possono avere diagrammi deterministici e non. Grafo di transizione e’ un grafo orientato con vertici etichettati da sinboli di Q e gli archi etichettati da simboli in T. I diagrammi di transizione modellano DFA

  50. DIAGRAMMI DI TRANSIZIONE I diagrammi di transizione sono deterministici, gli archi uscenti dallo stesso vertice hanno etichette distinte. I grafi di transizione sono in generale non deterministici: dallo stesso vertice possono uscire archi con la stessa etichetta.

More Related