Lets say I want to be able to declare a bunch of nodes, possibly with links to previous ones. And then declare paths trough those nodes, following the links. I'd like the DSL to look like this:
node A
node B1 -> A
node B2 -> A
node C1 -> B1
node C2 -> B1
path C2 -> B1 -> A
path B2 -> A
Here is an XText grammar that I'd like to use. Note that I'm placing nodes links in the multi-valued feature nodes
of the path.
Model:(
nodes += Node
| paths += Path
)*
;
Node:
'node' name=ID ('->' from=[Node])? ;
Path:
'path' nodes+=[Node] ('->' nodes+=[Node])* ;
Now, I need to constraint those [Node]
links in the path so that they only follow the declared ones. I guess, I have to do it via scoping -- with something like that:
override getScope(EObject ctx, EReference ref){
if(ref == MyDslPackage.Literals.PATH__NODES ){
if(ctx instanceof Path)
return Scopes::scopeFor(/* Node link, previous to the current one */);
}
return super.getScope(ctx,ref)
}
In order to get to the previous link, I'll need an index of the current one, but I cannot find a way to obtain it. Is there a way to get such an index? Should I do it somehow via accessing ctx.nodes
directly? (It seems to lead to a linking-resolution-cycle-error, but, maybe, I'm doing it properly.)
Edit. Changing the grammar adding {Path.parent=current}
and adding this to scoping does the trick:
return Scopes::scopeFor(#[ctx.parent.node.from])
Instead of parsing it into a list of references you should parse it into distinct Path objects with parent pathes like so:
Path:
'path' node=[Node] ({Path.parent=current} '->' node=[Node])* ;
It makes it easier to work with the individual path elements.