用于AST评估难题的Java解决方案

时间:2012-09-07 15:38:12

标签: java abstract-syntax-tree

我对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; }
}

1 个答案:

答案 0 :(得分:3)

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