To understand how an environment works as a map from identifiers to locations, and how nested regions of scope can be implemented in an interpreter as a stack of such environments.
Language L2 has a syntax based on Modula 2. Your task is to take the existing JavaCC grammar file, to generate skeleton Abstract Syntax Tree classes from it using jjtree, and to augment the classes with code that implements an interpreter for the language. The grammar, in abstract form, is:
Program = Block .
Block = begin ( Declaration )* StatementSeq end
Declaration = int Id ; | bool Id ;
StatementSeq = Statement ( ; Statement )*
Statement = Assign | IfThenElse | WhileLoop | Block
Assign = Id := Expression
IfThenElse = if BooleanExp then Statement OptElse
OptElse = {} | else Statement
WhileLoop = while BooleanExp do Statement
Expression = ArithExp | BooleanExp
ArithExp = Factor ( (+|-) Factor )*
Factor = SimpleExp ( (*|/) SimpleExp )*
SimpleExp = Id | Number | true | false | '(' Expression ')'
BooleanExp = ArithExp [ (=|>|<) ArithExp | not BooleanExp ]
Note that a BooleanExp can be just an ArithExp to include the constants true and false and a simple identifier, but also something like x+1 which should be semantically disallowed. Avoiding this problem with syntax rules would have meant a much more complex grammar. A sample program is:
begin
int x; bool b;
x := 1;
b := true;
if not b then
x := 2
else begin
int y;
y := x + 1;
b := false
end
end.
In order to handle re-use of names in inner, nested blocks, the store in language L1 must be split into a part that handles local versus non-local variables, and a global part that handles binding of values. The environment will map identifiers to locations, which will be just integers, starting from zero. Each block will get its own environment but environments will be pushed on a stack so that nested environments can be handled. E.g. in the example above, the outer block declares a variable x, so its environment will contain the mapping x -> location 0. The inner block redeclares x, so its enviroment will contain the mapping x -> location 1. This environment will be pushed on a stack of environments, so that using a variable becomes a search backwards from the top of the stack to find the environment where it was declared. Using b in the inner block means looking in the outer environment for its declaration. The store can remain a global data structure as it was in L1.
When a block is exited, its environment is popped from the stack, and any locations used in it can be re-used for another block at the same nesting level. So, in the example below, the other x has location 0, the first inner x has location 1 and so does the second inner x, since its environment takes the place of the first inner block's environment:
begin
int x; <- location 0
…
begin
int x; <- location 1
…
end;
…
begin
int x; <- also location 1
…
end;
…
end.
All you need is the grammar file L2.jjt, and a test file test.l2. Use a separate directory to store the code – don't confuse L1 classes with L2 classes. This sample program is:
begin
int x;
int p;
x := 6;
p := 0;
begin
bool b;
b := true;
while b do begin
int pp;
pp := x * x;
p := p + pp;
x := x -1;
b := x > 0;
end
end
end.
Add the following lines to your .cshrc file and remember to ‘source’ it after the changes.
setenv PATH ~rth/public/javacc-3.2/bin:$PATH
setenv PATH ~rth/public/jdk1.5.0_04/bin:$PATH
Run jjtree on the .jjt file to generate the .jj file. E.g.:
jjtree l2.jjt
Run javacc on the .jj file to generate the parser classes and the AST classes. E.g.:
javacc l2.jj
Run javac to compile the .java files. E.g.:
javac *.java
Run java with the name of your interpreter class, and the name of the test input file. E.g.:
java L2Intepreter test.l2
Your interpreter must produce the correct store when given the program in test.l2. Test your interpreter with simpler programs before you give it this one.
When you are done, make a Java archive with the command ‘jar cvf l2homework.jar *.java l2.jjt’, and submit it through the submission page (accessed from the Homework page).
Macrh 5th before midnight.