interface IExprVisitor<T> {
public abstract void Accept(IExprVisitor v);
public abstract T Accept<T>(IExprVisitor<T> v);
public double Value { get; set; }
public override void Accept(IExprVisitor v) { v.On(this); }
public override T Accept<T>(IExprVisitor<T> v) { return v.On(this); }
public Expr Left { get; set; }
public Expr Right { get; set; }
public override void Accept(IExprVisitor v) { v.On(this); }
public override T Accept<T>(IExprVisitor<T> v) { return v.On(this); }
class Printer: IExprVisitor<string> {
public string On(Plus plus) {
return plus.Left.Accept(this) + " + " + plus.Right.Accept(this);
public string On(Num num) {
return num.Value.ToString();
class Interpreter: IExprVisitor<double> {
public double On(Plus plus) {
return plus.Left.Accept(this) + plus.Right.Accept(this);
public double On(Num num) {
class Compiler: IExprVisitor<string> {
public string On(Plus plus) {
return plus.Left.Accept(this) + plus.Right.Accept(this) + "add\n";
public string On(Num num) {
return "push " + num.Value + "\n";
public static void Main()
Left = new Num() { Value = 1 },
Right = new Num() { Value = 2 }
Right = new Num() { Value = 42 }
var printer = new Printer();
var evaluator = new Interpreter();
var compiler = new Compiler();
Console.WriteLine("PRINT = {0}", e.Accept(printer));
Console.WriteLine("EVAL = {0}", e.Accept(evaluator));
Console.WriteLine("CODE = \n---------\n{0}---------", e.Accept(compiler));