gpt4 book ai didi

java - 将 Xtext 与 StringTemplate 代码生成器链接起来

转载 作者:搜寻专家 更新时间:2023-11-01 01:55:29 25 4
gpt4 key购买 nike

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

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

structs:
TempStruct
tempValue : double;
unitOfMeasurement : String;

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

上述DSL规范的语法如下:

       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.java等文件Sensor.java

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

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

最佳答案

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

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

如果您想将其作为一个独立的过程来执行,您应该按照 Xtext FAQ 中的步骤进行操作.他们解释了如何加载 EMF 资源。之后,您可以执行与基于 Eclipse 的解决方案中几乎相同的操作。即,实现 IGenerator 并将结果传递给 IFileSystemAccess。

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

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

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

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

第二步是实现生成器。以下片段可用于“MyDslGenerator.xtend”类:

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 的等价物是这样的:

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

}

下一步必须更改 stub “Main.java”的内容以反射(reflect)输入文件的位置和预期的输出路径。

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”的内容是

Hello Pankesh!

现在您可以运行主类,在 Eclipse 中快速刷新后,您会在我的运行时项目中找到新的“输出”文件夹和一个文件“Sample.txt”:

Generated with StringTemplate, Pankesh!

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

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»!
''')
}
}

关于java - 将 Xtext 与 StringTemplate 代码生成器链接起来,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10917386/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com