2010-09-29 11 views
7

Jestem nowy w firmie Antlr, ale wcześniej korzystałem z Flex/Bison. Chcę wiedzieć, czy to, co chcę zrobić, używając Antlr jest możliwe.Czy mogę użyć stworzonego przez Antlr lexera/analizatora składni do parsowania pliku PDDL i zwrócenia danych do programu Java?

Chcę przeanalizować plik PDDL za pomocą Antlr i zbudować własną reprezentację zawartości pliku PDDL w klasie Java, którą napisałem, gdy parsowany jest plik PDDL (w akcjach dla reguł?). Po zakończeniu parsowania pliku chcę przywrócić reprezentację obiektu zawartości pliku do programu Java, aby uruchomić inne operacje.

Tak więc, zasadniczo, chcę wywołać Antler wyprodukowany parser PDDL na pliku PDDL z wewnątrz programu Java i zwrócić obiekt, który opisuje plik PDDL do głównego programu Java.

Czy to możliwe? Próbowałem spojrzeć na dokumentację, ale nie znalazłem dobrej odpowiedzi.

Dziękuję bardzo.

+1

+1 Ciekawe pytanie, ale tytuł jest nieco niejasny . Być może uzyskasz więcej informacji za pomocą: "Czy mogę osadzić parser generowany przez Antlr w programie Java, a następnie wywołać go w celu przeanalizowania pliku?" –

Odpowiedz

8

Więc zasadniczo chcę powołać poroża produkowane PDDL parsera na plik PDDL od wewnątrz programu Java i mieć go zwrócić obiekt, który opisuje plik PDDL głównego programu Java.

Czy to możliwe?

Pewnie.

Najpierw musisz opisać swój język w pliku gramatycznym (ANTLR). Najłatwiej jest to zrobić w połączeniu gramatyki. Połączona gramatyka stworzy lekser i parser dla Twojego języka. Kiedy język staje się bardziej złożony, lepiej jest oddzielić te dwie, ale na początek łatwiej będzie użyć tylko jednego (połączonego) pliku gramatycznego.

Załóżmy, że język PDDL jest prostym językiem: jest to ciąg jednej lub więcej liczb w zapisie szesnastkowym (0x12FD), ósemkowym (0745) lub dziesiętnym (12345) oddzielonym białymi spacjami. Język ten można opisać w następujący antlr pliku gramatyki zwanego 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;} 
    ; 

W tym gramatykę, zasady (analizowania, numer, Hex, ... są zasady), które zaczynają z kapitałem są Lexer-rules. Pozostałe to reguły parsera.

z tej gramatyki, można utworzyć lexer i analizatora składni takiego:

java -cp antlr-3.2.jar org.antlr.Tool PDDL.g 

która produkuje (co najmniej) pliki PDDLParser.java i PDDLLexer.java.

Teraz utworzyć małą klasę testową, w której można korzystać z tych Lexer i parsera klasy:

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(); 
    } 
} 

gdzie zawartość pliku source.txt może wyglądać następująco:

0xcAfE 0234 
66678 0X12 0777 

Teraz skompilować wszystko .java pliki:

javac -cp antlr-3.2.jar *.java 

i uruchomić główną klasę:

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

// *nix/MacOS 
java -cp .:antlr-3.2.jar Main 

Jeśli wszystko pójdzie dobrze, nic nie będzie drukowane na konsoli.

Teraz mówisz, że chcesz, aby analizator składni zwrócił pewne obiekty na podstawie zawartości pliku źródłowego. Załóżmy, że chcemy, aby nasza gramatyka zwróciła wartość List<Integer>. Można to zrobić poprzez osadzenie „działania” w regułach gramatycznych tak:

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;} 
    ; 

Jak widać, można pozwolić zasady zwrotu przedmiotów (returns [Type t]) i można osadzić zwykły kod Java czy owijanie go w { i } . Część w regule parse jest umieszczana na początku metody parse w pliku PDDLParser.java.

Przetestuj nowy parser z tej klasy:

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); 
    } 
} 

a zobaczysz co następuje drukowane do konsoli:

After parsing :: [51966, 156, 66678, 18, 511] 
0

Jest to z pewnością możliwe, ponieważ Antlr służy do generowania analizatorów, które następnie są wywoływane jako część większego systemu (np. Kompilator lub statyczny analizator kodu).

Zacznij od Terence'a Parra The Definitive Antlr Reference: Building Domain-Specific Languages. Jest autorem Antlra, a także niezwykle przejrzystym i pozbawionym żargonu nauczycielem zajmującym się przetwarzaniem języka.

Martin Fowler's Domain-Specific Languages używa Antlr w wielu swoich przykładach. Na przykład na stronie 200 pokazuje prosty przykład "Hello World", w którym program w języku Java wywołuje Antlr, aby przeanalizować plik ludzi do powitania, a podczas wykonywania go wysyła pozdrowienia. Oto gdzie praca zostanie zrobione (strona 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) ; 
    } 
    } 

Trzecia dobra książka jest nowa Terence'a na DSL Language Implementation Patterns. Opisuje różne sposoby użycia Antlr, na przykład do napisania generatora abstrakcyjnego drzewa składni do wstawienia do kompilatora.

Powiązane problemy