Xtext Tip: How to change the default delimiter of your FQNs

In a previous tip I showed how to add FQN support to your Xtext DSL. In this tip, we are going to customize our FQN to have a different separator. The full code for this example can be found here.

The basic block language

I am using the block language of the previous tip, but this time we are using the characters -> as separator

block Block1 {
	
	field field1
	field field2

	block SubBlock {
		field field2
	}
	alias field3 aliases field2

}
block Block2 {
	alias field1 aliases Block1->SubBlock->field2 // this is an FQN with a -> as separator
}

Customize the FQN separator

First we change the grammar. The new grammar looks like this:

grammar com.idiomaticsoft.dsl.block.Block with org.eclipse.xtext.common.Terminals

generate block "http://www.idiomaticsoft.com/dsl/block/Block"

Model:
	blocks+=Block*;

Block:
	'block' name=ID '{' (members+=Member)* '}';

Member:
	Block | Field | Alias;

Field:
	'field' name=ID;

Alias:
	'alias' name=ID 'aliases' alias=[Member|MemberFQN]; 

MemberFQN: // This rule describes the new form of the FQN
	ID ("->" ID)*;

The next step is to customize the delimiter itself. This modification is so common that it is enough to override one method to make it happen. First, we extend the default implementation IQualifiedNameConverter and override the method getDelimiter:

package com.idiomaticsoft.dsl.block.scoping;

import org.eclipse.xtext.naming.IQualifiedNameConverter.DefaultImpl;

public class BlockQualifiedNameConververImpl extends DefaultImpl {
	@Override
	public String getDelimiter() {
		return "->";
	}
}

Second, we create configure Xtext to use this class instead of the default one. This is done in the RuntimeModule:

package com.idiomaticsoft.dsl.block;

import org.eclipse.xtext.naming.IQualifiedNameConverter;

import com.google.inject.Binder;
import com.idiomaticsoft.dsl.block.scoping.BlockQualifiedNameConververImpl;

/**
 * Use this class to register components to be used at runtime / without the
 * Equinox extension registry.
 */
public class BlockRuntimeModule extends AbstractBlockRuntimeModule {

	
	@Override
	public void configure(Binder binder) {
		binder.bind(IQualifiedNameConverter.class).to(BlockQualifiedNameConververImpl.class);
		super.configure(binder);
	}

}

Once we have this, we can enjoy our new delimiter.

comments powered by Disqus