001package composite.three;
002
003public class ExprFactory {
004        private ExprFactory() {}
005        static public Expr newConst(int v) {
006                return new Const(v);
007        }
008        static public Expr newPlus(Expr l, Expr r) {
009                return new BinOp(l, new OpAdd(), r);
010        }
011        static public Expr newMinus(Expr l, Expr r) {
012                return new BinOp(l, new OpSub(), r);
013        }
014        static public Expr newMult(Expr l, Expr r) {
015                return new BinOp(l, new OpMul(), r);
016        }
017        static public Expr newQuot(Expr l, Expr r) {
018                return new BinOp(l, new OpDiv(), r);
019        }
020
021        private static final class Const implements Expr {
022                private final int v;
023                public Const(int v) {
024                        this.v = v;
025                }
026                public int eval() {
027                        return v;
028                }
029                public String toString() {
030                        return Integer.toString(v);
031                }
032        }
033
034        private static final class BinOp implements Expr {
035                private final Expr l;
036                private final Expr r;
037                private final Op op;
038                public BinOp(Expr l, Op op, Expr r) {
039                        if ((l == null) || (op == null) || (r == null)) {
040                                throw new IllegalArgumentException();
041                        }
042                        this.op = op;
043                        this.l = l;
044                        this.r = r;
045                }
046                public int eval() {
047                        return op.run(l.eval(), r.eval());
048                }
049                public String toString() {
050                        return l.toString() + " " + r.toString() + " " + op.toString();
051                }
052        }
053
054        private static interface Op {
055                public abstract int run(int x, int y);
056        }
057        private static final class OpAdd implements Op {
058                public String toString() { return "+"; }
059                public int run(int x, int y) { return x+y; }
060        }
061        private static final class OpSub implements Op {
062                public String toString() { return "-"; }
063                public int run(int x, int y) { return x-y; }
064        }
065        private static final class OpMul implements Op {
066                public String toString() { return "*"; }
067                public int run(int x, int y) { return x*y; }
068        }
069        private static final class OpDiv implements Op {
070                public String toString() { return "/"; }
071                public int run(int x, int y) { return x/y; }
072        }
073}
074