ANTLR — это генератор парсеров, который позволяет создавать парсер по описанию грамматики на одном из основных языков программирования. Он сам написан на java и прекрасно работает с Java.
Пошаговое руководство:
1) Поставить Oracle Java JDK и Intellij Idea, (можно пропустить этот шаг, если они уже поставлены), и запустить Intellij Idea
2) File-Setting-Plugins
![](https://habrastorage.org/webt/na/s9/b0/nas9b0lm-x41tb_a1jlc9th6c_s.png)
Bвести в поле поиска ANTLR и поставить плагин ANTLR v4 grammar plugin. Возможно, понадобится дополнительный поиск по всем репозиториям.
![](https://habrastorage.org/webt/ko/rq/xi/korqxiltojjctxglqv1iq-yi14e.png)
3) Для Maven проекта добавить в pom.xml или создать новый проект.
в dependencies
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>4.7</version>
</dependency>
и в plugins
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr4-maven-plugin</artifactId>
<version>4.7</version>
<executions>
<execution>
<goals>
<goal>antlr4</goal>
</goals>
</execution>
</executions>
</plugin>
Подробности https://github.com/antlr/antlr4/blob/master/doc/java-target.md
4) Далее создам и добавляем вручную файл грамматики с расширением .g4. Имя файла должно совпадать с словом после grammar в первой строчке. Составляется она примерно так: берем то, что нужно парсить, и разбиваем на отдельные токены. Для токенов описываем лексемы, например все английские буквы [a-zA-Z];, все числа [0-9] и т.п.. Для примера взято содержимое примера с официального сайта для файла 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
5) Далее правой кнопкой мыши кликнуть по второй строчке файла, которая начинается с r и выбрать пункт меню Test Rule r
![](https://habrastorage.org/webt/yp/qj/on/ypqjonklbrwj-tfharr5bwmi-xk.png)
Внизу откроются окна проверки грамматики. В данном случае, плагин показывает ошибку, скорее всего связанную с тем, что это тестовый пример, однако парсер генерируется. Про это можно почитать здесь https://github.com/antlr/antlr4/issues/118, и пока ее проигнорируем. Но в реальных проектах, надо бы внимательнее обращать внимание на эти ошибки.
![](https://habrastorage.org/webt/2l/od/on/2lodon29ewm7ltdffusn6r-bmra.png)
6) Кликаем по файлу грамматики правой кнопкой мыши, выбираем пункт меню Configute ANTLR Recoqnizer и генерируем парсер
![](https://habrastorage.org/webt/1e/iw/21/1eiw21hcp6yhdtkwshoiwslsgem.png)
После этого появится в правом нижнем углу сообщение об успехе
7) Далее снова кликаем по файлу правой кнопкой мыши и выбираем пункт меню Configute ANTLR,
![](https://habrastorage.org/webt/t_/at/ds/t_atdsvwqjgem5tmnuox8rd_tau.png)
и выходит окно для конфигурирования генерации файлов
![](https://habrastorage.org/webt/ff/x8/6c/ffx86c8hgqqnosaayakerhajfuk.png)
В этом окне вводим данные о папке назначения и языке программирования, в нашем случае Java, нужны ли visitor или listener, а также другую требуемую информацию, и нажимаем кнопку ОК
![](https://habrastorage.org/webt/ih/qi/8j/ihqi8j7nqot3gsenqgleyfoeuem.png)
И ANTLR после этого генерирует файлы для распознавания. Тем не менее, хотя выходной каталог указан, часто создается новая папка gen в корне проекта, причем java не распознает эти файлы.
![](https://habrastorage.org/webt/nd/uh/ri/nduhrijnav_pde3xdchrt89et5e.png)
Для того, чтобы java увидела эти файлы, папку нужно либо пометить правой кнопкой мыши «Mark Directory As» на «Generated Sources Root» на папку gen.
![](https://habrastorage.org/webt/z4/xo/ve/z4xove4my_nigg4_nu-kfjvrgzo.png)
И должно получится так:
![](https://habrastorage.org/webt/7j/0k/ij/7j0kijolfhgymppnj6di4j5fljs.png)
8) ANTLR сгенерировал такие классы:
Класс HelloParser.java — это описание класса парсера, то есть синтаксического анализатора, отвечающего грамматике Hello:
public class HelloParser extends Parser { ... }
Класс HelloLexer.java — это описание класса лексера, или лексического анализатора, отвечающего грамматике HelloInit:
public class HelloLexer extends Lexer { ... }
Hello.tokens, HelloLexer.tokens — это вспомогательные классы, которые содержат информацию о токенах HelloListener.java, HelloBaseListener.java, HelloBaseVisitor, HelloVisitor — это классы, содержащие описания методов, которые позволяют выполнять определенный действия при обходе синтаксического дерева
9) После этого добавим класс HelloWalker (хотя это класс не обязателен, этот код можно изменить и добавить в Main для вывода информации)
public class HelloWalker extends HelloBaseListener {
public void enterR(HelloParser.RContext ctx ) {
System.out.println( "Entering R : " + ctx.ID().getText() );
}
public void exitR(HelloParser.RContext ctx ) {
System.out.println( "Exiting R" );
}
}
10) И, наконец, класс Main — точка входа в программу
public class Main {
public static void main( String[] args) throws Exception
{
HelloLexer lexer = new HelloLexer(CharStreams.fromString("hello world"));
CommonTokenStream tokens = new CommonTokenStream(lexer);
HelloParser parser = new HelloParser(tokens);
ParseTree tree = parser.r();
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk(new HelloWalker(), tree);
}
}
11) Запускаем метод main, и получаем на выходе в консоли успешно отработанный парсинг
Entering R : world
Exiting R
> Код проекта выложен здесь
Комментарии (8)
Hixon10
07.11.2017 21:42Отличное введение в тему — tomassetti.me/antlr-mega-tutorial
Готовые грамматики для много чего — github.com/antlr/grammars-v4
grossws
Если уж используете
antlr4-maven-plugin
и, собственно,maven
, то лучше уж использовать принятые соглашения:*.g4
располагать вsrc/main/antlr4/
, сгенерированные файлы будут лежать вtarget/generated-sources/antlr4/
, которую IDEA автоматически пометит как generated sources root.Также,
ANTLRInputStream
deprecated, так что лучше использоватьCharStreams.from*
(CharStreams.fromString
в данном случае).savimar Автор
В target/generated-sources/antlr4/ Idea не помечает generated sources root, ни автоматически,
ни вручную, вообще их не видит, (да и не должна видеть эти файлы), так что вернула в gen, остальное исправлено
grossws
У меня 2017.2.5 помечает автоматически. Вы уверены, что у вас maven-проект, а не что-нибудь другое, куда
pom.xml
добавился позже? Если не удаётся пометить вручную — идите в youtrack.jetbrains.com, УМВР.С чего вы взяли, что IDEA не должна их видеть я не понял. У меня аналогично видятся файлы в
target/generated-sources/annotations
, сгенерированныеorg.immutables:value
.KvanTTT
Устарел, но при этом не понятно как, например, на новом API просто заюзать регистронезависимый поток? А он много где используется: диалекты SQL, PHP. Автор ANTLR консервативен и без особо охоты мержит риквесты с фичами, однако из-за нововведений с юникодом приходится использовать такие вот deprecated классы.
grossws
А где в antlr4
ANTLRInputStream
даёт поддержку case insensitive? Мне пока не приходилось развлекаться с регистронезависимыми языками. Нельзя ли её сделать на уровне созданияTokenStream
?KvanTTT
Пока что поддерживается в плагине antlr4test-maven-plugin и используется для грамматик в оффициальном репозитории.
Но, возможно, скоро он будет доступен и из коробки: https://github.com/antlr/antlr4/pull/2046
У меня пока что особо не получалось, вот даже вопрос на stackoverflow создавал.
grossws
Понятно. Мне пока не актуально, но спасибо за развёрнутый ответ.