Analisi sintattica. Syntax Analysis. albero. sintattico. parser. scanner. Errori sintattici

Documenti analoghi
albero sintattico parser scanner Errori sintattici

Analisi sintattica. Analisi sintattica. albero. sintattico. parser. scanner. Errori sintattici

Parser top-down. Top-Down Parsing

Grammatiche context-free

Linguaggi Liberi dal Contesto. Linguaggi Liberi dal Contesto

Linguaggi formali e compilazione

Analisi sintattica (parser)

Linguaggi context free. Analizzatori sintattici e alberi di analisi

1. Calcolare FIRST e FOLLOW dei simboli non terminali della seguente grammatica:

Proprietà dei linguaggi non contestuali

Grammatiche. Rosario Culmone, Luca Tesei. 20/11/2006 UNICAM - p. 1/49

Linguaggi e Traduttori: Analisi sintattica

Linguaggi e Ambienti di Programmazione

Espressività e limitazioni delle grammatiche regolari

1. Calcolare FIRST e FOLLOW dei simboli non terminali della seguente grammatica:

Automa deterministico con prospezione 1. < {q}, Σ, Σ V, δ, q, S, Φ > δ(a, X) = α R. se a Gui(X α) senza spostamento della testina.

Pumping lemma per i linguaggi Context-free

Dispensa 1. Da un punto di vista logico l architettura di un compilatore si può suddividere in due parti: Analisi e Sintesi.

Analizzatore lessicale o scanner. Lo scanner rappresenta un'interfaccia fra il programma sorgente e l'analizzatore sintattico o parser.

Grammatiche Parse trees Lezione del 17/10/2012

PROLOG E ANALISI SINTATTICA DEI LINGUAGGI Quando si vuole definire in modo preciso la sintassi di un linguaggio si ricorre a una grammatica G=(V n,v t

LINGUAGGI DI ALTO LIVELLO. Si basano su una macchina virtuale le cui mosse non sono quelle della macchina hardware

LINGUAGGI DI ALTO LIVELLO

LINGUAGGI CONTEXT FREE. Lezione Lezione

Riconoscitori e analizzatori sintattici. Scanning e parsing. Funzionamento di un parser: la tecnica Shift/Reduce. Esempio

Contenuti del corso. Parsing: esempio. Cosa aggiungiamo in questo corso. Parsing. Data una grammatica: E T T + E

Traduttore diretto dalla sintassi (seconda parte) Giuseppe Morelli

acuradi Luca Cabibbo e Walter Didimo Esercizi di Informatica teorica - Luca Cabibbo e Walter Didimo 1

Grammatiche. Grammatiche libere da contesto Grammatiche regolari Potenza delle grammatiche libere e regolari Struttura di frase: Alberi di derivazione

Linguaggi e Traduttori: Analisi lessicale

LINGUAGGI DI ALTO LIVELLO. Si basano su una macchina virtuale le cui mosse non sono quelle della macchina hardware

Parser Bottom UP. Giuseppe Morelli

Parte n.4 Linguaggi: Gerarchia ed Operazioni

Fondamenti d Informatica: linguaggi formali. Barbara Re, Phd

Forme Normali. Forma normale di Chomsky. E caratterizzata da regole di due tipi. A! BC dove A, B, C $ V N A! a con a $ V T. Forma normale di Greibach

Linguaggi di Programmazione

Fasi di un Compilatore

Quiz sui linguaggi CF

Corso di Linguaggi e Traduttori 1 AA GRAMMATICHE

Forma Normale di Chomsky

Definizione di Grammatica

Dall algoritmo al calcolatore: concetti introduttivi. Fondamenti di Programmazione

Yet Another Compiler-Compiler. Generazione automatica di analizzatori sintattici

Verificare se una grammatica e LL(1) e costruirne la tabella di parsing. Verificare se una grammatica e LR(0) e costruirne la tabele ACTION e GOTO

Definizioni syntax-directed

Linguaggi di alto livello. Barriera di astrazione. Pascal. Cobol. Fortran. Basic. Modula-2. Lisp. Simula67 Scheme. Smalltalk C++ Prolog AN

Unità Didattica 2 I Linguaggi di Programmazione

a cura di Luca Cabibbo e Walter Didimo

Le grammatiche formali

Corso di Programmazione Linguaggi di Programmazione

C++ Barriera di astrazione. Barriera di astrazione. Basic. Basic. Lisp. Lisp. Pascal. Prolog. Pascal. Prolog. Cobol. Fortran IMPERATIVI FUNZIONALI

Corso di Fondamenti di Informatica Linguaggi di Programmazione

Automi e Linguaggi Formali Automi a stack (Pushdown automata)

Corso di Programmazione Linguaggi di Programmazione. Linguaggio. Messaggio

I Linguaggi di Programmazione

Semantica e traduzione guidata dalla sintassi (cenni)

Dispensa 2. Data una grammatica context free esistono tre metodi diversi per costruirne la parsing table per un parser LR:

7. Automi a Pila e Grammatiche Libere

LINGUAGGI DI ALTO LIVELLO

Parser bottom-up. Esempio. V = {S, A, B, C} T = {a, b, d, e} P = { S aa R1 A BaA R2 A e R3 B ac R4 B AdC R5

Linguaggi Regolari e Linguaggi Liberi

Traduzione guidata dalla sintassi

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica

Descrizione dei Linguaggi di Programmazione

Costruzione dell insieme dei Follow

Automi e Linguaggi Formali

Linguaggi di Programmazione Corso C. Parte n.3 Linguaggi Liberi da Contesto e Linguaggi Contestuali. Nicola Fanizzi

Corso di Linguaggi di Programmazione

GRAMMATICHE DEI LINGUAGGI DI PROGRAMMAZIONE. Cosimo Laneve

Espressioni aritmetiche

Espressioni Regolari

Un po di storia sui linguaggi

Linguaggi per il Web

Linguaggi, Traduttori e le Basi della Programmazione

Linguaggi di programmazione - Principi e paradigmi 2/ed Maurizio Gabbrielli, Simone Martini Copyright The McGraw-Hill Companies srl

Esercitazioni di Linguaggi e Traduttori

Funzioni, Stack e Visibilità delle Variabili in C

Definire tramite una grammatica ad attributi il

Corso di Linguaggi di Programmazione + Laboratorio Docente: Marco de Gemmis

Analisi lessicale (scanner)

Concetti di base sugli automi e sui linguaggi formali

LA SINTASSI DEI LINGUAGGI DI PROGRAMMAZIONE. Ivan Lanese

Il Modello di un Compilatore. La costruzione di un compilatore per un particolare linguaggio di programmazione e' abbastanza complessa.

Linguaggi e Grammatiche Liberi da Contesto

Espressioni regolari

Programma del corso. Elementi di Programmazione. Introduzione agli algoritmi. Rappresentazione delle Informazioni. Architettura del calcolatore

Analizzatori Lessicali con JLex. Giuseppe Morelli

Informatica 3. LEZIONE 2: Sintassi e semantica

Università degli studi Roma Tre. linguaggio Java. A cura di A. Orlandini. Linguaggi: Sintassi e Semantica - Il. Il linguaggio Java

Lezioni del corso di Progetto di Linguaggi e Traduttori

Introduction. The Structure of a Compiler

Analisi lessicale (scanner)

Il Modello di un Compilatore. La costruzione di un compilatore per un particolare linguaggio di programmazione e' abbastanza complessa.

GRAMMATICA FORMALE. Albero sintattico

Parsing. Marco Pennacchiotti. Tel Ing.dell Informazione, stanza 1035 (primo piano) 1 Luglio 2005

Programmazione. Marco Anisetti. Università degli Studi di Milano, Dipartimento di Informatica

MODULO 04 ELEMENTI DI TEORIA DEI LINGUAGGI FORMALI

Introduzione alla programmazione

(1) Linguaggio L = insieme di stringhe, sequenze finite di elementi del vocabolario

Transcript:

Analisi sintattica Syntax Analysis albero programma scanner tokens parser sintattico rrori sintattici Un parser deve riconoscere la struttura di una stringa di ingresso, la cui struttura è fornita in termini di regole di produzione di una CFG, BNF, o diagrammi sintattici. Un parser è una macchina astratta che raggruppa input in accordo con regole grammaticali.

Sintassi La sintassi è costituita da un insieme di regole che definiscono le frasi formalmente corrette e allo stesso tempo permettono di assegnare ad esse una struttura (albero sintattico) che ne indica la decomposizione nei costituenti immediati. Ad es. la struttura di una frase (ovvero di un programma) di un linguaggio programmativo ha come costituenti le parti dichiarative e quelle esecutive. Le parti dichiarative definiscono i dati usati dal programma. Le parti esecutive si articolano nelle istruzioni, che possono essere di vari tipi: assegnamenti, istruzioni condizionali, frasi di lettura, ecc. I costituenti del livello più basso sono gli elementi lessicali già considerati, che dalla sintassi sono visti come atomi indecomponibili. Infatti la loro definizione spetta al livello lessicale. Sintassi La teoria formale dei linguaggi offre diversi modelli, ma nella quasi totalità dei casi il tipo di sintassi adottata è quello noto come sintassi libera o non-contestuale (context-free) che corrisponde al tipo 2 della gerarchia di Chomsky. I metodi sintattici per il trattamento del linguaggio sono semplici ed efficienti: la definizione del linguaggio attraverso le regole delle sintassi libere è diretta ed intuitiva; gli algoritmi deterministici di riconoscimento delle frasi sono veloci (hanno complessità lineare) e facili da realizzare partendo dalla sintassi. Tutti questi vantaggi hanno imposto le sintassi libere come l unico metodo pratico per definire formalmente la struttura di un linguaggio.

Sintassi Ma quello che si può ottenere con una sintassi libera è limitato e spesso insufficiente; la sintassi non basta a definire le frasi corrette del linguaggio di programmazione, perché una stringa sintatticamente corretta non è detto che lo sia in assoluto; infatti essa potrebbe violare altre condizioni non esprimibile nel modello noncontestuale. Ad esempio è noto che la sintassi non può esprimere le seguente condizioni: in un programma ogni identificatore di variabile deve comparire in una dichiarazione; il tipo del parametro attuale di un sottoprogramma deve essere compatibile con quello del parametro formale corrispondente. Sintassi Un altro limite del modello sintattico libero tocca le esigenze di calcolo della traduzione. Se si guardano le traduzioni definibili con i soli metodi sintattici, esse sono decisamente povere inadeguate ai problemi reali (compilazione di un linguaggio programmativo nel linguaggio macchina) Da queste critiche sarebbe sbagliato concludere che i metodi sintattici sono inutili: al contrario essi sono indispensabili come supporto (concettuale e progettuale) su cui poggiare i più completi strumenti della semantica.

Parser Il parser lavora con stringhe di tokens source program Lexical Analyze r token get next token Parser parse tree sempio: Consideriamo l analisi della frase 1 + 2 * 3 secondo la seguente grammatica Parser <expr> ::= <expr> + <expr> <expr> * <expr> L analisi sintattica può essere vista come un number processo per costruire gli alberi sintattici (parse tree). The syntax of a programming is described by a context-free grammar (CFG). We will use BNF (Backus-Naur Form) notation in the description of CFGs. Il parser verifica se un programma sorgente soddisfa le regole implicate da una grammatica context-free o no. Se le soddisfa, il parser crea l albero sintattico (del programma Altrimenti genera un messaggio di errore. Una grammatica non contestuale Da una specifica rigorosa della sintassi dei linguaggi di programmazione Il progetto della grammatica e la fase iniziale del progetto del compilatore sistono strumenti automatici per costruire automaticamente il compilatore dalla grammatica

Parser Due differenti metodi di analisi sintattica top-down: l albero sintattico è creato dalla radice alle foglie bottom-up: l albero sintattico è creato dalle foglie alla radice Il parser può lavorare in una varietà di modi ma esso tipicamente processa l input da sinistra a destra. Parser sia top-down che bottom-up possono essere implmentati in modo efficente solo per alcune sottoclassi di gramatiche context-free: LL per top-down LR per bottom-up Una left-most (right-most) derivation è una derivazione nella quale durante ogni passo solo il non-terminale più a sinistra 8destra) è sostituito. Grammatiche di tipo Context-Free Le strutture ricorsive presenti nei linguaggi di programmazione sono definite da una grammatica context-free. In una grammatica context-free grammar, noi abbiamo: Un insieme finito di terminali T (l insieme dei tokens) Un insieme finito di no terminali V(variabili sintattiche) Un insieme finito di produzioni nella forma A α dove A V e α (V T)* Un start symbol (uno dei non-terminal) sempio T = { (, ), id, +, *, /, -} V = {} + * / - ( ) id

Derivazioni + + deriva da Possiamo sostituire con by + Perr poter fare questo deve esistere una produzione + nella grammatica. + id+ id+id Una sequenza di sostituzioni di non-terminali e chiamata una derivazione di id+id da. In generale un passo di derivazione è αaβ αγβ se A γ in G α (V T)* e β (V T)* α 1 α 2... α n (α n deriva da α 1 o α 1 èderivatodaα n ) one step * zero o più steps + 1 o più steps Le produzioni devono avere le seguenti proprietà: no produzioni inutili o ridondanti (i.e., A A), no non-terminals senza produzioni (e.g., A Ba dove B non è definito), no cicli infiniti (e.g., A Aa senza altre produzioni per A), no ambiguita : una grammatica con più alberi sintattici per la stessa espressione è ambigua descrivere correttamente il linguaggio.

CFG - Terminologia L(G) è il linguaggio generato da G. Una frase di L(G) è una stringa di simboli terminali di G. Se S è l assioma o + start symbol di G allora ω è una frase di L(G) iff S ω dove ω T*. Se G è una grammatica context-free, L(G) è un linguaggio context-free. Due grammatiche sono equivalenti se producono lo stesso * linguaggio. S α Se α contiene non-terminali, è chiamata forma di frase di G. Se α non contiene no-terminali è chiamata frase di G. Left-Most and Right-Most Derivations Left-Most Derivation lm lm lm lm lm - -() -(+) -(id+) -(id+id) Right-Most Derivation rm rm rm rm rm - -() -(+) -(+id) -(id+id) top-down parser cerca una left-most derivation del programma sorgente bottom-up parser cerca una right-most derivation del programma sorgente

Parse Tree Inner nodes dell albero sintattico sono simboli non-terminal, le foglie simboli terminali. - - -() - -(+) - ( ) ( ) -(id+) - ( ) -(id+id) - ( ) + + + id id id Un albero sintattico è una rappresentazione grafica di una derivazione. Ambiguita Una grammatica è ambigua se esistono più alberi sintattici per la stessa frase. + id+ id+* id+id* id+id*id + id id * id * +* id+* id+id* id+id*id * + id id id

Per poter costruire un parser la grammatica non deve essere ambigua Grammatica non ambigua unica selezione nell albero sintattico per una frase Le ambiguità nella grammatica devono essere eliminate durante il progetto di un compilatore Ambiguità stmt if expr then stmt if expr then stmt else stmt otherstmts if 1 then if 2 then S 1 else S 2 stmt if expr then stmt else stmt 1 if expr then stmt S 2 stmt if expr then stmt 1 if expr then stmt else st 2 S 1 1 2 2 S 1 S

Ambiguità Noi preferiamo il secondo albero sintattico (else corrisponde al if più vicino). Dobbiamo eliminare l ambiguità con tale obbiettivo La grammatica non-ambigua sarà: stmt matchedstmt unmatchedstmt matchedstmt if expr then matchedstmt else matchedstmt otherstmts unmatchedstmt if expr then stmt if expr then matchedstmt else unmatchedstmt Ambiguita Precedenza degli operatori Grammatiche ambigue possono essere rese non-ambigue in accordo alle precedenze degli operatori e alle regole di associativià degli operatori. + * ^ id () +T T T T*F F F G^F G G id () precedenze: ^ (right to left) * (left to right) + (left to right)

Ricorsione sinistra (Left Recursion) Una grammatica è left recursive se ha un non + terminale A tale che A Aα per qualche stringa α Le tecniche di parser Top-down non possono gestire grammatiche left-recursive. Una grammatica left-recursive deve esssere convertita in una non left-recursive. La ricorsione sinistra può comparire in un singolo passo della derivazione (immediate left-recursion), o può comparire in più che un passo. Immediate Left-Recursion A A α β dove β Aγ e γ (V T)* A βa A αa ε grammatica equivalente In generale A A α 1... A α m β 1... β n dove β i Aγ e γ (V T)* A β 1 A... β n A A α 1 A... α m A ε grammatica equivalente

sempio +T T T T*F F F id () T +T ε T F T T *F T ε F id () eliminate immediate left recursion Left-Recursion Problema!! Una grammatica che non e direttamente left-recursive, ma lo è in modo indirettp. Anche in questo caso va eliminata la ricorsione sinistra sempio S Aa b A Sc d S Aa Sca A Sc Aac

Algoritmo per l eliminazione della ricorsione sinistra - Ordinare I non-terminali A 1... A n -for i from 1 to n do { - for j from 1 to i-1 do { sostituire ogni produzione A i A j γ con A i α 1 γ... α k γ } dove A j α 1... α k } - eliminare la ricorsione sinistra nelle produzioni di A i sempio S Aa b A Ac Sd f - Ordinare I non-terminali: S, A per S: - non c e una ricorsione sinistra diretta. for A: - sostituiamo A Sd con A Aad bd Cosi avremoa Ac Aad bd f - liminiamo la ricorsione sinistra in A A bda fa A ca ada ε Avremo la grammatica non ricorsiva equivalente: S Aa b A bda fa A ca ada ε

sempio S Aa b A Ac Sd f - Ordinare I non-terminali : A, S per A: liminamo la ricorsione sinistra in A A SdA fa A ca ε per S: - Sostituiamo S Aa with S SdA a fa a Così avremo S SdA a fa a b - liminamo la ricorsione sinistra in S S fa as bs S da as ε Avremo la grammatica non ricorsiva equivalente: S fa as bs S da as ε A SdA fa A ca ε Left-Factoring (fattorizzazione sinistra) Un parser predittivo richiede una grammatica leftfactored. grammatica grammatica equivalente stmt if expr then stmt else stmt if expr then stmt

Left-Factoring (cont.) In generale, A αβ 1 αβ 2 dove α (V T)* - {ε}, β 1 (V T)* - {ε}, β 2 (V T)* - {ε} e β 1. Noi possiamo riscrivere la grammatica come segue A αa A β 1 β 2 Algoritmo Per ogni non-terminale A con due o più alternative (produzioni) con una parte non vuota comune A αβ 1... αβ n γ 1... γ m diventa A αa γ 1... γ m A β 1... β n

sempio A abb ab cdg cdeb cdfb A aa cdg cdeb cdfb A bb B A aa cda A bb B A g eb fb sempio A ad a ab abc b A aa b A d ε b bc A aa b A d ε ba A ε c

Le frasi possono essere analizzate da sinistra a destra (L parser), possono essere costruite con derivazioni left-most (LL(k) parser) o right-most (LR(k) parser) utilizzando k symboli di lookahead! LL è più conosciuta come top-down parser. LR è più conosciuta come bottom-up parser. Per ragioni pratiche k deve essere piccolo. Per un compilatore è auspicabile l uso di grammatiche che possono essere analizzate in modo deterministico con al più k symboli di lookahead. L assenza di ambiguità è condizione necessaria per un analisi determinstica Consideriamo un bottom up parse per abbcde generato dalla seguente grammatica con assioma S, eseguento un approccio left-most matches First. S aacbe A Ab b B d

abbcde aabcbe aacbe S applicando B d applicando A b applicando A Ab applicando S aacbe A 2 S 4 A 1 B 3 a b b c d e Definzione di First(α) Data una grammatica non contestuale G(V,T,P,S) si definisce First(α) il seguente sottoinsieme di T: se α = aβ con a T allora a First(α) se α = Aβ con A T allora se una produzione A γallora First(γ) First(α) se una produzione A εallora First(β) First(α) First(α) è l insieme di tutti i terminali con cui può iniziare una stringa derivata da α. Se α *ε allora ε First(α). First(α) = {a T α * a β} if a *ε then {ε} else

sempio T = {a, b, c, d, e}, V = {S, B, C} P = { S ase B, B bbe C, C cce d } S = S First(aSe) = {a} First(B) = First(bBe) First(C) = {b} First(cCe) First(d) = {b} {c} {d} = {b, c, d} First(bBe) = {b} First(C) = First(cCe) First(d) = {c} {d} = {c, d} First(cCe) = {c} First(d) = {d} sempio T = {a, b, c, d, e} V = {A, B, C, D} P = { A B Ce a B bc, C Dc D d ε} S = A First(B) = First(b) ={b} First(C e) = First (Dc) = First(d) First(ε) = {d} {ε} = {d, ε } First(a) = {a} First(bC )= {b} First(Dc) = First(d) First(ε) = {d} {ε} = {d, ε } First(d) = {d} First(ε )= {ε }

sempio T = {(, +, ), v, f} V = {, Prefix, Tail} P = { Prefix() v Tail Prefix f ε Tail + ε } S = First(Prefix() ) = {f} {ε} First(v Tail) = {v} First(f) = {f} First(ε )= {ε} First(+) = {+} sempio T = {a, (, ), +, ","} V = {, T, L, P} P = { + T T T a () a(l) L P ε, P P "," } S = First() = {a, (} First(T) = {a, (} First(L) = {ε, a, (} First(P) = {a, (} T = {a, b, c, d, e} V = {A, B, C, D} P = { A B C Ce a B bc C Dc D D d ε } S = A First(A) = {a, b, d, c, e, ε } First(B) = {b} First(C) = {d, c, ε } First(D) = {d, ε }

Definizione di Follow(A) Data una grammatica non contestuale G(V,T,P,S) si definisce Follow(A) l insieme dei terminali che seguono in una qualsiasi frase. sso è definito come segue: Follow(A) = {a T S + Aa.} (if S * A then {ε} else } T = {a, b, c, d, e}, V = {S, B, C} P = { S ase B, B bbe C, C cce d } S = S Follow(S) = {e, $} Follow(B) = {e, $} Follow(C) = {e, $} T = {a, (, ), +, ","} V = {, T, L, P} P = { + T T T a () a(l) L P ε, P P "," } S = Follow() = {+, ),,, $} Follow(T) = {+, ),,, $} Follow(L) = { ) } Follow(P) = {),, }

T = {(, +, ), v, f} V = {, Prefix, Tail} P = { Prefix() v Tail Prefix f ε Tail + ε } S = Follow(Prefix ) = { ( } Follow() = {$} Follow(Tail) = { $ } T = {a, b, c, d, e} V = {A, B, C, D} P = { A B Ce a B bc, C Dc D d ε} S = A Follow(A) = {$} Follow(B) = {$} Follow(C) = {$, e} Follow(D) = {c} T = {a, b, c, d, e} V = {A, B, C, D} P = { A B C Ce a B bc C Dc D D d ε } S = A Follow(A) = {$} Follow(B) = Follow(A) = {$} Follow(C) = Follow(A) Follow(B) {e} = {e, $} Follow(D) = {c } Follow(C) = {c, e, $}