Using Python you are asked to write an interpreter which use
Using Python you are asked to write an interpreter which uses the top-down recursive-descent method and inherited/synthesized attributes to parse and evaluate a very simple programming language. The tiny strong-typed language’s grammar is given below:
<prog> ::= <decl_list> <stmt_list>
<decl-list> ::= <decl> | <decl> <decl_list>
<decl> ::= <type> <id_list> ;
<type> ::= int | real
<id_list> ::= id | id {, <id_list>}
<stmt_list> ::= <stmt> | <stmt> <stmt_list>
<stmt> ::= id = <expr> ; |
iprint <expr> ; |
rprint <expr> ;
<expr> ::= <term> {+ <term> | - <term>}
<term> ::= <factor> {* <factor> | / <gactor>}
<factor> ::= <base> ^ <factor> | <base>
<base> ::= (<expr>) | id | number
Note that the iprint prints an integer expression, while the rprint prints the result of a real expression.
The interpreter should be written in Python. It takes one input file which contains the program to be executed. The input file name is given from the command line. For example, spirit % eval.py sample.tiny
The interpreter eval.py reads the program file sample.tiny, checks the syntax and outputs the result if the program is legitimate; otherwise, the interpreter prints “Syntax Errors”.
Below are some test examples:
int s, t ;
real r, pi ;
print 2 + 3 * 4 ;
s = 3 + 4 ;
t = 6 – 2 ;
print s * t ^ 2 ;
print (s + t)*(s – t) ;
r = 7.0 ; pi = 3.1416
print 4.0 * pi
Solution
def tokenize_python(program):
 import tokenize
 from cStringIO import StringIO
 type_map = {
 tokenize.NUMBER: \"(literal)\",
 tokenize.STRING: \"(literal)\",
 tokenize.OP: \"(operator)\",
 tokenize.NAME: \"(name)\",
 }
 for t in tokenize.generate_tokens(StringIO(program).next):
 try:
 yield type_map[t[0]], t[1]
 except KeyError:
 if t[0] == tokenize.ENDMARKER:
 break
 else:
 raise SyntaxError(\"Syntax error\")
 yield \"(end)\", \"(end)\"
def tokenize(program):
 for id, value in tokenize_python(program):
 if id == \"(literal)\":
 symbol = symbol_table[id]
 s = symbol()
 s.value = value
 else:
 # name or operator
 symbol = symbol_table.get(value)
 if symbol:
 s = symbol()
 elif id == \"(name)\":
 symbol = symbol_table[id]
 s = symbol()
 s.value = value
 else:
 raise SyntaxError(\"Unknown operator (%r)\" % id)
 yield s


