我可以使用Antlr创建的词法分析器/解析器来解析PDDL文件并将数据返回给Java程序吗?

Ste*_*ven 7 java antlr pddl

我是Antlr的新手,但之前使用过Flex/Bison.我想知道使用Antlr我想做什么是可能的.

我想使用Antlr解析PDDL文件,并在解析PDDL文件时编写的Java类中构建我自己的PDDL文件内容表示(在规则的操作中?).在文件完成解析之后,我想将文件内容的对象表示返回给Java程序以运行其他操作.

基本上,我想从Java程序内部在PDDL文件上调用Antler生成的PDDL解析器,并让它返回一个描述PDDL文件到主Java程序的对象.

这可能吗?我试过看文档,但没有找到一个好的答案.

非常感谢.

Bar*_*ers 8

基本上,我想从Java程序内部在PDDL文件上调用Antler生成的PDDL解析器,并让它返回一个描述PDDL文件到主Java程序的对象.

这可能吗?

当然.

首先,您需要在(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;}
  ;
Run Code Online (Sandbox Code Playgroud)

在这个语法中,以大写字母开头的规则(解析,数字,十六进制,......是规则)是词法规则.其他的是解析器规则.

从这个语法中,你可以像这样创建一个词法分析器和解析器:

java -cp antlr-3.2.jar org.antlr.Tool PDDL.g
Run Code Online (Sandbox Code Playgroud)

它产生(至少)文件PDDLParser.javaPDDLLexer.java.

现在创建一个小测试类,您可以在其中使用这些lexer和parser类:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

其中source.txt文件的内容可能如下所示:

0xcAfE 0234
66678 0X12 0777
Run Code Online (Sandbox Code Playgroud)

现在编译所有.java文件:

javac -cp antlr-3.2.jar *.java
Run Code Online (Sandbox Code Playgroud)

并运行主类:

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

// *nix/MacOS
java -cp .:antlr-3.2.jar Main
Run Code Online (Sandbox Code Playgroud)

如果一切顺利,控制台上不会打印任何内容.

现在你说你想让解析器根据源文件的内容返回某些对象.假设我们希望我们的语法返回一个List<Integer>.这可以通过在你的语法规则中嵌入"actions"来完成,如下所示:

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;}
  ;
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,你可以让规则返回(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);
    }
}
Run Code Online (Sandbox Code Playgroud)

并且您将看到以下内容被打印到控制台:

After parsing :: [51966, 156, 66678, 18, 511]
Run Code Online (Sandbox Code Playgroud)