ANTLR4 и цель Python

У меня проблемы с запуском цели Python в ANTLR4. Кажется, что доступно очень мало примеров, и переход к соответствующему коду 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")

Итак, во-первых, я не могу гарантировать, что строка, которую я ей даю, действительна, потому что я не получаю никакого вывода на экран. Как узнать по объекту tree, совпало ли что-нибудь? Как извлечь соответствующие правила/токены?

Пример Python был бы отличным, если это возможно.


person Dustin Oprea    schedule 14.05.2015    source источник


Ответы (4)


Я слышу вас, у вас те же проблемы прямо сейчас. Документация Python для версии 4 бесполезна, а версия 3 сильно отличается от нее, чтобы ее можно было использовать. Я думаю о том, чтобы вернуться к Java, чтобы реализовать свои вещи.

Что касается вашего кода: я думаю, что ваш собственный прослушиватель должен наследоваться от сгенерированного HelloListener. Вы можете сделать печать там.

Также попробуйте проанализировать неверный ввод, чтобы увидеть, запускается ли парсер вообще. Я не уверен насчет строки с getattr(parser, rule_name)(). Я следовал инструкциям (к сожалению, очень коротким) документации для цели Antlr4 Python: https://theantlrguy.atlassian.net/wiki/display/ANTLR4/Python+Target

Вы также можете найти некоторую документацию о слушателях там. Надеюсь, поможет.

person fabs    schedule 20.05.2015

Этот вопрос кажется старым, но у меня тоже были такие же проблемы, и я узнал, как с этим бороться. При использовании строк в python вы должны использовать функцию antlr4.InputStream как указано здесь

Итак, в конце концов вы можете получить рабочий пример с таким кодом (на основе ответа Алана и пример из 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()
person devopsfun    schedule 22.05.2018

Я создал пример для Python 2 с использованием грамматики Hello.

Вот соответствующий код:

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.

person Alan    schedule 16.03.2016

Документация antlr была обновлена, чтобы задокументировать поддержку целей python 3 и python 4. Примеры из книги antlr, преобразованные в python3, можно найти здесь, их достаточно, чтобы начать работу. .

person Jehandad    schedule 03.10.2017