Deriving from XBase [message #1689918] |
Tue, 24 March 2015 12:24  |
Eclipse User |
|
|
|
Hy
Let's say i want a language like XBase, but with some more literals. The approach i found to achive that can be found here: [http ://koehnlein.blogspot.de/2011/07/extending-xbase.html]. According to it i create a grammar-rule, that has the name of an XBase-grammar-rule (XLiteral in that case), define it similarly and add some alternatives i like. The thing i don't get from the blog-entry: Where to place the code that describes how my additional alternatives are handled by the XBase-Compiler used in my model-inferrer? The blog-entry doesn't reveal where the code-snippets belong to.
A related question: In my model-inferrer i want to wrap an XExpression (let's call it foo) into an if-statement. I tried the following: I have created a subclass of XIfExpressionImpl (no modified or additional functionality -- only for creating an instance with the correct attributes, since the constructor of XIfExpressionImpl is protected) and simply used it as the body of a method in my inferrer; just like "body = new MyXIfExpressionImpl(if_expression, foo, else_expression);". But unfortunately all i get from this is a missing body in the output (and no error or warning telling me what the problem might be). What is the correct way to do it?
Greetings,
Fenris
PS: Is there a documentation for the model-inferrer-language?
|
|
|
|
|
|
|
Re: Deriving from XBase [message #1690395 is a reply to message #1690372] |
Fri, 27 March 2015 02:35   |
Eclipse User |
|
|
|
Hi,
have a look at the jvmmodelinferrer (use the domain model example as the example it is meant to be)
unfortunately this depends on the rest of the grammar but a simple implementation could look like
(asuming you inferr the context of the notification to a class - based on the domain model example)
Feature:
Property | Operation |Notification;
package org.eclipse.xtext.example.domainmodel.jvmmodel
import com.google.inject.Inject
import org.eclipse.xtext.example.domainmodel.domainmodel.Entity
import org.eclipse.xtext.example.domainmodel.domainmodel.Notification
import org.eclipse.xtext.example.domainmodel.domainmodel.Operation
import org.eclipse.xtext.example.domainmodel.domainmodel.Property
import org.eclipse.xtext.naming.IQualifiedNameProvider
import org.eclipse.xtext.xbase.jvmmodel.AbstractModelInferrer
import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor
import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1
class DomainmodelJvmModelInferrer extends AbstractModelInferrer {
@Inject extension JvmTypesBuilder
@Inject extension IQualifiedNameProvider
def dispatch infer(Entity entity, extension IJvmDeclaredTypeAcceptor acceptor, boolean prelinkingPhase) {
accept(entity.toClass( entity.fullyQualifiedName )) [
documentation = entity.documentation
if (entity.superType != null)
superTypes += entity.superType.cloneWithProxies
// let's add a default constructor
members += entity.toConstructor []
// and one which can be called with a lambda for initialization.
val procedureType = typeRef(Procedure1, typeRef(it)) /* Procedure<MyEntity> */
members += entity.toConstructor [
parameters += entity.toParameter("initializer", procedureType)
// here we implement the body using black box Java code.
body = '''
initializer.apply(this);
'''
]
// now let's go over the features
for ( f : entity.features ) {
switch f {
Notification: {
val notification = f
members += notification.toMethod("notification_"+notification.name, Void.TYPE.typeRef()) [
body = '''
if (_notification_«notification.name»_internal_predicate()) {
_notification_«notification.name»_internal();
}
'''
]
members += notification.toMethod("_notification_"+notification.name+"_internal", Void.TYPE.typeRef()) [
body = notification.code
]
members += notification.toMethod("_notification_"+notification.name+"_internal_predicate", Boolean.TYPE.typeRef()) [
body = notification.predicate
]
}
// for properties we create a field, a getter and a setter
Property : {
val field = f.toField(f.name, f.type)
members += field
members += f.toGetter(f.name, f.type)
members += f.toSetter(f.name, f.type)
}
// operations are mapped to methods
Operation : {
members += f.toMethod(f.name, f.type ?: inferredType) [
documentation = f.documentation
for (p : f.params) {
parameters += p.toParameter(p.name, p.parameterType)
}
// here the body is implemented using a user expression.
// Note that by doing this we set the expression into the context of this method,
// The parameters, 'this' and all the members of this method will be visible for the expression.
body = f.body
]
}
}
}
// finally we want to have a nice toString methods.
members += entity.toToStringMethod(it)
]
}
}
resulting for an example model
entity X {
notification y ~ true : {println(true)}
}
in
public class X {
public void notification_y() {
if (_notification_y_internal_predicate()) {
_notification_y_internal();
}
}
public void _notification_y_internal() {
InputOutput.<Boolean>println(Boolean.valueOf(true));
}
public boolean _notification_y_internal_predicate() {
return true;
}
}
|
|
|
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.05492 seconds