Как деактивировать токены с помощью Antlr4 - PullRequest
1 голос
/ 11 марта 2020

Мне нужно проанализировать с помощью antlr4 текстовый файл, состоящий из множества блоков данных, каждый из которых имеет заголовок блока данных (одна строка) и несколько строк данных (1 .. *).

Заголовок блока данных всегда помечается цифрой «1» в первой позиции строки, за которой следуют несколько полей alphanumeri c.

DataRow также состоит из полей alphanumeri c (dataFields), Character '1 'может быть первым полем данных, но никогда не находиться в первой позиции строки.

Это пример ввода для разбора:

1   DataHeaderField1 datafield2 DataBlock1
    DB1_Row1_F1 DB1_Row1_F2    DB1_Row1_F3  DataBlock1
    DB1_Row2_F1 DB1_Row2_F2    DB1_Row2_F3  DataBlock1

1   DataHeaderField1 datafield2 DataBlock2
    DB2_Row1_F1 DB2_Row1_F2    DB2_Row1_F3  DataBlock2
    DB2_Row2_F1 DB2_Row2_F2    DB2_Row2_F3  DataBlock2
    DB2_Row3_F1 DB2_Row3_F2    DB2_Row3_F3  DataBlock2

....

Грамматика, которую я пробовал:

grammar ReadDataBlocks;
start_parsing: dataBlock+ EOF;
dataBlock: commonHeader  row+;
commonHeader: ONE_AT_FIRST_POS APLHANUMERIC* NL ;
row: APLHANUMERIC+ NL;

ONE_AT_FIRST_POS:   '1' {getCharPositionInLine() == 1}?;

APLHANUMERIC : (LETTER
                |
                DIGIT)+;
DIGIT: [0-9];
LETTER: [a-zA-Z];
NL: '\r'? '\n';
ESPACES : [ \t]+ -> skip;

Для анализа файла, который я деактивировал токены в лексере, как показано в моей грамматике, путем указания токена ONE_AT_FIRST перед токеном DI GIT, поэтому в любое время «1» обнаруживается в первом положении не должно быть анализируется как DI GIT.

Проблема заключается в том, что когда анализатор проходит через '1', расположенный в любой другой позиции, он все еще идентифицируется как ONE_AT_FIRST_POS, выдавая следующее сообщение:

* 101 8 *

1 Ответ

1 голос
/ 11 марта 2020

После запуска:

public class Main {

    public static void main(String[] args) {

        String source = "1   headerData1 headData2 HeadDataN\n    row1Data Row2Data 1 333 rowNData";
        Lexer lexer = new ReadDataBlocksLexer(CharStreams.fromString(source));
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        tokens.fill();

        for (Token t : tokens.getTokens()) {
            System.out.printf("%-20s `%s`\n", ReadDataBlocksLexer.VOCABULARY.getSymbolicName(t.getType()), t.getText());
        }
    }
}

я получаю следующий вывод:

ONE_AT_FIRST_POS     `1`
APLHANUMERIC         `headerData1`
APLHANUMERIC         `headData2`
APLHANUMERIC         `HeadDataN`
NL                   `
`
APLHANUMERIC         `row1Data`
APLHANUMERIC         `Row2Data`
APLHANUMERIC         `1`
APLHANUMERIC         `333`
APLHANUMERIC         `rowNData`
EOF                  `<EOF>`

Я думаю, что вы забыли восстановить классы анализатора после добавления предиката.

...