2

the question is very simple.
How do I implement long, double and float types correctly in my Xtext grammar so I can use them later in my interpreter? the interpreter is an extend class.

EDIT 1

In my code i have something like

IDValue: value=ID;
StringValue: value=STRING;
IntValue : value=INT;

SimpleValue:

     IntValue | StringValue
;

And i would like to have something like

DoubleValue : value=DOUBLE;

In my interpreter I can do

if (p.var0 instanceof StringValue)  : 

I expect to do also

 if (p.var0 instanceof DoubleValue)  : 

EDIT 2

This is the grammar:

Set:
    'SET' '(' attribute=ID ',' value=(AttributeValue ) ')'
;


StringValue: value=STRING;
IntValue : value=INT;
LongValue : value = LONG;
DoubleValue : value=DOUBLE;

SimpleValue:

     IntValue | StringValue | LongValue | DoubleValue
;


Structure: {Structure}
    '{' ID ':' var0=AttributeValue (',' ID ':' var1+=AttributeValue)* '}'
;

Array: {Array}
    '[' var0=AttributeValue(',' var1+=AttributeValue)* ']' 
;

AttributeValue : 
    SimpleValue |
    Structure |
    Array 
;

LONG returns ecore::ELong: INT ("L"|"l");
DOUBLE returns ecore::EDouble : INT'.'INT;

And this is the class in my interpreter where I execute the Set function and must recongnize the type of the variable (it's in Xtend):

def dispatch void exec(Set s) {
    val setAttribute = LocalMapAttribute.get(s.attribute.toString)
    val cosem = LocalMapCosem.get(setAttribute.object)
    val setValue = s.value.getType
    if (setValue instanceof Array) {Jtest.SetFunction(cosem,setAttribute.attribute_name,ArrayToList(setValue),"Array")} 
    else if (setValue instanceof String) {Jtest.SetFunction(cosem,setAttribute.attribute_name,setValue)}
    else if (setValue instanceof Structure) {Jtest.SetFunction(cosem,setAttribute.attribute_name,StructToList(setValue),"Struct")}
    else if (setValue instanceof Long) {println("LONG DETECTED" + setValue)}
    else if (setValue instanceof Double) {println("DOUBLE DETECTED" + setValue)}
    else if (setValue instanceof Integer) {Jtest.SetFunction(cosem,setAttribute.attribute_name,setValue )}
    
} 

To recongnize the type I use these methods:

def dispatch Array  getType (Array array){
//println("SET with Array") 
return array
}
def dispatch getType (SimpleValue simple){
    //println("SET with Simple Value") 
    return getTypeSimple(simple)
}
def dispatch Structure getType (Structure structure){
    //println("SET with Strcutre")
    return structure
}
def dispatch String getTypeSimple (StringValue str){
    //println("SET with Sting")
    return (str.value as String)
}
def dispatch int getTypeSimple (IntValue Int){
    //println("SET with int")
    return (Int.value )
}
def dispatch double getTypeSimple (DoubleValue Int){
    
    println("SET with DoubleValue")
    return (Int.value )
}
def dispatch long getTypeSimple (LongValue Int){
    println("SET with LongValue")
    return (Int.value )
}

The Value Converter:

public class MyDslValueConverters extends DefaultTerminalConverters {

    IValueConverter<Long> longValueConverter = new IValueConverter<Long>() {

        @Override
        public Long toValue(String string, INode node) throws ValueConverterException {
            // TODO make this more robust
            return Long.parseLong(string.substring(0, string.length()-1));
        }

        @Override
        public String toString(Long value) throws ValueConverterException {
            // TODO make this more robust
            return Long.toString(value)+"L";
        }

    };
    
    IValueConverter<Double> DoubleValueConverter = new IValueConverter<Double>() {

        @Override
        public Double toValue(String string, INode node) throws ValueConverterException {
            // TODO make this more robust
            return Double.parseDouble(string);
        }

        @Override
        public String toString(Double value) throws ValueConverterException {
            // TODO make this more robust
            return Double.toString(value);
        }

    };

}
Stefan Zobel
  • 3,182
  • 7
  • 28
  • 38
BR.Hamza
  • 99
  • 14

1 Answers1

2

you can import the ecore metamodel and thus its datatypes using import "http://www.eclipse.org/emf/2002/Ecore" as ecore. Then you can use them as return value in a terminal or datatype rule LONG returns ecore::ELong: INT ("L"|"l");. Finally you have to implement a ValueConverter that does the Convertion from String to Long and Vice Versa

public class MyDslValueConverters extends DefaultTerminalConverters {

    IValueConverter<Long> longValueConverter = new IValueConverter<Long>() {

        @Override
        public Long toValue(String string, INode node) throws ValueConverterException {
            // TODO make this more robust
            return Long.parseLong(string.substring(0, string.length()-1));
        }

        @Override
        public String toString(Long value) throws ValueConverterException {
            // TODO make this more robust
            return Long.toString(value)+"L";
        }

    };

    @ValueConverter(rule = "LONG")
    public IValueConverter<Long> LONG() {
        return longValueConverter;
    }

}

And dont forget the binding

class MyDslRuntimeModule extends AbstractMyDslRuntimeModule {

    override bindIValueConverterService() {
        return MyDslValueConverters
    }

}
Christian Dietrich
  • 11,778
  • 4
  • 24
  • 32
  • I don't generate java code from my xtext file.I'm making an Interpreted Languages. I'm not sure if your solution compatible for me – BR.Hamza Dec 08 '16 at 13:46
  • I pricise in the `pluging.xml` that the runtime lauches the interpreter class. making changes in `MyDslRuntimeModule` wouldn't it affect that ? – BR.Hamza Dec 08 '16 at 14:04
  • I don't get that point. I don't know what you pluging.xml does. If you mean plugin.xml in yourdsl.ui plugin it will be picked – Christian Dietrich Dec 08 '16 at 14:12
  • I'm trying to follow what you said. (it may seems as a stupide question) But how do I use the `public Long toValue(String string, INode node) ` method in my code – BR.Hamza Dec 08 '16 at 14:45
  • you dont. you simply say `long mylong=myObject.getMyLongProperty()` – Christian Dietrich Dec 08 '16 at 14:52
  • wich type is `myObject` ? – BR.Hamza Dec 08 '16 at 15:21
  • in your case it might be `LongValue` – Christian Dietrich Dec 08 '16 at 15:22
  • to add double I tried to do the same thing. but i does some problems in `class MyDslRuntimeModule extends AbstractMyDslRuntimeModule { override bindIValueConverterService() { return MyDslValueConverters } }` – BR.Hamza Dec 08 '16 at 16:17
  • please explain what problems you get – Christian Dietrich Dec 08 '16 at 16:21
  • I add `DOUBLE returns ecore::EDouble : INT('.'INT)?` in the Xtext file `IValueConverter DoubleValueConverter = new IValueConverter() { public Double toValue(String string, INode node) throws ValueConverterException { return Double.parseDouble(string.substring(0, string.length()-1)); } public String toString(Double value) throws ValueConverterException { return Double.toString(value)+"L"; }};` in the `MyDslValueConverters` After generating the artificats i get in MyDslRuntimeModule that the AbstractMyDslRuntimeModule is not a type – BR.Hamza Dec 08 '16 at 16:48
  • sure running the workflow does not give you any errors. i bet your grammar is ambigous (INT/vs DOUBLE) – Christian Dietrich Dec 08 '16 at 16:54
  • for some strange reason after resolving the ambiguity. when i right someting like "255L" in the .mydsl it doesn't recognize it. but the Double works fine I used this in the grammar. `LONG returns ecore::ELong: INT ("L"|"l"); DOUBLE returns ecore::EDouble : INT'.'INT;` – BR.Hamza Dec 08 '16 at 17:31
  • Can you please post complete sample grammar, value converter and test model to the question – Christian Dietrich Dec 08 '16 at 17:32
  • i assume you did not do the value converter right, how does it look like? – Christian Dietrich Dec 08 '16 at 17:48
  • i miss the methods LONG and DOUBLE that actually bind the value converter instances – Christian Dietrich Dec 08 '16 at 17:50
  • sorry i don't understant – BR.Hamza Dec 08 '16 at 17:54
  • where is this one in your valueConverter ` @ValueConverter(rule = "LONG") public IValueConverter LONG() { return longValueConverter; }` – Christian Dietrich Dec 08 '16 at 17:55
  • oh oh, i delete it when making the double function – BR.Hamza Dec 08 '16 at 17:57
  • bit xtext wont find these valueconverters if you dont have the methods – Christian Dietrich Dec 08 '16 at 17:59