Ambiguous alternatives [message #802098] |
Sun, 19 February 2012 11:56 |
Uli B Messages: 36 Registered: January 2012 |
Member |
|
|
The following rule Object always takes the first alternative (OK, both start with name=ID), and eventually leads to a "Couldn't resolve reference to ..." error.
Object:
reference=[Assignment] | ((name=ID '=')? value=Expression);
Assignment:
{Object} name=ID '=' value=Expression;
Is there any way to achieve "If the reference can be resolved, take it. Otherwise, take the alternative"?
Best Regards
Uli
[Updated on: Sun, 19 February 2012 12:25] Report message to a moderator
|
|
|
|
Re: Ambiguous alternatives [message #802130 is a reply to message #802117] |
Sun, 19 February 2012 13:07 |
Uli B Messages: 36 Registered: January 2012 |
Member |
|
|
Hi Phil, thanks for your reply. I already tried syntactic predicates. Doesn't help. And I think the parser cannot do anything here (isn't it the linker which finds the reference or not?). So if at all, it must be at a later stage, where this is to be tweaked. But I have no clue. I could at some extra keyword (like a leading '$' for references), but since this is not necessary for later processing, I didn't really want that.
[Updated on: Sun, 19 February 2012 13:08] Report message to a moderator
|
|
|
|
Re: Ambiguous alternatives [message #802485 is a reply to message #802130] |
Mon, 20 February 2012 02:26 |
Henrik Lindberg Messages: 2509 Registered: July 2009 |
Senior Member |
|
|
On 2012-19-02 14:07, Uli B wrote:
> Hi Phil, thanks for your reply. I already tried syntactic predicates.
> Doesn't help. And I think the parser cannot do anything here (isn't it
> the linker which finds the reference or not?). So if at all, it must be
> at a later stage, where this is to be tweaked. But I have no clue. I
> could at some extra keyword (like a leading '$' for references, but
> since this is not necessary for later processing, I didn't really want
> that.
I have implemented a grammar for a language where this type of construct
is common (i.e. it is either a reference or something else - and in my
case is is worse, because what it may link to is determined by context).
In my case, I wrote my own linking.
What you could try is to do the following:
- have one rule that assigns the ID, use a predicate so this is always
choosen, and place it first of the two) as the serializer picks the
first rule if there is an ambiguity.
i.e. something like
MyRule returns MyObj: ((=> someValue = ID)|(someLink = [SomeType|ID])) ;
- Perform the extra linking by implementing your own linker class
derived from LazyLinker - implement the method afterModelLinked. Bind
your linker in the runtime module as a replacement for the currently
used linker.
- In the afterModelLinked method - perform the extra linking step by
iterating the model to find all MyObj instances, and if they have
"someValue" set to an ID that is found in the index, get the reference
and set it as "someLink".
There are a couple of additional responsibilities when it comes to
linking as the environment needs to find information to construct "build
order", and to know changes that may require a rebuild. For the built in
support for links this is done automatically. Using a solution like the
above may be covered by the default implementation. If not, you need to
record names you resolved/could not resolve/ambiguous resolved (so that
if one of those names appear or disappear in the index, you will get a
rebuild/relink). You also need to record the references you are adding.
Finally, all the recorded material is being asked for when the resource
is "described"; this is done in a ResourceDescriptionStrategy - where
you can pick up the recorded information and return it mixed in whit the
default provided information, and in ResourceDescription where the set
of imported names is produced. (If you need any of these things, you can
look at my code in cloudsmith/geppetto at github).
I have not tried the solution I am proposing. My implementation does not
have the reference as a feature; instead I use an adapter to associate
the resulting reference from the custom linking with the object
functioning as a reference.
- You may have to deal with serialization too; if the value is found
both as an ID, and as a reference the serilizer is facing an ambiguity
(the grammar states one or the other). Don't know if it is enough to
make the reference transient (but then it may be skipped by the default
support for references...).
You have to experiment and see what works for you.
One of the Xtext gurus may have some other advice that makes this easier.
As you already pointed out, the easiest solution is to use a syntactic
marker that differentiates between plain ID and a reference (e.g. using
a '$' prefix or similar) - then it all works out of the box.
Regards
- henrik
|
|
|
Re: Ambiguous alternatives [message #807513 is a reply to message #802485] |
Sun, 26 February 2012 16:00 |
Uli B Messages: 36 Registered: January 2012 |
Member |
|
|
Thank you so much Henrik for your detailed comment. For the extra linking, I'm trying to use afterModelLinked. Here is what I have so far:
@Override
protected void afterModelLinked(EObject model, IDiagnosticConsumer diagnosticsConsumer) {
IResourceDescriptions index = resourceDescriptionsProvider.getResourceDescriptions(model.eResource());
IResourceDescription resDesc = index.getResourceDescription(model.eResource().getURI());
if (resDesc != null) {
Iterable<IEObjectDescription> exportedObjects = resDesc.getExportedObjectsByType(MyDslPackage.Literals.OBJECT);
Iterator<EObject> iter = model.eAllContents();
while (iter.hasNext()) {
EObject o = iter.next();
if (o instanceof Object) {
// (name, value): if ("name", "value"): assigned, if (null, "value"): unassigned, (if (null, null): reference, n/a), if (null, "name" (from index)): unresolved
String n = ((Object) o).getName();
String v = ((Object) o).getValue();
Iterator<IEObjectDescription> itex = exportedObjects.iterator();
while (itex.hasNext()) {
IEObjectDescription od = itex.next();
if ((n == null) && (v.equals(od.getName().getLastSegment()))) { // name is null and value is the name of an exported Object
// Found it. But now: How to link o to od?
break;
}
}
}
}
}
}
The code checks for each instance of an "Object" o if it has a value that can be found as a name of an object od in the index. If so, o cross references od. Now, how can I perform the actual link? I had a look at what the LazyLinker does, but that didn't make things clearer to me ...
Any suggestions?
Best Regards
Uli
|
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.04386 seconds