首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用StringTemplate代码生成器链接Xtext

使用StringTemplate代码生成器链接Xtext
EN

Stack Overflow用户
提问于 2012-06-06 23:30:37
回答 1查看 2.8K关注 0票数 4

在我的当前项目中,我正在尝试将用xtext编写的DSL规范与用StringTemplate编写的代码生成器联系起来。

例如,我的DSL规范的语法如下所示。我通过xText提供的很好的编辑器工具输入此信息。

代码语言:javascript
复制
structs:
    TempStruct
        tempValue : double;
            unitOfMeasurement : String;

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

上述DSL规范的语法如下:

代码语言:javascript
复制
       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.javaField.javaAttribute.javaSensor.java等文件。

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

我的问题是,我如何实例化语义模型(由xText生成),以及我需要做什么才能链接到StringTemplate文件?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-06-07 03:24:48

如果您想在Eclipse中使用StringTemplate生成代码:

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

如果您希望将其作为一个独立的过程来执行,则应该遵循Xtext FAQ中的步骤。它们解释了如何加载EMF资源。之后,您可以执行与基于Eclipse的解决方案基本相同的操作。也就是说,实现IGenerator并将结果传递给IFileSystemAccess。

给你一个简短的例子,这是在几分钟内开始应该做的事情:

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

代码语言:javascript
复制
fragment = generator.GeneratorFragment {
    generateMwe = false
    generateJavaMain = true
}

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

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

代码语言:javascript
复制
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的等价物应该是这样的:

代码语言:javascript
复制
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‘的内容,以反映输入文件的位置和预期的输出路径。

代码语言:javascript
复制
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.");
    }
}

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

代码语言:javascript
复制
Hello Pankesh!

现在您可以运行主类,在Eclipse中快速刷新之后,您可以在我的运行时项目中找到新的'output‘文件夹,其中包含一个文件'Sample.txt':

代码语言:javascript
复制
Generated with StringTemplate, Pankesh!

顺便说一句: Xtext文档包含了一个关于如何使用Xtend生成代码的tutorial -它比StringTemplate更好,因为它与Eclipse和现有的Java实用程序无缝地集成在一起:

代码语言:javascript
复制
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»!
        ''')
    }
}
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10917386

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档