Why doesn't linking work in my Xtext-based DSL?
The following is the Xtext grammar for my DSL.
Model:
variableTypes=VariableTypes predicateTypes=PredicateTypes variableDeclarations=
VariableDeclarations rules=Rules;
VariableType:
name=ID;
VariableTypes:
'var types' (variableTypes+=VariableType)+;
PredicateTypes:
'predicate types' (predicateTypes+=PredicateType)+;
PredicateType:
name=ID '(' (variableTypes+=[VariableType|ID])+ ')';
VariableDeclarations:
'vars' (variableDeclarations+=VariableDeclaration)+;
VariableDeclaration:
name=ID ':' type=[VariableType|ID];
Rules:
'rules' (rules+=Rule)+;
Rule:
head=Head ':-' body=Body;
Head:
predicate=Predicate;
Body:
(predicates+=Predicate)+;
Predicate:
predicateType=[PredicateType|ID] '(' (terms+=Term)+ ')';
Term:
variable=Variable;
Variable:
variableDeclaration=[VariableDeclaration|ID];
terminal WS:
(' ' | '\t' | '\r' | '\n' | ',')+;
And, the following is a program in the above DSL.
var types
Node
predicate types
Edge(Node, Node)
Path(Node, Node)
vars
x : Node
y : Node
z : Node
rules
Path(x, y) :- Edge(x, y)
Path(x, y) :- Path(x, z) Path(z, y)
The following is my subclass of the generated Switch
class that demonstrates the getPredicateType()
returns null on a Predicate
node.
public class ModelPrinter extends MyDSLSwitch<Object> {
protected Object visitChildren(EObject objec开发者_如何学Got) {
for (EObject eobj : object.eContents()) {
doSwitch(eobj);
}
return object;
}
@Override
public Object casePredicate(Predicate object) {
System.out.println(object.getPredicateType());
return object;
}
@Override
public Object defaultCase(EObject object) {
return visitChildren(object);
}
}
When I used the ModelPrinter
class to traverse the EMF object model corresponding to the above program, I realized that the nodes are not linked together properly. For example, the getPredicateType()
method on a Predicate
node returns null
. Having read the Xtext user's guide, my impression is that the Xtext default linking semantics should work for my DSL. But, for some reason, the AST nodes of my DSL don't get linked together properly. Can anyone help me in diagnosing this problem?
Finally, I figured out the problem. The links were not set properly because I wasn't loading the model properly. I had just used the parser to load the model. So, I didn't get the links. Therefore, I used the following code snippet from Xtext FAQ to load the model correctly. Then, I passed the returned model to my switch class.
// "workspace" is a string that contains the path to the workspace containing the DSL program.
new org.eclipse.emf.mwe.utils.StandaloneSetup().setPlatformUri(workspace);
Injector injector = new MyDslStandaloneSetup().createInjectorAndDoEMFRegistration();
XtextResourceSet resourceSet = injector.getInstance(XtextResourceSet.class);
resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
// "DSLProgram" is a string that contains the path to the file of the DSL program relative to the workspace set above.
Resource resource = resourceSet.getResource(URI.createURI("platform:/resource/" + DSLProgram), true);
Model model = (Model) resource.getContents().get(0);
I have tried it out, but I am not familiar with the Switch, I rather used Xpand/Xtend to access predicateTypes from Predicate and generated their names.
Template.xpt:
«IMPORT myDsl»; «DEFINE main FOR Model-» «FILE "output.txt"-» «FOREACH this.rules.rules.body.last().predicates AS p-» «p.predicateType.name» «ENDFOREACH-» «ENDFILE-» «ENDDEFINE»
and the output.txt:
Path Path
I guess this is the expected behaviour.
精彩评论