ANTLR4:如何使用 python3 获取源代码中的位置

ANTLR4: How to get the position in the source with python3

我想使用 ANTLR4 通过 Python3 程序分析 COBOL 文件。 为此,我需要知道令牌(比如说 MOVE 语句)在文件中出现的位置(至少是行,如果可能的话还有字符位置)。我特别需要这个,因为我想解析 COPY 语句(类似于 C 中的#include <>)并确保我在解析文件时知道我在哪一部分。

我已经在这里搜索并发现了类似的问题,但它们似乎不适用于 python 实现(不再)。例如。这个:Previous Question about that topic, probably for Java

如果我尝试此解决方案,我会在调用 getStartIndex() 或 getSymbol() 时立即收到错误消息(AttributeError:'StartRuleContext' 对象没有属性 'getStartIndex')。

似乎只有 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)