Могу ли я использовать Antlr создал LEXER / PARSER для анализа файла PDDL и возврат данных в программу Java?

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

  •  26-09-2019
  •  | 
  •  

Вопрос

Я новичок в Antlr, но раньше использовал Flex / Bison. Я хочу знать, возможно ли то, что я хочу сделать с использованием ANTLR.

Я хочу разбирать файл PDDL с помощью ANTLR и создать свое собственное представление содержимого файла PDDL в классе Java, который я написал, так как файл PDDL проанализирован (в действиях для правил?). После завершения файла Parsing я хочу вернуть объект представления содержимого файла в программу Java для запуска других операций.

По сути, я хочу вызвать Antler Parser PDDL в файле PDDL из файла PDDL изнутри Java-программы и вернуть ее объект, который описывает файл PDDL к главной программе Java.

Это возможно? Я пытался смотреть на документацию, но не нашел хороший ответ.

Большое спасибо.

Это было полезно?

Решение

По сути, я хочу вызвать Antler Parser PDDL в файле PDDL из файла PDDL изнутри Java-программы и вернуть ее объект, который описывает файл 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;}
  ;

В этой грамматике правила (анализ, номер, Hex, ... являются правилами), которые начинаются с капитала, являются лексером-правилами. Другие - это анализаторы-правила.

Из этой грамматики вы можете создать Lexer и парсер, как это:

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>. Отказ Это может быть сделано путем встраивания «Действия» в ваших грамматических правилах, как это:

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, если его упаковывать { а также }. Отказ То @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);
    }
}

И вы увидите следующее, напечатанное на консоль:

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

Другие советы

Это, безусловно, возможно, поскольку ANTLR предназначен для генерации парсеров, которые затем выбираются как часть большей системы (например, компилятора или анализатор статического кода).

Начните с Теренс Парра Окончательный эталон ANTLR: построение доменных языков. Отказ Он автор ANTLR, а также необычайно чистый и безжальский учитель на языковой обработке.

Мартин Фаулер Языки, специфичные домена Использует ANTLR во многих его примерах. Например, на Page 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) ;
    }
  }

Третья хорошая книга - новый новый на DSLS Языковые модели внедрения. Отказ Он описывает различные способы использования ANTLR, например, например, для записи генератора абстрактного синтаксического дерева, чтобы поместить в компилятор.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top