Calcolatrice(Albero+id) Scopo: Leggere un'espressione aritmetica in notazione infissa (l'espressione puo' contenere anche degli identificatori). Visualizzare l'espressione in notazione postfissa. Leggere da input dei valori da assegnare agli identificatori e visualizzare il risultato dell'espressione File: Calcolatrice.java ParserEspressioni.java Expr.java Descrittore.java SymbolTable.java Utilizza classi del package lt2.calc Avvio dell'applicazione: metodo main di Calcolatrice.java Note relative ai file: ^^^^^^^^^^^^^^^^^^^^^ *** Calcolatrice.java Questa classe contiene il metodo main che svolge i seguenti compiti: 1. legge da input una espressione aritmetica in notazione infissa 2. visualizza l'espressione in notazione postfissa 3. legge da input i valori per gli identificatori presenti nell'espressione 4. calcola e visualizza il risultato. Le operazioni 3 e 4 possono essere ripetute piu' volte per calcolare il risultato con valori delle variabili differenti. *** ParserEspressioni.java Esamina un'espressione aritmetica, i cui token vengono forniti tramite un analizzatore lessicale, e costruisce un abstract syntax tree che la rappresenta, con associata una symbol table per gli identificatori. In particolare la classe e' dotata di: - un costruttore che riceve come argomento l'analizzatore lessicale che fornira' i token - un metodo parse() che effettua il parsing e restituisce il riferimento alla radice del parse tree - un metodo getSymbolTable() che restituisce un riferimento alla symbol table (la symbol table, inizialmente vuota, risultera' riempita dopo l'invocazione del metodo parse()). *** Expr.java Definisce la classe astratta Expr, con le sottoclassi concrete per la rappresentazione come abstract syntax tree. La classe fornisce: - un metodo calcola() che ha il compito di fornire il risultato dell'espressione - un metodo toString() che ha il compito di fornire una stringa che rappresenta l'espressione in notazione postfissa Ciascuna sottoclasse concreta dispone di un costruttore, che dipende dal tipo di espressione rappresentata dalla sottoclasse. *** Descrittore.java Descrive un identificatore come coppia . Fornisce due costruttori, uno che riceve solo il nome (e assegna di default 0 a valore), l'altro che riceve nome e valore. Vi sono inoltre i metodi - String getIdentificatore() che restituisce il nome dell'identificatore, - int getValore() - void modificaValore(int nuovo). *** SymbolTable.java Rappresenta una tabella di oggetti di tipo Descrittore. Fornisce - un costruttore privo di argomenti che crea la tabella vuota - un metodo Descrittore trova(String s) che ricerca nella tabella un descrittore per l'identificatore fornito tramite l'argomento. Se la ricerca ha successo ne restituisce il riferimento, altrimenti restituisce il riferimento null. - un metodo aggiungi(Descrittore d) per aggiungere un elemento alla tabella - un metodo Descrittore trovaEAggiungi(String s) che ricerca nella tabella un descrittore per l'identificatore fornito tramite l'argomento e, se non lo trova, ne inserisce uno nuovo (ricerca con inserimento). - un metodo iterator() per ottenere un iteratore che permetta di scandire gli elementi presenti nella tabella. Note relative alle implementazioni: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ *** Calcolatrice.java Il metodo main dopo avere letto l'espressione da input: - crea un analizzatore lessicale per tale espressione - crea un parser che riceve i token dall'analizzatore lessicale Successivamente chiede al parser di produrre l'albero corrispondente all'espressione (invocazione di parse()). Invocando il metodo toString() di tale albero si ottiene la notazione postfissa. Per il calcolo dell'espressione e' necessario leggere da input i valori da assegnare alle variabili presenti nella symbol table. A tale scopo il metodo main esegue le seguenti operazioni: - chiede al parser di fornire la symbol table (invocazione di getSymbolTable()) - esamina uno alla volta gli elementi presenti (ciclo for-each) e, per ciascuno di essi, chiede all'utente di inserire un valore intero - invoca il metodo calcola() dell'albero per ottenere il risultato da visualizzare. *** ParserEspressioni.java Il parser ricorsivo discendente e' basato sulla versione precedente. L'unica differenza e' la gestione degli identificatori. A tale scopo, associata al parser vi e' la symbol table, inizialmente vuota. Quando viene trovato un identificatore (metodo fattore), si effettua una ricerca con inserimento nella symbol table; la ricerca restituisce il descrittore dell'identificatore nella symbol table. Il nodo di tipo IdExpr costruito nell'albero fara' riferimento a tale descrittore. *** Expr.java La sottoclasse concreta IdExpr memorizza il riferimento al descrittore, all'interno della symbol table, dell'identificatore considerato.