diff --git a/src/main/java/uk/ac/cam/acr31/oop/democode1920/lecture5/Expression.java b/src/main/java/uk/ac/cam/acr31/oop/democode1920/lecture5/Expression.java
new file mode 100644
index 0000000000000000000000000000000000000000..22327cce1f77cb93341a0c7ac0a42c45d50ae43b
--- /dev/null
+++ b/src/main/java/uk/ac/cam/acr31/oop/democode1920/lecture5/Expression.java
@@ -0,0 +1,58 @@
+package uk.ac.cam.acr31.oop.democode1920.lecture5;
+
+public class Expression {
+
+  private static final int LITERAL = 1;
+  private static final int PLUS = 2;
+  private static final int MULT = 3;
+
+  private final int type;
+  private final int value;
+  private final Expression left;
+  private final Expression right;
+
+  public Expression(int type, int value, Expression left, Expression right) {
+    this.type = type;
+    this.value = value;
+    this.left = left;
+    this.right = right;
+  }
+
+  // factory method
+  // static constructor
+  static Expression literal(int v) {
+    return new Expression(LITERAL, v, null, null);
+  }
+
+  static Expression plus(Expression left, Expression right) {
+    return new Expression(PLUS, 0, left, right);
+  }
+
+  static Expression mult(Expression left, Expression right) {
+    return new Expression(MULT, 0, left, right);
+  }
+
+  int evaluate() {
+    switch (type) {
+      case LITERAL:
+        return value;
+      case PLUS:
+        return left.evaluate() + right.evaluate();
+      case MULT:
+        return left.evaluate() * right.evaluate();
+    }
+    throw new UnsupportedOperationException();
+  }
+
+  public String toString() {
+    switch (type) {
+      case LITERAL:
+        return String.valueOf(value); //  return ""+value
+      case PLUS:
+        return String.format("(%s + %s)",left,right);
+      case MULT:
+        return String.format("(%s * %s)",left,right);
+    }
+    throw new UnsupportedOperationException();
+  }
+}
diff --git a/src/main/java/uk/ac/cam/acr31/oop/democode1920/lecture5/ExpressionEvaluator.java b/src/main/java/uk/ac/cam/acr31/oop/democode1920/lecture5/ExpressionEvaluator.java
index 2d29134ac3b51e0cdb1a1c58551bfb9a8e319c0b..58bd70958f1be3a90508bb42d19c6a0c968186d3 100644
--- a/src/main/java/uk/ac/cam/acr31/oop/democode1920/lecture5/ExpressionEvaluator.java
+++ b/src/main/java/uk/ac/cam/acr31/oop/democode1920/lecture5/ExpressionEvaluator.java
@@ -11,5 +11,24 @@ public class ExpressionEvaluator {
     //   1  *
     //     / \
     //    2  3
+    {
+      Expression one = Expression.literal(1);
+      Expression two = Expression.literal(2);
+      Expression three = Expression.literal(3);
+      Expression mult = Expression.mult(two, three);
+      Expression plus = Expression.plus(one, mult);
+      System.out.println(plus.evaluate());
+      System.out.println(plus);
+    }
+
+    {
+      SuperExpression one = new Literal(1);
+      SuperExpression two = new Literal(2);
+      SuperExpression three = new Literal(3);
+      SuperExpression mult = new Mult(two, three);
+      SuperExpression plus = new Plus(one, mult);
+      System.out.println(plus.evaluate());
+      System.out.println(plus);
+    }
   }
 }
diff --git a/src/main/java/uk/ac/cam/acr31/oop/democode1920/lecture5/Literal.java b/src/main/java/uk/ac/cam/acr31/oop/democode1920/lecture5/Literal.java
new file mode 100644
index 0000000000000000000000000000000000000000..534cbc8c1cccc2efd4e29491d3a833aba6fb3a5a
--- /dev/null
+++ b/src/main/java/uk/ac/cam/acr31/oop/democode1920/lecture5/Literal.java
@@ -0,0 +1,20 @@
+package uk.ac.cam.acr31.oop.democode1920.lecture5;
+
+public class Literal extends SuperExpression {
+
+  private final int value;
+
+  public Literal(int value) {
+    this.value = value;
+  }
+
+  @Override
+  int evaluate() {
+    return value;
+  }
+
+  @Override
+  public String toString() {
+    return value+"";
+  }
+}
diff --git a/src/main/java/uk/ac/cam/acr31/oop/democode1920/lecture5/Mult.java b/src/main/java/uk/ac/cam/acr31/oop/democode1920/lecture5/Mult.java
new file mode 100644
index 0000000000000000000000000000000000000000..770e22176435e90682bb1eb3a8f614ff2f316e84
--- /dev/null
+++ b/src/main/java/uk/ac/cam/acr31/oop/democode1920/lecture5/Mult.java
@@ -0,0 +1,21 @@
+package uk.ac.cam.acr31.oop.democode1920.lecture5;
+
+public class Mult extends SuperExpression {
+  private final SuperExpression left;
+  private final SuperExpression right;
+
+  public Mult(SuperExpression left, SuperExpression right) {
+    this.left = left;
+    this.right = right;
+  }
+
+  @Override
+  int evaluate() {
+    return left.evaluate() * right.evaluate();
+  }
+
+  @Override
+  public String toString() {
+    return String.format("(%s * %s)", left, right);
+  }
+}
diff --git a/src/main/java/uk/ac/cam/acr31/oop/democode1920/lecture5/Plus.java b/src/main/java/uk/ac/cam/acr31/oop/democode1920/lecture5/Plus.java
new file mode 100644
index 0000000000000000000000000000000000000000..adcd571c3b61f22728299d76b35c9f288d932e6d
--- /dev/null
+++ b/src/main/java/uk/ac/cam/acr31/oop/democode1920/lecture5/Plus.java
@@ -0,0 +1,21 @@
+package uk.ac.cam.acr31.oop.democode1920.lecture5;
+
+public class Plus extends SuperExpression {
+  private final SuperExpression left;
+  private final SuperExpression right;
+
+  public Plus(SuperExpression left, SuperExpression right) {
+    this.left = left;
+    this.right = right;
+  }
+
+  @Override
+  int evaluate() {
+    return left.evaluate() + right.evaluate();
+  }
+
+  @Override
+  public String toString() {
+    return String.format("(%s + %s)", left, right);
+  }
+}
diff --git a/src/main/java/uk/ac/cam/acr31/oop/democode1920/lecture5/SuperExpression.java b/src/main/java/uk/ac/cam/acr31/oop/democode1920/lecture5/SuperExpression.java
new file mode 100644
index 0000000000000000000000000000000000000000..26c873a9b79d61edef4806070af39437f71b3fa0
--- /dev/null
+++ b/src/main/java/uk/ac/cam/acr31/oop/democode1920/lecture5/SuperExpression.java
@@ -0,0 +1,6 @@
+package uk.ac.cam.acr31.oop.democode1920.lecture5;
+
+public abstract class SuperExpression {
+
+  abstract int evaluate();
+}