Skip to main content



      Home
Home » Modeling » TMF (Xtext) » local scope, qualified name and Cyclic resolution of lazy links(How to get the name of a cross-reference)
local scope, qualified name and Cyclic resolution of lazy links [message #707310] Mon, 01 August 2011 09:35 Go to next message
Eclipse UserFriend
Hi all, I am currently building an IDE for ATS (www.ats-lang.org). With your help (http://www.eclipse.org/forums/index.php/t/226107/ http://www.eclipse.org/forums/index.php/t/226022/), I made progress dealing with local scope. Now I got into some problems dealing with both scope and cross-reference. For clarity, I use the following sample grammar for language "Myscope".
=================================================
grammar org.xtext.example.mydsl.MyScope with org.eclipse.xtext.common.Terminals

generate myScope "http://www.xtext.org/example/mydsl/MyScope"

Program:
	body
;

body: {body}
	mdec+=scopedec*
	(mscope+=scope
	| mdef+=def
	)*
;

scopedec:
	'extern' 'scope' ent=ID
;
scope: {scope}'scope' entity=[scopedec | ID] mbody=body 'end';

def: name=ID '=' (mint=INT | mval=[def | ID]);
=================================================
The corresponding source code would be something like this
=================================================
extern scope sz
xx = 3
ze = 4
scope sz  
  xx = 3
  qq = 4  
  rr = xx
  ze = 4
  ff = ze
end
=================================================

I bind my own "MyScopeQualifiedNameProvider" to the runtime. The code goes as follows
=======================================

public class MyScopeQualifiedNameProvider extends
		DefaultDeclarativeQualifiedNameProvider {
	
	@Inject
	private IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();
	
	private int counter = 3;
	private Hashtable<EObject, String> nametable = new Hashtable<EObject, String>();

	public QualifiedName getFullyQualifiedName(final EObject obj) {
		QualifiedName t = super.getFullyQualifiedName(obj);
		if (obj instanceof scope) {
			String name = nametable.get(obj);
			if (name == null) {
				name = ((scope)obj).getEntity().getEnt();
				// name = Integer.toString(counter++);
				System.out.println("====================" + name);
				
				nametable.put(obj, name);
			}
			t=converter.toQualifiedName(name);
		}
		if (t != null) {
			System.out.println("====================" + t.toString());
		}
		return t;
	}

}
=====================================

But when I run the eclipse application, I got the following error
====================
An internal error occurred during: "XtextReconcilerJob".
Cyclic resolution of lazy links : scope.entity->scope.entity
=====================

I guess it has something to do with the cross-reference which I didn't understand very well. In my code, I really want to get the corresponding string of scope. How can I do it? Thanks a lot.
Re: local scope, qualified name and Cyclic resolution of lazy links [message #707327 is a reply to message #707310] Mon, 01 August 2011 10:10 Go to previous messageGo to next message
Eclipse UserFriend
Hi,

the basic problem is that your name calculation requires cross references to be resolved. If I understand you correctly, the solution to your problem should be simply to extract the text of the entity-feature from the node model. Check out available methods in the Node(Model)Utils class for navigating from the semantic model to the parse tree model.

Alex
Re: local scope, qualified name and Cyclic resolution of lazy links [message #707341 is a reply to message #707327] Mon, 01 August 2011 10:22 Go to previous messageGo to next message
Eclipse UserFriend
Thank you very much Alexander.

Let me make it more clear. For the following code, I just want to get the string "bbb" when handle the "scope".
=======================
extern scope aaa
xx = 3
scope bbb
  xx = 3
  rr = xx
end
=======================

I don't want to jump to the actual referred ojbect. Therefore, I think your suggestion is what I need.

[Updated on: Mon, 01 August 2011 10:30] by Moderator

Re: local scope, qualified name and Cyclic resolution of lazy links [message #707383 is a reply to message #707341] Mon, 01 August 2011 11:26 Go to previous messageGo to next message
Eclipse UserFriend
The following is my new "MyScopeQualifiedNameProvider". It works well.
=============================================
package org.xtext.example.mydsl.naming;

import java.util.Collections;
import java.util.Hashtable;

import org.eclipse.xtext.nodemodel.BidiIterator;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.naming.DefaultDeclarativeQualifiedNameProvider;
import org.eclipse.xtext.naming.IQualifiedNameConverter;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.util.IResourceScopeCache;
import org.eclipse.xtext.util.PolymorphicDispatcher;
import org.eclipse.xtext.util.SimpleAttributeResolver;
import org.eclipse.xtext.util.Strings;
import org.eclipse.xtext.util.Tuples;

import org.xtext.example.mydsl.myScope.scope;
import org.xtext.example.mydsl.myScope.scopedec;

import com.google.common.base.Function;
import com.google.inject.Inject;
import com.google.inject.Provider;

public class MyScopeQualifiedNameProvider extends
		DefaultDeclarativeQualifiedNameProvider {

	private PolymorphicDispatcher<QualifiedName> qualifiedName = new PolymorphicDispatcher<QualifiedName>(
			"qualifiedName", 1, 1, Collections.singletonList(this),
			PolymorphicDispatcher.NullErrorHandler.<QualifiedName> get()) {
		@Override
		protected QualifiedName handleNoSuchMethod(Object... params) {
			return null;
		}
	};

	@Inject
	private IQualifiedNameConverter converter = new IQualifiedNameConverter.DefaultImpl();

	@Inject
	private IResourceScopeCache cache = IResourceScopeCache.NullImpl.INSTANCE;

	private Function<EObject, String> resolver = SimpleAttributeResolver
			.newResolver(String.class, "name");

	protected Function<EObject, String> getResolver() {
		return resolver;
	}

	private int counter = 0;
	private Hashtable<EObject, String> nametable = new Hashtable<EObject, String>();

	public QualifiedName getFullyQualifiedName(final EObject obj) {
		return cache.get(Tuples.pair(obj, "fqn"), obj.eResource(),
				new Provider<QualifiedName>() {

					public QualifiedName get() {
						EObject temp = obj;
						String name = null;
						if (temp instanceof scope) {
							name = nametable.get(temp);
							if (name == null) {
								// name = ((scope)temp).getEntity().getEnt();
								ICompositeNode cnode = NodeModelUtils
										.findActualNodeFor(temp);
								BidiIterator<INode> iter = cnode.getChildren()
										.iterator();
								int k = 0;
								while (iter.hasNext()) {
									name = NodeModelUtils.getTokenText(iter
											.next());
//									System.out.println("===================="
//											+ name + "_" + k);
									if (4 == k) {
										break;
									}
									k++;
								}
								nametable.put(temp, name);
							}
						} else if (temp instanceof scopedec) {
							name = ((scopedec) obj).getEnt();
						} else {
							QualifiedName qualifiedNameFromDispatcher = qualifiedName
									.invoke(temp);
							if (qualifiedNameFromDispatcher != null)
								return qualifiedNameFromDispatcher;
							name = getResolver().apply(temp);
							if (Strings.isEmpty(name))
								return null;
						}
						QualifiedName qualifiedNameFromConverter = converter
								.toQualifiedName(name);

						while (temp.eContainer() != null) {
							temp = temp.eContainer();
							QualifiedName parentsQualifiedName = getFullyQualifiedName(temp);
							if (parentsQualifiedName != null) {
								qualifiedNameFromConverter = parentsQualifiedName
										.append(qualifiedNameFromConverter);
								break;
							}
						}
						System.out.println("===================="
						+ qualifiedNameFromConverter.toString());
						return qualifiedNameFromConverter;
					}
				});
	}

}

=======================
The only thing which makes me to feel uncomfortable is the hard coded comparison "if (4 == k)". But in the end, something has to be hard coded.

[Updated on: Mon, 01 August 2011 11:30] by Moderator

Re: local scope, qualified name and Cyclic resolution of lazy links [message #708128 is a reply to message #707383] Tue, 02 August 2011 09:46 Go to previous messageGo to next message
Eclipse UserFriend
Hi,

I think the hard coding should not be necessary. There are at least two alternatives

a) NodeModelUtils has a method findNodesForFeature that you could query with the entity feature of scope (Use DslPackage.Literals to obtain it analogous to the validation api)
b) you could use the grammar access of your language (have it injected) and check if the grammar element you get from INode is the correct one.

Alex
Re: local scope, qualified name and Cyclic resolution of lazy links [message #884688 is a reply to message #708128] Mon, 11 June 2012 11:50 Go to previous message
Eclipse UserFriend
Thank you for pointing to NodeModelUtils.findNodesForFeature here, very useful info. FTR: I've created a new bug report issue 382266 (I can't post links here yet) suggesting this may be added to documentation.
Previous Topic:Xtend 2.3 may has a bug for generic type support
Next Topic:QualifiedNameProvider not working
Goto Forum:
  


Current Time: Wed Jul 23 01:10:06 EDT 2025

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

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

Back to the top