Definizioni syntax-directed

Documenti analoghi
Intro. Traduzione guidata dalla sintassi. Attributi. Due notazioni a diversi livelli. Due notazioni a diversi livelli. Il flusso concettuale

Traduzione guidata dalla sintassi

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

Linguaggi e Ambienti di Programmazione

Costruzione dell insieme dei Follow

Traduttore diretto dalla sintassi (seconda parte) Giuseppe Morelli

Definire tramite una grammatica ad attributi il

Yet Another Compiler-Compiler. Generazione automatica di analizzatori sintattici

Grammatiche Parse trees Lezione del 17/10/2012

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

Semantica e traduzione guidata dalla sintassi

Inserimento in una lista ordinata

Grammatiche context-free

Un esempio di compilatore realizzato con flex e bison

Elementi lessicali. Lezione 4. La parole chiave. Elementi lessicali. Elementi lessicali e espressioni logiche. Linguaggi di Programmazione I

Fasi di un Compilatore

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

Analizzatore Lessicale Parte I Scanner

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

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

Espressioni aritmetiche

Alberi. Strutture dati: Alberi. Alberi: Alcuni concetti. Alberi: definizione ricorsiva. Alberi: Una prima realizzazione. Alberi: prima Realizzazione

ALBERI DI RICERCA BINARI (O ALBERI BINARI DI RICERCA)

Esercitazioni di Linguaggi e Traduttori

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

Esercitazione 6. Alberi binari di ricerca

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

Variabili. Unità 2. Domenico Daniele Bloisi. Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR

Pumping lemma per i linguaggi Context-free

Argomenti Avanzati.! I puntatori! Stack! Visibilità delle Variabili

Cognome e Nome : Corso e Anno di Immatricolazione: Modalità di Laboratorio (Progetto/Prova) :

n n 1 n = > Il calcolo del fattoriale La funzione fattoriale, molto usata nel calcolo combinatorio, è così definita

Analisi lessicale (scanner)

Esercizi Strutture dati di tipo astratto

Analisi lessicale (scanner)

Aritmetica postfissa

Variabili. Unità 2. Domenico Daniele Bloisi. Corso di Programmazione e Metodi Numerici Ingegneria Aerospaziale BAER

L intero è o il valore zero o una stringa di cifre che inizia con una cifra diversa sa zero.

Automi e Linguaggi Formali

Informatica 3. LEZIONE 2: Sintassi e semantica

Dispensa YACC. 1.1 YACC: generalità

Informatica 3. Informatica 3. LEZIONE 2: Sintassi e semantica. Lezione 2- Modulo 1. Le componenti di un linguaggio di programmazione

Espressività e limitazioni delle grammatiche regolari

e Algoritmi Marco Piastra Intelligenza Artificiale I Soddisfacibilità

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

La sintassi del C APPENDICE H

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

Dispensa YACC: generalità

Evoluzione del FORTRAN 14/03/2016. LABORATORIO DI PROGRAMMAZIONE Corso di laurea in matematica 15 IL LINGUAGGIO FORTRAN

Per semplicità eliminiamo le ripetizioni nell'albero.

Un esempio di mutua ricorsione

Fondamenti di Programmazione Recupero Primo Parziale 30 Gennaio 2008 Traccia A

Verso i puntatori: Cosa è una variabile?

Implementazione dell albero binario in linguaggio C++

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

Espressioni. Espressioni. Valutazione di un espressione. Espressioni semplici

albero sintattico parser scanner Errori sintattici

Linguaggio C: puntatori

Alberi n-ari: specifiche sintattiche e semantiche. Realizzazioni. Visita di alberi n-ari.

Linguaggio C - le strutture di controllo: sequenza, selezione, iterazione

4. I moduli in Access 2000/2003

Sintassi. Logica. Sintassi di Matita. Claudio Sacerdoti Coen. Universitá di Bologna 16,18/10/2017. Claudio Sacerdoti Coen

JavaScript Core Language. Prof. Francesco Accarino IIS Atiero Spinelli Sesto San Giovanni via leopardi 132

Funzioni, Stack e Visibilità delle Variabili in C

Complessità algoritmi su strutture dati (riassunto)

Complessità algoritmi su strutture dati

Alberi. Alberi: definizioni. Alberi Binari. Esercizi su alberi binari: metodi ricorsivi. Struttura dati per alberi generici. ASD-L - Luca Tesei

Pile Le pile: specifiche e realizzazioni attraverso rappresentazioni sequenziali e collegate. Pile e procedure ricorsive

Algoritmi e Strutture Dati

Alberi binari e alberi binari di ricerca

Il tipo Text. N. Del Buono

Costanti e Variabili

Le etichette nei programmi. Istruzioni di branch: beq. Istruzioni di branch: bne. Istruzioni di jump: j

COMPILATORI: MODELLO COMPILATORI: MODELLO ANALIZZATORE LESSICALE. Si noti che le variabili sono associate allo stesso numero identificativo

Le funzioni in JavaScript. Modularizzazione

Unità Didattica 2 Linguaggio C. Espressioni, Operatori e Strutture linguistiche per il controllo del flusso

L organizzazione dei programmi

Il tipo astratto coda con priorità: specifiche sintattiche e semantiche. Realizzazioni.

Indice. Ordine di valutazione. Espressioni in C++ Le espressioni in C++ (CAP 4) Alberto Garfagnini e Marco Mazzocco A.A. 2014/ * 20 / 2

INFORMATICA DI BASE Linguaggio C Prof. Andrea Borghesan

Capitolo 5 - Funzioni

Alberi e alberi binari I Un albero è un caso particolare di grafo

Programmazione. 1 Introduzione. Tutto per la gloria di Dio.

Alberi Binari di Ricerca

Fondamenti d Informatica: linguaggi formali. Barbara Re, Phd

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

Le basi del linguaggio Java

6 - Blocchi e cicli. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

Programmazione Procedurale in Linguaggio C++

Espressioni. Espressione = meccanismo fondamentale per esprimere computazioni in un LP importante comprenderne la semantica!

Esercizio 2 (punti 7) Dato il seguente programma C: #include <stdio.h> int swap(int * nome, int length);

Fondamenti di Informatica 6. Algoritmi e pseudocodifica

ESERCITAZIONE 5!! 7 dicembre 2016!! Programmazione concorrente in ADA!!

Note per la Lezione 4 Ugo Vaccaro

Linguaggi e Traduttori: Analisi sintattica

Cenni sul preprocessore e il suo utilizzo

Puntatori in C. Puntatori. Variabili tradizionali Esempio: int a = 5; Proprietà della variabile a: nome: a

Il linguaggio Java Istruzioni di Controllo

Esercitazioni di Informatica 3

Basi di Dati: Corso di laboratorio

Transcript:

Definizioni syntax-directed Esempio: Notazione infissa Notazione postfissa Produzioni E E 1 + T E E 1 T E T T 0 T 1 T 2... T 9 Regole semantiche E.t := E 1.t _T.t _ + E.t := E 1.t _T.t _ - E.t := T.t T.t := 0 T.t := 1 T.t := 2 T.t := 9

Movimenti di un robot Seq Seq Istr begin Istr est ovest nord sud begin ovest sud est est sud Traduciamo la sequenza in una posizione relativa al punto di partenza: (-1,0) (0,0) (-1,-1) (1,-1) (0,-1) (1,-2)

Produzioni Seq begin Seq Seq 1 Istr Istr est Istr ovest Istr nord Istr sud Regole semantiche Seq.x := 0 Seq.y := 0 Seq.x := Seq 1.x + Istr.dx Seq.y := Seq 1.y + Istr.dy Istr.dx := 1, Istr.dy := 0 Istr.dx := -1, Istr.dy := 0 Istr.dx := 0, Istr.dy := 1 Istr.dx := 0, Istr.dy := -1

Attributi ereditati Dichiarazioni: int NUM, ELEM, K Produzioni D T L L L 1, id L id T int T real Regole semantiche L.in := T.type L 1.in := L.in, addtype (id.entry, L.in) addtype (id.entry, L.in) T.type := integer T.type := real

D T L, int L id 3, L id 2 id 1

D T.type = integer L.in = integer int L.in = integer, id 3, L.in = integer id 2 id 1

Grafo delle dipendenze e ordine di valutazione for ogni nodo n dell albero di parsificazione do for ogni attributo a del simbolo della grammatica associato ad n do costruisci un nodo per a for ogni nodo n dell albero di parsificazione do for ogni regola semantica b := f(c 1,...,c k ) associata alla produzione usata in n do for i = 1 to k do costruisci un arco dal nodo c i al nodo b

Esempio: costruzione di alberi sintattici Funzioni usate: mknode (op, left, right): crea un nodo operatore con label op e i puntatori agli operandi, restituisce il puntatore al nodo creato. mkleaf (id, entry): crea un nodo identificatore con label id e un puntatore alla entry per l identificatore nella symbol-table, restituisce il puntatore al nodo creato. mkleaf (num, val): crea un nodo numero con label num e il valore del numero, restituisce il puntatore al nodo creato.

Definizione syntax-directed per costruire l albero sintattico Produzioni E E 1 + T E E 1 T E T T ( E ) T id T num Regole semantiche E.nptr := mknode ( +, E 1.nptr, T.nptr) E.nptr := mknode ( -, E 1.nptr, T.nptr) E.nptr := T.nptr T.nptr := E.nptr T.nptr := mkleaf (id, id.entry) T.nptr := mkleaf (num, num.val)

E.nptr = + E.nptr = + T.nptr = - E.nptr = - T.nptr = T.nptr = id id id id num num

Esempio: Lista delle differenze Definizione syntax-directed per costruire la lista delle differenze Produzioni C N#L L N;L 1 L N N 0 N 1... N 9 Regole semantiche C.list := L.list L.elem := N.val L.list := N.val - L.elem, L 1.list; L 1.elem := L.elem) L.list := N.val - L.elem N.val := 0 N.val := 1 N.val := 9 list, eval: sintetizzati elem: ereditato

C C.list = 2,-2,4 4#6;2;8 2,-2,4 N.val=4 N # L L.elem = 4 L.list = 2,-2,4 4 N.val=6 N ; L L.elem = 4 L.list = -2,4 6 N N.val=2 ; L L.elem = 4 L.list = 4 2 N N.val=8 8

Definizioni L-attribuiteL A X 1 X 2... X n Ogni attributo ereditato di X j dipende solo da: gli attributi dei simboli X 1 X 2... X j-1 a sinistra di X j nella produzione; gli attributi ereditati di A. Schemi di traduzione Uno schema di traduzione e una grammatica libera in cui gli attributi sono associati ai simboli della grammatica e le azioni semantiche, racchiuse tra parentesi graffe, sono inserite nei membri destri delle produzioni.

Gli schemi di traduzione sono un utile notazione per specificare la traduzione durante la parsificazione. E T R R addop T {print (addop. lessema)} R 1 ε T num {print (num.val)} Bisogna assicurare che il valore di un attributo sia disponibile quando un azione fa ad esso riferimento. Solo attributi sintetizzati: azioni alla fine del membro destro della produzione associata.

Attributi sintetizzati ed ereditati: un attributo ereditato per un simbolo al membro destro di una produzione deve essere calcolato con un azione prima del simbolo un azione non deve far riferimento a un attributo sintetizzato di un simbolo a destra dell azione un attributo sintetizzato per un non terminale a sinistra puo essere calcolato solo dopo che sono stati calcolati tutti gli attributi cui fa riferimento. Le azioni che calcolano questi attributi possono di solito essere posti alla fine del membro destro della produzione.

Definizione non L-attribuita Produzioni A L M A Q R Regole semantiche L.i := l (A.i) M.i := m (L.s) A.s := f (M.s) R.i := r (A.i) Q.i := q (R.s) A.s := f (Q.s)

Schema di traduzione che non soddisfa le condizioni: S A 1 A {A 2 1.in := 1; A 2.in := 2} {print (A.in)} A a Per una definizione diretta dalla sintassi L-attribuita è sempre possibile costruire uno schema di traduzione che soddisfa le tre condizioni precedenti. S {A 1.in := 1} A 1 {A 2.in := 2} A 2 A a {print (A.in)}

Ricorsione sinistra E E 1 num E num {E.val := E 1.val + num.val} {E.val := num.val} Equivalente grammatica senza ricorsione sinistra: E num R R num R ε

E E 1 num E num E num R R num R 1 R ε {E.val := E 1.val + num.val} {E.val := num.val} E E E num num R E num num R num num R ε

E E 1 num E num E num R num R ε {E.val := E 1.val + num.val} {E.val := num.val} {R.i := num.val} R {E.val := R.s} {R1.i := R.i + num.val} R 1 {R.s := R 1.s} {R.s := R.i} E 5+7 E 5+7 3+2 E num 7 3 num R.i=3 E 3 num 2 2 num R.i=3+2 num 3 7 num R.i=5+7 R.s := 1 ε

A A 1 Y A X {A.a := g (A 1.a, Y.y)} {A.a := f (X.x)} A X R R YR ε A X R R Y R 1 R ε {R.i := f (X.x)} {A.a := R.s} {R 1.i := g (R.i, Y.y)} {R.s := R 1.s} {R.s := R.i}

Eliminazione ricorsione sinistra: Esempio E E 1 + T E E 1 -T E T T ( E ) T num {E.val := E 1.val + T.val} {E.val := E 1.val - T.val} {E.val := T.val} {T.val := E.val} {T.val := num.val} La grammatica non è LL(1)

E T R R + T R 1 R - T R 1 R ε T ( E ) T num {R.i := T.val} {E.val := R.s} {R 1.i := R.i + T.val} {R.s := R 1.s} {R 1.i := R.i -T.val} {R.s := R 1.s} {R.s := R.i} {T.val := E.val} {T.val := num.val}

E 4+3=7 E 7 9-5=4 E + T 3 T R 9 9 7 E 9 - T 5 3 num num 9 - T 5 R 9-5=4 7 T 9 num 5 5 num + T 3 4+3=7 R 7 num 9 3 num ε R.i e R.s sono gli attributi, ereditato e sintetizzato rispettivamente, che giocano il ruolo di E.val nella grammatica con ricorsione sinistra.

Eliminazione ricorsione sinistra: Esempio Produzioni E E 1 + T E E 1 T E T T ( E ) T id T num Regole semantiche E.nptr := mknode ( +, E 1.nptr, T.nptr) E.nptr := mknode ( -, E 1.nptr, T.nptr) E.nptr := T.nptr T.nptr := E.nptr T.nptr := mkleaf (id, id.entry) T.nptr := mkleaf (num, num.val)

E T R R + T R 1 R - T R 1 R ε T ( E ) T num T id {R.i := T.nptr} {E.nptr := R.s} {R 1.i := mknode ( +, R.i, T.nptr)} {R.s := R 1.s} {R 1.i := mknode ( -, R.i, T.nptr)} {R.s := R 1.s} {R.s := R.i} {T.nptr := E.nptr} {T.nptr := mkleaf (num, num.val)} {T.nptr := mkleaf (id, id.entry)}

E.nptr = T.nptr = T R.i = R.s = num - T.nptr = R.i = - R.s = num id id + T.nptr = R.i + = R.s = id ε id

E.nptr = + - id num id

Valutazione top-down di grammatiche L-attribuiteL L analizzatore a discesa ricorsiva per grammatiche LL(1) può essere modificato in modo da valutare gli L-attributi. Ad ogni non terminale si associa una funzione che ha come parametri i valori degli attributi ereditati della variabile e restituisce i valori dei suoi attributi sintetizzati. La funzione per un non terminale ha una variabile locale per ogni attributo ereditato o sintetizzato per i simboli che compaiono nelle parti destre delle produzioni dal non terminale.

Codice per le parti destre delle produzioni: Per ogni non terminale B si genera un assegnazione <c 1,..., c k > := B(b 1,... B n ), che è una chiamata alla funzione associata a B. Per ogni terminale a i valori degli attributi sintetizzati vengono assegnati alle corrispondenti variabili e l esame passa al simbolo successivo. Le azioni semantiche vengono ricopiate dopo aver sostituito i riferimenti agli attributi con le variabili corrispondenti.

Valutazione top-down di grammatiche L-attribuiteL function A(e 1,... e n ) var s 1,..., s m, X 1 _x 1,..., X 1 _x k,..., X h _x 1,..., X h _x r begin if cc Gui(A α 1 ) then body (α 1 ) else if cc Gui(A α 2 ) then body (α 2 ). else if cc Gui(A α k ) then body (α k ) else ERRORE( ) return < s 1,..., s m > end

Produzioni C N#L L N;L 1 L N N 0... N 9 ε Regole semantiche C.list := L.list; L.elem := N.val L.list := cons N.val(N.val - L.elem, - L.elem, L 1.list; L 1.list); L 1.elem := L.elem L.list := N.val - L.elem N.val := 0 N.val := 9 C N#L L N;L 1 L ε N 0... N 9 L.list := null Insiemi guida {0, 1,..., 9} {0, 1,..., 9} { } {0} {9}

Schema di traduzione C N# {L.elem := N.val} L {C.list := L.list} L N; {L 1.elem := L.elem} L 1 {cons (N.val - L.elem, L 1.list)} {L.list := null} L ε N 0 {N.val := 0}... N 9 {N.val := 9}

N 0 {N.val := 0}... N 9 {N.val := 9} function N var val begin if cc = 0 then cc := PROSS val := 0 else if cc = 1 then cc := PROSS val := 1. else if cc = 9 then cc := PROSS val := 9 else ERRORE( ) return < s 1,..., s m > end

L N; L ε L 1 {L 1.elem := L.elem} {L.list := cons (N.val - L.elem, L 1.list)} {L.list := null} function L (elem) var list, N_val, L_elem, L_list begin if cc {0, 1,..., 9} then N_val := N if cc = ; then cc := PROSS L_elem := elem L_list := L (L_elem) list := cons (N_val - L_elem, L_list) else ERRORE( ) else if cc = then list := null else ERRORE( ) return list end

C N# L {L.elem := N.val} {C.list := L.list} function C var list, N_val, L_elem, L_list begin if cc {0, 1,..., 9} then N_val := N if cc = # then cc := PROSS L_elem := N_val L_list := L (L_elem) list := L_list else ERRORE( ) else ERRORE( ) return list end