我对这个关于各种语言的 AST 构建和评估的讨论很感兴趣。我正在研究 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; }
}