Use Python to finish an interpreter for the mini-command language in the Lecture
Notes, Chapter 1, extended with if-commands, global declarations, and procedure calls.
A sample program looks like this:
===================================================
int x;
proc p: x = (x - 1) end;
x = 2;
while x : print x; call p end;
if (x + 1) : call p else print (x-9) end
===================================================
Here is the execution of this program:
python run.py
Type program; OK to do it on multiple lines; terminate with !
as the first symbol on a line by itself:
int x;
proc p: x = (x - 1) end;
x = 2;
while x : print x; call p end;
if (x + 1) : call p else print (x-9) end
!
Parse tree:
[[['int', 'x'], ['proc', 'p', [['=', 'x', ['-', 'x', '1']]]]], [['=', 'x', '2'], ['while', 'x', [['print', 'x'], ['call', 'p']]], ['if', ['+', 'x', '1'], [['call', 'p']], [['print', ['-', 'x', '9']]]]]]
Execution:
2
1
final namespace = {'x': -1, 'p': [['=', 'x', ['-', 'x', '1']]]}
The program is parsed into its tree and
interpreted, which causes the namespace (storage) to hold
values for x and p. While the loop repeats, 2 and 1 are printed as x counts down to 0. The final value of the namespace is displayed.
Here the grammar of the language we implement:
===================================================
PROGRAM ::= DECLIST COMMANDLIST
DECLIST ::= DECLARATION ; DECLIST | (nothing)
DECLARATION ::= int VAR | proc VAR : COMMANDLIST end
COMMANDLIST ::= COMMAND | COMMAND ; COMMANDLIST
COMMAND ::= VAR = EXPRESSSION
| print EXPRESSION
| while EXPRESSION : COMMANDLIST end
| if EXPRESSION : COMMANDLIST else COMMANDLIST end
| call VAR
EXPRESSION ::= NUMERAL | VAR | ( EXPRESSION OPERATOR EXPRESSION )
OPERATOR is + or -
NUMERAL is a sequence of digits from the set, {0,1,2,...,9}
VAR is a string of lower-case letters, not a keyword
===================================================
I have already modified the parser from Chapter 1 to build parse trees for this grammar.
The input to the interpreter you write is the list-represented tree constructed by the parser.
The syntax of trees is this:
===================================================
PTREE ::= [ DLIST, CLIST ]
DLIST ::= [ DTREE* ]
where DTREE* means zero or more DTREEs
DTREE ::= ["int", VAR] | ["proc", VAR, CLIST]
CLIST ::= [ CTREE+ ]
where CTREE+ means one or more CTREEs
CTREE ::= ["=", VAR, ETREE] | ["print", ETREE] | ["while", ETREE, CLIST]
| ["if", ETREE, CLIST, CLIST] | ["call", VAR]
ETREE ::= NUMERAL | VAR | [OP, ETREE, ETREE]
where OP is either "+" or "-"
===================================================
Notice how the trees match the grammar constructions. Since the trees are nested lists, it is easy to disassemble them and compute on their parts.
You will extend the mini-command interpreter so that it processes the trees for if-commands, declarations, and procedure calls. Here are the semantic concepts you must implement:
Type program; OK to do it on multiple lines; terminate with ! as the first symbol on a line by itself: x = 2; y = (x + 1); print y ! Parse tree: [[], [['=', 'x', '2'], ['=', 'y', ['+', 'x', '1']]]] Execution: 3 final namespace = {'y': 3, 'x': 2}That is, the interpreter understands the mini-command language from Chapter 2.
Now, your job is to revise interpret.py (and that file only --- no others!) to have if-commands, declarations, and procedures. Extend the interpreter in the standard "interpreter design pattern," that is, each form of parse tree has its own interpret function. So, you must modify interpretCTREE and add two new functions, interpretDLIST and interpretDTREE.
Remember to document the two new functions and modify the documentation of the other functions to match the extended language.
Important: Read the short explanation, Notes on lists and dictionaries, to learn how to implement procedures. (There are other links to Python documentation on the CIS505 home page.)
IMPORTANT: Python uses indentation to show the nesting of commands. You can indent using either spaces or tabs, but you cannot mix them. In my code, I used all spaces to do indentation. (If you mix leading tabs with leading spaces you will get strange syntax errors.) You are warned.
Write and test the interpreter in three stages:
The teaching assistants will study your work and your tests and apply some additional tests before scoring the submission.
Important: This assignment must be done by you, individually, so that you acquire some basic skills with scripting and dynamic data structures. It is certainly OK to discuss the assignment with the instructor, TAs, or your colleagues, but all the coding must be typed by you alone, and all the concepts in the coding must be stored in your head so that you can reproduce them on demand.