1

I'm working on an Xtext project that uses parts of the Xbase grammar. In my code I'm analysing the DSL program in order to generate some Java code. It's easy to turn an existing XExpression into Java code using XbaseCompiler but that's not what I need. Instead, I need to generate a different program.

Currently I'm simply generating Java code (i.e. constructing a String). What I'd like to do is constructing a new XExpression, maybe even using parts of the original one, and then compile it to Java.

The different XExpressions have zero-args constructors, so I tried instantiating one and even set some of the properties. However the compiler crashed and I can't work out which properties it is missing.

Kirill Rakhman
  • 42,195
  • 18
  • 124
  • 148
  • i dont know if this is a good idea but that is hard to say from the context you have, since every thing done beyond writing a jvmmodelinferrer should be well considered since it may not be that easy. but you may look for XbaseFactory.eInstance.createXXX as is is usually done with all EMF stuff – Christian Dietrich Jul 08 '15 at 19:42

1 Answers1

3

I would prefer to generate the expression as String and then use the Xtext parser to do the heavy lifting for you, i.e. let it parse the String and create the corresponding XExpression objects for you. How you do that properly depends on the context you're in (OSGI or standalone).

Here is a standalone example (can be run from a simple main method) for the "Scripting Language" from the Xtext documentation:

public class StandaloneParser {

    @Inject
    private IParser parser;

    public StandaloneParser() {
        Injector injector = new ScriptingStandaloneSetup().createInjectorAndDoEMFRegistration();
        injector.injectMembers(this);
    }

    public EObject parse(String input) {
        IParseResult result = parser.parse(new StringReader(input));
        if (result.hasSyntaxErrors()) {
            throw new RuntimeException("Syntax errors");
        }
        return result.getRootASTElement();
    }

}

Example for a caller:

public class Main {

    public static void main(String[] args) {
        StandaloneParser parser = new StandaloneParser();
        EObject result = parser.parse("val answer = 7 * 6;");
        System.out.println(result);
    }

}

If you try to create such an expression programatically you'll have a hard time. It could look like this (Xtend code):

val factory = XbaseFactory.eINSTANCE
val expression = factory.createXVariableDeclaration => [
    name = "answer"
    right = factory.createXBinaryOperation => [
        leftOperand = factory.createXNumberLiteral => [
            value = "7"
        ]
        feature = // TODO retrieve the JvmOperation: org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_multiply(int,int)
        rightOperand = factory.createXNumberLiteral => [
            value = "6"
        ]
    ]
]
Franz Becker
  • 705
  • 5
  • 8
  • Thanks for your answer! Let's say I'm inspecting an XBlockExpression that accesses variables declared elsewhere. How can I tell the parser to use the same context (i.e. scope) for the new expression so I can access the same variables? – Kirill Rakhman Jul 09 '15 at 11:31
  • That highly depends on your concrete model / grammar. Taking the scripting language as an example, you could perform an EcoreUtil.copyAll(...) on the whole model (or modify the existing), remove some expressions and put in your own at the places you want. If that doesn't give you enough information to go on please file a new question with more details on your use-case (note that I won't be available until Tuesday). – Franz Becker Jul 09 '15 at 22:04
  • Thanks, I will have a look. – Kirill Rakhman Jul 10 '15 at 10:06
  • I decided to stick with generating Java code by hand. – Kirill Rakhman Jul 14 '15 at 21:56