因此,本质上,我想从 Java 程序内部对 PDDL 文件调用 Antler 生成的 PDDL 解析器,并让它向主 Java 程序返回一个描述 PDDL 文件的对象。
这可能吗?
当然。
首先,您需要在(ANTLR)语法文件中描述您的语言。最简单的方法是在组合语法中做到这一点。组合语法将为您的语言创建词法分析器和解析器。当语言变得更复杂时,最好将这两者分开,但开始时,只使用一个(组合)语法文件会更容易。
假设 PDDL 语言只是一种简单的语言:它是一个或多个数字的连续,可以是十六进制 (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 代码(如果将其包装在{
and中) }
。规则中的@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]