Calcolatrice(Albero) Scopo: Leggere un'espressione aritmetica in notazione infissa (l'espressione puo' contenere anche degli identificatori). Visualizzare l'espressione in notazione postfissa. Visualizzare il risultato dell'espressione, nel caso non contenga identificatori. File: Calcolatrice.java ParserEspressioni.java Expr.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. calcola e visualizza il risultato. *** ParserEspressioni.java Esamina un'espressione aritmetica, i cui token vengono forniti tramite un analizzatore lessicale, e costruisce un abstract syntax tree che la rappresenta. 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 *** 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. Il metodo calcola per la classe IdExpr corrispondente agli identificatori, solleva una eccezione. 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; invocando il metodo calcola() si ottiene il risultato. *** ParserEspressioni.java Il parser ottiene i token da esaminare dall'analizzatore lessicale (campo scanner) assegnato tramite il costruttore. L'unico metodo fornito all'esterno e' il metodo parse(), che effettua l'analisi sintattica e restituisce la radice del parse tree ottenuto. Il metodo implementa un parser ricorsivo discendente e si basa sui tre metodi ausiliari espressione, termine e fattore. Volendo implementare un parser differente (ad esempio bottom-up), si dovra' modificare l'implementazione di questo metodo. *** Expr.java Vengono fornite le sottoclassi concrete: a) per gli operatori binari: - PiuExpr corrispondente all'operatore + - MenoExpr corrispondente all'operatore - - PerExpr corrispondente all'operatore * - DivisoExpr corrispondente all'operatore / Ognuna di queste classi e' implementata memorizzando un riferimento alla sottoespressione di sinistra e uno a quello di destra (i costruttori ricevono come argomenti tali riferimenti). b) per gli operatori unari: - UnMenoExpr corrispondente all'operatore - - UnPiuExpr corrispondente all'operatore + Entrambe le classi sono implementate memorizzando un riferimento alla sottoespressione a cui l'operatore e' applicato. c) per le espressioni base: - IdExpr per gli identificatori, che memorizza il nome dell'identificatore - NumExpr per le costanti, che memorizza il valore della costante. Non e' necessaria una classe per l'espressione racchiusa tra parentesi (si usa direttamente Expr). Volendo aggiungere altri operatori, occorrera' definire le sottoclassi di Expr corrispondenti.