def test_div(self): env = Env(expr.Const, expr.NO_VALUE) three = expr.Const(3) nine = expr.Const(9) x = expr.Var('x') y = expr.Var('y') self.assertEqual(expr.Div(x, y), expr.Div(x, y)) self.assertNotEqual(expr.Div(x, y), expr.Times(x, y)) self.assertEqual(expr.Div(nine, three).eval(env), expr.Const(3)) self.assertEqual( expr.Div(nine, expr.Times(three, three)).eval(env), expr.Const(1))
def test_times(self): env = Env(expr.Const, expr.NO_VALUE) three = expr.Const(3) four = expr.Const(4) x = expr.Var('x') y = expr.Var('y') self.assertEqual(expr.Times(x, y), expr.Times(x, y)) self.assertNotEqual(expr.Times(x, y), expr.Plus(x, y)) self.assertEqual(expr.Times(three, four).eval(env), expr.Const(12)) self.assertEqual( expr.Times(three, expr.Times(three, four)).eval(env), expr.Const(36))
def test_plus(self): env = Env(expr.Const, expr.NO_VALUE) eight = expr.Const(8) nine = expr.Const(9) x = expr.Var('x') y = expr.Var('y') self.assertEqual(expr.Plus(x, y), expr.Plus(x, y)) self.assertEqual(expr.Plus(eight, nine).eval(env), expr.Const(17)) self.assertEqual( expr.Plus(eight, expr.Plus(nine, eight)).eval(env), expr.Const(25)) self.assertEqual(repr(expr.Plus(eight, nine)), "Plus(Const(8),Const(9))") self.assertEqual(str(expr.Plus(eight, nine)), "(8 + 9)")
def test_assign(self): """Assignments: Assign(var, exp) """ env = Env(expr.Const, expr.ZERO) x = expr.Var('x') y = expr.Var('y') # y is undefined here, should give value 0, # giving x value 9 assignment = expr.Assign(x, expr.Plus(y, expr.Const(9))) # print(assignment) x_exp = assignment.eval(env) y_val = expr.Assign(y, expr.Const(3)).eval(env) # y == 3, x == 9 here result = expr.Plus(x, expr.Const(4)).eval(env) self.assertEqual(result, expr.Const(13))
def _primary(stream: TokenStream) -> expr.Expr: """Constants, Variables, and parenthesized expressions""" log.debug(f"Parsing primary with starting token {stream.peek()}") token = stream.take() if token.kind is TokenCat.CONST: log.debug(f"Returning Const node from token {token}") return expr.Const(int(token.value)) elif token.kind is TokenCat.IDENT: log.debug(f"Variable {token.value}") return expr.Var(token.value) elif token.kind is TokenCat.LPAREN: nested = _expr(stream) require(stream, TokenCat.RPAREN, consume=True) return nested else: raise InputError(f"Confused about {token} in expression")
def _stmt(stream: TokenStream) -> expr.Expr: """ assignment ::= IDENT '=' expression ';' """ if stream.peek().kind is TokenCat.WHILE: return _while(stream) if stream.peek().kind is TokenCat.IF: return _if(stream) if stream.peek().kind is not TokenCat.IDENT: raise InputError(f"Expecting identifier at beginning of assignment, got {stream.peek()}") target = expr.Var(stream.take().value) if stream.peek().kind is not TokenCat.ASSIGN: raise InputError("Expecting assignment symbol, got {stream.peek()}") stream.take() # Discard token value = _expr(stream) if stream.peek().kind is not TokenCat.SEMI: raise InputError(f"Expecting semicolon after assignment, got {stream.peek()}") stream.take() # Discard token return expr.Assign(target, value)