私はANTLRは、Javaプログラムに解析PDDLファイルへのレクサー/パーサと戻りデータを作成し使用することはできますか?
質問
私はANTLRに新しいですが、前のFlex /バイソンを使用していました。私が使用して何をしたいのかANTLRが可能であるかどうかを知りたい。
私はANTLRを使用してPDDLファイルを解析し、PDDLファイルが解析されるように私が書いたJavaクラスにPDDLファイルの内容を自分の表現を構築したい(ルールのアクションで?)。ファイルを解析し終わった後、私は上の他の操作を実行するためにJavaプログラムにファイルの内容のオブジェクト表現を返すようにしたいです。
だから、基本的に、私はJavaプログラム内からPDDLファイルにPDDLパーサを生成し、それがメインのJavaプログラムにPDDLファイルを記述するオブジェクトを返す必要がありアントラーを呼び出したい。
これは可能ですか?私はマニュアルを見て試してみましたが、良い答えを見つけることができます。
どうもありがとうございました。
解決
だから、基本的に、私はJavaプログラム内からPDDLファイルにPDDLパーサを生成し、それがメインのJavaプログラムにPDDLファイルを記述するオブジェクトを返す必要がありアントラーを呼び出したい。
これは可能でしょうか?
確かます。
まず、(ANTLR)文法ファイルにあなたの言語を記述する必要があります。最も簡単に組み合わせる文法でこれを行うことです。組み合わせ文法はあなたの言語のレクサーとパーサを作成します。言語はより複雑になると、それはこれらの2を分離するのではなく、アウトを開始するために、ちょうど1(組み合わせ)文法ファイルを使用する方が簡単になります優れています。
レッツがPDDL言語だけで簡単言語であると言う:それは、一つ以上の数字のいずれかを16進数で(0x12FD)の連続で、オクタル(0745)、または小数(12345)の表記は、空白で区切られています。この言語は、次の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;}
;
この文法では、ルール(パース、数、六角、...ルールです)資本で始めレクサー・ルールであること。他のものは、パーサー・ルールです。
この文法から、このようなレクサーとパーサを作成することができます:
java -cp antlr-3.2.jar org.antlr.Tool PDDL.g
(少なくとも)を生成し、ファイルPDDLParser.java
とPDDLLexer.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;}
;
あなたが見ることができるように、あなたはルールがreturns [Type t]
と{
でそれを包む場合、オブジェクト(}
)と缶が単純なJavaコードを埋め込む返させることができます。 @init
ルールでparse
部がparse
ファイル内PDDLParser.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]
他のヒント
これは、確かに可能である(例えば、コンパイラや静的コード分析)。
テレンス・パーの決定的ANTLRリファレンスとスタート:建物ドメイン固有言語。彼はまた、ANTLRの著者、および言語処理上の異常に明確かつ専門用語のない先生です。
その多くのでANTLRを使用する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) ;
}
}
第三の良い本はDSLの言語実装パターンにテレンスの新しいものですの。彼は、コンパイラの中に入れて、抽象構文木・ジェネレータを書き込むためのインスタンスの場合と同様に、ANTLRを使用するためのさまざまな方法を説明します。