Use Python to write an interpreter for the mini-C language
that looks like the one
in the Lecture notes, Chapter 2, Section 2.1.
Here is the language's grammar:
===================================================
P : Program
C : Command
E : Expression
D : Declaration
L : LefthandSide
I : Identifier
N : Numeral
P ::= D ; C
C ::= C1 ; C2 | L = E | while E { C } | print E
E ::= N | ( E1 + E2 ) | ( E1 == E2 ) | ( E1 != E2 ) | L | &L
D ::= int I | int* I | D1 ; D2
L ::= I | *I
N ::= 0 | 1 | 2 | ...
I ::= strings of letters, not including the keywords,
int, while, print
===================================================
The language has integer (int) variables and integer-pointer (int*) variables.
See Section 2.2 to review the semantics of variables, &, and * when they
appear within expressions and within the left-hand sides of assignments.
The input to the interpreter is a list-represented operator tree.
The syntax of operator trees looks like the example from Chapter 1,
Section 1.3.3:
===================================================
PTREE ::= [ DLIST, CLIST ]
CLIST ::= [ CTREE+ ]
where CTREE+ means one or more CTREEs
CTREE ::= ["=", LTREE, ETREE] | ["while", ETREE, CLIST] | ["print", ETREE]
ETREE ::= NUM | ["+", ETREE, ETREE] | ["==", ETREE, ETREE] | ["!=", ETREE, ETREE]
| ["deref", LTREE] | ["ref", LTREE ]
DLIST ::= [ DTREE+ ]
where DTREE+ means one or more DTREEs
DTREE ::= ["int", ID] | ["int*", ID]
LTREE ::= ID | ["deref", LTREE]
NUM ::= a nonempty string of digits
ID ::= a nonempty string of letters
===================================================
(Note that "*" is converted to "deref" and "&" is converted
to "ref". This will help you think straight when you write the
interpreter. "==" and "!=" are the equal and not-equal operators which
return Boolean values)
You are free to use code from the online textbook in implementing your interpreter. You will certainly need to modify the existing code so that it processes operator trees that match the above grammar. The interesting part is writing the semantics of variables, because you must respect the data types in the variable declarations:
int x; int* y; y = &x; *y = 2and it places a 2 in the cell named by x. But this is illegal:
int* y; y = &ybecause y is an int* variable and not an int variable. Similarly, this is illegal:
int x; int* y; x = &y
You probably want to refer to the interpreter in Section 2.1.1. When a type check fails, your interpreter shall report an error message and exit gracefully, instead of crash.
You should write and test the interpreter functions in stages.
Say that you have written evalDTREE, evalCTREE,
and evalETREE and saved these in the file, interp.py.
You test like this: Open a command window and type
===================================================
python -i interp.py
>>> evalETREE(["+", "2", "1"])
...should display ("int",3)...
>>> evalDTREE(["int", "x"])
...should allocate a cell in memory and bind its location to x...
>>>evalCTREE(["=", "x", ["+", "2", "1"]])
...should place 3 into x's cell in memory...
===================================================
At any time during your testing, you can examine the values of
env and memory by merely typing their names, e.g.,
===================================================
>>> env
{"x":("int",0)}
>>>memory
[3]
===================================================
When you are convinced that your interpreter is operating correctly,
try it on these programs. (Note: just cut-and-paste these tests
into your command window.)
===================================================
evalPTREE([[["int", "a"]],
[["=", "a", ["+", "2", "1"]],
["=", "a", ["+", ["deref", "a"], ["deref", "a"]]]
]
])
evalPTREE([[["int", "a"]],
[["=", "a", "3"],
["while", ["!=", ["deref", "a"], "6"],
[["=", "a", ["+", ["deref", "a"], "1"]]]],
["print", ["deref", "a"]]
]
])
evalPTREE([[["int", "a"],
["int*", "b"],
["int*", "c"]
],
[["=", "b", ["ref", "a"]],
["=", "c", ["deref", "b"]],
["=", ["deref", "c"], "2"],
["print", ["deref", "a"]],
["print", ["deref", "b"]],
["print", ["deref", "c"]]
]
])
# This example contains multiple errors:
evalPTREE([[["int", "a"],
["int*","a"],
["int", "b"],
["int*", "c"]
],
[["=", "b", ["deref", "b"]],
["=", "c", "2"],
["=", "c", ["+", ["ref", "b"], "1"]],
["=", "c", ["ref", "c"]]
]
])
===================================================