当前位置: 首页 > 工具软件 > Xtext > 使用案例 >

java生成text_java – 使用StringTemplate代码生成器链接Xtext

薄兴昌
2023-12-01

在我当前的项目中,我试图链接用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.java,Field.java,Attribute.java,Sensor.java等文件.

我可以清楚地看到这个语义模型可以与StringTemplate文件链接.

StringTemplate文件获取类的对象.例如,StringTemplate文件将TemperatureSensor(Sensor实例)作为Input并生成Java代码.

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

解决方法:

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

在DSL的运行时项目中找到生成器存根.那里

应该是一个实现IGenerator接口的类.该

方法#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());

}

}

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

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

Hello Pankesh!

现在你可以运行主类了,在Eclipse中快速刷新之后,你会在我的运行时项目中找到一个带有单个文件’Sample.txt’的新’output’文件夹:

Generated with StringTemplate, Pankesh!

顺便说一句:Xtext文档包含一个关于如何使用Xtend生成代码的tutorial – 它比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,stringtemplate,xtext

来源: https://codeday.me/bug/20190613/1233034.html

 类似资料: