Какой инструмент лучше всего подойдет для создания естественного DSL на Java?
Вопрос
Пару дней назад прочитал запись в блоге (http://ayende.com/Blog/archive/2008/09/08/Implementing-generic-natural-language-DSL.aspx), где автор обсуждает идею универсального анализатора DSL естественного языка с использованием .NET.
На мой взгляд, блестящая часть его идеи заключается в том, что текст анализируется и сопоставляется с классами, использующими те же имена, что и предложения.
В качестве примера возьмем следующие строки:
Create user user1 with email test@email.com and password test Log user1 in Take user1 to category t-shirts Make user1 add item Flower T-Shirt to cart Take user1 to checkout
Будет преобразовано с использованием коллекции «известных» объектов, которая принимает результат анализа.Вот некоторые примеры объектов (в моем примере используется Java):
public class CreateUser {
private final String user;
private String email;
private String password;
public CreateUser(String user) {
this.user = user;
}
public void withEmail(String email) {
this.email = email;
}
public String andPassword(String password) {
this.password = password;
}
}
Таким образом, при обработке первого предложения класс CreateUser будет совпадать (очевидно, потому что это объединение «создать пользователя»), и, поскольку он принимает параметр в конструкторе, синтаксический анализатор примет «user1» в качестве пользовательского параметра.
После этого анализатор определит, что следующая часть «с электронной почтой» также соответствует имени метода, и, поскольку этот метод принимает параметр, он будет анализировать «test@email.com» как параметр электронной почты.
Я думаю, вы уже поняли идею, да?Одним из вполне понятных применений этого, по крайней мере для меня, было бы позволить тестировщикам приложений создавать «сценарии тестирования» на естественном языке, а затем анализировать предложения в классы, которые используют JUnit для проверки поведения приложения.
Я хотел бы услышать идеи, советы и мнения об инструментах или ресурсах, которые могли бы написать такой парсер с использованием Java.А еще лучше, если бы мы могли избежать использования сложных лексеров или таких фреймворков, как ANTLR, которые, я думаю, могли бы использовать молоток, чтобы убить муху.
Более того, если кто-то собирается начать проект с открытым исходным кодом, мне это определенно будет интересно.
Решение
Учитывая сложность лексического анализа и синтаксического анализа, я не знаю, хочу ли я писать все это вручную. АНТЛР его не так уж и сложно подобрать, и я думаю, что его стоит изучить, исходя из вашей проблемы. Если вы используете грамматику синтаксического анализа для построения и абстрагирования синтаксического дерева из входных данных, затем довольно легко обработать это AST с помощью древовидной грамматики.Древовидная грамматика легко справится с выполнением описанного вами процесса.
Вы найдете ANTLR во многих местах, включая Eclipse, Groovy и Grails для начала. Полный справочник по ANTLR даже позволяет довольно легко освоить базовые знания довольно быстро.
Ранее в этом году у меня был проект, который должен был обрабатывать текст запроса, созданный пользователем.Я начал обрабатывать его вручную, но это быстро стало утомительным.Мне потребовалось пару дней, чтобы набрать скорость ANTLR, и через несколько дней у меня была запущена начальная версия моей грамматики и процессора.Последующие изменения и корректировки требований убили бы любую пользовательскую версию, но потребовали относительно небольших усилий для настройки, как только я запустил и заработал грамматики ANTLR.
Удачи!
Другие советы
Если вы называете это «естественным языком», вы обманываете себя.Это по-прежнему язык программирования, просто пытающийся имитировать естественный язык, и я подозреваю, что он потерпит неудачу, как только вы углубитесь в детали реализации.Чтобы сделать это однозначным, вам придется наложить ограничения на синтаксис, которые запутают пользователей, которые будут думать, что они пишут «по-английски».
Преимущество DSL (или, во всяком случае, должно быть) заключается в том, что он прост и понятен, но при этом является мощным средством решения проблемной области.Имитирование естественного языка является второстепенной задачей и фактически может быть контрпродуктивным для достижения этих основных целей.
Если кто-то слишком глуп или ему не хватает способности к формально строгому мышлению, необходимому для программирования, то язык программирования, имитирующий естественный язык, НЕ превратит его волшебным образом в программиста.
Когда был изобретен COBOL, некоторые всерьез полагали, что через 10 лет спрос на профессиональных программистов будет нулевым, поскольку COBOL был «как английский», и любой, кому требовалось программное обеспечение, мог написать его сам.И мы все знаем, как это работает.
Возможно, вы захотите рассмотреть Xтекст, который внутри использует ANTLR и делает некоторые приятные вещи, такие как автоматическое создание редактора для вашего DSL.
Впервые я услышал о DSL от компании Jetbrains, создателя IntellJ Idea.
У них есть этот инструмент: MPS (система метапрограммирования)
Эта серия блогов, состоящая из нескольких частей, посвященная использованию Antlr, может оказаться полезной в качестве отправной точки.Он использует Antlr 2, поэтому в Antlr 3 некоторые вещи будут отличаться:
http://tech.puredanger.com/2007/01/13/implementing-a-scripting-language-with-antlr-part-1-lexer/
Презентации/статьи Марка Волкмана об Antlr также весьма полезны:
http://www.ociweb.com/mark/programming/ANTLR3.html
Я поддержу предложение о книге Definitive ANTLR, которая тоже превосходна.
«Одним из вполне понятных применений этого, по крайней мере для меня, было бы позволить тестировщикам приложений создавать «сценарии тестирования» на естественном языке, а затем анализировать предложения в классы, которые используют JUnit для проверки поведения приложения»
То, о чем вы здесь говорите, звучит точно так же, как инструмент FitNesse.Точно так, как вы описываете, клиенты пишут «сценарии» приемочных тестов на каком-то языке, который имеет для них смысл, а программисты создают системы, которые позволяют пройти тесты.Даже реализация, о которой вы говорите, во многом аналогична тому, как работает FitNesse: словарь, используемый в сценариях, объединяется для формирования имен функций и т. д., так что платформа FitNesse знает, какую функцию вызывать.
В любом случае, проверьте :)