Due: Wednesday, April 19
In the early days, Logo was used to control a simple robot, called a turtle. Users could issue commands such as FORWARD 50 to make the turtle advance 50 steps, or RIGHT 90 to make it turn ninety degrees. The turtle robot carried a pen, so users could produce drawings on paper, such as the one shown to the left, by controlling the turtle and its pen. The turtle, which has since moved on screen, has become one of the most familiar and important parts of the Logo language
As a dialect of LISP, Logo is a complex and powerful language. For this project you will design and implement a much simplified version of Logo. Simple Logo should retain the features most commonly used by beginning users so that it can be used to provide an introduction to computer programming.
Simple Logo will consist of a basic turtle graphics package and support for a set of commands allowing the user to control the turtle and the pen using basic programming constructs such as conditionals, loops, and procedures. When the user launches the Simple Logo interpreter from the command line, it should bring up a shell and a turtle graphics window. The interpreter will need to receive, parse, and execute commands from the shell, reporting any errors it encounters along the way (and not crashing!).
Simple Logo should provide the following functionality:
Parsing involves matching the terminals given in the user's command with those given in the grammar to ensure they are in the correct order (as determined by the non-terminals). Interpretation means executing the code as it is understood by the parser. The execution will either access the interpreter's memory (variables or procedures) or access the turtle. In other words, the logo grammar defines how the user can write these commands, and your interpreter defines what happens when a command is issued.
The Simple Logo language has been restrictively defined to make writing it a reasonable project. In particular, the limited definition should make it easier to do parsing and error checking. The grammar for logo is available online here. You should already have code that can read a grammar file; however, you will need to add a new type of terminal that matches regular expressions (i.e., any word or any number) to read the logo grammar.
The parser will need to read in a line at a time, from either a terminal or a file, and divide the input string into tokens. Given the restricted definition of the language, there should only be one command per line and the command should be in prefix form, with the command name at the beginning of the input string. There can also be lines which assign a variable to have the value of another variable, a number, or a command. For example, :x = SUM 40 50 would be valid input. The job of the parser is to match the appropriate command handler with the specified command name. In matching a command name with a handler, remember that you have to search not only the built in commands but also the user-defined procedures. The parser can then pass control to the handler, also giving the handler a possibly empty list of arguments.
One way to think about the command interpreter is as a set of command handlers which each know how to execute a specific command. Most of the handlers will be very straightforward: the numeric operation handlers will need to make calculations and the turtle graphic commands will need to make calls to the turtle graphics library. The loops, conditionals, and subroutine definitions will be slightly trickier. Remember that the repeat, if, and to commands are the only commands which will have input on more than one line. Procedures are user-defined commands with their functionality composed of existing logo commands (including other user-defined procedures). You will also have to think about how to handle the list of instructions that correspond to each procedure.
Variables will also be somewhat tricky. You don't need to implement any concept of scope (i.e. local variables), so you could just have a table of all of the variables that exist and their current values. Scope would be cool and we're sure you could handle it, but it's not required. When a variable is passed to a command, its value will need to be looked up.
Also, to make things simpler, all commands should return a value. If no return value is defined, the command should return 0.
As specified above, we will expect some amount of error checking. It should be fairly easy to check for parsing errors, by checking each issued command against the set of legal commands and user-defined procedures which comprise the Simple Logo name space. Another measure of error checking to take is to count the number of argument tokens for each command and to compare the expected number of arguments with the given number of arguments. You should also think about how to identify and handle bad user input values.
The GUI for Simple Logo must allow the user to enter Logo commands (in an editable text area), display errors (in an uneditable area), and show the turtle graphics. It should also allow the user to save and load logo files. The exact layout of the GUI and the components used to implement them are up to you. All I/O must take place in a graphical window, and not from the shell.
There is a lot of room for creativity and extras in this project, but as always, do not start implementing any of these until Simple Logo, as specified, is functional. You are welcome to design your program to support any of these features. Some ideas: