CIT 594 Implementing the Little Ol’ Language
Spring 2011, David Matuszek
In the previous assignment you wrote a program to parse a language with a very simple syntax. It consists of only three types of things: words (functions), numbers, and blocks. The syntax is exclusively prefixthe name of a function always precedes its argumentsso there are no complicated infix operations (like 2+3*4
). The only punctuation used to help define the structure of the parse tree is the bracketed list.
In this assignment you will continue the definition of the language by specifying a number of function words, and implementing an interpreter for them.
You are building on the work done in the previous assignment. Your project and your main class were named LittleLanguage
. (You may change this name; I recommend LOL
.) Add a Run button to your GUI.
When the Run button is clicked, parse the contents of the window, just as if you had clicked the Parse button, but this time do not display the results of the parse. If there are errors, inform the user; but if there are no errors, interpret ("run") the program.
In the language you will implement, every function has a value. The value of a block is the value of the last thing in the block. To keep things simple, all values are real numbers. Logical "false" is represented by the number 0
; logical "true" is represented by any other number (but usually 1
).
Function  Arity  Examples  Semantics  Value 

set 
2  set x plus x 1 
The second argument is evaluated, and the result assigned to the first argument (which must be a word).  The value assigned to the variable. 
abs 
1 
abs x 
The argument is evaluated, and its absolute value is computed.  The value of the argument, if nonnegative, otherwise the negative of the argument. 
plus 
2 
plus 5 y 
The two arguments are evaluated and added together.  The sum of the two arguments. 
minus 
2 
minus count 1 
The two arguments are evaluated and the second is subtracted from the first.  The difference of the two arguments. 
times 
2 
times m n 
The two arguments are evaluated and multiplied together.  The product of the two arguments. 
divide 
2 
divide sum count 
The two arguments are evaluated and the first is divided by the second.  The quotient of the two arguments. 
mod 
2 
mod n 2 
The two arguments are evaluated and the Java % operator is applied to the two values. 
The "mod: of the two arguments. 

2 

The two arguments are evaluated and compared.  1 if the first argument is less than the second argument, 0 otherwise. 

2 

The two arguments are evaluated and compared.  1 if the first argument is greater than the second argument, 0 otherwise. 
equals? 
2 
equals? plus 2 2 4 
The two arguments are evaluated and compared.  1 if the two arguments are within 0.00001 of each other, 0 otherwise. 
and? 
2 
and? 
The first argument is evaluated. If it is nonzero, the second argument is evaluated.  0 if either argument is zero, else 1 
or? 
2 
or? 
The first argument is evaluated. If it is zero, the second argument is evaluated.  1 if either argument is nonzero, else 0 . 
not? 
1 
not? 
The argument is evaluated, and its "truth value" is reversed.  1 if the argument is zero, 0 if it isn't. 
if 
3 
if lessthan? x y 
The first argument is evaluated. If it is nonzero, the second argument is evaluated, else the third argument is evaluated.  If the first argument is nonzero ("true"), the value is the value of the second argument, else it is the value of the third argument. 
while 
2 
while lessthan? x 1000 
The first argument is evaluated. If it is nonzero, the second argument is evaluated. Then the first argument is reevaluated. This process continues until the first argument becomes zero.  The final value of the second argument. If the second argument is never evaluated, the value of the while is 0 . 
repeat 
2 
repeat 100 
The first argument is evaluated. If it is positive, the second argument is evaluated that many times.  The final value of the second argument. If the second argument is never evaluated, the value is the value of the first argument. 
each 
3 

For each "thing" in the second argument, evaluate it, and set the first unevaluated argument to that value; then evaluate the third argument.  The value of each is the value of the last evaluated expression in the third argument. If either the second or third argument is the empty block, the value of each is 0 . 
ask 
1 
ask [How high is the sky?] 
Opens a JOptionPane input dialog, with a String version of the unevaluated first argument as the message. Then print (to the GUI) both the question and the user's response. 
If the user enters a number, the value of ask is that number. If the user clicks Cancel, the value is 0 . If the user enters a nonnumber, ask is repeated until a number is obtained. 
tell 
1 
tell x 
Opens a JOptionPane message dialog, and displays the first argument twice, both unevaluated and evaluated. For example, "The value of x is 22" . Also print both to the GUI. 
The value of tell is the value of the evaluated argument. 
if
above for an example.)The program
You need a HashMap
to keep track of the values of variables. Create one. Initially it will be empty, but as your program performs set
functions (see the table above), you will be putting variables into this table, and changing their values. While this is easy to do using the HashMap
methods get
and put
, I recommend not using these methods directly. Instead, write a store
method that calls put
and a fetch
method that calls get
. This will help in the next assignment, when you will need to change the way you keep track of the values of variables.
You need a table of functions and their arities, which you developed for the last assignment (though the list of functions has changed).
You need to evaluate a tree (representing the LOL program). Write a recursive method (I called mine eval
) to look at what is in the root of the tree that is passed to it, and do something accordingly.
Here's what the method needs to check (in some order):
"[]"
)? If so, get its arity (except for "[]"
), then:
"set"
then ..."abs"
then ..."plus"
then ...Each LOL function has to be coded separately (because they do different things), but there is also a lot of commonality. Most of the functions need to evaluate their arguments (but not alwaysfor example, if
should evaluate only two of its three arguments). Take advantage of this commonality by devising some good helper functions. Remember, good programmers are creatively lazy, and find good ways to reduce the amount of code they have to write.
You need to unit test each LOL function. I recommend a lot of smaller tests, rather than one big test for the entire eval
method (or whatever you call it).
Implement Euclid's algorithm in LOL. It should accept negative numbers as well as positive ones, but always produce a positive result. Put your program on a file named euclid.lol
.