2012-06-06 2 views
4

현재 프로젝트에서 xtext로 작성된 DSL 사양과 StringTemplate로 작성된 코드 생성기를 연결하려고합니다.Xtext와 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 (센서의 인스턴스)을 입력으로 받아 Java 코드를 생성합니다.

제 질문은 (xText로 생성 된) 시맨틱 모델을 어떻게 인스턴스화 할 수 있으며 StringTemplate 파일과 연결하려면 어떻게해야합니까?

답변

7

IFF 당신은 이클립스 내에서 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 Main.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()); 
    } 

} 

가 :

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

자바 상당이 라인을 따라 뭔가 될 것 ' 입력 파일 및 예상 출력 경로

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'의 내용은

Hello Pankesh! 

지금 메인 클래스를 실행할 수 있으며 Eclipse에서 빠른 새로 고침 후, 당신은 하나의 파일 '내 런타임 프로젝트의 새로운'출력 '폴더를 찾을 수있다 의 Sample.txt '

Generated with StringTemplate, Pankesh! 

는 Btw는 다음 Xtext 문서는 Xtend으로 코드를 생성하는 방법에 대한 tutorial 포함 -은 이클립스와 기존의 Java 유틸리티를 매끄럽게 통합되어 있기 때문에 StringTemplate보다 더 좋은 :

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

감사합니다. Sebastian. xtend로 코드 생성기를 작성하고 싶습니다. 그러나 문제는 코드 생성기가 String Template 파일로 작성된다는 것입니다. 조언 해 주셔서 감사합니다. 나는 너의 접근 방식을 시도 할 것이다. 아무 것도 해결되지 않으면 xtext에 대한 편집기 지원을 사용하고 ANTLR 문법을 분석하여 파싱합니다. – Pankesh

+0

세바스찬님께 예를 들어 설명해주십시오. – Pankesh

+0

세 바스 챤님께, "문법 스 니펫이 완료되면 VocSpec 인스턴스 목록에 대한 액세스를 제공하는 getContents를 제공합니다"라는 문장을 친절하게 설명하십시오. 나는 문법 이상의 것을 썼다. 당신은 위의 문법이 인스턴스 생성을 위해 완전하지 않다는 것을 의미합니까? – Pankesh