Write a program that runs programs.
What to build
An interpreter for a very small language, combining most of this course.
Requirements
set NAME VALUEcreates or replaces a variable.add NAME VALUEandmul NAME VALUEchange an existing variable.print NAMEprints a variable's value.- An unknown variable prints
error: unknown NAME. - A value that is not a whole number prints
error: bad number VALUE.
Input
The first line has n. Each of the next n lines is a command.
Output
One line for each print or error.
Constraints
n is from 1 to 200.
Example
Input:
4
set x 5
add x 3
mul x 2
print x
Output:
16
Why it works
This is how real interpreters are organised: one loop reads statements, a table stores names, and errors are reported without bringing the whole program down.
Examples
Example 1 · Input
4 set x 5 add x 3 mul x 2 print x
Expected output
16
Example 2 · Input
2 print y add y 1
Expected output
error: unknown y error: unknown y
Prompts inside input() are ignored when checking, so input("n: ") is fine.
Hints
Hint 1
Store the variables in a dictionary.
Hint 2
Use a custom exception, and raise it for a variable that does not exist or a value that is not a number.
Hint 3
Put the try inside the loop, so that one bad line does not stop the rest.
Solution
Show one correct solution (try it yourself first)
class LanguageError(Exception):
pass
variables = {}
def number(text):
try:
return int(text)
except ValueError:
raise LanguageError(f"bad number {text}")
def lookup(name):
if name not in variables:
raise LanguageError(f"unknown {name}")
return variables[name]
def run(parts):
command = parts[0]
name = parts[1]
if command == "set":
variables[name] = number(parts[2])
elif command == "add":
variables[name] = lookup(name) + number(parts[2])
elif command == "mul":
variables[name] = lookup(name) * number(parts[2])
else:
print(lookup(name))
n = int(input())
for _ in range(n):
try:
run(input().split())
except LanguageError as error:
print(f"error: {error}")