Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Inheritance in XText
Inheritance in XText [message #1839617] Wed, 24 March 2021 15:26 Go to next message
John Henbergs is currently offline John HenbergsFriend
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 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
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 #1839697 is a reply to message #1839620] Thu, 25 March 2021 22:23 Go to previous messageGo to next message
Alfredo Aldundi is currently offline Alfredo AldundiFriend
Messages: 38
Registered: July 2009
Member
You can implement this logic inside the YourLangScopeProvider.

override getScope(EObject context, EReference reference) {
    if (reference === YourLangPackage.Literals....) {
        val forest = context as InheritForests
        return Scopes.scopeFor(...); // get the trees from inherited forest
    }
    ...
}
Re: Inheritance in XText [message #1839699 is a reply to message #1839697] Thu, 25 March 2021 23:50 Go to previous messageGo to next message
John Henbergs is currently offline John HenbergsFriend
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 #1839718 is a reply to message #1839699] Fri, 26 March 2021 11:55 Go to previous messageGo to next message
Alfredo Aldundi is currently offline Alfredo AldundiFriend
Messages: 38
Registered: July 2009
Member
Xtext knows nothing about the desired semantics of your model. You have to implement that all yourself. So the example scope provider below just gives you candidates for the superElement reference. In case you map this to Java check out the model inferrer.

regarding your second question: check the src-gen folder of the project that contains the .xtext file. My guess would by MyScopingDslPackage.
Re: Inheritance in XText [message #1839764 is a reply to message #1839718] Sat, 27 March 2021 22:10 Go to previous message
John Henbergs is currently offline John HenbergsFriend
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!
Previous Topic:Xtend replacement for DSL creation?
Next Topic:Xbase customization - Problem introducing support for IN construct in my language
Goto Forum:
  


Current Time: Fri Apr 19 09:43:26 GMT 2024

Powered by FUDForum. Page generated in 0.03242 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top