Home » Modeling » TMF (Xtext) » Type var, var, var;(Modifying model during parse.)
Type var, var, var; [message #673245] |
Mon, 23 May 2011 01:54 |
Lex Messages: 4 Registered: May 2011 |
Junior Member |
|
|
I would like to be able to parse the following statement:
class Foo {
int number;
str var1, var2;
}
Into the following model:
Class {
name = Foo
properties = [
Property { name = number, type = int },
Property { name = var1, type = str},
Property { name = var2, type = str}
]
}
I'm using the following Xtext (simplified a little for this post):
Class:
'class' name=ID '{'
(propertyTypes+=[DataType] properties+=Property (',' properties+=Property)* ';')*
'}'
Property returns Property: {Property} name=ID;
The 'propertyTypes' above is a throw away, it's just there to make Xtext happy, I only care that there is a match, then when Property matches, I want to back track and get the DataType.
I have the following Extension to add 'type' to Property:
process(xtext::GeneratedMetamodel gm):
addPropertyAttributes((ecore::EClass) gm.ePackage.getEClassifier('Property'));
addPropertyAttributes(ecore::EClass c):
c.eStructuralFeatures.add(
let type = new ecore::EReference :
type.setName('type') ->
type.setEType(c.ePackage.getEClassifier('DataType')) ->
type
);
The goal from there was to add a Value converter to Property that would back track until it found a DataType and then set that DataType on the Property:
public Property toValue(String name, INode node) {
Property p = (Property) node.getGrammarElement();
INode n;
while ((n = node.getPreviousSibling()) != null) {
EObject o = n.getGrammarElement();
if (o.eClass().getClassifierID()==SorcePackage.DATA_TYPE) {
p.setType((DataType) o);
return p;
}
}
throw new ValueConverterException("Unknown type.", node, new Exception());
}
Unfortunately I discovered that Value converters do not work for EObjects from this post:
[ couldn't post this link because i have less than 5 posts ]
What are my options to make this work? I really want to use Xtext but I can think of a lot of situations where I would want some way to backtrack or possibly even go ahead a little bit to get some context information and set attributes on a particular node (such as the above example illustrates).
Any help would be greatly appreciate.
|
|
| |
Re: Type var, var, var; [message #673390 is a reply to message #673349] |
Mon, 23 May 2011 13:49 |
Lex Messages: 4 Registered: May 2011 |
Junior Member |
|
|
Parsing it as a separate PropertyDeclaration is the way I did it initially but then my model didn't really match the semantics of my language.
and
Should be semantically equivalent and produce the same model. The second is merely a short cut for the first. Anytime I want to get a list of all properties of a class I would have to do some computation, I couldn't just return a list of properties. Also, any tools generated by Xtext wouldn't work as intended when displaying the list of properties in the outline or some other UI code. I would have to add special cases any place where a list of properties should be displayed.
Furthermore, it's my understanding that the point of a model is to represent the semantics of your language, not its syntax. The declaration shortcut is not semantically interesting and I would rather it didn't make it into my model.
I have not completely ruled this out though, depending on how hard it is going to be to make this work the right way I may just go back to having my model represent the syntax instead of the semantics at least for that portion of the language.
I have made some progress doing it the way I described in my original post. Xtext will not let you valueconvert an EObject but surprisingly they let you valueconvert an EJavaObject. I was able to change my code like this:
Model:
'model' name=ID '{'
(propertyTypes+=[DataType] properties+=Property (',' properties+=Property)* ';')*
'}'
Property returns ecore::EJavaObject: ID;
By using ecore::EJavaObject the Value Converter is actually triggered. And has the following code:
public Object toValue(String name, INode node) {
Property prop = SorceFactory.eINSTANCE.createProperty();
DataType type = SorceFactory.eINSTANCE.createDataType();
EObject o = null;
INode n = node;
while ((n = n.getPreviousSibling()) != null) {
o = n.getGrammarElement();
if (o instanceof org.eclipse.xtext.impl.CrossReferenceImpl) {
break;
}
}
type.setName(n.getText());
prop.setName(name);
prop.setType(type);
return prop;
}
The problem is that I couldn't figure out how to go from a CrossReference to a DataType (I create a new DataType but I don't think that's what I want to do). All I could get is a TypeRef but I don't understand well enough how all of the cross referencing works to be able to navigate from the reference to the actual object being referenced.
So, my questions are:
How can I get the DataType object from a CrossReference?
Are there any downsides to implementing this feature as I have done above?
Are there any benefits or downsides to implementing it as Alex suggested vs the method above?
Btw, here is what Xtext.log() in the unit tests looks like for a sample object:
input:
type Money {}
type Str {}
type Color {}
model Foo {
Str crackers, cheese;
}
output:
Sorce {
cref Element elements [
0: CustomType {
attr EString name 'Money'
}
1: CustomType {
attr EString name 'Str'
}
2: CustomType {
attr EString name 'Color'
}
3: Model {
attr EString name 'Foo'
ref DataType propertyTypes [
0: CustomType@//@elements.1
]
attr EJavaObject properties [
0: Property {
attr EString name 'crackers'
ref DataType type ref: DataType@(resource null)
}
1: Property {
attr EString name 'cheese'
ref DataType type ref: DataType@(resource null)
}
]
}
]
}
|
|
|
Re: Type var, var, var; [message #673398 is a reply to message #673390] |
Mon, 23 May 2011 14:16 |
Alexander Nittka Messages: 1193 Registered: July 2009 |
Senior Member |
|
|
Hi,
although the syntactic differences may not matter to you, the parser has to construct the model from the syntax.
int i1, i2, i3, i4;
boolean b1, b2, b3, b4;
is equivalent to
int i1;
boolean b1;
int i2;
...
but it is quite hard to define a grammar that will create the same model from both out of the box. You can adapt the model creation.
I'd rather provide utility methods for querying a class or work with an imported metamodel and add the custom methods to the corresponding classes.
Alex
Need training, onsite consulting or any other kind of help for Xtext?
Go visit http://xtext.itemis.com or send a mail to xtext@itemis.de
|
|
|
Goto Forum:
Current Time: Fri Apr 26 21:45:02 GMT 2024
Powered by FUDForum. Page generated in 0.03212 seconds
|