Анализ входных файлов с размером больше памяти компьютера требует трех шагов:
- Использование небуферизованных потоков символов и токенов
- Копирование текста из скользящего буфера и сохранение в токенах
- Попросить синтаксический анализатор не создавать деревья разбора
Цель - упрощенная грамматика для разбора файла, состоящего из множества строк, каждая из которых состоит из множества слов.
С учетом этого требования в следующем коде используется действие @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();
}
}