/*
* Nathaniel Lim, CS334, HW 6
*/
import java.lang.Integer;
/** Abstract class for all expressions */
abstract class Expr {
abstract <T> T accept(Visitor<T> v);
}
class Number extends Expr {
protected int n;
public Number(int n) { this.n = n; }
public <T> T accept(Visitor<T> v) {
return v.visitNumber(this.n);
}
}
class Sum extends Expr {
protected Expr left, right;
public Sum(Expr left, Expr right) {
this.left = left;
this.right = right;
}
public <T> T accept(Visitor<T> v) {
return v.visitSum(left.accept(v), right.accept(v));
}
}
class Div extends Expr {
protected Expr left, right;
public Div(Expr left, Expr right) {
this.left = left;
this.right = right;
}
public <T> T accept(Visitor<T> v) {
return v.visitDiv(left.accept(v), right.accept(v));
}
}
class Subtract extends Expr {
protected Expr left, right;
public Subtract(Expr left, Expr right) {
this.left = left;
this.right = right;
}
public <T> T accept(Visitor<T> v) {
return v.visitSubtract(left.accept(v), right.accept(v));
}
}
class Times extends Expr {
protected Expr left, right;
public Times(Expr left, Expr right) {
this.left = left;
this.right = right;
}
public <T> T accept(Visitor<T> v) {
return v.visitTimes(left.accept(v), right.accept(v));
}
}
/** Abstract class for all visitors */
abstract class Visitor<T> {
abstract T visitNumber(int n);
abstract T visitSum(T left, T right);
abstract T visitSubtract(T left, T right);
abstract T visitTimes(T left, T right);
abstract T visitDiv(T leftm, T right);
}
/** Example visitor to convert an Expr to a String */
class ToString extends Visitor<String> {
public String visitNumber(int n) {
return "" + n;
}
public String visitSum(String left, String right) {
return "(" + left + " + " + right + ")";
}
public String visitSubtract (String left, String right) {
return "(" + left + " - " + right + ")";
}
public String visitTimes (String left, String right) {
return "(" + left + " * " + right + ")";
}
public String visitDiv (String left, String right) {
return "(" + left + " / " + right + ")";
}
}
class Eval extends Visitor<Integer> {
public Integer visitNumber(int n){
return new Integer(n);
}
public Integer visitSum(Integer left, Integer right) {
return new Integer(left.intValue() + right.intValue() );
}
public Integer visitSubtract(Integer left, Integer right) {
return new Integer(left.intValue() - right.intValue() );
}
public Integer visitTimes(Integer left, Integer right) {
return new Integer(left.intValue() * right.intValue() );
}
public Integer visitDiv(Integer left, Integer right) {
return new Integer(left.intValue() / right.intValue() );
}
}
class Compile extends Visitor<String>{
public String visitNumber(int n){
return "PUSH(" + n + ")";
}
public String visitSum(String left, String right) {
return left + " " + right + " ADD";
}
public String visitSubtract(String left, String right) {
return left + " " + right + " SUB";
}
public String visitTimes(String left, String right) {
return left + " " + right + " MULT";
}
public String visitDiv(String left, String right) {
return left + " " + right + " DIV";
}
}
public class ExprVisitor {
public static void main(String args[]) {
Expr e = new Sum(new Number(3), new Number(2));
Expr e2 = new Sum(new Subtract(new Number (4), new Number (2)), new Times(new Number(3), new Number(4)));
ToString printer = new ToString();
String stringRep = e.accept(printer);
System.out.println(stringRep);
System.out.println(e.accept(new Eval()));
System.out.println(e.accept(new Compile()));
System.out.println(e2.accept(new ToString()));
System.out.println(e2.accept(new Eval()));
System.out.println(e2.accept(new Compile()));
Expr e3 = new Times(new Number (3), new Subtract(new Number (1), new Number (2)));
System.out.println(e3.accept(new Compile()));
}
}