001package iterator.exprone;
002import java.util.Iterator;
003import java.util.NoSuchElementException;
004import enumeration.Op;
005
006public interface Expr {
007        int evaluate();
008        Iterator<Object> postorderIterator();
009}
010
011class Const implements Expr {
012        private final int v;
013        public Const(int v) {
014                this.v = v;
015        }
016
017        public int evaluate() {
018                return v;
019        }
020        public Iterator<Object> postorderIterator() {
021                return new LeafIterator<>(v);
022        }
023}
024
025class BinOp implements Expr {
026        private final Expr l;
027        private final Expr r;
028        private final Op op;
029
030        public BinOp(Expr l, Op op, Expr r) {
031                if ((l == null) || (op == null) || (r == null)) {
032                        throw new IllegalArgumentException();
033                }
034                this.op = op;
035                this.l = l;
036                this.r = r;
037        }
038
039        public int evaluate() {
040                return op.eval(l.evaluate(), r.evaluate());
041        }
042        public Iterator<Object> postorderIterator() {
043                return new PostorderIterator<>
044                (op, l.postorderIterator(), r.postorderIterator());
045        }
046}
047
048
049class PostorderIterator<T> implements Iterator<T> {
050        private T v;
051        private final Iterator<T> l;
052        private final Iterator<T> r;
053
054        PostorderIterator(T v, Iterator<T> l, Iterator<T> r) {
055                this.v = v;
056                this.l = l;
057                this.r = r;
058        }
059        public boolean hasNext() {
060                return r.hasNext() || l.hasNext() || (v != null);
061        }
062        public T next() {
063                if (l.hasNext()) {
064                        return l.next();
065                } else if (r.hasNext()) {
066                        return r.next();
067                } else if (v != null) {
068                        T result = this.v;
069                        this.v = null;
070                        return result;
071                }
072                throw new NoSuchElementException();
073        }
074        public void remove() {
075                throw new UnsupportedOperationException();
076        }
077}
078
079class LeafIterator<T> implements Iterator<T> {
080        private T v;
081
082        public LeafIterator(T v) {
083                this.v = v;
084        }
085        public boolean hasNext() {
086                return (v != null);
087        }
088        public T next() {
089                if (v != null) {
090                        T result = this.v;
091                        this.v = null;
092                        return result;
093                }
094                throw new NoSuchElementException();
095        }
096        public void remove() {
097                throw new UnsupportedOperationException();
098        }
099}