ANTLR4. Доступ к объектам контекста с помощью действий - PullRequest
1 голос
/ 25 апреля 2020

Анализ входных файлов с размером больше памяти компьютера требует трех шагов:

  1. Использование небуферизованных потоков символов и токенов
  2. Копирование текста из скользящего буфера и сохранение в токенах
  3. Попросить синтаксический анализатор не создавать деревья разбора

Цель - упрощенная грамматика для разбора файла, состоящего из множества строк, каждая из которых состоит из множества слов.

С учетом этого требования в следующем коде используется действие @members и подклассификация синтаксического анализатора, сгенерированного ANTLR

Метод printPagesAndWords получает список LineContext объектов.

It печатает общее количество строк (с методом start, предоставленным LineContext), но не может получить доступ к количеству WORD на строку, при этом метод WORD() предоставляется объектом LineContext.

Вот что получится:

Number of lines in page:    3

Line start token:           word1
Number of words in line:    0

Line start token:           2323
Number of words in line:    0

Line start token:           554545
Number of words in line:    0

Кроме того, если я попытаюсь получить СЛОВА в строке, например, изменить строку

System.out.println("Number of words in line:\t"+row.WORD().size()+"\n");

на строку

System.out.println("Number of words in line:\t"+row.WORD(1).getText()+"\n");

The followi Возникает исключение ng:

Exception in thread "main" java.lang.NullPointerException
    at TestContext.printPagesAndWords(TestContext.java:11)
    at ContextParser.read(ContextParser.java:130)
    at Main.main(Main.java:11)

Ниже приводится полный набор файлов:

ContextLexer.g4

lexer grammar ContextLexer;
NL
 : '\r'? '\n'
 ;
WORD
 : ~[ \t\n\r]+
 ;
SPACE
 : [ \t] -> skip
 ;

ContextParser.g4

parser grammar ContextParser;

options {
  tokenVocab=ContextLexer;
}
@members{
void printPagesAndWords(List<LineContext> rows){};
}
read
 : dataLine+=line*  {printPagesAndWords($dataLine);}
 ;
line
 : WORD* NL
 ;

TestContext, расширяющий ContextParser

import org.antlr.v4.runtime.TokenStream;
import java.util.List;
public class TestContext extends ContextParser {
    public TestContext(TokenStream input) {
        super(input);
    }
    void printPagesAndWords(List<LineContext> rows){
        System.out.println("Number of lines in page:\t" + rows.size()+"\n");
        for(LineContext row: rows){
            System.out.println("Line start token:\t\t\t"+row.start.getText());
            System.out.println("Number of words in line:\t"+row.WORD().size()+"\n");
        }
    };
}

Основной класс:

import org.antlr.v4.runtime.*;
import java.io.IOException;
public class Main {
    public static void main(String[] args) throws IOException {
        String source = "word1 word2 number anothernumber \n 2323 55r ere\n554545 lll 545\n";
        ContextLexer lexer = new ContextLexer(CharStreams.fromString(source));
        lexer.setTokenFactory(new CommonTokenFactory(true));
        TokenStream tokens = new UnbufferedTokenStream<CommonToken>(lexer);
        TestContext parser = new TestContext(tokens);
        parser.setBuildParseTree(false);
        parser.read();
    }
}
...