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)