Using Python you are asked to write an interpreter which uses the top-down recur
ID: 3929901 • Letter: U
Question
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
Explanation / Answer
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
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.