Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » keywords & identifiers
keywords & identifiers [message #684258] Wed, 15 June 2011 09:58 Go to next message
Michael A. is currently offline Michael A.Friend
Messages: 3
Registered: June 2011
Junior Member
Hi,

I guess most of you know this feature - I think it's more of an Antlr issue. But let's get to the point :
My XText-DSL language & editor work fine except that I cannot "reuse" keywords of the language as identifiers. So once I've used an identifier as keyword or enum value in the language definition this very string is not available as identifier to the end user of the language/editor anymore.
Is there some elegant way to overcome this? configuration?


Thanks, Micha


Example:
=============
Grammar:
--------

Model:
elements+=(Rule1 | Rule2)*;

Rule1:
'KeyWord1' name=ID ';';

Rule2:
'KeyWord2' name=ID ';';

Language-Text:
---------------
KeyWord1 nameA; //ok
KeyWord2 nameB; //ok

KeyWord1 Keyword1; //still ok

Keyword1 KeyWord2; // !
Re: keywords & identifiers [message #684272 is a reply to message #684258] Wed, 15 June 2011 10:19 Go to previous messageGo to next message
Alexander Nittka is currently offline Alexander NittkaFriend
Messages: 1193
Registered: July 2009
Senior Member
Hi,

normally you would escape the keyword in your model (^KeyWord2); keywords are keywords for a reason, after all. If not do not want that (which will cause you all kinds of trouble) you introduce a datatype rule for ID and the allowed keywords. Please search this forum and the web for xtext/id/keyord. One possible thread is this one.

Alex


Need training, onsite consulting or any other kind of help for Xtext?
Go visit http://xtext.itemis.com or send a mail to xtext@itemis.de
Re: keywords & identifiers [message #684350 is a reply to message #684272] Wed, 15 June 2011 13:14 Go to previous messageGo to next message
Michael A. is currently offline Michael A.Friend
Messages: 3
Registered: June 2011
Junior Member
Thank's - looks like I'll have to stick with escaping.

Language-Text:
---------------
KeyWord1 nameA; //ok
KeyWord2 nameB; //ok

KeyWord1 ^KeyWord1; // btw there was a typo in my previous example
KeyWord1 ^KeyWord2;


Nevertheless I'm not really happy with this solution as it would require the user to escape quiet often when working with a comprehensive language which again might be implemented quite chatty in order to beeing more readable.

For the sake of curiosity - can anyone explain the technical reason why the parser prioritises my parser rule 'Rule1' containing the disrupting keyword higher than the terminal rule ID which may be expected after the keyword 'Keyword1'?


Micha
Re: keywords & identifiers [message #684358 is a reply to message #684350] Wed, 15 June 2011 13:25 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
Hi,

no the Problem is that the Lexer!!! lexes the keyword 'KeyWord1' and not the terminal ID
=> you have to live with the escaping or as alex suggested introduce a Datatype Rule

IdOrKeyword: ID | 'KeyWord1' | 'KeyWord2';

Rule1:
'KeyWord1' name=IdOrKeyword ';';

Rule2:
'KeyWord2' name=IdOrKeyword ';';

~Christian


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: keywords & identifiers [message #685849 is a reply to message #684358] Mon, 20 June 2011 11:14 Go to previous message
Michael A. is currently offline Michael A.Friend
Messages: 3
Registered: June 2011
Junior Member
Ok, after playing around with it for a while, now I think I've got a solution. It took me some time to get it working and as folks seem to run into this issue frequently - let me add some details to Christians hint.

Yes, we can enable endusers to use terms as identifiers which have already been used as keywords somewhere in our grammar. Therefor it's required to:

1) introduce an own ID-rule which is special to the current language. This datatype rule refers to the original ID rule and recites all keywords of the given language - that's the not-so-fun part.

Grammar
Model:
	elements+=(Rule1 | Rule2 | Rule3)*;
	
MyLangID : ID | 'NamedElement' | 'ReferenceTo' | 'EnumValue' | 'Value1' | 'Value2';
MyLangFQN : MyLangID('.'MyLangID)*;	

Rule1:
	'NamedElement' name=MyLangID';';

Rule2: 
	'ReferenceTo' ref=[Rule1|MyLangFQN] ';';

enum Enum1 : Value1 | Value2 | NamedElement;

Rule3: 
	'EnumValue' value=Enum1 ';';


2) disable keyword-highlighting in the editor for strings that are MyLangIDs. To do so I introduced a simple implementation of ISemanticHighlightingCalculator.
Drop this class in the .ui-package of the ui-project corresponding to you language-project.

package <MyLangPackage>.ui;

<imports ..>

public class MySemanticHighlightingCalculator implements ISemanticHighlightingCalculator {

	@Override
	public void provideHighlightingFor(XtextResource resource,
			IHighlightedPositionAcceptor acceptor) {
		
		if (resource == null) return;

		for(INode node : resource.getParseResult().getRootNode().getAsTreeIterable()) {
			
			EObject nodeGElem = node.getGrammarElement();
						
			if (nodeGElem != null)
				if (nodeGElem instanceof RuleCall) 
					if ( ((RuleCall)nodeGElem).getRule().getName().equals("MyLangID") ) {
						
						acceptor.addPosition(node.getOffset(), node.getLength(),
								DefaultHighlightingConfiguration.DEFAULT_ID);
					}
		} //for nodes
	} //m
	
} //class


Register you highlight-calculator in the UiModule by adding it like this:
public class MyDsl1LangUiModule extends <MyLangPackage>.ui.AbstractMyDsl1LangUiModule {
	
	public MyDsl1LangUiModule(AbstractUIPlugin plugin) {
		super(plugin);
	}
	
	public Class<? extends ISemanticHighlightingCalculator> bindSemanticHighlightingCalculator() {
		return MySemanticHighlightingCalculator.class;
	}
		
} //class


3) reenable escaping for the "new" ID-rule. There is a special value converter for the ID-rule that handles escaping (^Keyword === Keyword). This won't work out of the box for the newly introduced ID-rule. I reenabled it by adding an own value converter that reuses the ID-rule's one. Add this class to your language project.
package <MyLangPackage>;
<imports .. >

public class MySpecialValueConverterService extends DefaultTerminalConverters {
	
	@ValueConverter(rule = "MyLangID")
	public IValueConverter<String> MyLangID() {
		return ID();
	}
} //class


Register your value converter in your LangRuntimeModule like that:
package <MyLangPackage>;

<imports ..>

public class MyDsl1LangRuntimeModule extends <MyLangPackage>.AbstractMyDsl1LangRuntimeModule {
	
	@Override
	public Class<? extends IValueConverterService> bindIValueConverterService() {
	  return MySpecialValueConverterService.class;
	}
} //class


Now this example will work :

Language Text
NamedElement ReferenceTo; // I can "reuse" keywords
NamedElement Value1; // I can "reuse" enum values
     
ReferenceTo ReferenceTo; //works with references 
  
EnumValue Value1;

EnumValue NamedElement; //enum values & keywords won't collide either
      
NamedElement ^Value2;  //escaping still works      
ReferenceTo Value2;


Anything I missed? Further clues&hints?
Previous Topic:How to get textual dsl file from EMF model (XMI)
Next Topic:Inheritance issues in the grammar
Goto Forum:
  


Current Time: Thu Apr 25 14:30:36 GMT 2024

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

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

Back to the top