abstract class Pastry {
public void printMe ();
}
class Beignet extends Pastry {
@Override
public void printMe() {
System.out.println ("It's a beignet");
}
}
class Cruller extends Pastry {
@Override
public void printMe() {
System.out.println ("It's a cruller");
}
}
class PastryTest {
public static void main (String[] args) {
var ps = new Pastry[] {new Beignet(), new Cruller()};
for (var p : ps) {
p.printMe();
}
}
}
$ javac PastryTest.java $ java PastryTest It's a beignet It's a cruller
enum Pastry:
case Beignet
case Cruller
import Pastry.*
def printPastry (p: Pastry) =
p match
case Beignet => println("It's a Beignet")
case Cruller => println("It's a Cruller")
def main(args:Array[String]) =
var ps = List(Beignet, Cruller)
for (p <- ps) do printPastry(p)
$ scala Pastry.scala It's a Beignet It's a Cruller
interface PastryVisitor {
public void visitBeignet(Beignet beignet);
public void visitCruller(Cruller cruller);
}
abstract class Pastry {
public abstract void accept(PastryVisitor visitor);
}
class Beignet extends Pastry {
@Override
public void accept(PastryVisitor visitor) {
visitor.visitBeignet(this);
}
}
class Cruller extends Pastry {
@Override
public void accept(PastryVisitor visitor) {
visitor.visitCruller(this);
}
}
class PastryPrinter implements PastryVisitor {
public void visitBeignet(Beignet beignet) {
System.out.println ("It's a beignet");
}
public void visitCruller(Cruller cruller) {
System.out.println ("It's a cruller");
}
}
public class PastryTest {
public static void main (String[] args) {
var printer = new PastryPrinter ();
var ps = new Pastry[] {new Beignet(), new Cruller()};
for (var p : ps) {
p.accept(printer);
}
}
}
$ javac PastryTest.java $ java PastryTest It's a beignet It's a cruller
Simple language with two binary operators
expr → expr "-" expr [Subtraction] expr → expr "÷" expr [Division] expr → NUMBER
enum Expr:
case SubExpr (left: Expr, right: Expr)
case DivExpr (left: Expr, right: Expr)
case NumExpr (num: Int)
import Expr.*
def printExpr (e: Expr) : String =
e match
case SubExpr (left, right) => "( " + printExpr(left) + " - " + printExpr(right) + " )"
case DivExpr (left, right) => "( " + printExpr(left) + " / " + printExpr(right) + " )"
case NumExpr (num) => num.toString
def evalExpr (e: Expr) : Int =
e match
case SubExpr (left, right) => evalExpr(left) - evalExpr(right)
case DivExpr (left, right) => evalExpr(left) / evalExpr(right)
case NumExpr (num) => num
def main(args:Array[String]) =
val expr = SubExpr (NumExpr (9), DivExpr (NumExpr(6), NumExpr (3)));
println (printExpr (expr))
println (evalExpr (expr))
$ scala Expr.scala ( 9 - ( 6 / 3 ) ) 7
interface ExprVisitor<T> {
public T visitSubExpr(SubExpr expr);
public T visitDivExpr(DivExpr expr);
public T visitNumExpr(NumExpr expr);
}
abstract class Expr {
public abstract <T> T accept(ExprVisitor<T> visitor);
}
class SubExpr extends Expr {
public Expr left;
public Expr right;
public SubExpr (Expr left, Expr right) {
this.left = left;
this.right = right;
}
@Override
public <T> T accept(ExprVisitor<T> visitor) {
return visitor.visitSubExpr(this);
}
}
class DivExpr extends Expr {
public Expr left;
public Expr right;
public DivExpr (Expr left, Expr right) {
this.left = left;
this.right = right;
}
@Override
public <T> T accept(ExprVisitor<T> visitor) {
return visitor.visitDivExpr(this);
}
}
class NumExpr extends Expr {
public int num;
public NumExpr (int num) {
this.num = num;
}
public <T> T accept(ExprVisitor<T> visitor) {
return visitor.visitNumExpr(this);
}
}
class ExprPrinter implements ExprVisitor<String> {
public String visitSubExpr(SubExpr expr) {
String left = expr.left.accept(this);
String right = expr.right.accept(this);
return "( " + left + " - " + right + " )";
}
public String visitDivExpr(DivExpr expr) {
String left = expr.left.accept(this);
String right = expr.right.accept(this);
return "( " + left + " / " + right + " )";
}
public String visitNumExpr(NumExpr expr) {
return Integer.toString(expr.num);
}
}
class ExprEvaluator implements ExprVisitor<Integer> {
public Integer visitSubExpr(SubExpr expr) {
Integer left = expr.left.accept(this);
Integer right = expr.right.accept(this);
return left - right;
}
public Integer visitDivExpr(DivExpr expr) {
Integer left = expr.left.accept(this);
Integer right = expr.right.accept(this);
return left / right;
}
public Integer visitNumExpr(NumExpr expr) {
return expr.num;
}
}
public class ExprTest2 {
public static void main (String[] args) {
var printer = new ExprPrinter ();
var evaluator = new ExprEvaluator ();
var expr = new SubExpr (new NumExpr (9), new DivExpr (new NumExpr(6), new NumExpr (3)));
System.out.println (expr.accept(printer));
System.out.println (expr.accept(evaluator));
}
}
$ javac ExprTest2.java $ java ExprTest ( 9 - ( 6 / 3 ) ) 7
expression → literal | unary | binary | grouping literal → NUMBER | STRING | "true" | "false" | "nil" grouping → "(" expression ")" unary → ( "-" | "!" ) expression binary → expression operator expression operator → "==" | "!=" | "<" | "<=" | ">" | ">=" | "+" | "-" | "*" | "/"