Posso utilizzare un lexer/parser creato da Antlr per analizzare il file PDDL e restituire i dati a un programma Java?

StackOverflow https://stackoverflow.com/questions/3818442

  •  26-09-2019
  •  | 
  •  

Domanda

Sono nuovo su Antlr, ma ho già usato Flex/Bison.Voglio sapere se quello che voglio fare usando Antlr è possibile.

Voglio analizzare un file PDDL utilizzando Antlr e creare la mia rappresentazione del contenuto del file PDDL in una classe Java che ho scritto mentre il file PDDL viene analizzato (nelle azioni per le regole?).Al termine dell'analisi del file, desidero restituire la rappresentazione dell'oggetto del contenuto del file al programma Java su cui eseguire altre operazioni.

Quindi, in sostanza, voglio invocare un parser PDDL prodotto da Antler su un file PDDL dall'interno di un programma Java e fare in modo che restituisca un oggetto che descriva il file PDDL al programma Java principale.

È possibile?Ho provato a consultare la documentazione, ma non ho trovato una buona risposta.

Grazie mille.

È stato utile?

Soluzione

  

Quindi, in sostanza, voglio richiamare un corno prodotto PDDL parser su un file PDDL dall'interno di un programma Java e lo hanno restituire un oggetto che descrive il file PDDL al programma principale Java.

     

È possibile?

Certo.

Per prima cosa è necessario per descrivere la lingua in un (ANTLR) file di grammatica. Il metodo più semplice è quello di farlo in una grammatica combinato. Una grammatica combinato creerà un lexer e parser per la propria lingua. Quando il linguaggio diventa più complesso, è meglio separare questi due, ma per iniziare, sarà più facile da usare una sola (combinato) file di grammatica.

Diciamo che la lingua PDDL è solo una lingua facile: è un susseguirsi di uno o più numeri sia in esadecimale (0x12FD), ottale (0745) o decimale (12345) notazione separate da spazi bianchi. Questo linguaggio può essere descritta nel seguente file di grammatica ANTLR chiamato 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;}
  ;

In questa grammatica, le regole (parse, il numero, Hex, ... sono le regole) che iniziano con un capitale sono lexer-regole. Gli altri sono parser-regole.

Da questa grammatica, è possibile creare un lexer e parser in questo modo:

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

che produce (almeno) i file PDDLParser.java e PDDLLexer.java.

Ora creare un po 'di classe di test in cui è possibile utilizzare queste classi lexer e 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();
    }
}

dove il contenuto del file source.txt potrebbero apparire così:

0xcAfE 0234
66678 0X12 0777

Ora compilare tutti i file .java:

javac -cp antlr-3.2.jar *.java

ed eseguire la classe principale:

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

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

Se tutto va bene, nulla viene stampato sulla console.

Ora si dice che si voleva lasciare il ritorno parser alcuni oggetti in base al contenuto del file di origine. Diciamo che vogliamo che la nostra grammatica restituire un List<Integer>. Questo può essere fatto, grazie all'integrazione di "azioni" nelle regole grammaticali in questo modo:

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

Come si può vedere, si può lasciare che le regole restituiscono oggetti (returns [Type t]) e possibile incorporare codice Java semplice se avvolgendolo in { e }. La parte @init nella regola parse è posto all'inizio del metodo parse nel file PDDLParser.java.

Prova il nuovo parser con questa classe:

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

e vedrete la seguente fase di stampa alla console:

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

Altri suggerimenti

Ciò è certamente possibile, dal momento che Antlr è progettato per generare parser che vengono poi invocati come parte di un sistema più ampio (ad esempio, un compilatore o un analizzatore di codice statico).

Inizia con quello di Terence Parr Il riferimento definitivo ad Antlr:Creazione di linguaggi specifici del dominio.È l'autore di Antlr e anche un insegnante insolitamente chiaro e privo di termini tecnici sull'elaborazione del linguaggio.

Di Martin Fowler Linguaggi specifici del dominio usa Antlr in molti dei suoi esempi.Ad esempio, a pagina 200 mostra un semplice esempio "Hello World" in cui un programma Java chiama Antlr per analizzare un file di persone da salutare, e mentre lo fa emette i saluti.Ecco dove viene svolto il lavoro (pagina 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) ;
    }
  }

Un terzo buon libro è il nuovo libro di Terence sulle DSL Modelli di implementazione del linguaggio.Descrive vari modi per utilizzare Antlr, come ad esempio scrivere un generatore di alberi di sintassi astratto da inserire in un compilatore.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top