从 Java 模型生成带有 XText 的 DSL 文件
Generate DSL file with XText from Java model
我最近开始使用 XText。
到目前为止,我已经能够定义一个简单的语法,完成 JvmModelInferrer 并生成相应的 java 类 和 .java 文件。
是否可以从一组自定义 Java 类 自动生成 DSL 文件(考虑到它的语法)?
让我举个简单的例子。
我有以下语法:
MODEL:
entities+=ENTITY*
;
ENTITY:
'entity' name=ValidID 'as'
(elements+=PROPERTY)*
'end'
;
PROPERTY:
(many?='many')? 'property' name=ID 'of' type=JvmTypeReference
;
如果我有以下sample.myDsl
entity Book as
property title of String
property numPages of Integer
end
entity Author as
property name of String
property surname of String
end
我得到 Book.java 和 Author.java 文件。在我的项目中,我有一个处理器可以分析 java 文件并从中创建对象,所以如果我 运行 前一个 Book.java 和 Author.java 上的处理器,我会得到两个实例自定义实体 java 类型。每个实体实例都有一组 属性 个实例。因此,Java 模型与 xtext 语法非常相似。
是否可以将这两个对象 "feed" 到 XText,或者定义一个 Inferrer 来指定翻译,并考虑到相同的 .xtext 语法文件,自动生成一个 .myDsl 文件?
使用 xtext 通常没有问题
- 将模型创建为 ast
- 将其添加到资源
- 保存资源以使其序列化
如果你使用 xbase 和 jvmmodelinferrrer 构建 ast 如果你从模型引用到推断的 jvm 元素可能会很痛苦
或者尝试将 xbase 表达式构建为 ast
这是一个使用域模型示例的简单复杂示例
package org.eclipse.xtext.example.domainmodel.tests
import com.google.inject.Injector
import org.eclipse.emf.common.util.URI
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.emf.ecore.resource.ResourceSet
import org.eclipse.xtext.common.types.JvmParameterizedTypeReference
import org.eclipse.xtext.common.types.util.TypeReferences
import org.eclipse.xtext.example.domainmodel.DomainmodelStandaloneSetup
import org.eclipse.xtext.example.domainmodel.domainmodel.DomainmodelFactory
import org.eclipse.xtext.resource.DerivedStateAwareResource
import org.eclipse.xtext.resource.SaveOptions
import org.eclipse.xtext.xbase.jvmmodel.JvmTypeReferenceBuilder
class Main {
var static extension DomainmodelFactory factory = DomainmodelFactory.eINSTANCE
def static void main(String[] args) {
var Injector injector = new DomainmodelStandaloneSetup().createInjectorAndDoEMFRegistration()
val ResourceSet resourceSet = injector.getInstance(ResourceSet)
val Resource r0 = resourceSet.createResource(URI.createURI("base/Base.dmodel"))
val Resource r1 = resourceSet.createResource(URI.createURI("model/Person.dmodel"))
val typeReferenceBuilder = injector.getInstance(JvmTypeReferenceBuilder.Factory).create(resourceSet)
val typeReferences = injector.getInstance(TypeReferences)
val model = createDomainModel
r1.contents += model
val model0 = createDomainModel
r0.contents += model0
// build the ast using xtends with clause
model0 => [
elements += createPackageDeclaration => [
name = "base"
elements += createEntity => [
name = "Base"
features+= createProperty => [
name = "id"
type = typeReferenceBuilder.typeRef("java.lang.String")
println(type)
]
]
]
]
//trigger the inferrer on resource 0
(r0 as DerivedStateAwareResource) => [
fullyInitialized = false
installDerivedState(false)
]
// build the ast of the second resource
model => [
elements += createPackageDeclaration => [
name = "model"
elements += createEntity => [
val base = typeReferences.findDeclaredType("base.Base", resourceSet)
println(base)
superType = typeReferenceBuilder.typeRef(base) as JvmParameterizedTypeReference
println(superType)
name = "Person"
features+= createProperty => [
name = "name"
type = typeReferenceBuilder.typeRef("java.lang.String")
println(type)
]
]
]
]
//save the resources
r0.save(SaveOptions.defaultOptions.toOptionsMap)
r1.save(SaveOptions.defaultOptions.toOptionsMap)
}
}
我最近开始使用 XText。 到目前为止,我已经能够定义一个简单的语法,完成 JvmModelInferrer 并生成相应的 java 类 和 .java 文件。
是否可以从一组自定义 Java 类 自动生成 DSL 文件(考虑到它的语法)?
让我举个简单的例子。
我有以下语法:
MODEL:
entities+=ENTITY*
;
ENTITY:
'entity' name=ValidID 'as'
(elements+=PROPERTY)*
'end'
;
PROPERTY:
(many?='many')? 'property' name=ID 'of' type=JvmTypeReference
;
如果我有以下sample.myDsl
entity Book as
property title of String
property numPages of Integer
end
entity Author as
property name of String
property surname of String
end
我得到 Book.java 和 Author.java 文件。在我的项目中,我有一个处理器可以分析 java 文件并从中创建对象,所以如果我 运行 前一个 Book.java 和 Author.java 上的处理器,我会得到两个实例自定义实体 java 类型。每个实体实例都有一组 属性 个实例。因此,Java 模型与 xtext 语法非常相似。
是否可以将这两个对象 "feed" 到 XText,或者定义一个 Inferrer 来指定翻译,并考虑到相同的 .xtext 语法文件,自动生成一个 .myDsl 文件?
使用 xtext 通常没有问题
- 将模型创建为 ast
- 将其添加到资源
- 保存资源以使其序列化
如果你使用 xbase 和 jvmmodelinferrrer 构建 ast 如果你从模型引用到推断的 jvm 元素可能会很痛苦 或者尝试将 xbase 表达式构建为 ast 这是一个使用域模型示例的简单复杂示例
package org.eclipse.xtext.example.domainmodel.tests
import com.google.inject.Injector
import org.eclipse.emf.common.util.URI
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.emf.ecore.resource.ResourceSet
import org.eclipse.xtext.common.types.JvmParameterizedTypeReference
import org.eclipse.xtext.common.types.util.TypeReferences
import org.eclipse.xtext.example.domainmodel.DomainmodelStandaloneSetup
import org.eclipse.xtext.example.domainmodel.domainmodel.DomainmodelFactory
import org.eclipse.xtext.resource.DerivedStateAwareResource
import org.eclipse.xtext.resource.SaveOptions
import org.eclipse.xtext.xbase.jvmmodel.JvmTypeReferenceBuilder
class Main {
var static extension DomainmodelFactory factory = DomainmodelFactory.eINSTANCE
def static void main(String[] args) {
var Injector injector = new DomainmodelStandaloneSetup().createInjectorAndDoEMFRegistration()
val ResourceSet resourceSet = injector.getInstance(ResourceSet)
val Resource r0 = resourceSet.createResource(URI.createURI("base/Base.dmodel"))
val Resource r1 = resourceSet.createResource(URI.createURI("model/Person.dmodel"))
val typeReferenceBuilder = injector.getInstance(JvmTypeReferenceBuilder.Factory).create(resourceSet)
val typeReferences = injector.getInstance(TypeReferences)
val model = createDomainModel
r1.contents += model
val model0 = createDomainModel
r0.contents += model0
// build the ast using xtends with clause
model0 => [
elements += createPackageDeclaration => [
name = "base"
elements += createEntity => [
name = "Base"
features+= createProperty => [
name = "id"
type = typeReferenceBuilder.typeRef("java.lang.String")
println(type)
]
]
]
]
//trigger the inferrer on resource 0
(r0 as DerivedStateAwareResource) => [
fullyInitialized = false
installDerivedState(false)
]
// build the ast of the second resource
model => [
elements += createPackageDeclaration => [
name = "model"
elements += createEntity => [
val base = typeReferences.findDeclaredType("base.Base", resourceSet)
println(base)
superType = typeReferenceBuilder.typeRef(base) as JvmParameterizedTypeReference
println(superType)
name = "Person"
features+= createProperty => [
name = "name"
type = typeReferenceBuilder.typeRef("java.lang.String")
println(type)
]
]
]
]
//save the resources
r0.save(SaveOptions.defaultOptions.toOptionsMap)
r1.save(SaveOptions.defaultOptions.toOptionsMap)
}
}