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 or down. The pen starts at point (0,0) in the up 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.


Back to course home page