2013-03-14 84 views
4

我尝试定义一些XTEXT为specifiying变量按照以下语法XTEXT逗号分隔的变量声明

variables 
    MyVar1 : Bool at 0x020 value=true; 
    MyVar2, MyVar3 : Int at 0x030 value 200; 
end-variables 

因此,每个定义是语法

VarName ["," VarName]* ":" Type ["at" HEX]? ["value" VALUE]? ";" 

所有变量应以他们的参考和访问导致大纲应该是这样的:

variables 
+-MyVar1 : Bool 
+-MyVar2 : Int 
+-MyVar3 : Int 

编辑: 这里要求我的实际语法,这相当于上面的一些语句的语法定义。

Variable: 
    name=ID 
; 
Declaration_Var: 
    'variables' 
    vars+=Declaration_Var_Body+ 
    'end-variables' ';' 
; 
Declaration_Var_Body: 
    varDecl+=Variable(',' varDecl +=Variable)* 
    ':' type=[TR_Any] 
    ('at' address=HEX)? 
; 
TR_Any: 
    ... 
; 
terminal HEX: 
    ... 
; 

有了这个,以下字符

variables 
    Test1, Test2, Test3 : DWORD at 0x20; 
end_var; 

导致的轮廓是这样的顺序:

<unnamed> 
+-- 0x20 
| +-- Test1 
| +-- Test2 
| +-- Test3 

这几乎是与我期望的相反。我所期望的以及我想要在大纲中生成的内容与此类似(数据类型和地址不能在那里显示,但至少它们必须可以作为生成的变量声明类的属性访问)

Test1 
+-- DWORD 
+-- 0x20 
Test2 
+-- DWORD 
+-- 0x20 
Test3 
+-- DWORD 
+-- 0x20 
+0

请问您可以发表您当前的语法并提出具体问题吗? – 2013-03-15 15:24:46

+0

我在那里添加了一些更详细的描述 – abs 2013-03-18 18:07:46

+0

好吧,现在我明白你的问题了。你实际上只是对看起来很漂亮的轮廓感兴趣,或者是以你描述的方式修改内部结构吗? – 2013-03-19 10:44:03

回答

1

查看涵盖您的案例的屏幕录像:http://xtextcasts.org/episodes/18-model-optimization

您需要修改模型和元模型。要修改元模型,您需要定义一个后处理器。以下后处理器将type属性目录添加到Variable类。

有关详细信息,请参阅:http://christiandietrich.wordpress.com/tag/postprocessor/

class MyXtext2EcorePostProcessor implements IXtext2EcorePostProcessor { 
    override process(GeneratedMetamodel metamodel) { 
    metamodel.EPackage.process 
    } 

    def process(EPackage p) { 
    for (clazz : p.EClassifiers.filter(typeof(EClass))) { 
     if (clazz.name == typeof(Variable).simpleName) { 
     val typeAttribute = EcoreFactory::eINSTANCE.createEAttribute 
     typeAttribute.name = "type" 
     typeAttribute.EType = EcorePackage::eINSTANCE.EString 
     clazz.EStructuralFeatures += typeAttribute 
     } 
    } 
    } 
} 

然后,你必须把它绑定扩展Generator这样的:

public class ExtendedGenerator extends Generator { 
    public ExtendedGenerator() { 
    new XtextStandaloneSetup() { 
     @Override 
     public Injector createInjector() { 
     return Guice.createInjector(new XtextRuntimeModule() { 
      @Override 
      public Class<? extends IXtext2EcorePostProcessor> 
           bindIXtext2EcorePostProcessor() { 
      return MyXtext2EcorePostProcessor.class; 
      } 
     }); 
     } 
    }.createInjectorAndDoEMFRegistration(); 
    } 
} 

最后使用新ExtendedGenerator在mwe2的工作流程:

... 
Workflow { 
    ... 
    bean = StandaloneSetup { 
    ... 
    component = postprocessor.ExtendedGenerator { // Set ExtendedGenerator! 
     ... 
    } 
    ... 
    } 
    ... 
} 
... 

然后你必须填写你的新的type属性与数据。您可以执行IDerivedStateComputer界面。

class MyDerivedStateComputer implements IDerivedStateComputer { 

    override discardDerivedState(DerivedStateAwareResource resource) { 
    resource.allContents.filter(typeof(VariableDefinition)).forEach [ 
     type = null 
    ] 
    } 

    override installDerivedState(DerivedStateAwareResource resource, 
           boolean preLinkingPhase) { 
    resource.allContents.filter(typeof(VariableDefinition)).forEach [ 
     type = (eContainer as DefinitionBlock).type 
    ] 
    } 
} 

然后,你必须绑定它像这样(第二和第三结合的方法仅适用于非Xbase的项目需要)

public class MyDslRuntimeModule extends AbstractMyDslRuntimeModule { 
    public Class<? extends IDerivedStateComputer> bindIDerivedStateComputer() { 
    return MyDerivedStateComputer.class; 
    } 

    // Not needed for Xbase-projects 
    @Override 
    public Class<? extends XtextResource> bindXtextResource() { 
    return DerivedStateAwareResource.class; 
    } 

    // Not needed for Xbase-projects 
    public Class<? extends IResourceDescription.Manager> 
         bindIResourceDescriptionManager() { 
    return DerivedStateAwareResourceDescriptionManager.class; 
    } 
} 

你可以再进一步,重组对你的模型飞行以满足您的需求。请在这里发布您的解决方案作为一个单独的答案,以防你走得那么远。

+0

不完全是我在找什么。在您的语法中,可以指定一个变量列表,如 'MyVar1:MyType,MyVar2:MyType,...' 我需要像这样指定它们: 'MyVar1,MyVar2,...:MyType'(请参见语法定义在问题中) – abs 2013-03-18 18:11:24