albero sintattico parser scanner Errori sintattici

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

Algebra di Boole Algebra di Boole

Trattamento degli errori

Programmazione. Cognome... Nome... Matricola... Prova scritta del 11 luglio 2014

2. Sintassi e Semantica

Linguaggi e tecnologie per il Web

Come funziona il linguaggio COME FUNZIONA IL LINGUAGGIO

Programmazione Dichiarativa. Programmazione Logica. SICStus PROLOG PROLOG. Bob Kowalski: "Algoritmo = Logica + Controllo"

Programmazione. Cognome... Nome... Matricola... Prova scritta del 22 settembre Negli esercizi proposti si utilizzano le seguenti classi:

Il calcolatore. Architettura di un calcolatore (Hardware)

Analizzatore lessicale o scanner

ESERCIZI IN PIÙ I NUMERI COMPLESSI

VBA è un linguaggio di scripting derivato da Visual Basic, da cui prende il nome. Come ogni linguaggio ha le sue regole.

Modulo 2 Data Base - Modello Relazionale

Riconoscere e formalizzare le dipendenze funzionali

La codifica. dell informazione

Prof.ssa Laura Pagnozzi Prof. Ivano Coccorullo. Calcolo Combinatorio

Linguaggi formali e compilazione

Unità Didattica 3 Linguaggio C. Generalità sulle Funzioni. Variabili locali e globali. Passaggio di parametri per valore.

Le aree dell informatica

Dispensa YACC: generalità

Procedura operativa per la gestione della funzione di formazione classi prime

7. OSSA. Alessio Maculani

Analisi. Calcolo Combinatorio. Ing. Ivano Coccorullo

Introduzione a Visual Basic Lezione 2 Cicli e anomalie

Fondamenti di Programmazione

4 GLI ARRAY E LE STRINGHE

Esercizi sulla conversione tra unità di misura

Programmazione Ricorsione

Esercitazione n o 3 per il corso di Ricerca Operativa

Sistemi Web per il turismo - lezione 3 -

Lezione 8. La macchina universale

Ingegneria del Software 9. Macchine a stati. Dipartimento di Informatica Università di Pisa A.A. 2014/15

INTRODUZIONE ALLE BASI DATI RELAZIONALI

COMPILAZIONE. Tarsformazione di linguaggi

Ingegneria del Software

CAPITOLO V. DATABASE: Il modello relazionale

SOTTOSPAZI E OPERAZIONI IN SPAZI DIVERSI DA R n

1.2 MONOMI E OPERAZIONI CON I MONOMI

PowerDIP Software gestione presenze del personale aziendale. - Guida all inserimento e gestione dei turni di lavoro -

Algoritmi. Un tema centrale dell informatica è lo studio degli algoritmi.

Linguaggi e Traduttori: Introduzione al corso

La disposizione estetica della lettera commerciale

INDICAZIONI PER LA RICERCA DEGLI ASINTOTI VERTICALI

I database. Introduzione alla teoria delle basi di dati

Somma di numeri floating point. Algoritmi di moltiplicazione e divisione per numeri interi

Italiano Tecnico La relazione di lavoro

FONDAMENTI DI INFORMATICA

UD4 - MATLAB. M-file. Efficienza degli algoritmi. Formati d uscita

Il sistema informativo deve essere di tipo centralizzato e accessibile mediante un computer server installato nella rete locale dell albergo.

LINGUAGGI DI PROGRAMMAZIONE LINGUAGGI DI BASSO LIVELLO

Lezione 3 Progettazione di siti

0.1 Esercizi calcolo combinatorio

Gestione delle eccezioni in Java

Normalizzazione. Definizione

Sul pattern Decorator

Cos è un Calcolatore?

7 Disegni sperimentali ad un solo fattore. Giulio Vidotto Raffaele Cioffi

Le sue caratteristiche:

Metodi per la risoluzione di sistemi lineari

RELAZIONI BINARIE. Proprietà delle relazioni Data una relazione R, definita in un insieme non vuoto U, si hanno le seguenti proprietà :

Macchina di Turing ... !!... !!! a b b! b a! Nastro di Input. testina. s t q i. s r. Unità di Controllo q j S / D / F

Gli algoritmi: definizioni e proprietà

Principi e Metodologie della Progettazione Meccanica

Appunti del corso di Informatica 1 (IN110 Fondamenti) 3 Modelli di calcolo

Corso di Laurea in Matematica per l Informatica e la Comunicazione Scientifica

Applicazioni lineari e diagonalizzazione. Esercizi svolti

Laurea triennale - Comunicazione&DAMS - UNICAL. Dr. Marco Manna 1

WINDOWS Avviare Windows95. Avviare Windows95 non è un problema: parte. automaticamente all accensione del computer. 2. Barra delle applicazioni

Progettazione logica

Internet (- working). Le basi.

Steel&Graphics srl Via Cà Nova Zampieri 4/E San Giovanni Lupatoto VR Tel. 045/ Fax. 045/

EQUAZIONI DI PRIMO GRADO

Capitolo 5: Macchine di Turing e calcolabilitá secondo Turing

Ministero della Salute

E una notazione per descrivere gli algoritmi.

Topologie delle reti di telecomunicazione

Sistemi di equazioni lineari

Introduzione alle macchine a stati (non definitivo)

Occupazione e disoccupazione

Lezione 6 Le pile. Informatica. 28 Aprile 2016

TEORIA RELAZIONALE: INTRODUZIONE

Lezione 4. Sommario. L artimetica binaria: I numeri relativi e frazionari. I numeri relativi I numeri frazionari

IL TIME MANAGEMENT: ORGANIZZARE IL TEMPO E GOVERNARLO

ACCESS. Database: archivio elettronico, dotato di un programma di interfaccia che facilita la registrazione e la ricerca dei dati.

Teoria della Progettazione delle Basi di Dati Relazionali

Interpretazione astratta

LA PREDISPOSIZIONE DELLA NOTA INTEGRATIVA

BILANCIO DEI VINCOLI ED ANALISI CINEMATICA

* in giallo le modifiche apportate rispetto alla versione precedente datata 17/04/2012

Esercizi svolti sui sistemi lineari

Progetto Automi e Linguaggi Parser svliluppato con JLex e cup

Il linguaggio SQL: query innestate

Transcript:

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. 1

La sintassi è costituita da un insieme di regole che definiscono le frasi formalmente corrette 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 di programmazione 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. 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 efficienti la definizione del linguaggio attraverso le regole delle sintassi libere dal contesto è 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 grammatiche libere dal contesto come l unico metodo pratico per definire formalmente la struttura di un linguaggio. 2

Non tutte le regole di un linguaggio di programmazione possono essere espresse in termini nel modello noncontestuale. Ad esempio non puo espremere le seguenti regole: 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 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. Il parser lavora con stringhe di tokens Programa sorgente Scanner token get next token Parser Albero sintattico 3

Le strutture ricorsive presenti nei linguaggi di programmazione sono definite da una grammatica contextfree. Una grammatica context-free (CFG) è definita come Un insieme finito di terminali S (sono i token prodotti dallo scanner) Un insieme di non terminali V. Un assioma o simbolo iniziale (uno dei non terminali. Un insieme di produzioni (dette anche rewriting rules con la seguente forma A X 1... X m dove X 1 to X m possono essere terminali o non terminali. Se m =0 si ha A che è una produzione valida Le strutture ricorsive presenti nei linguaggi di programmazione sono definite da una grammatica contextfree. Una grammatica context-free (CFG) è definita come Un insieme finito di sempio terminali V (sono i token prodotti dallo scanner) T = { (, ), id, vsl, +, *, /, -} Un insieme di non terminali V = {} V. + Un assioma o simbolo iniziale (uno dei non terminali. Un insieme di produzioni (dette * anche rewriting rules con la seguente forma / - A X 1... X m ( ) dove X 1 to X m possono essere id terminali o non terminali. val Se m =0 si ha A che è una produzione valida 4

+ + deriva da Possiamo sostituire con con + 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 è derivato da n ) one step * zero o più steps + 1 o più steps V = { Prog, Seq, Istr, xpr} T = { {, ;, id, +,} } Assioma = Prog Prog { Seq } Seq Istr; Seq Seq Istr { Seq } Istr id = xpr xpr id xpr xpr + id V = { Prog, Seq, Istr, xpr} T = { {, ;, id, +, } } Assioma = Prog Prog { Seq } Seq Seq ; Istr Istr {Seq } id = xpr xpr id xpr + id 5

Per esempio partendo da Prog possiamo generare, applicando ripetutamente le produzione le seguenti stringhe: Prog { Seq } { Istr ; Seq} {Istr; Istr ; Seq} { id = xpr ; Istr, } { id = id ;Istr ; } { id = id ; id = xpr } { id = id ; id = xpr + id} { id = id ; id = id + id} Le produzioni devono avere le seguenti proprietà: no produzioni inutili o ridondanti (i.e., A A), no non-terminali nella RHS di una produzione senza produzioni con LHS uguale al non terminale (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 6

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. Derivazione canonica sinistra (Left-Most Derivation) - -() -(+) -(id+) -(id+id) Derivazione canonica destra (Right-Most Derivation) - -() -(+) -(+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 7

I nodi non foglie 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. sempio: Consideriamo l analisi della frase 1 + 2 * 3 secondo la seguente grammatica <expr> ::= <expr> + <expr> <expr> * <expr> L analisi sintattica può essere vista come un processo number per costruire gli alberi sintattici (parse tree). La sintassi di un programma è descritto da un agrammatica libera dal contesto (CFG). La notazione BNF (Backus-Naur Form) è una notazione per la descrzione di una CFG. 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 8

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 T = { (, ), id, +, *, /, -} V = {} + * / - ( ) id Per poter costruire un parser la grammatica non deve essere ambigua Grammatica non ambigua un unico albero sintattico per ogni frase del linguaggio Le ambiguità nella grammatica devono essere eliminate durante il progetto del compilatore 9

istr if expr then istr if expr then istr else istr otheristrs if 1 then if 2 then S 1 else S 2 istr if expr then istr else istr istr if expr then istr 1 if expr then istr S 2 1 if expr then istr else istr 2 S 1 1 2 2 S 1 S Noi preferiamo il secondo albero sintattico (else corrisponde al if più vicino). Dobbiamo eliminare l ambiguità con tale obiettivo La grammatica non-ambigua sarà: istr matchedistr unmatchedistr matchedistr if expr then matchedistr else matchedistr otheristrs unmatchedistr if expr then istr if expr then matchedistr else unmatchedistr 10

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 id () precedenze: * (left to right) + (left to right) 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. 11

A A dove A e (V T)* A A A A grammatica equivalente In generale A A 1... A m 1... n A 1 A... n A A 1 A... m A dove i A e (V T)* grammatica equivalente +T T T T*F T F F id F () eliminate immediate left recursion T +T T F T T *F T T F id F () 12

Una grammatica che non e direttamente left-recursive, ma lo è in modo indiretto Anche in questo caso va eliminata la ricorsione sinistra sempio S Aa b A Sc d S Aa Sca A Sc Aac - 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 } 13

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 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 14

Un parser top down deterministico richiede una grammatica left-factored. grammatica grammatica equivalente istr if (expr ) istr else istr if (expr) istr In generale, A 1 2 dove (V T)* - { }, 1 (V T)* 2 (V T)* e 1 2. Noi possiamo riscrivere la grammatica come segue A A A 1 2 15

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 A abb ab cdg cdeb cdfb A aa cdg cdeb cdfb A bb B A aa cda A bb B A g eb fb 16

A ad a ab abc b A aa b A d b bc A aa b A d ba A c istr if (expr ) istr else istr if (expr) istr istr if (expr ) istr X X else istr X 17

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 look-ahead! 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 18

abbcde aabcbe aacbe S applicando B d applicando A b applicando A Ab applicando S aacbe A 1 A 2 S 4 B 3 a b b c d e 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 contextfree: LL per top-down LR per bottom-up Una left-most (right-most) derivation è una derivazione nella quale durante ogni passo viene sostituito solo il non-terminale più a sinistra (destra). 19

Data una grammatica non contestuale G(V,T,P,S) si definisce First( ) = {a in T * a } Quindi First( ) è il seguente sottoinsieme di T: se = a con a T allora a First( ) se = A con A V 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 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} 20

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(bC) ={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( )= { } 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(+) = {+} 21

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, } 22

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, $} 23

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) = {), $ } 24

T = {a, b, c, d, e} V = {A, B, C, D} P = { S = A A B Ce a B bc, C Dc D d } 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, $} 25