ANTLR4: как получить позицию в исходном коде с помощью python3

Я хотел бы использовать ANTLR4 для анализа файлов COBOL с помощью программы Python3. Для этого мне нужно знать позицию, в которой токен (скажем, оператор MOVE) находится в файле (по крайней мере, строка и, если возможно, также позиция символа). Мне это особенно нужно, потому что я хочу разрешить операторы COPY (аналогично #include <> в C) и убедиться, что я знаю, в какой части я нахожусь, при синтаксическом анализе файла.

Я уже искал здесь и нашел похожие вопросы, но они, кажется, не работают для реализации Python (больше). Например, этот: Предыдущий вопрос по этой теме, вероятно, для Java

Если я пробую это решение, я получаю сообщение об ошибке, как только я вызываю getStartIndex() или getSymbol() (AttributeError: у объекта 'StartRuleContext' нет атрибута 'getStartIndex').

1 ответ

Кажется, что только объекты типа TerminalNodesImpl содержат необходимую информацию. Я придумал следующий код, хотя я не настолько счастлив, что мне приходится использовать instanceof(), чтобы проверить, есть ли у меня правильный тип узла. Если у кого-то есть более чистый способ получить информацию, пожалуйста, дайте мне знать.

class Cobol85PreprocessorPrintListener(Cobol85PreprocessorListener):
    def enterEveryRule(self, ctx):
        print("<< enterEveryRule type ", type(ctx))
        terminal= ctx
        depth= 0
        while terminal is not None and not isinstance(terminal, tree.Tree.TerminalNode):
            terminal= terminal.getChild(0)
            depth+= 1
        if terminal is not None:
            symbol= terminal.getSymbol()
            print('\tThe info was found in depth %d here:' % depth)
            self.printSymbolDetails(symbol, '\t\t')

    def printSymbolDetails(self, symbol, indent='\t'):
        print(indent + 'symbol=', symbol)
        print(indent + 'text=  ', symbol.text)
        print(indent + 'start= ', symbol.start)
        print(indent + 'stop=  ', symbol.stop)
        print(indent + 'line=  ', symbol.line)
        print(indent + 'column=', symbol.column)

Более простой и правильный способ - использовать visitTerminalметод. Слушатель ANTLR предоставляет этот метод, вызываемый при посещении конечного узла. Затем вы можете получить необходимую информацию из токена.

    def visitTerminal(self, node: TerminalNode):
       terminal = node.getSymbol()
        self.print_symbol_detail(terminal)

    def print_symbol_detail(self, terminal, indent='\t'):
       print(indent + 'symbol=', terminal)
       print(indent + 'text=  ', terminal.text)
       print(indent + 'type=  ', terminal.type)
       print(indent + 'start= ', terminal.start)
       print(indent + 'stop=  ', terminal.stop)
       print(indent + 'line=  ', terminal.line)
       print(indent + 'column=', terminal.column)
       print('-'*75)
Другие вопросы по тегам