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)
我想使用 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)