Я хотел бы начать работу с ANTLR, но, потратив несколько часов на рассмотрение примеров на сайте antlr.org , я все еще не могу получить четкое представление о грамматике процесса Java.
Есть ли какой-нибудь простой пример, что-то вроде калькулятора четырех операций, реализованного с помощью ANTLR, проходящего через определение синтаксического анализатора и вплоть до исходного кода Java?
Ответы:
Примечание : этот ответ для ANTLR3 ! Если вы ищете пример ANTLR4 , тогда в этом разделе « Вопросы и ответы» показано, как создать простой анализатор выражений и вычислитель с использованием ANTLR4 .
Сначала вы создаете грамматику. Ниже приведена небольшая грамматика, которую вы можете использовать для оценки выражений, построенных с использованием 4 основных математических операторов: +, -, * и /. Вы также можете группировать выражения, используя круглые скобки.
Обратите внимание, что эта грамматика является очень простой: она не обрабатывает унарные операторы (минус в: -1 + 9) или десятичные числа, такие как .99 (без начального числа), чтобы назвать только два недостатка. Это всего лишь пример, который вы можете работать над собой.
Вот содержимое файла грамматики Exp.g :
(Правила парсера начинаются со строчной буквы, а правила лексера начинаются с заглавной буквы)
После создания грамматики вы захотите сгенерировать из нее парсер и лексер. Загрузите ANTLR jar и сохраните его в том же каталоге, что и ваш файл грамматики.
Выполните следующую команду в вашей оболочке / командной строке:
Он не должен выдавать никаких сообщений об ошибках , и теперь должны быть сгенерированы файлы ExpLexer.java , ExpParser.java и Exp.tokens .
Чтобы увидеть, все ли работает правильно, создайте этот тестовый класс:
и скомпилируйте это:
и затем запустите его:
Если все идет хорошо, ничего не выводится на консоль. Это означает, что парсер не нашел никакой ошибки. При изменении
"12*(5-6)"
в"12*(5-6"
и затем перекомпилировать и запустить его, там должно быть напечатано следующее:Хорошо, теперь мы хотим добавить немного кода Java к грамматике, чтобы парсер действительно делал что-то полезное. Добавление кода может быть сделано путем размещения
{
и}
внутри вашей грамматики с некоторым простым Java-кодом внутри.Но сначала: все правила парсера в файле грамматики должны возвращать примитивное двойное значение. Вы можете сделать это, добавив
returns [double value]
после каждого правила:который требует небольшого объяснения: каждое правило должно возвращать двойное значение. Теперь, чтобы «взаимодействовать» с возвращаемым значением
double value
(которое НЕ находится внутри простого блока кода Java{...}
) изнутри блока кода, вам нужно добавить знак доллара передvalue
:Вот грамматика, но теперь с добавленным кодом Java:
и так как наше
eval
правило теперь возвращает double, измените ваш ANTLRDemo.java на это:Снова (заново) сгенерируйте свежий лексер и парсер из вашей грамматики (1), скомпилируйте все классы (2) и запустите ANTLRDemo (3):
и теперь вы увидите результат выражения,
12*(5-6)
напечатанного на вашей консоли!Опять же: это очень краткое объяснение. Я призываю вас просмотреть вики ANTLR и прочитать некоторые учебные пособия и / или поиграть с тем, что я только что опубликовал.
Удачи!
РЕДАКТИРОВАТЬ:
В этом посте показано, как расширить приведенный выше пример, чтобы
Map<String, Double>
можно было предоставить переменную, которая содержит переменные в предоставленном выражении.Чтобы этот код работал с текущей версией Antlr (июнь 2014 г.), мне нужно было внести несколько изменений.
ANTLRStringStream
нужно было статьANTLRInputStream
, возвращаемое значение нужно было изменить сparser.eval()
наparser.eval().value
, и мне нужно было удалитьWS
предложение в конце, потому что значения атрибутов, такие как$channel
, больше не могут появляться в действиях лексера.источник
parser.eval()
? Это не ясно ЗДЕСЬ или на ANTLR3 Wiki!eval
это правило синтаксического анализатора, которое возвращаетdouble
. Таким образом, естьeval()
метод, который вы можете вызвать в экземпляре классаExpParser
, как я продемонстрировал вANTLRDemo.main(...)
. После создания лексера / парсера просто откройте файл,ExpParser.java
и вы увидите, что естьeval()
метод, возвращающий adouble
.Мега-учебник АНТЛР Габриэле Томассетти очень полезен
Здесь есть примеры грамматики, примеры посетителей на разных языках (Java, JavaScript, C # и Python) и многое другое. Настоятельно рекомендуется.
РЕДАКТИРОВАТЬ: другие полезные статьи Габриэле Томассетти на ANTLR
источник
Для Antlr 4 процесс создания кода Java ниже: -
Обновите свое имя фляги в classpath соответственно.
источник
На странице https://github.com/BITPlan/com.bitplan.antlr вы найдете библиотеку Java ANTLR с некоторыми полезными вспомогательными классами и несколькими полными примерами. Он готов к использованию с Maven и, если вам нравятся Eclipse и Maven.
https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/main/antlr4/com/bitplan/exp/Exp.g4
это простой язык выражений, который может делать операции умножения и сложения. https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/test/java/com/bitplan/antlr/TestExpParser.java имеет соответствующие модульные тесты для этого.
https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/main/antlr4/com/bitplan/iri/IRIParser.g4 - это анализатор IRI, который разделен на три части:
https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/test/java/com/bitplan/antlr/TestIRIParser.java имеет для этого модульные тесты.
Лично я нашел это самой сложной частью, чтобы получить право. Смотрите http://wiki.bitplan.com/index.php/ANTLR_maven_plugin
https://github.com/BITPlan/com.bitplan.antlr/tree/master/src/main/antlr4/com/bitplan/expr
содержит еще три примера, которые были созданы для проблемы производительности ANTLR4 в более ранней версии. Тем временем эта проблема была исправлена, как показывает тестовый пример https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/test/java/com/bitplan/antlr/TestIssue994.java .
источник
версия 4.7.1 была немного другой: для импорта:
для основного сегмента - обратите внимание на CharStreams:
источник