Home » Modeling » TMF (Xtext) » Inheritance in XText
Inheritance in XText [message #1839617] |
Wed, 24 March 2021 15:26 |
John Henbergs Messages: 239 Registered: October 2020 |
Senior Member |
|
|
Hi all,
I am writing a grammar which is as following:
Country:
name=ID "{"
forests=Forests;
Forests:
Forest | InheritForest
;
Forest:
"forest"name=ID
"tree" trees+= Tree ("," trees+= Tree)*
;
InheritForest:
"inherit forest" name=[Forest | QualifiedName]
"remove" [Tree | QualifiedName]
"tree" trees+= Tree ("," trees+= Tree)*
;
Tree:
name=ID
;
_________________________________________________
And this is an example written with this grammar. Notice that these examples are written in three different files, located in the same project.
country C1{
forest F1 {
treeT1, T2, T3;
} }
country C2{
forest F2 {
tree T1, T2, T3;
} }
country C3{
inherit forest F2 {
remove T1;
} }
So I create two countries C1, C2, for each of them I create a forest, and for each forest I create multiple trees.
C3 instead of creating a forest will inherit the forest F2 from C2. The idea is that when you inherit F2 from C2 , now C3 shoud contain a forest F2 (and all its attributes- trees) and remove T1.
However, when I type remove I can write both C1.F1.T1 and C2.F2.T1 even though being that I inherit F2 I want to receive only C2.F2.T1 (or C3.F2.T1, being that I inherit that tree and it should now be part of C3).
What approach is usually suggested for this sort of inheritance based on your experience and could the one I am presenting now be modified to work?
Many thanks,
John
|
|
|
Re: Inheritance in XText [message #1839620 is a reply to message #1839617] |
Wed, 24 March 2021 16:45 |
John Henbergs Messages: 239 Registered: October 2020 |
Senior Member |
|
|
Or another option would be that instead of inheriting the forest, I could inherit the country and have the following example:
countryC1{
forest {
treeT1, T2, T3;
} }
countryC2{
forest {
tree T1, T2, T3;
} }
countryC3 inherits country C1 {
forest {
remove T1;
} }
However, the issue is the same, even though this second example where I inherit the country instead of the forest is much closer to what I want. When I say that C3 inherits from C1, I want the only possible suggestions when I remove a tree to be the ones that are inherited from C1, not also the other ones that are in C2.
I understand that only because I write inherit it doesn't actually inherit all those things, but that is what I would like to do, and I would like to be able to only reference the attributes of the classes from which I am inheriting.
|
|
| |
Re: Inheritance in XText [message #1839699 is a reply to message #1839697] |
Thu, 25 March 2021 23:50 |
John Henbergs Messages: 239 Registered: October 2020 |
Senior Member |
|
|
Hi Alfredo,
Thank you for your answer. I have been reading a bit into this issue and it seems to be the only solution, but there is no concrete example and I am not really an experienced developer, so if you could help me out here I would really appreciate it. From XText guide I got the following example:
grammar org.xtext.example.mydsl.MyScopingDsl with
org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyScopingDsl"
Root:
elements+=Element;
Element:
'element' name=ID ('extends' superElement=[Element])?;
@Override
public IScope getScope(EObject context, EReference reference) {
// We want to define the Scope for the Element's superElement cross-reference
if (context instanceof Element
&& reference == MyDslPackage.Literals.ELEMENT__SUPER_ELEMENT) {
// Collect a list of candidates by going through the model
// EcoreUtil2 provides useful functionality to do that
// For example searching for all elements within the root Object's tree
EObject rootElement = EcoreUtil2.getRootContainer(context);
List<Element> candidates = EcoreUtil2.getAllContentsOfType(rootElement, Element.class);
// Create IEObjectDescriptions and puts them into an IScope instance
return Scopes.scopeFor(candidates);
}
return super.getScope(context, reference);
}
Now my first question is: Would this code work to inherit Elements and everything they may contain or just elements? So if element include other rules, do I have to write code to collect all of them, or only for elements is enough?
For example in my case I have a forest which is made of trees. But what if the forest would be made of trees, animals, and houses? Would I have to write a rule for each of them? If possible can you please provide an example of how that can be achieved cause as I said I am not really a developer.
Second question: When I try this example, it say MyDslPackage cannot be resolved into a variable. What can I do about it? Where to find the exact name, and if this name should work for my grammar too then what could be wrong?
I also retrieved this example from the XText book, but not really sure what approach I should follow.
@Inject extension SmallJavaTypeProvider
def scope_SJMember(SJMemberSelection sel, EReference r) {
var parentScope = IScope::NULLSCOPE val type = sel.receiver.typeFor
if (type == null || type.isPrimitive) return parentScope
for (c : type.classHierarchy.reverseView) {
parentScope = Scopes::scopeFor(c.members, parentScope)
}
Scopes::scopeFor(type.members, parentScope) }
Many thanks!
[Updated on: Fri, 26 March 2021 00:08] Report message to a moderator
|
|
| |
Re: Inheritance in XText [message #1839764 is a reply to message #1839718] |
Sat, 27 March 2021 22:10 |
John Henbergs Messages: 239 Registered: October 2020 |
Senior Member |
|
|
Hi Alfredo,
Thank you for the explanation. As I mentioned earlier, I am not really a developer and not really sure how to implement that. I also haven't been able to find examples that provide this sort of inheritance using the ScopeProvider, so if you know of any good examples, or if you can give me a lead based on this following grammar that would be highly appreciated.
While working on it I saw that for me it is more important to actually inherit countries than forests, so I would like to have the following:
country C1 {
forest F1 {
house H1, H2, H3;
tree T1, T2, T3;
}
}
country C2 inherits country C1 {
Forest F2 {
house H6;
exclude H1; \\this should not be an error because it should be inherited from C1
exclude T2;
}
}
Can you provide an example on how I can achieve exactly this?
I tried to use imports to achieve something similar and I was able to implement it through this tutorial, but this isn't exactly what I want. However I cannot seem to find my way around scoping.
Many thanks!
|
|
|
Goto Forum:
Current Time: Wed Apr 24 21:56:31 GMT 2024
Powered by FUDForum. Page generated in 0.03762 seconds
|