我尝试根据以下语法
定义一些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 :(得分: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;
}
}
您可以更进一步,动态重组您的模型,以满足您的需求。如果您走得那么远,请在此处将您的解决方案作为单独的答案发布。