简体   繁体   English

从Java模型使用XText生成DSL文件

[英]Generate DSL file with XText from Java model

I have recently started working with XText. 我最近开始使用XText。 So far I have been able to define a simple grammar, complete the JvmModelInferrer and generate the corresponding java classes and .java files. 到目前为止,我已经能够定义一个简单的语法,完成JvmModelInferrer并生成相应的java类和.java文件。

Is it possible to generate automatically the DSL file (taking into account its grammar) from a set of custom Java classes? 是否可以从一组自定义Java类自动生成DSL文件(考虑其语法)?

Let me provide a simple example. 让我提供一个简单的例子。

I have the following grammar: 我有以下语法:

MODEL:
    entities+=ENTITY*
;

ENTITY:
    'entity' name=ValidID 'as'
        (elements+=PROPERTY)*
    'end'
;

PROPERTY:
    (many?='many')? 'property' name=ID 'of' type=JvmTypeReference
;

If I have the following sample.myDsl 如果我有以下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

I get the Book.java and the Author.java files. 我得到了Book.java和Author.java文件。 In my project I have a processor that analyzes java files and creates objects from them, so if I run the processor on the previous Book.java and Author.java I would get two instances of a custom Entity java type. 在我的项目中,我有一个处理器来分析java文件并从中创建对象,因此,如果我在先前的Book.java和Author.java上运行该处理器,则会得到两个自定义Entity Java类型的实例。 Each Entity instance would have a set of Property instances. 每个Entity实例将具有一组Property实例。 So, the Java model is very similar to the xtext grammar. 因此,Java模型与xtext语法非常相似。

Is it possible to "feed" these two objects to XText, maybe define an Inferrer to specify the translations, and taking into account the same .xtext grammar file, generate automatically a .myDsl file? 是否可以将这两个对象“馈送”到XText,也许定义一个Inferrer来指定翻译,并考虑相同的.xtext语法文件,自动生成一个.myDsl文件?

with xtext it is ususally no problem to 使用xtext,通常没有问题

  • create the model as ast 创建模型为ast
  • add it to a resource 将其添加到资源
  • save the resource to get it serialized 保存资源以使其序列化

if you use xbase and jvmmodelinferrrer building the ast might be a kind of pain if you reference from a model to a inferred jvm element or try to build xbase expressions as ast here is a simple complex example using the domainmodel example 如果您使用xbase和jvmmodelinferrrer来构建ast,这可能是一种痛苦,如果您从模型中引用到一个推断的jvm元素或尝试以ast形式构建xbase表达式,那么这是使用domainmodel示例的一个简单的复杂示例

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)
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM