Eclipse Xtext Grammar Cross References

When we were discussing Qualified Names on this page we saw that there is a built-in containment relationship between the objects in a model.

However we sometimes need to represent a relationship between objects which is not a containment relationship (so if the object holding the relationship is deleted the object that it is pointing to does not disapear - there is no 'ownership').

relationship

These links are made using some string to represent the object.

In the xtext grammar square brackets represent this type of cross reference, that is a non-containment reference.

Syntax Element Means
[t|n] cross reference to an (already existing) object of type' t' via a name that has the syntax of 'n'

Where:

If the CrossReferenceTerminal is not explicitly included then it will default to ID, that is, [Type] is a shorthand for [Type|ID]

Example

This is taken from 15min tutorial here.

We want one entity to extend another.

entity HasAuthor {
  author: String
}
 
entity Post extends HasAuthor {
  title: String
  content: String
  many comments: Comment
}

This is a non-containment reference, so we use a cross reference in the grammar like this:

Entity :
    'entity' name = ID ('extends' superType = [Entity | QualifiedName])? '{'
    features += Feature*
    '}'
;

Another Example

Here is another example, cut down to its essentials to illustrate some points.

The grammar is shown below:

cross reference
grammar com.euclideanspace.naming.Example with org.eclipse.xtext.common.Terminals

generate example "https://www.euclideanspace.com/naming/Example"

Model: a+=A*;
	
A: 'a' name=ID
  ('{' b+=B* c+=C* '}')?;

B: 'b' name=ID;

C: 'c' name=[B|ID];
When we start this program up in a new instance of eclipse we can see that the cross-link gives an error unless it links to an instance of B within the same A. cross reference
a tom
a dick
a tom2
a dick2 {b harry c tom}
a tom3 {b harry b tom}

This gave the error: Couldn't resolve reference to B 'tom'

If we changed the 4th line to

a dick2 {b harry c harry}

This code also generated runtime error messages, indicating that we need to change some of the code:

!SESSION 2012-11-12 09:14:04.062 -----------------------------------------------
eclipse.buildId=M20120914-1800
java.version=1.7.0_09
java.vendor=Oracle Corporation
BootLoader constants: OS=linux, ARCH=x86_64, WS=gtk, NL=en_GB
Framework arguments:  -product org.eclipse.epp.package.modeling.product
Command-line arguments:  -product org.eclipse.epp.package.modeling.product -data /home/martin/workspace/../runtime-EclipseApplication -dev file:/home/martin/workspace/.metadata/.plugins/org.eclipse.pde.core/Eclipse Application/dev.properties -os linux -ws gtk -arch x86_64 -consoleLog

!ENTRY org.eclipse.jface.text 4 0 2012-11-12 09:14:56.173
!MESSAGE Unexpected runtime error while computing a text hover
!STACK 0
org.eclipse.swt.SWTException: Failed to execute runnable (org.eclipse.xtext.conversion.ValueConverterException: ID 'tom3.harry' contains invalid characters: '.' (0x2e))
	at org.eclipse.swt.SWT.error(SWT.java:4361)
	at org.eclipse.swt.SWT.error(SWT.java:4276)
	at org.eclipse.swt.widgets.Synchronizer.syncExec(Synchronizer.java:196)
	at org.eclipse.ui.internal.UISynchronizer.syncExec(UISynchronizer.java:150)
	at org.eclipse.swt.widgets.Display.syncExec(Display.java:4291)
	at org.eclipse.xtext.ui.editor.hover.AnnotationWithQuickFixesHover.getHoverInfoInternal(AnnotationWithQuickFixesHover.java:692)
	at org.eclipse.xtext.ui.editor.hover.AbstractProblemHover.getHoverInfo2(AbstractProblemHover.java:56)
	at org.eclipse.xtext.ui.editor.hover.AbstractCompositeHover.getHoverInfo2(AbstractCompositeHover.java:90)
	at org.eclipse.jface.text.TextViewerHoverManager$4.run(TextViewerHoverManager.java:166)
Caused by: org.eclipse.xtext.conversion.ValueConverterException: ID 'tom3.harry' contains invalid characters: '.' (0x2e)
	at org.eclipse.xtext.conversion.impl.AbstractIDValueConverter.createTokenContentMismatchException(AbstractIDValueConverter.java:76)
	at org.eclipse.xtext.conversion.impl.AbstractIDValueConverter.createTokenContentMismatchException(AbstractIDValueConverter.java:1)
	at org.eclipse.xtext.conversion.impl.AbstractLexerBasedConverter.assertTokens(AbstractLexerBasedConverter.java:53)
	at org.eclipse.xtext.conversion.impl.AbstractLexerBasedConverter.toString(AbstractLexerBasedConverter.java:44)
	at org.eclipse.xtext.conversion.impl.AbstractDeclarativeValueConverterService.toString(AbstractDeclarativeValueConverterService.java:58)
	at org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider$1.createResolution(DefaultQuickfixProvider.java:160)
	at org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider$1.process(DefaultQuickfixProvider.java:136)
	at org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider$1.process(DefaultQuickfixProvider.java:1)
	at org.eclipse.xtext.util.concurrent.IUnitOfWork$Void.exec(IUnitOfWork.java:36)
	at org.eclipse.xtext.util.concurrent.AbstractReadWriteAcces.readOnly(AbstractReadWriteAcces.java:32)
	at org.eclipse.xtext.ui.editor.model.XtextDocument.readOnly(XtextDocument.java:78)
	at org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider.createLinkingIssueResolutions(DefaultQuickfixProvider.java:97)
	at org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider.getResolutionsForLinkingIssue(DefaultQuickfixProvider.java:88)
	at org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider.getResolutions(DefaultQuickfixProvider.java:202)
	at org.eclipse.xtext.ui.editor.quickfix.AbstractIssueResolutionProviderAdapter.getResolutions(AbstractIssueResolutionProviderAdapter.java:42)
	at org.eclipse.xtext.ui.editor.quickfix.XtextQuickAssistProcessor.createQuickfixes(XtextQuickAssistProcessor.java:122)
	at org.eclipse.xtext.ui.editor.quickfix.XtextQuickAssistProcessor.computeQuickAssistProposals(XtextQuickAssistProcessor.java:98)
	at org.eclipse.xtext.ui.editor.hover.AnnotationWithQuickFixesHover$CompletionProposalRunnable.run(AnnotationWithQuickFixesHover.java:592)
	at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
	at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
	at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3529)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3182)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:1029)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:923)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:86)
	at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:588)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:543)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:124)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:353)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:180)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:601)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:629)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:584)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1438)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1414)

!ENTRY org.eclipse.ui 4 0 2012-11-12 09:14:56.176
!MESSAGE Unhandled event loop exception
!STACK 0
org.eclipse.swt.SWTException: Failed to execute runnable (org.eclipse.xtext.conversion.ValueConverterException: ID 'tom3.harry' contains invalid characters: '.' (0x2e))
	at org.eclipse.swt.SWT.error(SWT.java:4361)
	at org.eclipse.swt.SWT.error(SWT.java:4276)
	at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:138)
	at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3529)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3182)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:1029)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:923)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:86)
	at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:588)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:543)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:124)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:353)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:180)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:601)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:629)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:584)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1438)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1414)
Caused by: org.eclipse.xtext.conversion.ValueConverterException: ID 'tom3.harry' contains invalid characters: '.' (0x2e)
	at org.eclipse.xtext.conversion.impl.AbstractIDValueConverter.createTokenContentMismatchException(AbstractIDValueConverter.java:76)
	at org.eclipse.xtext.conversion.impl.AbstractIDValueConverter.createTokenContentMismatchException(AbstractIDValueConverter.java:1)
	at org.eclipse.xtext.conversion.impl.AbstractLexerBasedConverter.assertTokens(AbstractLexerBasedConverter.java:53)
	at org.eclipse.xtext.conversion.impl.AbstractLexerBasedConverter.toString(AbstractLexerBasedConverter.java:44)
	at org.eclipse.xtext.conversion.impl.AbstractDeclarativeValueConverterService.toString(AbstractDeclarativeValueConverterService.java:58)
	at org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider$1.createResolution(DefaultQuickfixProvider.java:160)
	at org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider$1.process(DefaultQuickfixProvider.java:136)
	at org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider$1.process(DefaultQuickfixProvider.java:1)
	at org.eclipse.xtext.util.concurrent.IUnitOfWork$Void.exec(IUnitOfWork.java:36)
	at org.eclipse.xtext.util.concurrent.AbstractReadWriteAcces.readOnly(AbstractReadWriteAcces.java:32)
	at org.eclipse.xtext.ui.editor.model.XtextDocument.readOnly(XtextDocument.java:78)
	at org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider.createLinkingIssueResolutions(DefaultQuickfixProvider.java:97)
	at org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider.getResolutionsForLinkingIssue(DefaultQuickfixProvider.java:88)
	at org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider.getResolutions(DefaultQuickfixProvider.java:202)
	at org.eclipse.xtext.ui.editor.quickfix.AbstractIssueResolutionProviderAdapter.getResolutions(AbstractIssueResolutionProviderAdapter.java:42)
	at org.eclipse.xtext.ui.editor.quickfix.XtextQuickAssistProcessor.createQuickfixes(XtextQuickAssistProcessor.java:122)
	at org.eclipse.xtext.ui.editor.quickfix.XtextQuickAssistProcessor.computeQuickAssistProposals(XtextQuickAssistProcessor.java:98)
	at org.eclipse.xtext.ui.editor.hover.AnnotationWithQuickFixesHover$CompletionProposalRunnable.run(AnnotationWithQuickFixesHover.java:592)
	at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
	at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
	... 24 more

So to summarise, the checking of cross links depends on the fragments included in the mwe2 file:

Fragments Included Effect on Cross-links
exporting.SimpleNamesFragment Can link to any object of the required type regardless of its position in the structure or how many duplicates.

exporting.QualifiedNamesFragment
with a rule:
QualifiedName: ID ('.' ID)*;
added and replace ID with QualifiedName

Can link only within the same object unless we use dot '.' to specify another object in heiarchy. However duplicate instances can exist within the specified object.

exporting.SimpleNamesFragment
and
composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator
in
validation.JavaValidatorFragment

Can link to any object of the required type regardless of its position in the structure and there can be only one such object in the whole structure.

exporting.QualifiedNamesFragment
with QualifiedName replacing ID
and
composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator
in
validation.JavaValidatorFragment

 

Can link only within the same object unless we use dot '.' to specify another object in heiarchy. No duplicate instances can exist within the specified object.

Further Reading

For more information about naming go on to this page and importing on this page.

This itemis blog has more information about this topic.


metadata block
see also:
Correspondence about this page

This site may have errors. Don't use for critical systems.

Copyright (c) 1998-2023 Martin John Baker - All rights reserved - privacy policy.