package openmods.calc; import openmods.utils.Stack; public abstract class BinaryOperator<E> extends Operator<E> { public static final Associativity DEFAULT_ASSOCIATIVITY = Associativity.LEFT; public enum Associativity { LEFT { @Override protected boolean isLessThan(int left, int right) { return left <= right; } }, RIGHT { @Override protected boolean isLessThan(int left, int right) { return left < right; } }; protected abstract boolean isLessThan(int left, int right); } public final int precedence; public final Associativity associativity; private BinaryOperator(String id, int precedence, Associativity associativity) { super(id); this.precedence = precedence; this.associativity = associativity; } private BinaryOperator(String id, int precendence) { this(id, precendence, DEFAULT_ASSOCIATIVITY); } public abstract static class Direct<E> extends BinaryOperator<E> { public Direct(String id, int precedence, Associativity associativity) { super(id, precedence, associativity); } public Direct(String id, int precendence) { super(id, precendence); } public abstract E execute(E left, E right); @Override public final void execute(Frame<E> frame) { final Stack<E> stack = frame.stack(); final E right = stack.pop(); final E left = stack.pop(); final E result = execute(left, right); stack.push(result); } } public abstract static class Scoped<E> extends BinaryOperator<E> { public Scoped(String id, int precedence, Associativity associativity) { super(id, precedence, associativity); } public Scoped(String id, int precendence) { super(id, precendence); } public abstract E execute(SymbolMap<E> symbols, E left, E right); @Override public final void execute(Frame<E> frame) { final Stack<E> stack = frame.stack(); final E right = stack.pop(); final E left = stack.pop(); final E result = execute(frame.symbols(), left, right); stack.push(result); } } public abstract static class StackBased<E> extends BinaryOperator<E> { public StackBased(String id, int precedence, Associativity associativity) { super(id, precedence, associativity); } public StackBased(String id, int precendence) { super(id, precendence); } public abstract void executeOnStack(Frame<E> frame); @Override public final void execute(Frame<E> frame) { final Frame<E> executionFrame = FrameFactory.newLocalFrameWithSubstack(frame, 2); executeOnStack(executionFrame); executionFrame.stack().checkSizeIsExactly(1); } } @Override public boolean isLessThan(Operator<E> other) { if (other instanceof UnaryOperator) return true; // unary operators always have higher precedence than binary final BinaryOperator<E> o = (BinaryOperator<E>)other; return associativity.isLessThan(precedence, o.precedence); } @Override public String toString() { return "BinaryOperator [" + id + "]"; } }