# Implement an interpreter for simple ‘while programs’ (so called # because their only looping construct is ‹while›). The syntax is as # follows: # # • one line = one statement (no exceptions), # • the program is a sequence of statements, # • blocks are delimited by indentation (1–5 spaces), # • there are following statement types: # ◦ assignment, # ◦ ‹if› statement, # ◦ ‹while› statement. # # All variables are global and do not need to be declared (they come # into existence when they are first used, with a default value 0). # Variables are always integers. Variable names start with a letter # and may contain letters, underscores and digits. # # The ‹if› and ‹while› statements are followed by a «body»: a block # indented one space beyond the ‹if› or ‹while› itself. The body # might be empty. The ‹if› and ‹while› keywords are followed by a # single variable name. Zero means false, anything else means true. # # Assignments are of two forms: # # • constant assignments of the form ‹name = number› (where # ‹number› is an integer written in decimal, and might be # negative), # • 3-address code operations, of the form # # name₀ = operation name₁ name₂ # # Valid operations are: # # • logic: ‹and›, ‹or›, ‹nand› (the result is always 0 or 1), # • arithmetic: ‹add›, ‹sub›, ‹mul›, ‹div›, # • relational: # ◦ ‹lt›, ‹gt› (less/greater than), # ◦ ‹eq› (equals), # ◦ ‹leq› and ‹geq› (less/greater or equal). # # Example program: # # x = 0 # y = 7 # one = 1 # if x # x = add x x # while y # y = sub y one # x = add x one # # Write a function ‹do_while› which takes a ‘while program’ (as a # string) and returns a dictionary with variable names as keys and # their final values as values (of type ‹int›). # # If the program contains an error, create a special variable named # ‹#error› and set its value to the offending line number. Return # immediately after encountering the error. In this case, other # variables may or may not be included in the resulting dictionary. # # Check syntax before you start executing the program (i.e. the # following program should return an error on line 3 and should # «not» loop forever): # # x = 1 # while x # x ++ # # Syntax errors may be due to malformed statements (e.g. ‹while x = # 1›, ‹x ++› above, etc.), or due to undefined operations (e.g. ‹x = # mod x y›). Report the first error (nearest to the top of the # input). At runtime, detect and report any attempts to divide by # zero.