# simple_interpreter.py # Stephanie Taylor # Implements a simple interpreter # For a language with dynamic typing, no side effects, and only one scope # Then the State class (a dictionary) # Then the functions for the semantics. # This is a version which evaluates expressions only. # Abstract syntax # # Expression = BinaryExpression | Variable | Value # BinaryExpression = string op (+,-,*,/), Expression left, Expression right # Relation = string op (<,>,==,!=), Expression left, Expression right # Conjunction = string op (&&,II), Expression left, Expression right # Variable = string name # Value = a literal integer or boolean import AST # Where the nodes are defined class State: # dictionary that stores string names of vars # and AST.Value objects def __init__( self ): self.state = {} def update( self, var, value ): self.state[var.name] = value def getValue( self, var ): return self.state[var.name] def __str__( self ): retstr = '' for name in self.state: retstr += name + ": " + str(self.state[name]) + '\n' return retstr[:-1] # expr should be a BinaryExpression # state should be a State # returns a AST.Value def M_BinaryExpression( expr, state ): if expr.operator == '+': val = M_Expression( expr.left, state ).value + M_Expression( expr.right, state ).value elif expr.operator == '-': val = M_Expression( expr.left, state ).value - M_Expression( expr.right, state ).value elif expr.operator == '*': val = M_Expression( expr.left, state ).value * M_Expression( expr.right, state ).value elif expr.operator == '/': val = M_Expression( expr.left, state ).value / M_Expression( expr.right, state ).value elif expr.operator == '<': val = M_Expression( expr.left, state ).value < M_Expression( expr.right, state ).value elif expr.operator == '>': val = M_Expression( expr.left, state ).value > M_Expression( expr.right, state ).value elif expr.operator == '==': val = M_Expression( expr.left, state ).value == M_Expression( expr.right, state ).value elif expr.operator == '!=': val = M_Expression( expr.left, state ).value != M_Expression( expr.right, state ).value # with short-circuiting elif expr.operator == '&&': if M_Expression( expr.left, state ).value: val = M_Expression( expr.right, state ).value else: val = False elif expr.operator == '||': if not M_Expression( expr.left, state ).value: val = M_Expression( expr.right, state ).value else: val = True return AST.Value( val ) # expr should be an Expression # state should be a State # returns a AST.Value def M_Expression( expr, state ): if isinstance( expr, AST.BinaryExpression ): return M_BinaryExpression( expr, state ) elif isinstance( expr, AST.Variable ): return state.getValue( expr ) elif isinstance( expr, AST.Value ): return expr else: print( "error!", expr ) def main1(): # Make a Tree for the expression: 3 + 5 expr = AST.BinaryExpression( AST.Value(3), "+", AST.Value(5) ) # we have an empty state state = State() # Evaluate the tree value = M_Expression( expr, state ) print( value ) def main2(): # Given a state with b = 6 state = State() state.update( AST.Variable( "b" ), AST.Value(6) ) # Make the tree for the expression: (b-2)+4 expr = AST.BinaryExpression( AST.BinaryExpression(AST.Value(6),"-",AST.Value(2)), "+", AST.Value(4) ) # Evaluate the tree. value = M_Expression( expr, state ) print( value ) if __name__ == '__main__': main1() main2()