MiniLogo Language Description
MiniLogo is toy language inspired by Logo for programming simple 2D graphics. A MiniLogo program describes a picture by a sequence of move
commands that move a pen from one position to another on a Cartesian plane, drawing lines as it goes.
Overview and Examples
Below is a simple MiniLogo program that draws a 4x2 box with its bottom left corner at coordinate (1,1)
.
main () {
move(1, 1);
pen down;
move(5, 1);
move(5, 3);
move(1, 3);
move(1, 1)
}
Conceptually, the MiniLogo execution environment consists of two parts:
A canvas rooted at position
(0,0)
and extending infinitely upward and to the right.A pen which is always located at a point on the canvas and which can be in one of two states, either
up
ordown
. The pen starts at point(0,0)
in theup
state.
The move
command moves the pen from its current point to the point specified by its arguments. If the pen is down
when it moves, it draws a straight line connecting the two points. If the pen is up
, it just moves to the new point but does not draw a line. The state of the pen can be changed using the pen
command as illustrated in the example program above.
In addition to basic pen
and move
commands, a MiniLogo program can define and invoke macros. A macro is a procedure that receives integers as inputs and performs some commands. Within the body of a macro, commands can refer to input values by name. For example, below is the definition of a macro box
that describes how to draw a box of arbitrary width w
and height h
, with its bottom left corner at (x,y)
.
box(x, y, w, h) {
pen up;
move(x, y);
pen down;
move(x + w, y);
move(x + w, y + h);
move(x, y + h);
move(x, y)
}
Note that the macro begins by lifting the pen to make sure it doesn’t draw a line when moving to the initial point.
Every MiniLogo program has exactly one main
macro that takes no arguments and comes after all of the macro definitions. This is the entry point to the program, similar to the main function of a C program.
For example, here is a complete MiniLogo program that defines the box
macro and then uses it to draw several boxes.
box(x, y, w, h) {
pen up;
move(x, y);
pen down;
move(x + w, y);
move(x + w, y + h);
move(x, y + h);
move(x, y)
}
main() {
box(1, 1, 4, 2);
box(3, 4, 3, 4);
box(7, 4, 2, 1)
}
Finally, MiniLogo has a simple looping construct that enables running a block of commands repeatedly, with a variable that is incremented for each iteration.
For example, here is a MiniLogo program that defines the box
macro and then uses it to draw 15 boxes that get increasingly larger and shift up and to the right.
box(x, y, w, h) {
pen up;
move(x, y);
pen down;
move(x + w, y);
move(x + w, y + h);
move(x, y + h);
move(x, y)
}
main() {
for i = 1 to 15 {
box(i, i, i, i)
}
}
In this example, the body of the for
loop will execute 15 times. In the first iteration i=1
, in the second iteration i=2
, and so on. A for
loop can start and end on any integer. If the second integer is smaller than the first, the for
loop will count down rather than up.
Syntax
The concrete syntax of the MiniLogo language is defined by the following grammar:
int | ::= | (any integer) | |
var | ::= | (any variable name) | |
macro | ::= | (any macro name) | |
pars | ::= | ε | var , pars |
parameter list |
args | ::= | ε | expr , args |
argument list |
cmds | ::= | ε | cmd ; cmds |
command sequence |
block | ::= | { cmds } |
command block |
mode | ::= | down | up |
pen status |
expr | ::= | var | variable reference |
| | int | literal integer | |
| | expr + expr |
addition | |
| | expr * expr |
multiplication | |
| | ( expr ) |
grouping | |
cmd | ::= | pen mode |
change pen mode |
| | move ( expr , expr ) |
move pen to a new position | |
| | macro ( args ) |
call a macro | |
| | for var = expr to expr block |
for loop | |
def | ::= | macro ( pars ) block |
macro definition |
prog | ::= | def* main() block |
MiniLogo program |
Notes on Concrete Syntax
Expression grouping (parentheses) is used to disambiguate between different ways of parsing an expression into an AST. However, this production should not be present in the abstract syntax since it is not needed there (the tree structure indicates the grouping). For example, the expression (2 + 3) * 5
in concrete syntax indicates that the addition node is the left child of the multiplication node in the AST.
Multiplication binds more tightly than addition. This can be used to omit parentheses in the concrete syntax. That is, 2 + 3 * 5
is equivalent to 2 + (3 * 5)
but not the same as (2 + 3) * 5
.
Both addition and multiplication associate to the left, so 2 + 3 + 4
is equivalent to (2 + 3) + 4
.
In parameter and argument lists, commas (,
) are used to separate the elements. That is, we write a list of parameters as x, y, z
rather than x, y, z,
. Note that, strictly speaking, the grammar requires a comma at the end of the list too! However, we omit this last comma by convention in MiniLogo.
We use the same convention for command sequences within blocks. That is, semicolons separate commands. This is slightly different from the C-like syntax you’re used to, where a semicolon terminates every statement. This means that the last command in a block will not end in a semicolon.
(As with grouping, all these points about commas and semicolons are irrelevant to the abstract syntax!)
In prog note that main()
is part of the concrete syntax of MiniLogo. So the abstract syntax of a MiniLogo program will consist of a list of definitions and only the block of the main macro.