Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 347526

Summary: Allow syntactically identical cross references to objects within disjoint inheritance hierarchies
Product: [Modeling] TMF Reporter: Moritz Eysholdt <moritz.eysholdt>
Component: XtextAssignee: Project Inbox <tmf.xtext-inbox>
Status: CLOSED WONTFIX QA Contact:
Severity: enhancement    
Priority: P3 CC: sebastian.zarnekow, sven.efftinge
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Mac OS X - Carbon (unsup.)   
Whiteboard:

Description Moritz Eysholdt CLA 2011-05-27 17:44:43 EDT
currently, cross references in Xtext can only point to objects that have a common super type. Furthermore, it is currently no possible to have two cross references that are alternative to each other and have the same syntax. This is because the alternative's choice is made during parsing and not during linking.

However, with languages that integrate multiple Ecore models, it is not always desirable to put all objects that are referenceable in one location into the same inheritance. The problem gets worse when predefined Ecore models are used and customizing them is not an option.

Let's discuss what we can do about this; I can currently think of two solutions:



1. solution: allow syntactically ambiguous cross references:
---
Rule: 'myKeyword' (foo=[Foo|ID] | bar=[Bar|ID]);
---

We could identify this pattern during code generation and make sure the the generated antlr grammar is ambiguous free. Whether the foo-reference or the bar-reference gets initialized could be decided during the linking phase.

potential problems:
1. not sure how to create a node model for this case  since the node model needs to be available for resolving links but our current node model doesn't support "undecided" alternatives.
2. This partially circumvents our scoping semantics: currently, scoping defines shadowing of names via a hierarchy of scopes. For this example scoping would need to be invoked twice: once for foo and once for bar. If now a valid Foo and a valid Bar is found, the Linker would have to chose a winner.



2. solution: reference-objects:

---- ECore Model ----
EClass Model { containmentRef Ref myRef; }
EClass Ref {}
EClass FooRef extends Ref { crossRef Foo foo; }
EClass BarRef extends Ref { crossRef Bar bar; }
---------------------

Example grammar, with a made-up syntax:

Model: 'myKeyword' myRef=[(FooRef.foo=Foo|BarRef.bar=Bar)|ID];

Here, scoping is invoked once for foo and once for bar as well. If a Foo is found, an EObject of type FooRef is created, Foo is assigned to FoorRef.foo and FooRef to Model.myRef. Vice versa for Bar.

potential probles:
1. does emf support proxies for containment references?
2. the issue with circumvented scoping semantics exists as well.
3. the issue with the node model doesn't exist since this case is not syntactically ambiguous.


A workaround is of course to give up static typing:

---
Rule: ref=[EObject|ID];
---

I think my favorite is solution 1 since it can be generalized and the pattern of solution 2 can also be implemented with this approach:

---
Rule: 'myKeyword' myRef=(FooRef|BarRef);
FooRef: foo=[Foo|ID];
BarRef: foo=[Bar|ID];
---

This might be valuable for expression grammars to define the PrimaryExpression.
Comment 1 Sebastian Zarnekow CLA 2012-04-03 12:40:45 EDT
I don't see how this can be achieved with reasonable effort. Those who don't like the model that is produced by the parser could always use a derived state computer to enhance the model in order to provide a nicer API.

What do others think?
Comment 2 Sven Efftinge CLA 2012-04-03 14:48:00 EDT
I also don't think we'll ever add this since there are many ways to 'fix' the model in such situations after parsing, and it's a rare case.

@Moritz Close it?
Comment 3 Moritz Eysholdt CLA 2012-04-03 15:02:42 EDT
(In reply to comment #2)
> @Moritz Close it?

yeah, I guess that this is not happening in Xtext 2.x