xtext逗号分隔变量声明

时间:2013-03-14 20:03:26

标签: list variables definition xtext

我尝试根据以下语法

定义一些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

1 个答案:

答案 0 :(得分:2)

请在此处查看有关您案例的截屏视频: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();
  }
}

最后在你的mwe2-workflow中使用新的ExtendedGenerator

... 
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;
  }
}

您可以更进一步,动态重组您的模型,以满足您的需求。如果您走得那么远,请在此处将您的解决方案作为单独的答案发布。