/** file: ExpVisit.java - VISITOR per le classi delle espressioni "Exp" */
import java.awt.*;
import java.lang.Exception;
/** ===========
VISITOR
============ */
/** "ExpVisitor" e' l'interfaccia che serve per specializzare
i "visitor" delle espressioni.
Ogni sottoclasse deve implementare tutti i metodi (astratti)
in modo da eseguire la visita dell'albero che rappresenta
un'espressione.
Ogni metodo si chiama "VisitaXxx" dove "Xxx" e' il nome di
una classe (non astratta) contenuta nel file "Exp.java" */
interface ExpVisitor {
public abstract void VisitaPiuExp (PiuExp e);
public abstract void VisitaMenExp (MenExp e);
public abstract void VisitaPerExp (PerExp e);
public abstract void VisitaDivExp (DivExp e);
public abstract void VisitaSqrExp (SqrExp e);
public abstract void VisitaSqrtExp (SqrtExp e);
public abstract void VisitaInvExp (InvExp e);
public abstract void VisitaNumExp (NumExp e);
public abstract void VisitaAssignExp (AssignExp e);
public abstract void VisitaIdentExp (IdentExp e);
public abstract void VisitaIdentRefExp (IdentRefExp e) throws Exception;
}//ExpVisitor
/** ==================================
VISITOR PER DISEGNARE L'ALBERO
================================== */
class VisitorDisegnaAlbero implements ExpVisitor {
Graphics MyGraph;
TextArea MsgOut;
java.util.Stack VisStack = new java.util.Stack (); // lo STACK!
int level = 0;
int posx, posy,
fontSize,
dd1, dd2;
int amp = 3;
int maxx, maxy;
Integer ingombro = new Integer (0);
/** Costruisce un "visitor" di visualizzazione che usa "g" come
oggetto grafico (per disegnare) e il punto di coordinate
(x,y) dalla posizione alto-sinistra.
La TextArea serve se si vuole stampare i messaggi di
costruzione dell'albero grafico) */
public VisitorDisegnaAlbero (Graphics g, int x, int y,
TextArea a) {
MyGraph=g;
posx=x;
posy=y;
maxx=200;
maxy=150;
MsgOut=a;
MyGraph.setColor (Color.orange);
MyGraph.fillRect (0,0,600,400);
MyGraph.setFont (new Font("Curier", Font.BOLD, 18));
fontSize = MyGraph.getFont().getSize() -5;
dd1 = fontSize;
dd2 = dd1 / 2;
}
/** Disegna un nodo rotondo con uno specifico colore di fondo,
luce e ombra, a una certa posizione e con un testo */
protected void DisegnaNodo (Color cfill, Color cluc, Color comb,
int posNodeX, int posNodeY,
String Testo) {
int i;
int max = 2;
int tmp;
MyGraph.setColor (cfill);
MyGraph.fillOval (posNodeX-dd1, posNodeY-dd1-dd2,
dd1*3+max, dd1*2+dd2+max);
MyGraph.setColor (cluc);
for (i=0; i<=max; i++)
MyGraph.drawArc (posNodeX-dd1+i, posNodeY-dd1-dd2+i,
dd1*3, dd1*2+dd2,
50, 130);
MyGraph.setColor (comb);
for (i=0; i<=max; i++)
MyGraph.drawArc (posNodeX-dd1, posNodeY-dd1-dd2,
dd1*3+i, dd1*2+dd2+i,
230, 130);
MyGraph.setColor(Color.white);
MyGraph.drawString(Testo, posNodeX-3-1,posNodeY+3-1);
MyGraph.setColor(Color.black);
MyGraph.drawString(Testo, posNodeX-3+1,posNodeY+3+1);
MyGraph.setColor(Color.blue);
MyGraph.drawString(Testo, posNodeX-3, posNodeY+3);
tmp=(posNodeX-dd1)+(dd1*3+max);
if (maxx < tmp) maxx=tmp;
tmp=(posNodeY-dd1-dd2)+(dd1*2+dd2+max);
if (maxy < tmp) maxy=tmp;
}//DisegnaNodo
/** Rende la massima posizione "x" a cui arriva il disegno */
public int RendiMaxX() { return maxx; }
/** Rende la massima posizione "y" a cui arriva il disegno */
public int RendiMaxY() { return maxy; }
/** Traccia l'albero grafico dall'operatore "op" scendendo
ricorsivamente nel sottoalbero di sinistra e di destra */
protected void DisegnaAlbero (Exp sonl, Exp sonr, String op) {
int level = VisStack.size();
int oldIngombroVal,ingombroVal,delta;
int posNodeY, posNodeX,
posSonSinX,posSonDesX, posSonY;
VisStack.push(ingombro);
try {
sonl.accept (this);
posSonSinX = ((Integer)VisStack.pop()).intValue();
sonr.accept (this);
posSonDesX = ((Integer)VisStack.pop()).intValue();
oldIngombroVal= ((Integer)VisStack.pop()).intValue();
ingombroVal = ingombro.intValue();
delta = ingombroVal - oldIngombroVal;
posNodeY = posy + level*fontSize*amp;
posNodeX = posx + oldIngombroVal+delta/2-fontSize/2;
posSonY = posNodeY + fontSize * amp ;
MyGraph.setColor (Color.black);
MyGraph.drawLine (posNodeX-dd2, posNodeY,
posSonSinX+dd2, posSonY-dd1);
MyGraph.drawLine (posNodeX+dd2, posNodeY+fontSize/2,
posSonDesX+dd2, posSonY-dd1);
DisegnaNodo (Color.red, Color.white, Color.gray, //OPERAZIONE
posNodeX, posNodeY, op);
VisStack.push (new Integer(posNodeX));
} catch (Exception e)
{ MsgOut.appendText ("!!! ERRORE !!! "+ e +"\n"); }
}//DisegnaAlbero
protected void DisegnaAlberoMono (Exp sah, String op) {
int level = VisStack.size();
int oldIngombroVal,ingombroVal,delta;
int posNodeY, posNodeX,
posSonAheadX, posSonY;
VisStack.push(ingombro);
try {
sah.accept (this);
posSonAheadX = ((Integer)VisStack.pop()).intValue();
oldIngombroVal= ((Integer)VisStack.pop()).intValue();
ingombroVal = ingombro.intValue();
delta = ingombroVal - oldIngombroVal;
posNodeY = posy + level*fontSize*amp;
posNodeX = posx + oldIngombroVal+delta/2-fontSize/2;
posSonY = posNodeY + fontSize * amp ;
MyGraph.setColor (Color.black);
MyGraph.drawLine (posNodeX-dd2, posNodeY,
posSonAheadX+dd2, posSonY-dd1);
DisegnaNodo (Color.red, Color.white, Color.gray, //OPERAZIONE
posNodeX, posNodeY, op);
VisStack.push (new Integer(posNodeX));
} catch (Exception e)
{ MsgOut.appendText ("!!! ERRORE !!! "+ e +"\n"); }
}//DisegnaAlberoMono
/** Visita il nodo, istanza di una sottoclasse di "OpExp" */
protected void VisitaOpExp (OpExp e) {
DisegnaAlbero (e.left(), e.right(), e.op());
}
protected void VisitaUnExp (UnExp e) {
DisegnaAlberoMono (e.ahead(), e.op());
}
/** Visita una foglia dell'albero */
protected void VisitaAtomicExp (Exp e) {
int level = VisStack.size();
int posNodeX = posx+ingombro.intValue();
int posNodeY = posy+level*fontSize*amp;
DisegnaNodo (Color.green, Color.yellow, Color.lightGray, //NUMERO
posNodeX,posNodeY, e.toString());
ingombro = new Integer(ingombro.intValue()+fontSize*amp);
VisStack.push (new Integer(posNodeX));
}//VisitaAtomicExp
public void VisitaPiuExp (PiuExp e) { VisitaOpExp(e); }
public void VisitaMenExp (MenExp e) { VisitaOpExp(e); }
public void VisitaPerExp (PerExp e) { VisitaOpExp(e); }
public void VisitaDivExp (DivExp e) { VisitaOpExp(e); }
public void VisitaSqrExp (SqrExp e) { VisitaUnExp(e); }
public void VisitaSqrtExp(SqrtExp e){ VisitaUnExp(e); }
public void VisitaInvExp (InvExp e) { VisitaUnExp(e); }
public void VisitaNumExp (NumExp e) { VisitaAtomicExp (e); }
public void VisitaIdentExp (IdentExp e) {VisitaAtomicExp(e);}
public void VisitaIdentRefExp (IdentRefExp e) {VisitaAtomicExp(e);}
public void VisitaAssignExp (AssignExp e) { VisitaOpExp (e); }
}//VisitorDisegnaAlbero
/** ========================================
VISITOR PER RISCRIVERE L'ESPRESSIONE
======================================== */
class VisitorRiscriviExp implements ExpVisitor {
TextArea MsgOut;
String Valore = "";
int Notazione; // 0=PRE, 1=IN, 2=POST !!!
java.util.Stack VisStack = new java.util.Stack(); // lo STACK
public VisitorRiscriviExp (int InCheNotazione, TextArea a) {
MsgOut = a;
Notazione = InCheNotazione; // 0=PRE, 1=IN, 2=POST !!!
}
public VisitorRiscriviExp (TextArea a) {
this (1, a); // default: notazione infissa
}
public String Val() {
if (VisStack.empty())
MsgOut.appendText (" STACK VUOTO! Valore Vecchio = "+ Valore +"\n");
else {
Valore = (String) VisStack.pop(); //ESTRAE!
MsgOut.appendText (" POP da stack str.= '"+ Valore +"'\n");
}
return Valore; //se stack vuoto, rende il vecchio 'Valore'
}//Val
protected void VisitaOpExp (OpExp e) {
String StrSin, StrDes, StrParz;
try {
e.left().accept(this); // Visita il sottoalbero sinistro
StrSin=(String) VisStack.pop(); // Salva il risultato parziale
e.right().accept(this); // Visita il sottoalbero destro
StrDes=(String) VisStack.pop(); // Salva il risultato parziale
switch (Notazione) { // Crea la stringa parziale
case 0: // PREfissa
StrParz="( "+e.op()+" "+StrSin+" "+StrDes+" )";
break;
case 1: // INfissa
StrParz="( "+StrSin+" "+e.op()+" "+StrDes+" )";
break;
case 2: // POSTfissa
StrParz="( "+StrSin+" "+StrDes+" "+e.op()+" )";
break;
default: throw new Exception("Notazione Non Esistente");
}
VisStack.push (StrParz); // Inserisce in stack la stringa
MsgOut.appendText (" PUSH str.parziale '"+ StrParz +"'\n");
} catch (Exception ecc)
{ MsgOut.appendText ("!!! ERRORE !!! "+ ecc +"\n"); }
}//VisitaOpExp
protected void VisitaUnExp (UnExp e) {
String StrAva, StrParz;
try {
e.ahead().accept(this); // Visita l'unico sottoalbero
StrAva=(String) VisStack.pop(); // Salva il risultato parziale
switch (Notazione) { // Crea la stringa parziale
case 0: // PREfissa
case 1: // INfissa
StrParz="( "+e.op()+" "+StrAva+" )";
break;
case 2: // POSTfissa
StrParz="( "+StrAva+" "+e.op()+" )";
break;
default: throw new Exception("Notazione Non Esistente");
}
VisStack.push (StrParz); // Inserisce in stack la stringa
MsgOut.appendText (" PUSH str.parziale '"+ StrParz +"'\n");
} catch (Exception ecc)
{ MsgOut.appendText ("!!! ERRORE !!! "+ ecc +"\n"); }
}//VisitaUnExp
public void VisitaPiuExp (PiuExp e) { VisitaOpExp(e); }
public void VisitaMenExp (MenExp e) { VisitaOpExp(e); }
public void VisitaPerExp (PerExp e) { VisitaOpExp(e); }
public void VisitaDivExp (DivExp e) { VisitaOpExp(e); }
public void VisitaSqrExp (SqrExp e) { VisitaUnExp(e); }
public void VisitaSqrtExp (SqrtExp e){ VisitaUnExp(e); }
public void VisitaInvExp (InvExp e) { VisitaUnExp(e); }
public void VisitaNumExp (NumExp e) { VisStack.push(e.toString()); }
public void VisitaIdentExp (IdentExp e) { VisStack.push(e.Val()); }
public void VisitaIdentRefExp(IdentRefExp e) { VisStack.push(e.Val()); }
public void VisitaAssignExp (AssignExp e) { VisitaOpExp (e); }
} //VisitorRiscriviExp
/** =======================================
VISITOR PER VALUTARE UN ESPRESSIONE
======================================= */
class VisitorValutaExp implements ExpVisitor {
TextArea MsgOut;
double Valore; // Valore calcolato dell'espressione
double Arg1, Arg2; // Valori dei due argomenti correnti
java.util.Stack VisStack = new java.util.Stack(); //lo stack!
java.util.Hashtable Ambiente; // tavola per l'ambiente globale!
public VisitorValutaExp (TextArea a) throws Exception {
// Valuta Exp in ambiente vuoto
MsgOut = a;
Ambiente = new java.util.Hashtable(); // ALLOCO NUOVO AMBIENTE!
}
public VisitorValutaExp (java.util.Hashtable AmbAttuale,
TextArea a) throws Exception {
// Valuta Exp nell'ambiente passato!
this (a); // chiama costruttore di sopra
Ambiente = AmbAttuale; // ALIASING: CONDIVIDO LA STRUTTURA!
}
protected void VisitaOpExp (OpExp e) {
MsgOut.appendText (" Operazione (nodo)="+ e.myOp() +"\n");
try {
// Valuta sottoalbero sinistro
e.left().accept(this);
// e poi quello destro
e.right().accept(this);
//Estrae valore di destra
Arg1 = ((Double)VisStack.pop()).doubleValue();
MsgOut.appendText (" Pop I arg. (destra) = "+ Arg1 +"\n");
//Estrae valore di sinistra
Arg2 = ((Double)VisStack.pop()).doubleValue();
MsgOut.appendText (" Pop II arg.(sinistra) = "+ Arg2 +"\n");
} catch (Exception ecc)
{ MsgOut.appendText ("!!! ERRORE !!! "+ ecc +"\n"); }
}//VisitaOpExp
protected void VisitaUnExp (UnExp e) {
MsgOut.appendText (" Operazione (nodo)="+ e.myOp() +"\n");
try {
// Valuta sottoalbero
e.ahead().accept(this);
//Estrae valore
Arg1 = ((Double)VisStack.pop()).doubleValue();
MsgOut.appendText (" Pop arg. (unico) = "+ Arg1 +"\n");
} catch (Exception ecc)
{ MsgOut.appendText ("!!! ERRORE !!! "+ ecc +"\n"); }
}//VisitaUnExp
public double Val() {
if (VisStack.empty())
MsgOut.appendText (" Stack Vuoto! Valore Vecchio = "+ Valore +"\n");
else {
Valore=((Double)VisStack.pop()).doubleValue();
MsgOut.appendText (" POP da stack = "+ Valore +"\n");
}
return Valore; //se stack vuoto, rende il vecchio 'Valore'
}//Val
protected void EseguiPush (double ValOper, String OpCod) {
MsgOut.appendText (" Push di "+ValOper+" (="+Arg1+OpCod+Arg2+")\n");
VisStack.push (new Double(ValOper));
}//EseguiPush
protected void EseguiPushMono (double ValOper, String OpCod) {
MsgOut.appendText (" Push di "+ValOper+" (="+OpCod+Arg1+")\n");
VisStack.push (new Double(ValOper));
}//EseguiPush
public void VisitaPiuExp (PiuExp e) {
VisitaOpExp (e);
EseguiPush (Arg2+Arg1, "+"); //ESEGUE L'OPERAZIONE!
}
public void VisitaMenExp (MenExp e) {
VisitaOpExp(e);
EseguiPush (Arg2-Arg1, "-");
}
public void VisitaPerExp (PerExp e) {
VisitaOpExp (e);
EseguiPush (Arg2*Arg1, "*");
}
public void VisitaDivExp (DivExp e) {
VisitaOpExp (e);
EseguiPush (Arg2/Arg1, "/");
}
public void VisitaSqrExp (SqrExp e) {
VisitaUnExp(e);
EseguiPushMono (Arg1*Arg1, "sqr");
}
public void VisitaSqrtExp(SqrtExp e){
VisitaUnExp(e);
EseguiPushMono (Math.sqrt(Arg1), "sqrt");
}
public void VisitaInvExp (InvExp e) {
VisitaUnExp(e);
if (Arg1 != 0)
EseguiPushMono (1/Arg1, "inv");
else
EseguiPushMono (Double.POSITIVE_INFINITY, "inv");
}
public void VisitaNumExp (NumExp e) {
MsgOut.appendText (" Contenuto(foglia)="+ e +"\n");
MsgOut.appendText (" Push di "+e+"\n");
VisStack.push (new Double(e.Val()));
}
public void VisitaAssignExp (AssignExp e) {
String Arg1; //identificatore
Double Arg2;
try {
e.left().accept(this); // Visita l'IDENTIFICATORE
Arg1 = (String)VisStack.pop();
MsgOut.appendText (" Pop variab. da assegnare: "+ Arg1 +"\n");
e.right().accept(this); // Visita (valuta) l'ESPRESSIONE
Arg2 = (Double)VisStack.pop();
MsgOut.appendText (" Pop espress. da assegnare: "+ Arg2.toString() +"\n");
Ambiente.put (Arg1, Arg2); // SIDE-EFFECT: MODIFICA L'AMBIENTE
MsgOut.appendText (" Assegnazione (in ambiente) "+ Arg1 +" / "+ Arg2 +"\n");
MsgOut.appendText (" Push di "+Arg2+"\n");
VisStack.push (Arg2); // rende il valore calcolato nell'assegnazione
} catch (Exception ecc)
{ MsgOut.appendText ("!!! ERRORE !!! "+ ecc +"\n"); }
}
public void VisitaIdentExp (IdentExp e) {
String Arg = e.Val(); // Salva l'identificatore nello stack
MsgOut.appendText (" Push di "+Arg+"\n");
VisStack.push (Arg);
}
public void VisitaIdentRefExp (IdentRefExp e) throws Exception {
// Recupera il valore della variabile da "Ambiente"
MsgOut.appendText (" Cerco in ambiente 'Ident. "+ e.Val() +"\n");
for (java.util.Enumeration h=Ambiente.elements(); h.hasMoreElements(); ) {
MsgOut.appendText (" > "+ h.nextElement() +"\n");
}
Double Arg = (Double) Ambiente.get(e.Val()); //e.Val().intern()
if (Arg == null) {
VisStack.push (new Integer(0));
throw new Exception("ERRORE DI RIFERIMENTO");
}
else {
MsgOut.appendText (" Trovato in ambiente: "+ Arg.doubleValue() +"\n");
MsgOut.appendText (" Push di "+Arg+"\n");
VisStack.push (Arg);
}
}
}//VisitorValutaExp
//*FINE FILE*