用Java创建自然DSL的最佳工具是什么?

时间:2020-03-06 14:49:50  来源:igfitidea点击:

几天前,我阅读了一个博客条目(http://ayende.com/Blog/archive/2008/09/08/Implementing-generic-natural-language-DSL.aspx),作者在其中讨论了使用.NET的通用自然语言DSL解析器。

在我看来,他的想法最出色的部分是,使用与句子同名的文本来对文本进行解析和匹配。

例如,以下几行:

Create user user1 with email [email protected] 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"作为用户参数。

此后,解析器将确定"带有电子邮件"的下一部分也与方法名称匹配,并且由于该方法带有参数,因此它将" [email protected]"解析为电子邮件参数。

我想我们现在知道了,对不对?至少对我而言,一个非常明确的应用程序是允许应用程序测试人员以自然语言创建"测试脚本",然后将句子解析为使用JUnit检查应用程序行为的类。

我想听听有关可以使用Java编写此类解析器的工具或者资源的想法,技巧和意见。更好的是,如果我们可以避免使用复杂的词法分析器或者诸如ANTLR之类的框架,我认为可能会使用锤子杀死苍蝇。

除此之外,如果有人愿意为此启动一个开源项目,我肯定会感兴趣。

解决方案

考虑到词法分析的复杂性,我不知道是否要手工编写所有代码。 ANTLR并不难,我认为值得根据问题进行研究。如果使用解析语法从输入中构建语法树并从中提取语法树,则使用树语法处理AST相当容易。树语法可以轻松地处理我们描述的过程。

首先,我们会在包括Eclipse,Groovy和Grails在内的许多地方找到ANTLR。权威的ANTLR参考甚至使相当快速地掌握基础知识变得非常简单。

我有一个项目,必须在今年早些时候处理一些用户生成的查询文本。我开始尝试手动处理它,但很快变得不知所措。我花了几天时间来提高ANTLR的速度,并在几天内运行了语法和处理器的初始版本。对需求的后续更改和调整会终止所有自定义版本,但是一旦我启动并运行了ANTLR语法,就不需要花费太多的精力进行调整。

祝你好运!

我们可能要考虑Xtext,它内部使用ANTLR并做了一些不错的事情,例如自动为DSL生成编辑器。

我们可能会发现我使用Antlr做的这个由多个部分组成的博客系列作为起点非常有用。它使用的是Antlr 2,因此与Antlr 3有所不同:

http://tech.puredanger.com/2007/01/13/implementing-a-scripting-language-with-antlr-part-1-lexer/

Mark Volkman在Antlr上的演讲/文章也很有帮助:

http://www.ociweb.com/mark/programming/ANTLR3.html

我将对有关ANTLR权威书的建议进行第二次讨论,该建议也很出色。

我第一次听说DSL是来自IntellJ Idea的创建者Jetbrains。

他们拥有此工具:MPS(元编程系统)

"至少对于我来说,一个非常清楚的应用程序是允许应用程序测试人员以自然语言创建"测试脚本",然后将句子解析为使用JUnit来检查应用程序行为的类"

我们在这里所说的听起来完全像是FitNesse工具。
就像我们所描述的那样,客户使用对他们来说有意义的某种语言编写验收测试"脚本",而程序员则构建了使测试通过的系统。甚至我们讨论的实现也几乎完全符合FitNesse的工作方式,脚本中使用的词汇被串联起来形成函数名称等,以便FitNesse框架知道要调用的函数。

无论如何,请查看:)

如果我们称其为"自然语言",那就是在自欺欺人。它仍然是一种编程语言,只是一种试图模仿自然语言的语言,我怀疑一旦我们了解实现细节,它就会失败。为了明确起见,我们必须对语法施加限制,以使被误认为他们在写"英语"的用户感到困惑。

DSL的优点是(或者应该无论如何应该)是简单明了的,但在问题域方面却很强大。模仿自然语言是次要的问题,实际上可能与这些主要目标适得其反。

如果某人太愚蠢或者缺乏编程所需要的形式上严格的思考能力,那么模仿自然的编程语言就不会神奇地将他们变成程序员。

当COBOL发明时,有些人认真地认为,由于COBOL就像英语一样,十年之内对专业程序员的需求将为零,并且任何需要软件的人都可以自己编写它。我们都知道这是如何解决的。