Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » [XText] best practices for variable handling
[XText] best practices for variable handling [message #45488] Tue, 26 May 2009 21:37 Go to next message
Johannes Utzig is currently offline Johannes UtzigFriend
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 Go to previous messageGo to next message
Sebastian Zarnekow is currently offline Sebastian ZarnekowFriend
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
Re: [XText] best practices for variable handling [message #45673 is a reply to message #45583] Wed, 27 May 2009 18:38 Go to previous message
Johannes Utzig is currently offline Johannes UtzigFriend
Messages: 329
Registered: July 2009
Senior Member
Hi Sebastian,

thank you for your quick response.

Sebastian Zarnekow schrieb:
> Hi Johannes,
>
> I'm afraid I did not get your point to 100%, but please find some
> comments below.
>

You pretty much nailed it :)


> It is common practice to distinguish between variable declaration (you
> called it "statement" - I would inline the Variable, see below) and
> VariableReference.

Thank you. That answers the questions.
I wasn't sure if I should fiddle with XText until it swallows the model
how I would have designed it from scratch according to the business
logic, or if it would be better to keep the model close enough to the
actual language representation.


Thank you very much for your helpful answer and the grammar. That seems
to be exactly what I was looking for, now we only need to apply that
knowledge to the 'slightly' more complicated real-world grammar :)


Best regards,
Johannes
Previous Topic:NullPointerException on validation
Next Topic:Xtext and error recovery in block-level statements
Goto Forum:
  


Current Time: Sat Dec 21 14:32:53 GMT 2024

Powered by FUDForum. Page generated in 0.03408 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top