7

Antlr は初めてですが、以前は Flex/Bison を使用していました。Antlr を使用してやりたいことが可能かどうかを知りたいです。

Antlr を使用して PDDL ファイルを解析し、PDDL ファイルが解析されるときに記述した Java クラスで PDDL ファイルのコンテンツの独自の表現を構築したいと考えています (ルールのアクションで?)。ファイルの解析が終了したら、ファイルの内容のオブジェクト表現を Java プログラムに返して、他の操作を実行したいと考えています。

したがって、基本的には、Antler が生成した PDDL パーサーを Java プログラム内から PDDL ファイルで呼び出し、PDDL ファイルを記述するオブジェクトをメインの Java プログラムに返す必要があります。

これは可能ですか?ドキュメントを見てみましたが、良い答えが見つかりませんでした。

どうもありがとう。

4

2 に答える 2

8

したがって、基本的には、Antler が生成した PDDL パーサーを Java プログラム内から PDDL ファイルで呼び出し、PDDL ファイルを記述するオブジェクトをメインの Java プログラムに返す必要があります。

これは可能ですか?

もちろん。

まず、(ANTLR) 文法ファイルで言語を記述する必要があります。最も簡単なのは、結合された文法でこれを行うことです。結合された文法により、言語のレクサーとパーサーが作成されます。言語が複雑になると、これら 2 つを分離した方がよいのですが、最初は 1 つの (結合された) 文法ファイルだけを使用する方が簡単です。

PDDL 言語が単純な言語であるとしましょう。これは、空白で区切られた 16 進数 (0x12FD)、8 進数 (0745)、または 10 進数 (12345) 表記の 1 つ以上の数字の連続です。この言語は、次の ANTLR 文法ファイルで記述できますPDDL.g

grammar PDDL;

parse
  :  number+ EOF
  ;

number
  :  Hex
  |  Dec
  |  Oct
  ;

Hex
  :  '0' ('x' | 'X') ('0'..'9' | 'a'..'f' | 'A'..'F')+
  ;

Dec
  :  '0'
  |  '1'..'9' ('0'..'9')*
  ;

Oct
  :  '0' '0'..'7'+
  ;

Space
  :  (' ' | '\t' | '\r' | '\n'){$channel=HIDDEN;}
  ;

この文法では、大文字で始まる規則 (parse、number、Hex、... は規則) は字句解析規則です。他のものはパーサールールです。

この文法から、次のようなレクサーとパーサーを作成できます。

java -cp antlr-3.2.jar org.antlr.Tool PDDL.g

(少なくとも)ファイルPDDLParser.javaPDDLLexer.java.

次に、これらのレクサーおよびパーサー クラスを使用できる小さなテスト クラスを作成します。

import org.antlr.runtime.*;
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        File source = new File("source.txt");
        ANTLRInputStream in = new ANTLRInputStream(new FileInputStream(source));
        PDDLLexer lexer = new PDDLLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        PDDLParser parser = new PDDLParser(tokens);
        parser.parse();
    }
}

ファイルの内容は次のsource.txtようになります。

0xcAfE 0234
66678 0X12 0777

.javaすべてのファイルをコンパイルします。

javac -cp antlr-3.2.jar *.java

メインクラスを実行します。

// Windows
java -cp .;antlr-3.2.jar Main

// *nix/MacOS
java -cp .:antlr-3.2.jar Main

すべてがうまくいけば、コンソールには何も表示されません。

ここで、パーサーがソース ファイルの内容に基づいて特定のオブジェクトを返すようにしたいとします。文法が を返すようにしたいとしましょうList<Integer>。これは、次のように文法規則に「アクション」を埋め込むことで実行できます。

grammar PDDL;

parse returns [List<Integer> list]
@init{$list = new ArrayList<Integer>();}
  :  (number {$list.add($number.value);})+ EOF
  ;

number returns [Integer value]
  :  Hex {$value = Integer.parseInt($Hex.text.substring(2), 16);}
  |  Dec {$value = Integer.parseInt($Dec.text);}
  |  Oct {$value = Integer.parseInt($Oct.text, 8);}
  ;

Hex
  :  '0' ('x' | 'X') ('0'..'9' | 'a'..'f' | 'A'..'F')+
  ;

Dec
  :  '0'
  |  '1'..'9' ('0'..'9')*
  ;

Oct
  :  '0' '0'..'7'+
  ;

Space
  :  (' ' | '\t' | '\r' | '\n'){$channel=HIDDEN;}
  ;

ご覧のように、ルールにオブジェクトを返させることができ ( )、プレーンな Java コードをとreturns [Type t]でラップすることで埋め込むことができます。ルール内の部分は、ファイル内のメソッドの先頭に配置されます。{}@initparseparsePDDLParser.java

このクラスで新しいパーサーをテストします。

import org.antlr.runtime.*;
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        File source = new File("source.txt");
        ANTLRInputStream in = new ANTLRInputStream(new FileInputStream(source));
        PDDLLexer lexer = new PDDLLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        PDDLParser parser = new PDDLParser(tokens);
        List<Integer> numbers = parser.parse();
        System.out.println("After parsing :: "+numbers);
    }
}

次のようにコンソールに表示されます。

After parsing :: [51966, 156, 66678, 18, 511]
于 2010-09-29T08:18:28.557 に答える
0

Antlr は、より大きなシステム (コンパイラや静的コード アナライザーなど) の一部として呼び出されるパーサーを生成するように設計されているため、これは確かに可能です。

Terence Parr のThe Definitive Antlr Reference: Building Domain-Specific Languages から始めます。彼は Antlr の著者であり、言語処理について非常に明確で専門用語のない教師でもあります。

Martin Fowler のDomain-Specific Languagesでは、多くの例で Antlr を使用しています。たとえば、200 ページで、Java プログラムが Antlr を呼び出してあいさつする人々のファイルを解析し、その間にあいさつを発する単純な「Hello World」の例を示しています。ここで作業が行われます (206 ページ):

class GreetingsLoader. ..
  public void run() {
    try {
      GreetingsLexer lexer = new GreetingsLexer(new ANTLRReaderStream(input));
      GreetingsParser parser = new GreetingsParser(new CommonTokenStream(lexer));
      parser.helper = this;
      parser.script() ;
      if (hasErrors() ) throw new RuntimeException("it all went pear-shaped\n" +
 errorReport() ) ;
    } catch (IOException e) {
      throw new RuntimeException( e) ;
    } catch (RecognitionException e) {
      throw new RuntimeException( e) ;
    }
  }

3 番目の優れた本は、Terence の DSLs Language Implementation Patternsに関する新しい本です。彼は、Antlr を使用するさまざまな方法について説明しています。たとえば、抽象構文ツリー ジェネレーターを記述してコンパイラに挿入する方法などです。

于 2010-09-29T04:10:15.483 に答える