将Xtext与StringTemplate代码生成器链接 [英] Linking Xtext with StringTemplate code generator

查看:202
本文介绍了将Xtext与StringTemplate代码生成器链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我目前的项目中,我试图链接用xtext编写的DSL规范和用StringTemplate编写的代码生成器。

In my current project, I am trying to link the DSL specification written in xtext and code generator written in StringTemplate.

例如,我的DSL规范的语法如下。我通过xText提供的漂亮的编辑工具输入这些信息。

for instance, the syntax of my DSL specification is as follows. I am entering this information through nice editor facilities provided by xText.

structs:
    TempStruct
        tempValue : double;
            unitOfMeasurement : String;

abilities :
    sensors:    
        TemperatureSensor
            generate tempMeasurement : TempStruct;
            attribute responseFormat : String;  

上述DSL规范的语法如下:

The grammar of above mentioned DSL specification is as follows:

       VocSpec:

          'structs' ':'
          (structs += Struct)+

          'abilities' ':'
           ('sensors' ':' (sensors += Sensor)+ )+ 
         ;

      Sensor:
          name = ID
          ((attributes += Attributes ) |
          (sources += Sources))* 
          ;

     Sources:
          'generate' name=ID ':' type = Type ';' 
           ;

     Attributes:
         'attribute' name=ID ':' type = Type ';' 
           ; 

    Struct:
          name = ID
          (fields += Field)+ 
         ;

    Field:
         name=ID ':' type += Type ';' 
        ;

xText生成对应于上述规范的语义模型。在我们的示例中,xText生成语义模型,其中包含 struct.java Field.java ,<$等文件c $ c> Attribute.java , Sensor.java 等。

The xText generates semantic model corresponding to above mentioned Specification. In our example, xText generates Semantic model, which contains files such as struct.java, Field.java, Attribute.java, Sensor.java, etc.

I可以清楚地看到这个语义模型可以与 StringTemplate 文件链接。
StringTemplate 文件获取该类的对象。例如, StringTemplate 文件将 TemperatureSensor (传感器实例)作为输入并生成Java代码。

I can clearly see that this semantic model can be linked with the StringTemplate file. The StringTemplate file takes object of the class. For instance, StringTemplate file takes TemperatureSensor (instance of Sensor) as Input and generate Java code.

我的问题是如何实例化语义模型(由xText生成)以及如何与StringTemplate文件链接?

My question is how can I instantiate the semantic model ( generated by xText ) and What do I need to do to link with StringTemplate files ?

推荐答案

我想用Eclipse中的StringTemplate生成代码:

Iff you want to generate the code with StringTemplate from within Eclipse:

在运行时项目中找到生成器存根你的DSL。
应该是一个实现IGenerator接口的类。将使用资源和IFileSystemAccess的实例调用
方法#doGenerator。资源是EMF概念 - 基本上是对象物理位置的抽象。它提供getContents,反过来它将提供对VocSpec实例列表的访问(如果语法片段完整)。这些实例可以传递给您的字符串模板,它将产生输出。输出应该通过IFileSystemAccess#generateFile写入

Locate the generator stub in the runtime project of your DSL. There should be a class that implements the IGenerator interface. The method #doGenerator will be invoked with a resource and an instance of the IFileSystemAccess. The resource is an EMF concepts - basically an abstraction over the physical location of your objects. It offer getContents which in turn will provide access to a list of instances of VocSpec (if the grammar snippet is complete). These instances can be passed to your string template thing which will produce the output. The output should be written by means of IFileSystemAccess#generateFile

如果你想作为一个独立的进程来做,你应该按照 Xtext FAQ 。他们解释了如何加载EMF资源。之后,您可以像在基于Eclipse的解决方案中那样做。也就是说,实现IGenerator并将结果传递给IFileSystemAccess。

If you want to do that as a standalone process, you should follow the steps in the Xtext FAQ. They explain how to load the EMF resource. Afterwards you can do pretty much the same as in the Eclipse-based solution. That is, implement the IGenerator and pass the result to the IFileSystemAccess.

为了给你一个简短的例子,这是在几分钟内开始的:

To give you a short example, this is what should be done to get started in a few minutes:

首先,您应该在'GenerateMyDsl.mwe2'工作流程文件中启用以下代码段并运行工作流程。

First you should enable the following code snippet in the 'GenerateMyDsl.mwe2' workflow file and run the workflow.

fragment = generator.GeneratorFragment {
    generateMwe = false
    generateJavaMain = true
}

您将在运行时项目的包中找到带有后缀.generator的新工件。即'Main.java'文件。

You'll find a new artifact in the runtime project's package with the suffix .generator. Namely the 'Main.java' file.

第二步是实现生成器。以下代码段可以在'MyDslGenerator.xtend'类中使用:

The second step is to implement the generator. The following snippet can be used in the 'MyDslGenerator.xtend' class:

package org.xtext.example.mydsl.generator

import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.xtext.generator.IGenerator
import org.eclipse.xtext.generator.IFileSystemAccess
import org.antlr.stringtemplate.StringTemplate
import org.antlr.stringtemplate.language.DefaultTemplateLexer
import org.xtext.example.mydsl.myDsl.Model

class MyDslGenerator implements IGenerator {

    override void doGenerate(Resource resource, IFileSystemAccess fsa) {
        val hello = new StringTemplate("Generated with StringTemplate, $greeting.name$!", typeof(DefaultTemplateLexer))
        val model = resource.contents.head as Model
        hello.setAttribute("greeting", model.greetings.head)
        fsa.generateFile("Sample.txt", hello.toString())
    }
}

Java等价物将是这样的:

The Java equivalent would be something along these lines:

package org.xtext.example.mydsl.generator;

import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.language.DefaultTemplateLexer;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtext.generator.IFileSystemAccess;
import org.eclipse.xtext.generator.IGenerator;
import org.xtext.example.mydsl.myDsl.Model;

public class StringTemplateGenerator implements IGenerator {

    public void doGenerate(Resource input, IFileSystemAccess fsa) {
        StringTemplate hello = new StringTemplate("Generated with StringTemplate, $greeting.name$!", DefaultTemplateLexer.class);
        Model model = (Model) input.getContents().get(0);
        hello.setAttribute("greeting", model.getGreetings().get(0));
        fsa.generateFile("Sample.txt", hello.toString());
    }

}

接下来必须更改存根'Main.java'的内容,以反映输入文件的位置和预期的输出路径。

Next up one has to change the content of the stub 'Main.java' to reflect the location of the input file and the expected output path.

package org.xtext.example.mydsl.generator;

import java.util.List;

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.generator.IGenerator;
import org.eclipse.xtext.generator.JavaIoFileSystemAccess;
import org.eclipse.xtext.util.CancelIndicator;
import org.eclipse.xtext.validation.CheckMode;
import org.eclipse.xtext.validation.IResourceValidator;
import org.eclipse.xtext.validation.Issue;

import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Provider;

public class Main {

    public static void main(String[] args) {
        Injector injector = new MyDslStandaloneSetupGenerated().createInjectorAndDoEMFRegistration();
        Main main = injector.getInstance(Main.class);
        main.runGenerator("input/Sample.mydsl");
    }

    @Inject 
    private Provider<ResourceSet> resourceSetProvider;

    @Inject
    private IResourceValidator validator;

    @Inject
    private IGenerator generator;

    @Inject 
    private JavaIoFileSystemAccess fileAccess;

    protected void runGenerator(String string) {
        // load the resource
        ResourceSet set = resourceSetProvider.get();
        Resource resource = set.getResource(URI.createURI(string), true);

        // validate the resource
        List<Issue> list = validator.validate(resource, CheckMode.ALL, CancelIndicator.NullImpl);
        if (!list.isEmpty()) {
            for (Issue issue : list) {
                System.err.println(issue);
            }
            return;
        }

        // configure and start the generator
        fileAccess.setOutputPath("output/");
        generator.doGenerate(resource, fileAccess);

        System.out.println("Code generation finished.");
    }
}

输入文件位于运行时项目中新创建的文件夹'输入'。文件'Sample.mydsl'的内容是

The input file is located in the runtime project in a newly created folder 'input'. The content of the file 'Sample.mydsl' is

Hello Pankesh!

现在你可以运行主类了,在Eclipse中快速刷新之后,你会发现新的'输出'我的运行时项目中的文件夹,包含单个文件'Sample.txt':

Now you can run the main class and after a quick refresh in Eclipse, you find the new 'output' folder in my runtime project with a single file 'Sample.txt':

Generated with StringTemplate, Pankesh!

Btw:Xtext文档包含教程 - 它比StringTemplate好,因为它与Eclipse和现有Java无缝集成实用程序:

Btw: the Xtext documentation contains a tutorial on how to generate code with Xtend - it is nice than StringTemplate because it integrates seemlessly with Eclipse and existing Java utilities:

package org.xtext.example.mydsl.generator

import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.xtext.generator.IFileSystemAccess
import org.eclipse.xtext.generator.IGenerator
import org.xtext.example.mydsl.myDsl.Model

class MyDslGenerator implements IGenerator {

    override void doGenerate(Resource resource, IFileSystemAccess fsa) {
        val model = resource.contents.head as Model
        fsa.generateFile("Sample.txt", '''
            Generated with Xtend, «model.greetings.head»!
        ''')
    }
}

这篇关于将Xtext与StringTemplate代码生成器链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆