ANTLR4和Python目标

时间:2015-05-14 23:14:26

标签: python antlr antlr4

我在使用ANTLR4中的Python目标时遇到了问题。似乎很少有可用的示例,并且相应的Java代码似乎并不相关。

我正在使用标准的Hello.g4语法:

// Define a grammar called Hello
grammar Hello;
r  : 'hello' ID ;         // match keyword hello followed by an identifier
ID : [a-z]+ ;             // match lower-case identifiers
WS : [ \t\r\n]+ -> skip ; // skip spaces, tabs, newlines

示例(根据标准Hello.g4示例构建):

input_ = antlr4.FileStream(_FILENAME)
lexer = HelloLexer.HelloLexer(input_)
stream = antlr4.CommonTokenStream(lexer)
parser = HelloParser.HelloParser(stream)

rule_name = 'r'
tree = getattr(parser, rule_name)()

我还写了一个听众。为了断言/验证这是正确的,我将在此重复:

class HelloListener(antlr4.ParseTreeListener):
    def enterR(self, ctx):
        print("enterR")

    def exitR(self, ctx):
        print("exitR")

    def enterId(self, ctx):
        print("enterId")

    def exitId(self, ctx):
        print("exitId")

所以,首先,我不能保证我给它的字符串是有效的,因为我没有得到任何屏幕输出。如果匹配任何内容,如何从对象中判断?如何提取匹配的规则/令牌?

如果可能的话,Python示例会很棒。

4 个答案:

答案 0 :(得分:4)

我听到你,现在遇到同样的问题。 v4的Python文档是无用的,v3的不同之处在于可用。我正在考虑切换回Java来实现我的东西。

关于你的代码:我认为你自己的自定义监听器必须从生成的HelloListener继承。你可以在那里打印。

还尝试解析无效输入以查看解析器是否完全启动。我不确定getattr(parser,rule_name)()的行。我按照Antlr4 Python目标(不幸的很短)文档中的步骤进行操作:https://theantlrguy.atlassian.net/wiki/display/ANTLR4/Python+Target

您还可以在那里找到有关监听器内容的一些文档。希望它有所帮助。

答案 1 :(得分:2)

这个问题似乎很老,但我也有同样的问题,并找到了如何处理它。在python中使用字符串时,必须使用函数antlr4.InputStream作为pointed out here

所以,最后,您可以使用此类代码获得一个有效的示例(based on Alan's answeran example from dzone

from antlr4 import *
from grammar.HelloListener import HelloListener
from grammar.HelloLexer import HelloLexer
from grammar.HelloParser import HelloParser
import sys

class HelloPrintListener(HelloListener):
   def enterHi(self, ctx):
      print("Hello: %s" % ctx.ID())

def main():
   giveMeInput = input ("say hello XXXX\n")
   print("giveMeInput is {0}".format(giveMeInput))

   # https://www.programcreek.com/python/example/93166/antlr4.InputStream
   # https://groups.google.com/forum/#!msg/antlr-discussion/-9VJ5H9NcDs/OukVNCTQCAAJ
   i_stream = InputStream(giveMeInput)

   lexer = HelloLexer(i_stream)
   t_stream = CommonTokenStream(lexer)
   parser = HelloParser(t_stream)
   tree = parser.hi()
   printer = HelloPrintListener()
   walker = ParseTreeWalker()
   walker.walk(printer, tree)

if __name__ == '__main__':
   main()

答案 2 :(得分:1)

我使用Hello语法创建了an example for Python 2

以下是相关代码:

from antlr4 import *
from HelloLexer import HelloLexer
from HelloListener import HelloListener
from HelloParser import HelloParser
import sys

class HelloPrintListener(HelloListener):
    def enterHi(self, ctx):
        print("Hello: %s" % ctx.ID())

def main():
    lexer = HelloLexer(StdinStream())
    stream = CommonTokenStream(lexer)
    parser = HelloParser(stream)
    tree = parser.hi()
    printer = HelloPrintListener()
    walker = ParseTreeWalker()
    walker.walk(printer, tree)

if __name__ == '__main__':
    main()

正如fabs所说,关键是从生成的HelloListener继承。在这个问题上似乎有些挑剔,因为你可以看到你修改我的HelloPrintListener是否直接从ANTLR的ParseTreeListener继承。我想这会有效,因为生成的HelloListener只有空方法,但我看到了你看到的相同行为(从不调用监听器方法)。

即使缺少Python监听器的文档,但可用的方法与Java类似。

答案 3 :(得分:0)

antlr文档已更新,以记录对python 3和python 4目标的支持。转换为python3的antlr书籍中的示例可以找到here,它们足以让任何人开始。