Слушатели и посетители Antlr4 — что реализовать?

Я читаю «Полный справочник Antlr 4» и понимаю, как работают слушатели и посетители. Книга особенно хорошо объясняет, как прослушиватели связаны с парсерами SAX, и делает очевидным, когда методы будут вызываться во время реализации каждого из них. Я также вижу, что прослушиватели неплохо подходят для преобразования ввода в вывод, но я был бы признателен за краткое объяснение/пример того, когда использовать прослушиватель и когда использовать посетителя (или они оба должны использоваться в определенных случаях?).

Мое конкретное намерение состоит в том, чтобы создать интерпретатор (интерпретатор в стиле Cucumber/TinyBasic с некоторыми пользовательскими вызовами), который будет проверять наличие синтаксических ошибок и прекращать выполнение при ошибке из пользовательской функции без восстановления - хотелось бы увидеть полную реализацию такой вещи в antlr - если кто-нибудь знает о нем.

Спасибо заранее за любые советы.


person KevinY    schedule 21.12.2013    source источник
comment
@OP, не могли бы вы опубликовать обновление - что вы на самом деле использовали, и какие выводы. Спасибо   -  person Dinesh    schedule 28.09.2017


Ответы (4)


Если вы планируете напрямую использовать вывод синтаксического анализатора для интерпретации, посетитель — хороший выбор. У вас есть полный контроль над обходом, поэтому в условных выражениях посещается только одна ветвь, циклы можно посещать n раз и так далее.

Если вы переводите ввод на более низкий уровень, например. инструкции виртуальной машины, оба шаблона могут быть полезны.

Вы можете взглянуть на "Шаблоны языковой реализации", которые охватывают основные реализации интерпретатора.

В основном я использую шаблон посетителя, так как он более гибкий.

person FreeJack    schedule 21.12.2013

Вот цитата из книги, которая мне кажется актуальной:

Самая большая разница между механизмами слушателя и посетителя заключается в том, что методы слушателя вызываются предоставленным ANTLR объектом обхода, тогда как методы посетителя должны проходить своих дочерних элементов с явными вызовами посещения. Если вы забудете вызвать visit() для дочерних элементов узла, это означает, что эти поддеревья не будут посещены.

В паттерне посетителя у вас есть возможность направлять обход дерева, в то время как в слушателе вы только реагируете на ходока по дереву.

person Evgeni Petrov    schedule 10.06.2015

Между этими двумя шаблонами есть еще одно важное различие: посетитель использует стек вызовов для управления обходом дерева, тогда как слушатель использует явный стек, выделенный в куче и управляемый обходчиком. . Это означает, что большие входные данные для посетителя могут взорвать стек, в то время как у слушателя не возникнет проблем.

Если ваши входные данные могут быть потенциально неограниченными, или вы можете вызвать своего посетителя очень глубоко в дереве вызовов, вы должны использовать прослушиватель, а не посетитель, или, по крайней мере, проверить, что дерево синтаксического анализа не слишком глубокое. По этой причине методы кодирования некоторых компаний не поощряют или даже прямо запрещают нехвостовую рекурсию.

person Alex Reinking    schedule 09.10.2017

Из книги, стр. 120.

Посетители работают очень хорошо, если нам нужны возвращаемые значения для конкретного приложения, потому что мы можем использовать встроенный механизм возвращаемых значений Java. Если мы предпочитаем не вызывать явно методы посетителя для посещения дочерних элементов, мы можем переключиться на механизм слушателя. К сожалению, это означает отказ от чистоты использования возвращаемых значений метода Java.

Вот почему я использую посетителей.

person p_champ    schedule 29.01.2020