定义出的语法如下:
datatype String
entity Blog{
title: String
many posts: Post
}
entity HasAuthor{
author: String
}
entity Post extends HasAuthor{
title: String
content: String
many commnets: Comment
}
entity Comment extends HasAuthor{
content: String
}
1、语法中第一个规则通常作为入口或者开始的规则
Domainmodel:
elements += Type*
;
Domainmodel包含任意数量(*)的Type,且该Type会被加到(+=)一个名为elements的特性中去。
2、Type的规则表明Type是规则DataType或者(|)规则Entity。
Type:
DataType | Entity
;
3、规则DataType以关键字“datatype”开始,后面跟着一个标示符,该标示符被解析为规则ID,其中规则ID的定义在语法超集org.eclipse.xtext.common.Terminals中,规则ID是一个单词,即标示符。
DataType:
'datatype' name = ID
;
4、规则Entity也是以一个关键字开头,后面跟着一个名称(name)。
Entity:
'entity' name = ID ('extends' superType = [Entity])? '{'
features += Features*
'}'
;
后面是一个带有括号和可选项(?)的extends从句。因为名为superType的特性采用交叉引用(注意其中的中括弧),不对中括弧中的规则Entity进行解析,而仅仅对标示符进行解析(ID)。在链接过程中才会对Entity进行解析。最后,大括弧中可以由任意数量的Features。
5、Feature规则的定义如下:
Feature:
(many ?= 'many')? name = ID ':' type = [Type]
;
关键字many是用来对域建模DSL中对一个多值特性进行建模,赋值操作(?=)表明特性many的类型为boolean。
改进后语法定义
//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.commom HasAuthor{
title: String
content: String
many comments: Comment
}
entity Comment extend HasAuthor{
content: String
}
}
语法改进
1、由于Domainmodel不但包含类型而且包含包,因此,需要对入口进行修改。此外,需要定义通用的超类型Packages和Types:AbstractElement
Domainmodel:
(elements += AbstractElement)*
;
AbstractElement:
PackagesDeclaration | Type
;
2、PackageDeclaration包含一系列的Imports和AbstractElements,因为Imports可以作为root-Domainmodel,所以讲Import加入到AbstractElement中
PackageDeclaration:
'package' name = QualifiedName '{'
(elements += AbstractElement)*
'}'
;
AbstractElement:
PackageDeclaration | Type | Import
;
QualifiedName:
ID ('.' ID)*
QualifiedName有一点特殊,其不包含任何赋值。因此仅作为数据类型规则,返回一个字符串。因此Package的特性name是String类型
3、使用xtext,可以很方便的定义imports。如果在解析规则中使用ImportedNameSpace,基础结构将会视其为import,甚至支持通配符。
Import:
'import' importNamespace = QualifiedNameWithWildcard
;
QualifiedNameWithWildcard:
QualifiedName '.*'?
;
同QualifiedName类似,QualifiedNameWithWildcard返回一个字符串。
4、最后一步是允许用完整的命名来交叉引用,否则,只有import之后,才能进行引用。
Entity:
'entity' name = ID ('extends' superType = [Entity | QualifiedName])?
'{'
(features += Feature)*
'}'
;
Feature:
(many ?= 'many')? name = ID ':' type = [Type | QualifiedName]
;