[XText] best practices for variable handling [message #45488] |
Tue, 26 May 2009 21:37 |
Johannes Utzig Messages: 329 Registered: July 2009 |
Senior Member |
|
|
Hi,
I recently started to work with TMF XText and I am really impressed by
this fantastic tool so far.
However, while working on my grammar, I ran into some issues and I was
wondering if you could provide me with some best practices on how to
handle this kind of situation (since it is a fairly common use-case I
would say).
To bring this down to what it really is about, let's assume that I want
to write a very simple language with arithmetic expressions and variables.
Let's say it knows blocks, assignment statements and adding up INTs as
well as previously assigned variables.
To sum it up in an example that demonstrates all the language's
capabilities:
{
var aVariable = 5;
var anotherVariable = aVariable + 10 + 5;
{
var oneMore = anotherVariable;
}
}
My grammer could for example look like this:
grammar org.xtext.example.Expression with org.eclipse.xtext.common.Terminals
generate expression "http://www.xtext.org/example/Expression"
Model :
(blocks+=Block)*;
Block:
'{'
(statements+=Statement';')*
(blocks+=Block)*
'}';
Statement:
'var' output=Variable '=' input=Expression;
Variable:
name=ID;
Expression:
AtomicExpression | ChainExpression;
AtomicExpression:
LiteralExpression | VariableReference;
ChainExpression:
left=AtomicExpression '+' right=Expression;
LiteralExpression:
value=INT;
VariableReference:
value=[Variable];
Now when I look at the way I defined the Statement, it doesn't look like
the natural order to me. A Variable is contained in a Statement instead
of just being referenced and contained in the surrounding Block (which
would represent the scope the Variable is defined in).
Statement:
'var' output=Variable '=' input=Expression;
There doesn't seem to be a way to assign something to a reference of the
eContainer of Statement, so would this be the 'correct' way to model
such a relationship (Statement contains Variable), or is there a better way?
If I would decide that a Statement should reference a Variable by ID
instead of containing it, how could I get the Variable into its Block
container? Who would create it?
The only thing I could think of is custom Linker code that creates a
Variable on demand and places it into a feature of Block, but I'm not
sure if that's the way the linker is intended to work.
The next thing I notice is that I had to introduce a VariableReference
because I didn't see another way to handle all Expressions in a somewhat
unified fashion. This has the downside that the VariableReference is
some kind of logical proxy that I need to 'resolve' in my code by
calling getValue on it, instead of just having a reference to the actual
variable.
Using a Variable in an expression is clearly a reference since the
object is defined elsewhere, but a LiteralExpression seems more like a
containment reference.
Now it's obvious that the left/right features of a ChainExpression
cannot be a containment and a non-containment reference at the same
time, but I am wondering how this is supposed to be modeled.
Hopefully somebody can point out the obvious or provide me with a link
to the example that I couldn't find...
Thank you in advance and best regards,
Johannes Utzig
|
|
|
Re: [XText] best practices for variable handling [message #45583 is a reply to message #45488] |
Wed, 27 May 2009 07:53 |
Sebastian Zarnekow Messages: 3118 Registered: July 2009 |
Senior Member |
|
|
Hi Johannes,
I'm afraid I did not get your point to 100%, but please find some
comments below.
Am 26.05.2009 23:37 Uhr, schrieb Johannes Utzig:
> Hi,
>
> I recently started to work with TMF XText and I am really impressed by
> this fantastic tool so far.
Right ;-)
> However, while working on my grammar, I ran into some issues and I was
> wondering if you could provide me with some best practices on how to
> handle this kind of situation (since it is a fairly common use-case I
> would say).
I'll try my best.
> To bring this down to what it really is about, let's assume that I want
> to write a very simple language with arithmetic expressions and variables.
> Let's say it knows blocks, assignment statements and adding up INTs as
> well as previously assigned variables.
> To sum it up in an example that demonstrates all the language's
> capabilities:
>
> {
> var aVariable = 5;
> var anotherVariable = aVariable + 10 + 5;
> {
> var oneMore = anotherVariable;
> }
> }
Nothing fancy so far.
>
>
> My grammer could for example look like this:
>
> grammar org.xtext.example.Expression with
> org.eclipse.xtext.common.Terminals
>
> generate expression "http://www.xtext.org/example/Expression"
>
> Model :
> (blocks+=Block)*;
>
> Block:
> '{'
> (statements+=Statement';')*
> (blocks+=Block)*
> '}';
>
> Statement:
> 'var' output=Variable '=' input=Expression;
>
> Variable:
> name=ID;
>
> Expression:
> AtomicExpression | ChainExpression;
>
> AtomicExpression:
> LiteralExpression | VariableReference;
>
> ChainExpression:
> left=AtomicExpression '+' right=Expression;
>
> LiteralExpression:
> value=INT;
>
> VariableReference:
> value=[Variable];
>
Your grammar seems to be to complicated to achieve what you described.
Have you had a look at the documentation at www.xtext.org?
You'll find some information about unassigned rulecalls and actions.
It is common practice to distinguish between variable declaration (you
called it "statement" - I would inline the Variable, see below) and
VariableReference.
> Now when I look at the way I defined the Statement, it doesn't look like
> the natural order to me. A Variable is contained in a Statement instead
> of just being referenced and contained in the surrounding Block (which
> would represent the scope the Variable is defined in).
Transitive containment in a block is still containment, isn't it? But as
I already mentioned, I wouldn't declare a rule "Variable".
>
> Statement:
> 'var' output=Variable '=' input=Expression;
>
> There doesn't seem to be a way to assign something to a reference of the
> eContainer of Statement, so would this be the 'correct' way to model
> such a relationship (Statement contains Variable), or is there a better
> way?
> If I would decide that a Statement should reference a Variable by ID
> instead of containing it, how could I get the Variable into its Block
> container? Who would create it?
> The only thing I could think of is custom Linker code that creates a
> Variable on demand and places it into a feature of Block, but I'm not
> sure if that's the way the linker is intended to work.
>
This seems to be to complicated. I advise to not try to force Xtext into
your very own and somewhat - I repeat myself - complicated model.
> The next thing I notice is that I had to introduce a VariableReference
> because I didn't see another way to handle all Expressions in a somewhat
> unified fashion. This has the downside that the VariableReference is
> some kind of logical proxy that I need to 'resolve' in my code by
> calling getValue on it, instead of just having a reference to the actual
> variable.
> Using a Variable in an expression is clearly a reference since the
> object is defined elsewhere, but a LiteralExpression seems more like a
> containment reference.
> Now it's obvious that the left/right features of a ChainExpression
> cannot be a containment and a non-containment reference at the same
> time, but I am wondering how this is supposed to be modeled.
>
> Hopefully somebody can point out the obvious or provide me with a link
> to the example that I couldn't find...
>
> Thank you in advance and best regards,
> Johannes Utzig
>
I'ld model the grammar this way:
Model :
(statements+=Statement)*;
Statement:
Block | VariableDeclaration;
Block:
'{'
(statements+=Statement)*
'}';
VariableDeclaration returns Variable:
'var' name=ID '=' value=Expression ';';
Expression:
AtomicExpression
({ChainExpression.left=current} '+' right=Expression)?;
AtomicExpression returns Expression:
LiteralExpression | VariableReference;
LiteralExpression:
value=INT;
VariableReference:
value=[Variable];
Hope I got your point and provides some help,
Sebastian
|
|
|
|
Powered by
FUDForum. Page generated in 0.03408 seconds