Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Questions about scoping
Questions about scoping [message #987333] Mon, 26 November 2012 08:30 Go to next message
Cedric Moonen is currently offline Cedric Moonen
Messages: 274
Registered: August 2009
Senior Member
Hello,

I'm trying to provide scoping for some references in my model. I have a specific case where providing scoping becomes tricking.

Suppose that we have the following piece of grammar:

Ecu returns Ecu:
	'ecu' name=EString '{'
		'components:' componentRef+=ComponentPrototypeInstRef ("," componentRef+=ComponentPrototypeInstRef)* ';'
    '}';

ComponentPrototypeInstRef returns ComponentPrototypeInstRef:
	(context+=[ComponentPrototype]'.')* target=[ComponentPrototype]	
;


I would like to provide a scoping rule for the 'context' and 'target' references. However, two problems occur:

1) If the user types 'components:' and ask for content assist (Ctrl+space) my scoping rule is not invoked but however, the full list of existing ComponentPrototype is still displayed. I understood that the problem here is that because no instance of a ComponentPrototypeInstRef is created at that time, so my scoping rule cannot be called. However, I don't understand how Xtext is then able to supply the list. How can I override that behavior ?

2) If you look at the ComponentPrototypeInstRef, the 'context' reference is in fact a list of references. This is because a ComponentPrototype can be deeply nested (in the ComponentType, look at the attached picture to understand the domain model). So there, I need to provide scoping for this reference but I need to know which element in the list of 'context' I have to provide scoping for, otherwise I'll end up in a cyclic resolution of lazy links.

I however have one requirement (which is pretty strict): I cannot change the domain model! The Xtext syntax is based on a domain model and not the opposite.

  • Attachment: EMFmodel.PNG
    (Size: 7.09KB, Downloaded 60 times)
Re: Questions about scoping [message #987488 is a reply to message #987333] Mon, 26 November 2012 20:26 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian Dietrich
Messages: 6315
Registered: July 2009
Senior Member
HI,

just 2 short tipps without any further digging

(1) you can use an elements container als scoping context too.
(2) you can try access the node model during scoping to find out what is in the list (i dont know if this actually works in your usecase)

~Christian
Re: Questions about scoping [message #987646 is a reply to message #987488] Tue, 27 November 2012 12:28 Go to previous messageGo to next message
Cedric Moonen is currently offline Cedric Moonen
Messages: 274
Registered: August 2009
Senior Member
Christian, thanks for your reply.

1) That's a good suggestion, I didn't know this was possible. This indeed solves my problem in some other scenarios (more simple)

2) Yes, that's what was I was thinking to do initially. However, there's a 'small' problem, I'll explain on a concrete example. Suppose that the user writes something like "comp1.comp2." and then ask for code assist (Ctrl+space). In that case, my scoping method gets called and I see that I have two elements in my list (which are proxies yet). If I want to get the last element in the list this will trigger the proxy resolution which will finally end up in calling the same scoping method. And there, I again look at the list and see that there are 2 elements in the list and try to resolve the last one. This results in an exception (cyclic resolution of lazy links). This is of course logical.
The problem occurs in other situations too, since the scoping method is called to validate the elements.

I don't really see if there's a solution to this problem (except changing the domain model to have 'recursion' instead of a flat list of elements).
Re: Questions about scoping [message #987791 is a reply to message #987333] Wed, 28 November 2012 08:06 Go to previous messageGo to next message
Karsten Thoms is currently offline Karsten Thoms
Messages: 354
Registered: July 2009
Location: Dortmund
Senior Member

Cedric,

in your example the parser won't create an instance of ComponentPrototypeInstRef after entering "components". Use a create action to enforce this:
ComponentPrototypeInstRef returns ComponentPrototypeInstRef: {ComponentPrototypeInstRef}
	(context+=[ComponentPrototype]'.')* target=[ComponentPrototype]	
;


Before resolving the last one you should determine the previous one as context for your scope. Maybe you could share your ScopeProvider implementation for this part?

Regards,
~Karsten


Need professional support for Xtext, Xpand, EMF?
Go to: http://xtext.itemis.com
Twitter : @kthoms
Blog : www.karsten-thoms.de
Re: Questions about scoping [message #988365 is a reply to message #987791] Thu, 29 November 2012 15:41 Go to previous messageGo to next message
Cedric Moonen is currently offline Cedric Moonen
Messages: 274
Registered: August 2009
Senior Member
Hi Karsten,

Thanks for your answer.

Quote:
in your example the parser won't create an instance of ComponentPrototypeInstRef after entering "components".


I already tried that earlier but it didn't solve my problem. However, the solution proposed by Christian works fine.

Quote:
Before resolving the last one you should determine the previous one as context for your scope. Maybe you could share your ScopeProvider implementation for this part?


Here is my scoping rule method:

	protected IScope scope_ComponentPrototypeInstRef_context(
			ComponentPrototypeInstRef prototypeRef, EReference ref) {
		CompositionComponentType type = null;
		if (prototypeRef.getContext().size() == 0) {
			// Return the scope for all top level components
		} else {
			List<ComponentPrototype> context = prototypeRef.getContext();
			ComponentType compType = context.get(context.size() - 1).getType();
			if (compType instanceof CompositionComponentType) {
				type = (CompositionComponentType) compType;
			}
		}

		if (type != null && type instanceof CompositionComponentType) {
			CompositionComponentType composite = (CompositionComponentType) type;
			return Scopes.scopeFor(composite.getComponent());
		}
		return Scopes.scopeFor(new ArrayList<ComponentPrototype>());
	}


I removed the first part of the if/else, since this is specific to my context (but there's no problem there). The problem occurs because the line

ComponentType compType = context.get(context.size() - 1).getType();


will in fact end up in calling the same method when EMF tries to resolve the proxies in the list. And in the 'recursed' call to the method, the "context" list still contains all components. Which means that I will try once again to resolve the same element which will throw an exception because of cyclic resolution of lazy links.
Re: Questions about scoping [message #1007381 is a reply to message #988365] Tue, 05 February 2013 16:52 Go to previous messageGo to next message
Frank Tagne is currently offline Frank Tagne
Messages: 7
Registered: August 2012
Junior Member
Hello Everybody,

I think got an error similar to this. However, i can not apply your scoping function as answer because the Context returns by the scope is the element container, means here, "Ecu".

Here is my post : http://www.eclipse.org/forums/index.php/t/452495/

There is any idea ?

[Updated on: Tue, 05 February 2013 16:53]

Report message to a moderator

Re: Questions about scoping [message #1067566 is a reply to message #1007381] Tue, 09 July 2013 11:20 Go to previous message
Ian McDevitt is currently offline Ian McDevitt
Messages: 65
Registered: December 2012
Location: Belfast
Member
If you look at other projects where component chaining is done you'll see a specific pattern which creates a simple object when there is no '.' and then wraps that current object in a new object if there is a dot, and repeats the wrapping for more dots.

This example is not tested but should be somehting like this:

ComponentPrototypeInstRef returns ComponentPrototypeInstRef:
{ComponentPrototypeInstRef}
target=[ComponentPrototype]
( {ComponentPrototypeInstRef.context=current} '.' target=[ComponentPrototype] )*
;

So if there is no '.' then you simply have a ComponentPrototypeInstRef with target referencing a ComponentPrototype, and a null context.
And if you add a '.' with another prototype, you get a ComponentPrototypeInstRef with context referencing that 'current' simple ComponentPrototypeInstRef as the head of the chain and a target referencing the ComponentPrototype after the dot.
In the scoping function the elements in scope for the target reference are the elements of the context ComponentPrototypeInstRef.
See xbase modules as an example.
Note that 'context' as a name of a reference is confusing as it may not be the same context object in your scoping function.
Previous Topic:grammar problem (probably scoping)
Next Topic:Ambiguities in xText scoping "Context"
Goto Forum:
  


Current Time: Tue Sep 23 04:22:54 GMT 2014

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

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