package com.io7m.example.ccatpm; abstract class ArithmeticExpression { /** * An integer constant. */ public final static class ConstantExpression extends ArithmeticExpression { private final int value; @SuppressWarnings("synthetic-access") ConstantExpression( final int value) { super(ExpressionType.EXP_CONSTANT); this.value = value; } public final int getValue() { return this.value; } } static enum ExpressionType { EXP_CONSTANT, EXP_PLUS, EXP_MULTIPLY, EXP_SUBTRACT } /** * The product of two arithmetic expressions. */ public final static class MultiplyExpression extends ArithmeticExpression { private final ArithmeticExpression e_left; private final ArithmeticExpression e_right; @SuppressWarnings("synthetic-access") MultiplyExpression( final ArithmeticExpression e_left, final ArithmeticExpression e_right) { super(ExpressionType.EXP_MULTIPLY); this.e_left = e_left; this.e_right = e_right; } public final ArithmeticExpression getLeft() { return this.e_left; } public final ArithmeticExpression getRight() { return this.e_right; } } /** * The sum of two arithmetic expressions. */ public final static class PlusExpression extends ArithmeticExpression { private final ArithmeticExpression e_left; private final ArithmeticExpression e_right; @SuppressWarnings("synthetic-access") PlusExpression( final ArithmeticExpression e_left, final ArithmeticExpression e_right) { super(ExpressionType.EXP_PLUS); this.e_left = e_left; this.e_right = e_right; } public final ArithmeticExpression getLeft() { return this.e_left; } public final ArithmeticExpression getRight() { return this.e_right; } } /** * The difference of two arithmetic expressions. */ public final static class SubtractExpression extends ArithmeticExpression { private final ArithmeticExpression e_left; private final ArithmeticExpression e_right; @SuppressWarnings("synthetic-access") SubtractExpression( final ArithmeticExpression e_left, final ArithmeticExpression e_right) { super(ExpressionType.EXP_SUBTRACT); this.e_left = e_left; this.e_right = e_right; } public final ArithmeticExpression getLeft() { return this.e_left; } public final ArithmeticExpression getRight() { return this.e_right; } } private final ExpressionType type; private ArithmeticExpression( final ExpressionType type) { this.type = type; } public final ExpressionType getType() { return this.type; } }
package com.io7m.example.ccatpm; import com.io7m.example.ccatpm.ArithmeticExpression.ConstantExpression; import com.io7m.example.ccatpm.ArithmeticExpression.MultiplyExpression; import com.io7m.example.ccatpm.ArithmeticExpression.PlusExpression; import com.io7m.example.ccatpm.ArithmeticExpression.SubtractExpression; public final class Interpreter { public static int run( final ArithmeticExpression expr) { switch (expr.getType()) { case EXP_CONSTANT: { final ConstantExpression actual = (ConstantExpression) expr; return actual.getValue(); } case EXP_MULTIPLY: { final MultiplyExpression actual = (MultiplyExpression) expr; final int left = Interpreter.run(actual.getLeft()); final int right = Interpreter.run(actual.getRight()); return left * right; } case EXP_PLUS: { final PlusExpression actual = (PlusExpression) expr; final int left = Interpreter.run(actual.getLeft()); final int right = Interpreter.run(actual.getRight()); return left + right; } case EXP_SUBTRACT: { final SubtractExpression actual = (SubtractExpression) expr; final int left = Interpreter.run(actual.getLeft()); final int right = Interpreter.run(actual.getRight()); return left - right; } default: throw new AssertionError("unreachable!"); } } private Interpreter() { } }
package com.io7m.example.ccatpm.visitor; interface Expression { int accept(ExpressionVisitor visitor); }
package com.io7m.example.ccatpm.visitor; abstract class Binary { private final Expression left; private final Expression right; public Binary( final Expression left, final Expression right) { this.left = left; this.right = right; } public final Expression getLeft() { return this.left; } public final Expression getRight() { return this.right; } }
package com.io7m.example.ccatpm.visitor; final class Constant implements Expression { private final int value; public Constant( final int value) { this.value = value; } public int getValue() { return this.value; } @Override public int accept( final ExpressionVisitor visitor) { return visitor.visit(this); } }
package com.io7m.example.ccatpm.visitor; final class Add extends Binary implements Expression { public Add( final Expression left, final Expression right) { super(left, right); } @Override public int accept( final ExpressionVisitor visitor) { return visitor.visit(this); } }
package com.io7m.example.ccatpm.visitor; final class Multiply extends Binary implements Expression { public Multiply( final Expression left, final Expression right) { super(left, right); } @Override public int accept( final ExpressionVisitor visitor) { return visitor.visit(this); } }
package com.io7m.example.ccatpm.visitor; final class Subtract extends Binary implements Expression { public Subtract( final Expression left, final Expression right) { super(left, right); } @Override public int accept( final ExpressionVisitor visitor) { return visitor.visit(this); } }
package com.io7m.example.ccatpm.visitor; interface ExpressionVisitor { int visit(Add add); int visit(Constant constant); int visit(Multiply multiply); int visit(Subtract subtract); }
package com.io7m.example.ccatpm.visitor; public final class Interpreter { public static int evaluate( final Expression expression) { return expression.accept(new ExpressionVisitor() { @Override public int visit( final Add add) { return Interpreter.evaluate(add.getLeft()) + Interpreter.evaluate(add.getRight()); } @Override public int visit( final Constant constant) { return constant.getValue(); } @Override public int visit( final Multiply multiply) { return Interpreter.evaluate(multiply.getLeft()) * Interpreter.evaluate(multiply.getRight()); } @Override public int visit( final Subtract subtract) { return Interpreter.evaluate(subtract.getLeft()) - Interpreter.evaluate(subtract.getRight()); } }); } }