Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Problems getting ValueConverters to run(ValueConverters will not be called for some reason)
Problems getting ValueConverters to run [message #872538] Wed, 16 May 2012 09:46 Go to next message
Mikael Karpberg is currently offline Mikael KarpbergFriend
Messages: 8
Registered: April 2012
Location: Sweden
Junior Member
Hi!

I can't seem to get my value converters to be called, at all. I have this simple grammar example that should explain (XText 2, sorry about the ...., but I can't post "links" yet):

grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals

generate myDsl ".... MyDsl"

import ".... Ecore" as ecore

TestFile:
    pairs+=Pair*;
	
terminal fragment DIGIT: '0'..'9';
terminal fragment HEX_DIGIT: (DIGIT |'a'..'f'|'A'..'F');
terminal fragment ALPHANUM: ('a'..'z'|'A'..'Z'|'_'|DIGIT);

terminal STRING : '"' ( '\\' ('b'|'t'|'n'|'f'|'r'|'u'|'"'|"'"|'\\') | !('\\'|'"') )* '"';
terminal CHAR_CONST: "'" ( '\\' ('b'|'t'|'n'|'f'|'r'|'u'|'"'|"'"|'\\') | !('\\'|"'") )* "'";

terminal ID : ('a'..'z'|'A'..'Z'|'_') ALPHANUM*;
terminal HEXINT: '0' ('x'|'X') HEX_DIGIT+;
terminal OCTINT: '0' ('0'..'7')+;
terminal DOUBLE returns ecore::EDouble: DECINT (('.' DIGIT*) | (('.' DIGIT*)? ('E'|'e') ('-'|'+')? DECINT));  // Use terminal to avoid 'e' turning into a keyword
terminal DECINT: '0' | ('1'..'9' DIGIT*);

terminal INT returns ecore::EInt: 'this is never used, and just overrides the built in INT';

Pair:
    name=ID '=' value=Value;
    
Value:
	AnyIntegerLiteral | DoubleLiteral | STRING | CHAR_CONST;
    
DoubleLiteral returns ecore::EDouble hidden():
//    DECINT (('.' (DECINT | OCTINT)*) | (('.' (DECINT | OCTINT)*)? ('E'|'e') ('-'|'+')? DECINT));
    DOUBLE;

AnyIntegerLiteral returns ecore::EInt:
    HEXINT | OCTINT | DECINT;



The Runtime module contains:
public class MyDslRuntimeModule extends org.xtext.example.mydsl.AbstractMyDslRuntimeModule {
    @Override
    public Class<? extends IValueConverterService> bindIValueConverterService() {
        return CommonValueConverter.class;
    }
}


And then I have a CommonValueConverter.java with:
package org.xtext.example.mydsl;

import org.eclipse.xtext.common.services.DefaultTerminalConverters;
import org.eclipse.xtext.conversion.IValueConverter;
import org.eclipse.xtext.conversion.ValueConverter;
import org.eclipse.xtext.conversion.ValueConverterException;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.util.Strings;

public class CommonValueConverter extends DefaultTerminalConverters {
    private IValueConverter<Integer> intValueConverter = new IValueConverter<Integer>() {
        @Override
        public Integer toValue(String string, INode node) throws ValueConverterException {
            if (Strings.isEmpty(string)) {
                throw new ValueConverterException("Couldn't convert empty string to int", node, null);
            }
            int radix = 10;
            if (radix < 20)
            	throw new ValueConverterException("uh oh" + string, node, null);
            if (string.startsWith("0x")) {
                radix = 16;
                string = string.substring(2);
            } else if (string.startsWith("0")) {
                radix = 8;
                string = string.substring(1);
            }
            try {
                return Integer.parseInt(string, radix);
            } catch (NumberFormatException e) {
                throw new ValueConverterException("'"+string+"' is not a valid integer", node, e);
            }
        }
        @Override
        public String toString(Integer value) throws ValueConverterException {
            return Integer.toString(value);
        }
    };

    @ValueConverter(rule = "AnyIntegerLiteral")
    public IValueConverter<Integer> AnyIntegerLiteral() {
        return intValueConverter;
    }
}


As you can see, this should always throw an exception at the moment, since I wanted to test that it was called, and see that I got an error message. It's not called. Sad

I can't figure out why it's not called, the documentation is incomplete, and all examples and documentation vary in interfaces and completeness. Nothing I tried worked, though.

Can anyone help me figure this out, please?

Regards,
/Mikael

PS.
This value converter seems unnecessary in this example as it seems to accept hex numbers without problem for some reason, but in the code I cut it from, I just get "For Input: 0x15" errors on hex numbers, so I figured that I needed a value converter. Either way I can't get the value converter called in my big project nor in this example.

Re: Problems getting ValueConverters to run [message #872549 is a reply to message #872538] Wed, 16 May 2012 10:08 Go to previous messageGo to next message
Sebastian Zarnekow is currently offline Sebastian ZarnekowFriend
Messages: 3118
Registered: July 2009
Senior Member
Mikael,

value converters will not be called for rules that are used from within
data types rules. This would make it rather impossible to implement
something a converter for rules like:

Date: INT '/' INT '/' INT;

You have to register your impl for the rule Value, too.

Regards,
Sebastian
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com

Am 16.05.12 11:46, schrieb Mikael Karpberg:
> Hi!
>
> I can't seem to get my value converters to be called, at all. I have
> this simple grammar example that should explain (XText 2, sorry about
> the ...., but I can't post "links" yet):
>
>
> grammar org.xtext.example.mydsl.MyDsl with
> org.eclipse.xtext.common.Terminals
>
> generate myDsl ".... MyDsl"
>
> import ".... Ecore" as ecore
>
> TestFile:
> pairs+=Pair*;
>
> terminal fragment DIGIT: '0'..'9';
> terminal fragment HEX_DIGIT: (DIGIT |'a'..'f'|'A'..'F');
> terminal fragment ALPHANUM: ('a'..'z'|'A'..'Z'|'_'|DIGIT);
>
> terminal STRING : '"' ( '\\' ('b'|'t'|'n'|'f'|'r'|'u'|'"'|"'"|'\\') |
> !('\\'|'"') )* '"';
> terminal CHAR_CONST: "'" ( '\\' ('b'|'t'|'n'|'f'|'r'|'u'|'"'|"'"|'\\') |
> !('\\'|"'") )* "'";
>
> terminal ID : ('a'..'z'|'A'..'Z'|'_') ALPHANUM*;
> terminal HEXINT: '0' ('x'|'X') HEX_DIGIT+;
> terminal OCTINT: '0' ('0'..'7')+;
> terminal DOUBLE returns ecore::EDouble: DECINT (('.' DIGIT*) | (('.'
> DIGIT*)? ('E'|'e') ('-'|'+')? DECINT)); // Use terminal to avoid 'e'
> turning into a keyword
> terminal DECINT: '0' | ('1'..'9' DIGIT*);
>
> terminal INT returns ecore::EInt: 'this is never used, and just
> overrides the built in INT';
>
> Pair:
> name=ID '=' value=Value;
> Value:
> AnyIntegerLiteral | DoubleLiteral | STRING | CHAR_CONST;
> DoubleLiteral returns ecore::EDouble hidden():
> // DECINT (('.' (DECINT | OCTINT)*) | (('.' (DECINT | OCTINT)*)?
> ('E'|'e') ('-'|'+')? DECINT));
> DOUBLE;
>
> AnyIntegerLiteral returns ecore::EInt:
> HEXINT | OCTINT | DECINT;
>
>
>
> The Runtime module contains:
>
> public class MyDslRuntimeModule extends
> org.xtext.example.mydsl.AbstractMyDslRuntimeModule {
> @Override
> public Class<? extends IValueConverterService>
> bindIValueConverterService() {
> return CommonValueConverter.class;
> }
> }
>
>
> And then I have a CommonValueConverter.java with:
>
> package org.xtext.example.mydsl;
>
> import org.eclipse.xtext.common.services.DefaultTerminalConverters;
> import org.eclipse.xtext.conversion.IValueConverter;
> import org.eclipse.xtext.conversion.ValueConverter;
> import org.eclipse.xtext.conversion.ValueConverterException;
> import org.eclipse.xtext.nodemodel.INode;
> import org.eclipse.xtext.util.Strings;
>
> public class CommonValueConverter extends DefaultTerminalConverters {
> private IValueConverter<Integer> intValueConverter = new
> IValueConverter<Integer>() {
> @Override
> public Integer toValue(String string, INode node) throws
> ValueConverterException {
> if (Strings.isEmpty(string)) {
> throw new ValueConverterException("Couldn't convert empty string to
> int", node, null);
> }
> int radix = 10;
> if (radix < 20)
> throw new ValueConverterException("uh oh" + string, node, null);
> if (string.startsWith("0x")) {
> radix = 16;
> string = string.substring(2);
> } else if (string.startsWith("0")) {
> radix = 8;
> string = string.substring(1);
> }
> try {
> return Integer.parseInt(string, radix);
> } catch (NumberFormatException e) {
> throw new ValueConverterException("'"+string+"' is not a valid integer",
> node, e);
> }
> }
> @Override
> public String toString(Integer value) throws ValueConverterException {
> return Integer.toString(value);
> }
> };
>
> @ValueConverter(rule = "AnyIntegerLiteral")
> public IValueConverter<Integer> AnyIntegerLiteral() {
> return intValueConverter;
> }
> }
>
>
> As you can see, this should always throw an exception at the moment,
> since I wanted to test that it was called, and see that I got an error
> message. It's not called. :(
>
> I can't figure out why it's not called, the documentation is incomplete,
> and all examples and documentation vary in interfaces and completeness.
> Nothing I tried worked, though.
>
> Can anyone help me figure this out, please?
>
> Regards,
> /Mikael
>
> PS.
> This value converter seems unnecessary in this example as it seems to
> accept hex numbers without problem for some reason, but in the code I
> cut it from, I just get "For Input: 0x15" errors on hex numbers, so I
> figured that I needed a value converter. Either way I can't get the
> value converter called in my big project nor in this example.
>
>
Re: Problems getting ValueConverters to run [message #874655 is a reply to message #872549] Mon, 21 May 2012 10:19 Go to previous messageGo to next message
Mikael Karpberg is currently offline Mikael KarpbergFriend
Messages: 8
Registered: April 2012
Location: Sweden
Junior Member
Hi Sebastian!

Thanks for your help, but I'm still confused...

Value converters are not run for Terminals, you mean? I can't quite figure
out what you mean. The date example you gave should not make it hard to
implement a value converter for a date, if you put it on your DataType Rule
called "Date"? In my example "AnyIntegerLiteral" is also a DataType Rule, so
that should be fine, I would think? "Value" is a much too varied type for
my value converter to handle.

Any chance of a bit of clarification?

Also, looking at something like this page, it should be possible to have
value converters for Terminals also?

[Can't post URLs yet]
wiki.eclipse.org/Xtext/Documentation/ValueConverter

Regards,
Mikael

Sebastian Zarnekow wrote on Wed, 16 May 2012 12:08
Mikael,

value converters will not be called for rules that are used from within
data types rules. This would make it rather impossible to implement
something a converter for rules like:

Date: INT '/' INT '/' INT;

You have to register your impl for the rule Value, too.

Regards,
Sebastian

Am 16.05.12 11:46, schrieb Mikael Karpberg:
> Hi!
>
> I can't seem to get my value converters to be called, at all. I have
> this simple grammar example that should explain (XText 2, sorry about
> the ...., but I can't post "links" yet):
......
>

Re: Problems getting ValueConverters to run [message #874668 is a reply to message #874655] Mon, 21 May 2012 10:37 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
Hi no Sensation meant they will be called for normal eat tributes
xxx=INT but not for terminals used within data type rules


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Problems getting ValueConverters to run [message #874686 is a reply to message #874668] Mon, 21 May 2012 11:14 Go to previous messageGo to next message
Mikael Karpberg is currently offline Mikael KarpbergFriend
Messages: 8
Registered: April 2012
Location: Sweden
Junior Member
Christian Dietrich wrote on Mon, 21 May 2012 12:37
Hi no Sensation meant they will be called for normal attributes
xxx=INT but not for terminals used within data type rules


Hmm... So that means to get my value converter called, I should change my "Value" rule to something like this?

Value:
i=AnyIntegerLiteral | d=DoubleLiteral | s=STRING | c=CHAR_CONST;

Re: Problems getting ValueConverters to run [message #874694 is a reply to message #874686] Mon, 21 May 2012 11:30 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
Yes Or introduce avalueconverter for value

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Problems getting ValueConverters to run [message #874719 is a reply to message #874694] Mon, 21 May 2012 12:22 Go to previous messageGo to next message
Mikael Karpberg is currently offline Mikael KarpbergFriend
Messages: 8
Registered: April 2012
Location: Sweden
Junior Member
Ok. Thanks!
Re: Problems getting ValueConverters to run [message #889689 is a reply to message #874719] Tue, 19 June 2012 13:34 Go to previous message
Mikael Karpberg is currently offline Mikael KarpbergFriend
Messages: 8
Registered: April 2012
Location: Sweden
Junior Member
Wanted to put a note down on another thing I stumbled on.

The problem i found with both ValueConverters and other things like LabelProvider and OutlineTreeProvider was to a large degree because of my structure. I used a common language and built two languages on top of that, and I had to change the common providers and converters as expected. However, all the languages built on top of that must then inherit from the common instead of from the default to get all the common functionality (and then sometimes extend that a bit).

So, for example... my CommonLabelProvider inherits from DefaultEObjectLabelProvider, as per default:
  public class CommonLabelProvider extends DefaultEObjectLabelProvider {
      @Inject
      public CommonLabelProvider(AdapterFactoryLabelProvider delegate) {
          super(delegate);
      }

      public String image(Variable var) {
          return "Variable.png";
      }
  }

However, my other two languages, X and Y has to inherit from that instead of the default:
  public class XLabelProvider extends CommonLabelProvider {
      @Inject
      public AsmLabelProvider(AdapterFactoryLabelProvider delegate) {
          super(delegate);
      }
  }

and:
  public class YLabelProvider extends CommonLabelProvider {
      @Inject
      public AsmLabelProvider(AdapterFactoryLabelProvider delegate) {
          super(delegate);
      }

      public String image(YSpecial spec) {
          return "Y.png";
      }
  }

It seems obvious in hindsight, but when I first fought with it, it wasn't.

Also, when it comes to images, you have to copy the icons between all language projects, since the path will be different when the inherited method is called as part of an inheriting class.

Previous Topic:Correct scoping for "virtual" references
Next Topic:Strange behavior of the JvmModelInferrer
Goto Forum:
  


Current Time: Thu Apr 25 21:47:57 GMT 2024

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

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

Back to the top