簡體   English   中英

我可以使用Antlr創建的詞法分析器/解析器來解析PDDL文件並將數據返回給Java程序嗎?

[英]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.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();
    }
}

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM