现在的位置: 首页 > 综合 > 正文

Xtext——3. 十五分钟入门

2013年11月24日 ⁄ 综合 ⁄ 共 3721字 ⁄ 字号 评论关闭

十五分钟入门

 本章将实现一个小型的特定领域的语言来对实体和属性进行建模,类似于Rails、Grails、或Spring Roo。下面的语法还是很有吸引力的:

datatype String

entity Blog {

    title: String

    many posts: Post

}

entity HasAuthor {

    author: String

}

entity Post extends HasAuthor {

    title: String

    content: String

    many comments: Comment

}

entity Comment extends HasAuthor {

    content: String

}

    通过第1章的介绍安装好Xtext之后,启动Eclipse,创建一个新的工作区。

创建一个新的Xtext项目

    首先需要创建几个Eclipse项目,通过Eclipse向导:

            File->New->Project...->Xtext->Xtext project

    选择一个有意义的项目名称、语言名称,以及文件扩展名。例如:

    Main Project Name: org.example.domainmodel

    Language Name: org.example.domainmodel.Domainmodel

    DSL-File Extension: dmodel

    通过向导完成项目的创建之后,在工作区中可以看到三个新项目,其中:

        org.example.domainmodel包含了语法的定义和所有运行时组建(此法语法分析解析、链接、验证等)

        org.example.domainmodel.tests为单元测试

        org.example.domainmodel.ui是Eclipse编辑器,以及所有其他工作台相关的功能

自己制定语法

    向导会自动在编辑器中打开语法文件Domainmodel.xtext,如下所示,其中含有简单的Hello World语法:

grammar org.example.domainmodel.Domainmodel with

                                      org.eclipse.xtext.common.Terminals

generate domainmodel "http://www.example.org/domainmodel/Domainmodel"


Model:

    greetings+=Greeting*;

    

Greeting:

    'Hello' name=ID '!';

  

  现在,将上边的语法替换为下面我们定义的域建模语言:

grammar org.example.domainmodel.DomainModel with

                                      org.eclipse.xtext.common.Terminals

generate domainmodel "http://www.example.org/domainmodel/Domainmodel"


Domainmodel :

  elements += Type*

;

  

Type:

  DataType | Entity

;

  

DataType:

  'datatype' name = ID

;

 

Entity:

  'entity' name = ID ('extends' superType = [Entity])? '{'

     features += Feature*

  '}'

;

 

Feature:

  many?='many'? name = ID ':' type = [Type]

;

       现在详细看一下不同的语法规则所代表的意思:
 1. 语法中的第一个规则通常作为入口开始的规则。

Domainmodel :

  elements += Type*

;

     上面的意思是,Donmainmodel包含任意数量(*)的Type,且该Type会被加到(+=)一个名为elements的特性中。
2. Type的规则表明Type是规则DataType或(|)规则Entrity

Type:

  DataType | Entity

;

3. 规则DataType以关键字'datatype'开始,后边跟着一个标示符,该标示符被解析为规则ID,其中规则ID的定义在语法超集org.eclipse.xtext.common.Terminals中,规则ID是一个单词,即标示符。可以通过F3定位到ID的定义,通过调用ID返回的值被付给了特性name

DataType:

  'datatype' name = ID

;

4. 规则Entity也是以一个关键字开头,后边跟着一个名称(name)。

Entity :

  'entity' name = ID ('extends' superType = [Entity])? '{'

    features += Feature*

  '}'

;

    然后是一个带有括号和可选项(?)的extends从句。因为名为superType的特性采用交叉引用(注意其中的中括弧),不会中总括弧中的规则Entity的进行解析,而仅仅对标示符进行解析(ID规则)。在链接过程中才会对Entity进行解析。最后,大括弧中可以有任意数量的Features,其采用下面的规则5。

5. 最后一个(并不是不重要),规则Feature的定义如下:

Feature:

  (many ?= 'many')? name = ID ':' type = [Type] 

;

    关键字many用来对域建模DSL中对一个多值特性进行建模,赋值操作符(?=)表明特性many的类型为boolean,目前 已经了解了解析规则中的其他语法元素。
    域建模语法是Xtext的语法语言中最为重要的概念之一,已经了解到,关键字为一个字符串,然后通过简单的等于号(=)进行赋值,通过加等于(+=)进行多值赋值,通过文号等于(?=)进行布尔赋值。此外,了解了如何声明交叉引用,以及不同的赋值(?=表示可选,=任意数目,+=至少一次)。在第7节中会有更为详细的描述。现在来看一下这样的语言描述能做哪些事情。

生成语言

    我们已经定义了语法,现在需要执行代码生成器来生成各种语言组建,在项目中选中文件GenerateDomainmodel.mwe2,点击右键 Run As -> MWE2 Workow,将会触发Xtext语言生成器,会生成解析器和序列化器,以及一些其他基础结构代码。可以在控制台的日志消息中看到相应的过程。

运行生成的IDE插件

    现在,可以对IDE集成进行测试了。如果从Eclipse的菜单中选择Run -> Run Con gurations...,可以创建一个新的Eclipse应用,在左边树状列表中选择节点Eclipse Application并添加一个新的,给一个有意义的名称,然后到右边的Arguments那里配置VM arguments:

-XX:MaxPermSize=128m

-Xmx512m

    需要确保所配置的内存大小足够运行一个新的Eclipse实力。现在可以通过点击Run来创建一个新的进程。

    新启动的Eclipse工作台已经安装了刚才开发的插件。在新的工作太重,创建一个新的项目,例如File -> New ->Project... -> Java Project,然后添加一个新的文件,文件的扩展名为前面步骤中指定的扩展名(*.dmodel ),此时会打开所生成的编辑器,来试一下代码自动完成、语法高亮、语法验证、链接错误、突出显示、引用等功能。

第二次迭代:添加Package和Import

    创建了第一个DSL,在编辑器看一下效果,现在对其进行进一步的改进。域建模语言应支持包(Packages),用来防止命名冲突,这样可以更好的适用于目标环境(Java)。一个Package可能含有Types和其他包。为了能够应用命名,还需要添加import声明。 

    最后,我们想要将前边所使用的模型和新的模型需求放到不同的文件中。

// datatypes.dmodel

datatype String

// commons.dmodel

package my.company.common {

    

    entity HasAuthor {

        author: String

    }

}

// blogs.dmodel

package my.company.blog {

  

    import my.company.common.*

      

    entity Blog {

        title: String

        many posts: Post

    }

    

    entity Post extends my.company.common.HasAuthor {

抱歉!评论已关闭.