-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 言語でこれを行う場合、これはVisitor Patternの古典的なユースケースです。特に、コメントに記載されているプリティプリント操作にも関心がある場合はそうです。コメントで言及されている他の操作のいくつかに当てはまるかもしれませんが、それらはあまり自然に適合しません。

于 2012-09-07T17:18:28.077 に答える