したがって、基本的には、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.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;}
;
ご覧のように、ルールにオブジェクトを返させることができ ( )、プレーンな Java コードをとreturns [Type t]
でラップすることで埋め込むことができます。ルール内の部分は、ファイル内のメソッドの先頭に配置されます。{
}
@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]