[英]Can I use an Antlr created lexer/parser to parse PDDL file and return data to a Java program?
我是Antlr的新手,但之前使用過Flex / Bison。 我想知道使用Antlr我想做什么是可能的。
我想使用Antlr解析PDDL文件,並在解析PDDL文件時編寫的Java類中構建我自己的PDDL文件內容表示(在規則的操作中?)。 在文件完成解析之后,我想將文件內容的對象表示返回給Java程序以運行其他操作。
基本上,我想從Java程序內部在PDDL文件上調用Antler生成的PDDL解析器,並讓它返回一個描述PDDL文件到主Java程序的對象。
這可能嗎? 我試過看文檔,但沒有找到一個好的答案。
非常感謝。
基本上,我想從Java程序內部在PDDL文件上調用Antler生成的PDDL解析器,並讓它返回一個描述PDDL文件到主Java程序的對象。
這可能嗎?
當然。
首先,您需要在(ANTLR)語法文件中描述您的語言。 最簡單的方法是使用組合語法。 組合語法將為您的語言創建詞法分析器和解析器。 當語言變得更復雜時,最好將這兩者分開,但首先,只使用一個(組合的)語法文件會更容易。
假設PDDL語言只是一種簡單的語言:它是由十六進制(0x12FD),八進制(0745)或十進制(12345)表示的一個或多個數字的連續,用空格分隔。 可以在以下名為PDDL.g
ANTLR語法文件中描述該語言:
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
。
現在創建一個小測試類,您可以在其中使用這些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();
}
}
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>
。 這可以通過在你的語法規則中嵌入“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;}
;
正如您所看到的,您可以讓規則返回對象( returns [Type t]
),如果將它包裝在{
和}
,則可以嵌入純Java代碼。 parse
規則中的@init
部分放在PDDLParser.java
文件中的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旨在生成解析器,然后將其作為更大系統(例如,編譯器或靜態代碼分析器)的一部分進行調用。
從Terence Parr的The Definitive Antlr Reference:Building Domain-Specific Languages開始 。 他是Antlr的作者,也是語言處理方面非常清晰且沒有行話的老師。
Martin Fowler的Domain-Specific Languages在很多例子中都使用了Antlr。 例如,在第200頁,他展示了一個簡單的“Hello World”示例,其中Java程序調用Antlr來解析人們要問候的文件,並在執行此操作時發出問候語。 這是工作完成的地方(第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) ;
}
}
第三本好書是Terence關於DSL 語言實現模式的新書。 他描述了使用Antlr的各種方法,例如編寫一個抽象語法樹生成器以放入編譯器。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.