0

Tregex を使用してサブツリーを抽出するクラスを作成しました。プログラムにコンソール コマンドを使用させたくないので、「TregexPattern.java」からいくつかのコード スニップを使用しました。

一般に、文のツリーを持っているので、特定のサブツリーを抽出したい (ユーザーの操作なし)。

私がこれまでに行ったことは次のとおりです。

package edu.stanford.nlp.trees.tregex;
import edu.stanford.nlp.ling.StringLabelFactory;
import edu.stanford.nlp.trees.*;
import java.io.*;
import java.util.*;
public abstract class Test {
    abstract TregexMatcher matcher(Tree root, Tree tree, Map<String, Tree> namesToNodes, VariableStrings variableStrings);
    public TregexMatcher matcher(Tree t) {
        return matcher(t, t, new HashMap<String, Tree>(), new VariableStrings());
    }
    public static void main(String[] args) throws ParseException, IOException {
        String encoding = "UTF-8";
        TregexPattern p = TregexPattern.compile("NP < NN & <<DT"); //"/^MWV/" or "NP < (NP=np < NNS)"
        TreeReader r = new PennTreeReader(new StringReader("(VP (VP (VBZ Try) (NP (NP (DT this) (NN wine)) (CC and) (NP (DT these) (NNS snails)))) (PUNCT .))"), new LabeledScoredTreeFactory(new StringLabelFactory()));
        Tree t = r.readTree();
        treebank = new MemoryTreebank();
        treebank.add(t);
        TRegexTreeVisitor vis = new TRegexTreeVisitor(p, encoding);
        **treebank.apply(vis);  //line 26**
        if (TRegexTreeVisitor.printMatches) {
            System.out.println("There were " + vis.numMatches() + " matches in total.");
        }
    }
    private static Treebank treebank; // used by main method, must be accessible
    static class TRegexTreeVisitor implements TreeVisitor {
        private static boolean printNumMatchesToStdOut = false;
        static boolean printNonMatchingTrees = false;
        static boolean printSubtreeCode = false;
        static boolean printTree = false;
        static boolean printWholeTree = false;
        static boolean printMatches = true;
        static boolean printFilename = false;
        static boolean oneMatchPerRootNode = false;
        static boolean reportTreeNumbers = false;
        static TreePrint tp;
        PrintWriter pw;
        int treeNumber = 0;
        TregexPattern p;
        //String[] handles;
        int numMatches;
        TRegexTreeVisitor(TregexPattern p, String encoding) {
            this.p = p;
            //this.handles = handles;
            try {
                pw = new PrintWriter(new OutputStreamWriter(System.out, encoding), true);
            } catch (UnsupportedEncodingException e) {
                System.err.println("Error -- encoding " + encoding + " is unsupported.  Using ASCII print writer instead.");
                pw = new PrintWriter(System.out, true);
            }
            // tp.setPrintWriter(pw);
        }
        public void visitTree(Tree t) {
            treeNumber++;
            if (printTree) {
                pw.print(treeNumber + ":");
                pw.println("Next tree read:");
                tp.printTree(t, pw);
            }
            TregexMatcher match = p.matcher(t);
            if (printNonMatchingTrees) {
                if (match.find()) {
                    numMatches++;
                } else {
                    tp.printTree(t, pw);
                }
                return;
            }
            Tree lastMatchingRootNode = null;
            while (match.find()) {
                if (oneMatchPerRootNode) {
                    if (lastMatchingRootNode == match.getMatch()) {
                        continue;
                    } else {
                        lastMatchingRootNode = match.getMatch();
                    }
                }
                numMatches++;
                if (printFilename && treebank instanceof DiskTreebank) {
                    DiskTreebank dtb = (DiskTreebank) treebank;
                    pw.print("# ");
                    pw.println(dtb.getCurrentFile());
                }
                if (printSubtreeCode) {
                    pw.println(treeNumber + ":" + match.getMatch().nodeNumber(t));
                }
                if (printMatches) {
                    if (reportTreeNumbers) {
                        pw.print(treeNumber + ": ");
                    }
                    if (printTree) {
                        pw.println("Found a full match:");
                    }
                    if (printWholeTree) {
                        tp.printTree(t, pw);
                    } else {
                        **tp.printTree(match.getMatch(), pw);  //line 108**
                    }
                    // pw.println();  // TreePrint already puts a blank line in
                } // end if (printMatches)
            } // end while match.find()
        } // end visitTree
        public int numMatches() {
            return numMatches;
        }
    } // end class TRegexTreeVisitor
}

しかし、次のエラーが発生します。

Exception in thread "main" java.lang.NullPointerException
        at edu.stanford.nlp.trees.tregex.Test$TRegexTreeVisitor.visitTree(Test.java:108)
        at edu.stanford.nlp.trees.MemoryTreebank.apply(MemoryTreebank.java:376)
        at edu.stanford.nlp.trees.tregex.Test.main(Test.java:26)
Java Result: 1

変更やアイデアはありますか?

4

1 に答える 1

1

NullPointerException は通常、ソフトウェアのバグの指標です。

私も過去に同じ仕事をしていました。センテンスは依存関係パーサーで解析されました。結果の解析ツリーを XML(DOM) に置き、それに対して XPath クエリを実行することにしました。

パフォーマンスを向上させるために、xml を文字列に入れる必要はありません。すべての XML 構造を DOM としてメモリに保持してください (例: http://www.ibm.com/developerworks/xml/library/x-domjava/ )。

ツリー状のデータ構造のクエリに XPath を使用すると、次の利点が得られました。

  1. 文解析結果の読み込み・保存・転送が簡単にできます。
  2. XPath の堅牢な構文/機能。
  3. 多くの人が XPath を知っています (誰もがクエリをカスタマイズできます)。
  4. XML と XPath はクロスプラットフォームです。
  5. XPath および XML/DOM ライブラリの多数の安定した実装。
  6. XSLT を使用する機能。
  7. 既存の XML ベースのパイプラインとの統合XSLT+XPath -> XSD -> Do アクション (たとえば、ユーザーは自分の電子メール アドレスを指定し、フリーテキスト クレーム内のどこかでそれをどうするかをアクションします)
于 2011-07-12T09:15:32.593 に答える