#11 Custom Terminals
Aug 29, 2012 |
7 minutes |
Grammar
Lern how to use custom terminals with value converters to improve your DSL-grammar, model, generator and other Xtext components.
- Download:
- source code Project Files in Zip (102 KB)
- mp4 Full Size H.264 Video (18.8 MB)
- m4v Smaller H.264 Video (10.8 MB)
- webm Full Size VP8 Video (11 MB)
- ogv Full Size Theora Video (22.9 MB)
The Xtext grammar syntax (scroll down for custom terminals): http://www.eclipse.org/Xtext/documentation.html#syntax
Common terminals: http://www.eclipse.org/Xtext/documentation.html#_15
Definition of the custom terminal within the DSL-grammar:
xtext
terminal BINARY returns ecore::EInt:
('0' | '1')+ 'b'
;
terminal BINARY returns ecore::EInt: ('0' | '1')+ 'b' ;
Declaration of the user defined IValueConverterService:
MyDslRuntimeModule.java
public class MyDslRuntimeModule extends org.xtext.example.mydsl.AbstractMyDslRuntimeModule {
@Override
public Class<? extends IValueConverterService> bindIValueConverterService() {
return MyTerminalConverters.class;
}
}
public class MyDslRuntimeModule extends org.xtext.example.mydsl.AbstractMyDslRuntimeModule { @Override public Class<? extends IValueConverterService> bindIValueConverterService() { return MyTerminalConverters.class; } }
Implementation of the user defined IValueConverterService:
MyTerminalConverters.java
public class MyTerminalConverters extends DefaultTerminalConverters {
@Inject
private BINARYValueConverter binaryValueConverter;
@ValueConverter(rule = "BINARY")
public IValueConverter<Integer> BINARY() {
return binaryValueConverter;
}
}
public class MyTerminalConverters extends DefaultTerminalConverters { @Inject private BINARYValueConverter binaryValueConverter; @ValueConverter(rule = "BINARY") public IValueConverter<Integer> BINARY() { return binaryValueConverter; } }
Implementation of the binary number <-> integer converter:
BINARYValueConverter.java
public class BINARYValueConverter extends AbstractLexerBasedConverter<Integer> {
@Override
protected String toEscapedString(Integer value) {
return Integer.toBinaryString(value) + "b";
}
@Override
protected void assertValidValue(Integer value) {
super.assertValidValue(value);
if (value < 0)
throw new ValueConverterException(getRuleName() + "-value may not be negative (value: " + value + ").", null, null);
}
public Integer toValue(String string, INode node) {
if (Strings.isEmpty(string))
throw new ValueConverterException("Couldn't convert empty string to an binary value.", node, null);
try {
int intValue = Integer.parseInt(string.substring(0, string.length() - 1), 2);
return Integer.valueOf(intValue);
} catch (NumberFormatException e) {
throw new ValueConverterException("Couldn't convert '" + string + "' to an binary value.", node, e);
}
}
}
public class BINARYValueConverter extends AbstractLexerBasedConverter<Integer> { @Override protected String toEscapedString(Integer value) { return Integer.toBinaryString(value) + "b"; } @Override protected void assertValidValue(Integer value) { super.assertValidValue(value); if (value < 0) throw new ValueConverterException(getRuleName() + "-value may not be negative (value: " + value + ").", null, null); } public Integer toValue(String string, INode node) { if (Strings.isEmpty(string)) throw new ValueConverterException("Couldn't convert empty string to an binary value.", node, null); try { int intValue = Integer.parseInt(string.substring(0, string.length() - 1), 2); return Integer.valueOf(intValue); } catch (NumberFormatException e) { throw new ValueConverterException("Couldn't convert '" + string + "' to an binary value.", node, e); } } }