Linguaggi e Traduttori 2

Docente: Giovanni Pighizzini

Anno accademico 2004/2005


Materiale didattico

Analizzatori lessicali: esempi relativi a JFLex
Riconoscimento e parsing di linguaggi context-free (26-28 aprile 2005)
Parser ricorsivo-discendenti
Parser bottom-up
Generazione di codice


Analizzatori lessicali

JFlex
The fast scanner generator for Java

Esempi d'uso
Un semplice esempio di riconoscitore di elementi lessicali all'interno di un testo:
(N.B. Per alcuni  esempi è necessaria la versione 5.0 del linguaggio Java)

Una calcolatrice in notazione postfissa:

Un riconoscitore di numeri romani:
Parser ricorsivo-discendenti

Un parser ricorsivo discendente per le espressioni aritmetiche:



Parser bottom-up

CUP
Constructor of Useful Parsers

Esempi d'uso
Un parser per le espressioni aritmetiche:

Una calcolatrice:
Ancora la calcolatrice: in questa versione il parser costruisce un albero sintattico che rappresenta l'espressione.
Nota
L'analizzatore sintattico generato da CUP utilizza token prelevati dall'analizzatore lessicale da uno stream di input. La fine dello stream è indicata da un particolare token EOF. Nella maggior parte dei casi lo stream è un file di testo. Negli esempi precedenti, invece, l'input dell'applicazione è sempre una riga di testo. Mediante l'uso di
StringReader viene creato uno strem corrispondente alla stringa letta.
Forniamo qui un esempio in cui la lettura avviene da un file (lo standard input). Si tratta sempre di una calcolatrice, in cui possono essere inserite più espressioni, una per riga. Si notino le modifiche nel file di specifica sintattica, con una nuova variabile per trattare più righe di testo: Espressioni.java, seqExpr.cup, seqExpr.lex.

La calcolatrice estesa con gli identificatori.
La calcolatrice lavora in due fasi: nella prima fase trasforma l'espressione in un albero sintattico e in una symbol table. Nella seconda fase valuta l'espressione attraversando l'albero, dopo avere letto da input i valori delle variabili presenti nell'espressione. La valutazione può essere ripetuta, fornendo valori diversi per le variabili, senza dovere riesaminare l'espressione inserita dall'utente, ma servendosi direttamente dell'albero.


Generazione di codice

Negli esempi si utilizza una macchina a stack, implementata nella classe Macchina.java. Viene inoltre fornita la classe Codice.java, utile per generare il codice e memorizzarlo in un file. Alcune note relative alle istruzioni della macchina e all'uso di queste classi sono fornite nel documento Note sulla macchina a stack.
Nota: le classi MacchinaCodice fanno parte di un package di nome lt2.macchina. Per compilare e utilizzare correttamente le classi si consiglia di definire all'interno di una directory lt2, una sottodirectory di nome macchina. La directory lt2 dovrà essere collocata in una posizione accessibile secondo la variabile d'ambiente CLASSPATH. I sorgenti delle due classi possono essere collocati in macchina e compilati.

I seguenti esempi utilizzano solo un piccolo sottoinsieme delle istruzioni disponibili. Esempi d'uso di altre istruzioni, per la compilazione dei costrutti tipici dei linguaggi di programmazione, sono mostrati a lezione.

In particolare, il seguente esempio rielabora quello delle espressioni con gli identificatori (file di specifica lessicale expr.lex, file di specifica sintattica expr.cup). Come nella versione precedente il parser produce un albero sintattico, secondo le definizioni date nella classe astratta Expr.java e nelle relative sottoclassi, corrispondenti ai tipi concreti di espressioni. Queste classi contengono un metodo generaCodice che si occupa di generare il codice relativo alla particolare sottoespressione considerata. Le classi ExprConTab.java, Descrittore.java e SymbolTable.java sono state modificate per questa nuova versione. Viene infine fornita la classe Espressioni.java contenente il metodo main.

Eseguendo Espressione.java verrà chiesto all'utente di inserire un'espressione. Se l'espressione è scritta correttamente verrà generato un file di nome eseguibile contenente il codice corrispondente. L'applicazione Macchina.java permette di eseguire tale codice. Richiamando tale applicazione con l'opzione -L è possibile visualizzare il codice senza eseguirlo, mentre con l'opzione -d è possibile vedere ciascuna istruzione prima che venga eseguita.



WebCounter segnala  accessi a queste pagine dal 22 febbraio 2000


Ultimo aggiornamento: 31 maggio 2005
© Giovanni Pighizzini