ANTLR 2.7. Получить поток объектов из парсера - PullRequest
0 голосов
/ 27 июля 2011

Я использую ANTLR 2.7.6 для разбора грязного вывода другого приложения. К сожалению, у меня нет возможности перейти на ANTLR 3, хотя он уже давно отсутствует. Файл журнала, который я буду анализировать, лучше концептуализировать как список объектов, чем как дерево объектов, и он может быть очень большим (> 100 МБ), поэтому нецелесообразно читать все это в одном AST. (Мое приложение является многопоточным и обрабатывает от полдюжины до десятка этих файлов одновременно, поэтому память быстро заполняется.) Я хочу иметь возможность считывать каждый из этих объектов как из потока, чтобы я мог обработать их по одному одним. Обратите внимание, что сами объекты могут быть концептуализированы как маленькие деревья. Есть ли способ заставить мой анализатор ANTLR действовать как поток объектов, итератор или что-то в этом роде?

[См. Javadoc для ANTLR 2 .]

Редактировать : Вот концептуальный пример того, что я хотел бы сделать с анализатором.

import java.io.FileReader;
import antlr.TokenStream;
import antlr.CharBuffer;
//...
FileReader fileReader = new FileReader(filepath);
TokenStream lexer = new MyExampleLexer(new CharBuffer(fileReader));
MyExampleParser parser = new MyExampleParser(lexer);
for (Object obj : parser)
{
    processObject(obj);
}

Возможно, я работаю с неправильной парадигмой, как использовать анализатор Antlr? (Я понимаю, что синтаксический анализатор не реализует Iterator; но это концептуально такое поведение, которое я ищу.)

1 Ответ

1 голос
/ 27 июля 2011

AFAIK, ANTLR v2.x буферизует создание токенов.Парсер принимает TokenBuffer , который в свою очередь принимает TokenStream .Затем этот TokenStream опрашивается с помощью метода nextToken () , когда анализатору требуется больше токенов.

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

Обратите внимание, что я никогда не работал с ANTLR 2.x, поэтому я могу ошибаться.Вы наблюдали что-то другое?Если да, то как вы предлагаете источник ANTLR: в виде файла или в виде большой строки?Если это последнее, я рекомендую вместо этого предоставить файл.

РЕДАКТИРОВАТЬ

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

Это можно сделать, разрешив правилу основного синтаксического анализатора parse возвращать список чисел для каждой строки.Если достигнут EOF (конец файла), вы просто возвращаете null вместо списка.

Демонстрация с использованием ANTLR 2.7.6:

file: My.g

class MyParser extends Parser;

parse returns [java.util.List<Integer> numbers]
{
  numbers = new java.util.ArrayList<Integer>();
}
  :  (n:Number {numbers.add(Integer.valueOf(n.getText()));})+ LineBreak
  |  EOF {numbers = null;}
  ;

class MyLexer extends Lexer; 

Number
  :  ('0'..'9')+
  ;

LineBreak
  :  ('\r')? '\n'
  ;

Space
  :  (' ' | '\t') {$setType(Token.SKIP);}
  ;

файл: Main.java

import antlr.*;

public class Main {
  public static void main(String[] args) throws Exception {
    MyLexer lexer = new MyLexer(new java.io.StringReader("1 2 3\n4 5 6 7 8\n9 10\n"));
    MyParser parser = new MyParser(new TokenBuffer(lexer));
    int line = 0;
    java.util.List<Integer> numbers = null;
    while((numbers = parser.parse()) != null) {
      line++;
      System.out.println("line " + line + " = " + numbers);
    }
  }
}

Для запуска демонстрации:

* nix

java -cp antlr-2.7.6.jar antlr.Tool My.g
javac -cp antlr-2.7.6.jar *.java
java -cp .:antlr-2.7.6.jar Main

или на:

Windows

java -cp antlr-2.7.6.jar antlr.Tool My.g
javac -cp antlr-2.7.6.jar *.java
java -cp .;antlr-2.7.6.jar Main

, который будет выдавать следующий вывод:

line 1 = [1, 2, 3]
line 2 = [4, 5, 6, 7, 8]
line 3 = [9, 10]

Предупреждение

Любой, кто пытается этот код, пожалуйста, обратите внимание, чтоэто использует ANTLR 2.7.6.Если у вас нет веских причин для использования этой версии, настоятельно рекомендуется использовать последнюю стабильную версию ANTLR (v3.3 на момент написания этой статьи).

...