Declaring a xtext variable with delimiters

I am trying to define some XText for variable specifications according to the following syntax

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

Therefore, each definition is syntactically

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

All variables should be accessible by their link, and the result in the loop should look something like this:

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

Edit: In accordance with my actual grammar requested here, which is equivalent to the syntax definition, some lines above.

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

In this case, the following sequence of characters

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

leads to the following circuit:

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

which is almost the opposite of what I expected. What I expected and what I want to create in the loop looks like this (the data type and address should not be displayed there, but at least they should be available as properties of the generated class for variable declarations)

 Test1 +-- DWORD +-- 0x20 Test2 +-- DWORD +-- 0x20 Test3 +-- DWORD +-- 0x20 
+4
source share
1 answer

See the screencast covering your case here: http://xtextcasts.org/episodes/18-model-optimization

You need to change the model and metamodel. To change the metamodel, you need to define a post processor. The following postprocessor adds the type attribute directory to the Variable class.

See http://christiandietrich.wordpress.com/tag/postprocessor/ for more details.

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

Then you need to associate it with the Generator extension as follows:

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

And finally, use the new ExtendedGenerator in your mwe2 workflow:

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

Then you should populate your new type attribute with data. You can do this by implementing the IDerivedStateComputer interface.

 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 ] } } 

Then you need to bind it like this (the second and third binding methods are only needed for projects other than 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; } } 

You can go even further and rebuild your model on the fly to suit your needs. Please post your decision here as a separate answer if you go this far.

+1
source

Source: https://habr.com/ru/post/1469351/


All Articles