-1

我对这个关于各种语言的 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; }
}
4

1 回答 1

3

对于使用像 Java 这样的单调度 OO 语言执行此操作,这是访问者模式的经典用例,特别是如果您也对评论中提到的漂亮打印操作感兴趣。它可能适用于您评论中提到的其他一些操作,尽管它们不太适合。

于 2012-09-07T17:18:28.077 回答