Parsing ricorsivo discendente Il parsing ricorsivo discendente (recursive descent parsing) è un metodo di tipo top-down che può essere facilmente codificato.

Slides:



Advertisements
Presentazioni simili
Linguaggio C e C++.
Advertisements

Programmazione ad oggetti
Introduzione al linguaggio C++
I Linguaggi di programmazione
Traduzione ed Interpretazione
Linguaggio C++ Selezione.
Estendere i linguaggi: i tipi di dato astratti
Evoluzione dei linguaggi di programmazione
Analizzatori Lessicali con JLex
Sintassi (prima parte)
Analizzatori Sintattici con Cup Giuseppe Morelli.
Traduttore diretto dalla sintassi (seconda parte)
LR Parser Giuseppe Morelli. La maggior parte dei parser Bottom-Up è costituita dai cosiddetti parser LR(k) dove: L indica il verso dellanalisi della stringa.
Parser Bottom UP Giuseppe Morelli. Parser Bottom UP Un parser Bottom Up lavora costruendo il corrispondente albero di parsing per una data stringa di.
Inizio… Linguaggi Linguaggi di programmazione Linguaggi di programmazione Linguaggi di programmazione Linguaggi di programmazione Linguaggi Formali Linguaggi.
Costruzione delle tabelle di parsing LR canoniche
Definizione e tipi di implementazione
Semantica di linguaggi di programmazione Ne esistono differenti stili a seconda di paradigma di programmazione uso (validazione, prototyping, verifica.
Type Checking (1° parte)
Generazione di Codice Intermedio
Algoritmi e Programmazione
Anno accademico Il preprocessore del linguaggio C.
Fondamenti di Informatica I a.a Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.
Programmazione Procedurale in Linguaggio C++
Caratteri e stringhe di caratteri
TRADUZIONE DEL PROGRAMMA Una volta che un programma sia stato scritto in C, esso non può essere eseguito senza unulteriore traduzione. Ciò perché qualsiasi.
Argomenti dalla linea dei comandi Gli argomenti possono essere passati a qualsiasi funzione di un programma, compresa la main(), direttamente dalla linea.
Sistemi basati su conoscenza Conoscenza e ragionamento Prof. M.T. PAZIENZA a.a
Analisi e Sintesi di circuiti sequenziali
Corso di Laurea in Biotecnologie Informatica (Programmazione)
Corso di Informatica (Programmazione)
Programmazione Un programma descrive al computer, in estremo dettaglio, la sequenza di passi necessari a svolgere un particolare compito L’attività di.
Introduzione alla programmazione ll
Lezione 4: Costrutti Condizionali Prof. Raffaele Montella.
Analisi e Sintesi di circuiti sequenziali. Definizione Una macchina sequenziale é un sistema nel quale, detto I(t) l'insieme degli ingressi in t, O(t)
-calcolo Vogliamo studiare le problematiche relative al meccanismo di chiamata di funzione (eg differenze fra binding statico e dinamico) in isolamento.
Unità Didattica 2 I Linguaggi di Programmazione
I File.
Il Linguaggio C.
Espressioni condizionali
Gli algoritmi.
INSIEMI NUMERABILI L’analisi matematica introduce il concetto di insieme numerabile come insieme i cui elementi possono essere “contati” ossia che possiede.
LINGUAGGI DI PROGRAMMAZIONE
INTRODUZIONE l sistema operativo è il primo software che lutente utilizza quando accende il computer; 1)Viene caricato nella memoria RAM con loperazione.
ANTLR V.3 Renzi Alberto.
Linguaggi e Modelli Computazionali LS - Prof E.Denti
CAP. 2 ANALISI LESSICALE 2.1 Il ruolo dell'analizzatore lessicale
PROGRAMMAZIONE: linguaggi
Lo sviluppo del software e i linguaggi di programmazione
BIOINFO3 - Lezione 201 Come in ogni corso di introduzione ad un linguaggio di programmazione, proviamo a scrivere lormai celebre primo programma di prova.
Linguaggi e modelli computazionali LS Manni Tiziano
Lezione 3 Struttura lessicale del linguaggio
Introduzione a Javascript
Tecnologie di InternetDocument Type Definition Dott. Nicola Dragoni Document Type Definition  Document Type Definition (DTD)  Documento XML valido 
1 Fabio Scotti – Università degli Studi di Milano Fabio Scotti ( ) Laboratorio di programmazione per la sicurezza Valentina Ciriani ( )
Linguaggi e Modelli Computazionali LS Anno Accademico 2007/2008 Alessio Della Motta Un linguaggio per descrivere partite di Maraffone: il gioco più popolare.
Programmazione Attività di progettazione ed implementazione di programmi I programmi permettono di realizzare funzioni complesse su un hardware in grado.
Grammatiche Grammatiche libere da contesto Grammatiche regolari
Algoritmi.
Grammatiche non contestuali (1)
1 Macchine astratte, linguaggi, interpretazione, compilazione.
Il software Claudia Raibulet
FI - Algoritmi e Programmazione 1 Variabili Consentono di aumentare notevolmente la potenza espressiva. Una variabile è caratterizzata da:  Un nome 
Algoritmi e Programmazione (in C) Stefano Cagnoni e Monica Mordonini
Problemi, algoritmi e programmazione
Cloud informatica V anno. Introduzione a PHP Lo scripting PHP PHP è un linguaggio di scripting lato server. Le caratteristiche di un linguaggio di scripting.
Informatica Problemi e algoritmi. una situazione che pone delle domande cui si devono dare risposte. Col termine problema o situazione problematica s’indica.
Linguaggi, stringhe e alfabeti. Linguaggi e grammatiche Un linguaggio è un sistema di comunicazione tra persone che permette di trasmettere informazioni.
Istruzioni e algoritmi. Istruzioni Operative I passi elementari che compongono l’algoritmo sono le istruzioni. Distinguiamo: Istruzioni di input Istruzioni.
Unità di apprendimento 6
Transcript della presentazione:

Parsing ricorsivo discendente Il parsing ricorsivo discendente (recursive descent parsing) è un metodo di tipo top-down che può essere facilmente codificato manualmente se la grammatica consente di utilizzare il predictive parsing. Un parser ricorsivo discendente è costituito da un insieme di procedure mutuamente ricorsive, con una diversa procedura per ciascun simbolo non terminale della grammatica. Ogni procedura compie due azioni: –decide in base al lookahead token quale regola usare per il simbolo non terminale ad essa associato; –applica la regola scelta “mimando” il suo lato destro: per ogni simbolo non terminale chiama la corrispondente procedura e per ogni simbolo terminale verifica la corrispondenza con il lookahead token, facendo avanzare la sequenza di ingresso se il lookahead token non corrisponde con il token previsto dalla regola viene rilevato un errore sintattico

Problema Se la procedura associata al simbolo non terminale expr, una volta attivata, sceglie la prima alterativa della regola, verrà eseguita una chiamata ricorsiva alla stessa procedura −poiché tale chiamata non produce avanzamento della sequenza di ingresso la nuova istanza della procedura selezionerà nuovamente la stessa alternativa, innescando una sequenza infinita di chiamate ricorsive! Il problema è causato dal fatto che la regola è ricorsiva a sinistra −negli altri casi, l’eventuale chiamata ricorsiva avviene dopo un avanzamento sulla sequenza di ingresso e quindi in condizioni diverse da quelle iniziali Il parsing ricorsivo discendente non può essere impiegato su una grammatica che contenga regole ricorsive a sinistra

Soluzione Diventa: In entrambi i casi il linguaggio è costituito da sequenze che iniziano con β seguito da zero o più occorrenze di α.

Esempio

Parse tree di 9-5+2

Un esempio di analisi basata su parsing discendente Si voglia realizzare un sottoprogramma che analizzi espressioni aritmetiche contenenti gli operatori + e - in notazione in-fissa e le ristampi in notazione post-fissa. Si supponga per semplicità che gli operandi delle espressioni siano costanti intere da 0 a 9 e che non vi siano spazi all’interno delle espressioni.

Traduzione diretta dalla sintassi Viene adoperata una tecnica denominata traduzione diretta dalla sintassi che consiste nello specificare le azioni elaborative che operano la traduzione (azioni semantiche) in corrispondenza delle regole sintattiche della grammatica context-free, e nell’immaginare che tali azioni vengano eseguite man mano che procede la creazione/visita del parse tree. L’insieme di regole così ottenuto prende il nome di schema di traduzione. L’ordine con cui le azioni semantiche di uno schema di traduzione devono essere eseguite corrisponde ad una visita in post-ordine del parse tree.

Schema di traduzione

Parse tree contenente azioni semantiche

Parsing ricorsivo discendente

Parse tree contenente azioni semantiche Grammatica non ricorsiva a sinistra

L’analizzatore sintattico A questo punto possiamo procedere a codificare le procedure da associare ai simboli non terminali expr, term e rest. Per semplificare la codifica introduciamo la procedura match che provvede a verificare che il lookahead token corrisponda al token previsto t, e che avanza sulla sequenza in ingresso in caso di successo e segnala un errore in caso di insuccesso:

Procedure associate ai simboli non terminali della grammatica

La procedura MATCH()

Eliminazione della tail-recursion dalla procedura rest.

Procedura expr ottimizzata che sostituisce le procedure expr e rest

Un semplice interprete Il linguaggio da interpretare è molto semplice. Esso consente di scrivere due tipi di frase: le assegnazioni che hanno la forma: espressione => identificatore; e le valutazioni che hanno forma: espressione;

Esempio Per chiarire ulteriormente quanto detto, l’esecuzione del seguente programma nel linguaggio appena descritto: 100 => capitale; 12.5 => interesse; capitale; interesse; capitale => saldo; capitale * (1 + interesse/100) => saldo1; saldo1 * (1 + interesse/100) => saldo2; saldo; saldo1; saldo2;

Output

Lessico del linguaggio i token sono –i seguenti simboli costituiti da un solo carattere: + - * / ( ) ; –il simbolo, costituito da due caratteri: => –le costanti numeriche e gli identificatori, che seguono le regole mostrate in seguito –il simbolo corrisipondente al carattere di fine file che indicheremo con: eof Gli spazi e i caratteri di fine linea sono caratteri che possono separare token diversi, mentre i caratteri speciali non esplicitamente menzionati in precedenza non devono occorrere in un programma corretto.

Regole lessicali per le costanti numeriche e gli identificatori

Automa a stati finiti dell’analizzatore lessicale

L’albero sintattico del programma L’obiettivo del parser è quello di costruire l’albero sintattico del programma. –L’albero sintattico è un albero che descrive la struttura sintattica analizzata. Esso rappresenta la base su cui i compilatori e gli interpreti operano per giungere, rispettivamente, alla traduzione e all’esecuzione del programma in input. Ciascun nodo di un albero sintattico corrisponde a un simbolo (terminale o non) della sintassi. Nel caso il simbolo sia terminale il nodo è una foglia che contiene tutte le informazioni necessarie ad identificare il simbolo rappresentato. Nel caso che il simbolo sia non terminale il nodo contiene ancora le informazioni necessarie a identificare il simbolo rappresentato, ma ha un figlio per ogni componente della sua struttura.

L’albero sintattico del programma Ad esempio, con riferimento al diagramma sintattico corrispondente al simbolo non terminale statement, l’albero sintattico corrispondente sarà: –una foglia contenente il simbolo eof nel caso si sia seguita la via in alto; –un nodo contenente il simbolo => con due figli corrispondenti rispettivamente alla variabile e all’espressione, nel caso si sia seguita la via al centro; –un albero vuoto nel caso si sia seguita la via in basso.

Descrizione della sintassi mediante diagrammi sintattici (1)

Descrizione della sintassi mediante diagrammi sintattici (2)

Albero sintattico di una frase

Interpretazione del programma Una volta realizzati gli analizzatori lessicale e sintattico, l’interprete consiste in un programma che: – inizializza una tabella dinamica che implementa la memoria dell’interprete; per ogni istruzione presente nel programma: –costruisce il corrispondente albero sintattico –visita tale albero eseguendo le azioni elaborative da esso descritte. La visita dell’albero sintattico di un’istruzione può comportare –la creazione di nuove variabili (aggiunta di un’entry nella memoria) –la valutazione di un’espressione (visita in post-ordine del corrispondente albero sintattico) –l’assegnazione di un’espressione a una variabile (aggiornamento della memoria). Quest’ultima azione si può realizzare associando alla variabile la rappresentazione dell’albero sintattico dell’espressione.