我对this discussion about AST construction and evaluation in various languages感兴趣。我正在研究Java解决方案,看看我能从这个问题中学到什么。
我在下面的代码编译,但产生不正确的结果(即" oops"异常)。它不起作用,因为Java缺乏运行时调度。那有什么简单的解决方法吗?复杂的解决方法怎么样?例如。使用泛型给编译器提示?我只是在这里猜测。
我排除了一些想法:(1)在运行时使用instanceof按参数类型进行调度。 (2)构建一个查找表,将参数类型映射到适当的处理程序。 (3)在E的每个子类中放置一个评估函数,它适当地评估该子类。
我排除了(1)和(2)因为我想让编译器和/或运行时为我做这项工作。我已经排除了(3)因为我想将评估代码与表达式表示分开;这个想法是表示可能有多个操作(重新排序,简化)。
这是我到目前为止所拥有的。如上所述,此代码会产生错误的结果。
import java.util.*;
public class EV
{
public static Integer ev (E e, Map <String, Integer> env) { throw new RuntimeException ("oops: " + e); }
public static Integer ev (V e, Map <String, Integer> env) { return env.get (e.name); }
public static Integer ev (C e, Map <String, Integer> env) { return e.value; }
public static Integer ev (P e, Map <String, Integer> env) { return ev (e.a1, env) + ev (e.a2, env); }
public static Integer ev (T e, Map <String, Integer> env) { return ev (e.a1, env) * ev (e.a2, env); }
public static void main (String [] a)
{
E e = new P (new T (new C (2), new V ("a")), new V ("b"));
Map <String, Integer> env = new Hashtable <String, Integer> ();
env.put ("a", 123);
env.put ("b", 456);
System.out.println ("ev (e, env) => " + ev (e, env));
}
}
class E {}
class V extends E
{
String name;
public V (String name) { this.name = name; }
}
class C extends E
{
Integer value;
public C (Integer value) { this.value = value; }
}
class P extends E
{
E a1, a2;
public P (E a1, E a2) { this.a1 = a1; this.a2 = a2; }
}
class T extends E
{
E a1, a2;
public T (E a1, E a2) { this.a1 = a1; this.a2 = a2; }
}
答案 0 :(得分:3)
为了在像Java这样的单调度OO语言中执行此操作,这是Visitor Pattern的经典用例,特别是如果您还对评论中提到的漂亮打印操作感兴趣的话。它可能适用于您的评论中提到的其他一些操作,尽管它们不太适合。