A Little of Context
This language was developed as an example language to teach DSLs in the context of Public University subject in Argentina for which some of us are teachers.
We wanted to show a small yet powerful interpreted language.
And one of the goal was to shows something that will produce some visual effect, so that the student could really appreciate the execution of the language.
But we didn't want to actually spend a lot of time on the graphical part, creating a logo from scratch
So we just went ahead and searched on Google for an existing Logo project, which was JVM compatible.
We will just then create the XText language and use an interpreter to read or semantic model and call that Logo to perform the drawing.
That was exactly what we did.
Tortue
So as backend logo we used Tortue a GPL open source project
Here's a screenshot from their site
It actually comes as a full standalone java app.
But we will just use the classes as if it was an API.
And also make him draw into a canvas that we will embed into the running eclipse.
The Language Grammar
The logo language is kind of mid-sized. It's not a so small as a common DSL, but it is neither much complex or big as a typed GPL language.
Still it is a good exercise since it has many elements of a full blown GPL imperative language like C, pascal, Java, etc.
We will see here a couple of example programs to understand the language:
Moving the Turtle
This is a really simple program to start getting familiar with the language
PENDOWN
FORWARD 80
RIGHT 90
FORWARD 80
RIGHT 90
FORWARD 80
RIGHT 90
FORWARD 80
PENUP
It will draw the following:
They have side-effect, meaning that they change the state of the turtle to "drawing" or just "moving without drawing".
The the others: RIGHT, LEFT, FORWARD, are Move operations for controlling the turtle.
So, to start seeing some xtext code here is a rule that put together all these moves
MOVE:
FORWARD | LEFT | RIGHT | SET_X | SET_Y
;
This is part of our new language grammar in Xtext.
We will see each actual rule in the next section.Using variables
Now we can change the previous program to avoid repeating the size of each side of the square, using a variable.
PENDOWN
MAKE lado = 80
FORWARD lado
RIGHT 90
FORWARD lado
RIGHT 90
FORWARD lado
RIGHT 90
FORWARD lado
PENUP
The variable "lado" (spanish for "side") is declared through the keyword "MAKE" which assigns a name and an initial value to it.
Then we can see that all other operations like FORWARD could either use a simple value like a Number or a Variable Reference.
So now we can see the rules for these operations:
FORWARD: 'FORWARD' amount=EXPRESSION;
LEFT: 'LEFT' amount=EXPRESSION;
RIGHT: 'RIGHT' amount=EXPRESSION;
SET_X: 'SETX' amount=EXPRESSION;
SET_Y: 'SETY' amount=EXPRESSION;
We can see there that all of these rules expect a special keyword and then an EXPRESSION.
Which in turn is as we identified:
EXPRESSION:
VARIABLE_REF | VALUE
;
A value is simply a double number
VALUE:
val=DOUBLE
;
And a Variable reference is a little bit more complicated:
VARIABLE_REF: toVar=[REFERENCIABLE];
It is a reference (the syntax for that in xtext is to use the square brackets) to a REFERENCIABLE.
A Referenciable is:
REFERENCIABLE:
MAKE | PARAM
;
So this means that a referencia is a one of those variables or a PARAM, which we haven't seen yet.
But we will soon !
Repeat Loops
We can still simplify the example by reducing duplicated code, using a repeat loop.
PENDOWN
MAKE lado = 100
REPEAT 4
FORWARD lado
RIGHT 90
END REPEAT
PENUP
Lets see the grammar rules for this:
REPEAT:
'REPEAT' times=EXPRESSION
(commands+=SENTENCE)+
'END REPEAT'
;
Because "times" is of type EXPRESSION. Which we already see could be a VARIABLE_REF or a Variable.
This means you can do this
MAKE sides = 4
REPEAT sides
FORWARD lado
RIGHT 90
END REPEAT
We will go a little further fast with this one.
SENTENCE:
MAKE | CONTENT
| PROCEDURE_CALL
| OPERATION
| CONTROL_SENTENCES
| MOVE
| DRAWING_SENTENCE
Sentence is probably the most generic rule, since it could be one of the MOVE sentences that we already saw, to control the turtle movement, but also a DRAWING_SENTENCE, that we also saw. It could also be a MAKE, because you can define new variables within a REPEAT, for example.
And then more stuff we haven't seen yet like: PROCEDURE_CALL, CONTROL_SENTENCES, CONTENT, and OPERATION.
We will see each of them in further sections
Procedures
Our sample program draws a square, but if we want to draw many squares, we don't want to copy and paste that code, so, for reusing certain functionality we can define procedures, than can be called anytime.
TO makeASquare
PENDOWN
MAKE lado = 100
REPEAT 4
FORWARD lado
RIGHT 90
END REPEAT
PENUP
END TO
makeASquare
makeASquare
This program first defines a procedure named "makeASquare" and all of its sentences.
Then the program itself has two procedure calls to the same procedure.
So we have two new concepts for the language.
A procedure definition, which is:
TO:
'TO' name=ID (parameters+=PARAM)*
(commands+=SENTENCE)+
'END TO'
;
Notice that it could have a list of PARAM's. And the body is a list of SENTENCE's (we've already seen that it's basically "anything" -but not a procedure definition, you cannot define one within other-)
A param is:
PARAM:
':' name=ID
;
So now we now that from a REPEAT or a FORWARD, RIGHT, etc, you can use a value (double) or reference either a variable (MAKE), or a PARAM, in case you are within a procedure !.
The other new concept is the procedure call:
PROCEDURE_CALL:
to=[TO] (params+=EXPRESSION)*
;
Easy, a reference to a procedure (TO), and then an optional list of EXPRESSION, which will be evaluated and passed as the values for each parameter.
Remember EXPRESSION is either a value or a reference (to MAKE or PARAM).
Some Other Syntax Elements
There are a couple of other secondary elements in the language for example to control the font and the line color
CLEAR
HOME
CANVASCOLOR BLACK
FONTSIZE 36
FONTSTYLE BOLD
DRAWSTRING "THIS IS TORTUE TEXT"
Clear of course will erase the canvas. And home will move the turtle to the starting point (center)
Canvas color will set the background color.
Drawstring is as you probably guessed to write a text.
Here's a cool sample app which combines it with PEN COLOR
CLEAR
FONTSIZE 36
FONTSTYLE BOLD
SETX 140
MAKE color = 10
REPEAT 24
PENCOLOR color 0 color 50
LEFT 15
PENUP
FORWARD 45
PENDOWN
DRAWSTRING "THIS IS TORTUE TEXT"
SUM color = color + 10
END REPEAT
This produces the following image:
Cool ah ?
Thanks Tortue :P
Operations
There are a couple of simple mathematical operations to work with numbers.
DIVIDE blue = color / 2
All of this operations have two effects:
- Compute a value (on the right)
- Assigns that value into a variable (using a reference)
Here are the others:
SUM forwardamount = i + 1
MULTIPLY green = J * I
Here is a sample program which uses SUM
CLEAR
HOME
MAKE i = 1
MAKE color = 200
REPEAT 500
MAKE red = color
DIVIDE blue = color / 2
MAKE green = color
PENCOLOR red green blue 255
MAKE forwardamount = 0
SUM forwardamount = i + 1
FORWARD forwardamount
RIGHT 70
SUM i = i + 1
SUM color = color + 1
IF color > 255
// MAKE color = 200
SUM color = 0 + 200
END IF
END REPEAT
It draws the following:
Lets check the grammar:
OPERATION:
SUM
| SUBTRACT
| MULTIPLY
| DIVIDE
;
And they are all pretty similar:
SUM:
'SUM' targetVariable=[MAKE] '=' valOne=EXPRESSION '+' valTwo=EXPRESSION;
SUBTRACT:
'SUBTRACT' targetVariable=[MAKE] '=' valOne=EXPRESSION '-' valTwo=EXPRESSION;
MULTIPLY:
'MULTIPLY' targetVariable=[MAKE] '=' valOne=EXPRESSION '*' valTwo=EXPRESSION;
DIVIDE:
'DIVIDE' targetVariable=[MAKE] '=' valOne=EXPRESSION '/' valTwo=EXPRESSION;
Basically it has a variable reference. Notice that we don't use REFERENCIABLE here, so this means that you can only use MAKE variables and not PARAM. This means that you cannot reassign PARAMeters.
Then on the right part they are all binary operations, so they have two operands. Each operand is not exclusively a double number but an EXPRESSION.
So that you can SUM 2 with 2, but also 2 + a, or "a + b"
If
You should be getting the idea, this is just more of the same.
IF color > 255
// MAKE color = 200
SUM color = 0 + 200
END IF
This is the grammar for the if
IF:
'IF' condition=BOOLEAN_EXPRESSION
(commands+=SENTENCE)+
'END IF'
;
And something cool appears here, the BOOLEAN_EXPRESSION's.
BOOLEAN_EXPRESSION:
EQUALS
| GREATER_THAN
| LESSER_THAN
EQUALS: op1=EXPRESSION '=' op2=EXPRESSION;
GREATER_THAN: op1=EXPRESSION '>' op2=EXPRESSION;
LESSER_THAN: op1=EXPRESSION '<' op2=EXPRESSION;
And that's it.
This is pretty much all the syntax of the language
Full Tortue Syntax and Commands
For the complete syntax reference of Tortue you can visit:
Next
In the next part we will start to look at the interpreter and how to give some execution meaning to this grammar :)
No comments:
Post a Comment