本文,我们将实现表达式里面的 eval
函数,这样一个简易的解释器就实现了。
表达式的实现 对于数字和字符串这种自己进行估算的表达式,我们直接返回值就行了:
1 2 3 4 5 6 7 8 9 10 11 class NumberExpression (Expression ): def __init__ (self,exp ): self.value = int(exp) def eval (self,evaluator,env ): return self.value class StringExpression (Expression ): def __init__ (self,exp ): self.value = exp[1 :len(exp)-1 ] def eval (self,evaluator,env ): return self.value
对于变量表达式,我们要根据环境变量找到变量的值并返回,而对赋值表达式,我们使用环境变量改变该变量的值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class VariableExpression (Expression ): def __init__ (self,exp ): self.name = exp def eval (self,evaluator,env ): return env.get_variable(self.name) class AssignmentExpression (Expression ): def __init__ (self,exp ): self.variable = exp[1 ] self.value = exp[2 ] def eval (self,evaluator,env ): value = evaluator.eval(exp.value,env) env.set_variable(self.variable,value) print("ok" )
对于定义表达式,我们分为两种情况:定义函数和定义变量,对于定义函数,我们把函数里的内容转化为 lambda 表达式,再让 lambda 表达式进行 eval,转化为 Procedure 表达式。对于定义变量,直接使用环境变量定义即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class DefineExpression (Expression ): def __init__ (self,exp ): if isinstance(exp[1 ],list): self.variable = exp[1 ][0 ] self.value = LambdaExpression(['lambda' ,exp[1 ][1 :],exp[2 ]]) else : self.variable = exp[1 ] self.value = exp[2 ] def eval (self,evaluator,env ): value = evaluator.eval(self.value,env) env.define_variable(self.variable,value) print("ok" ) class LambdaExpression (Expression ): def __init__ (self,exp ): self.args = exp[1 ] self.body = exp[2 ] def eval (self,evaluator,env ): return ProcedureExpression(["procedure" ,self.args,self.body,env]) class ProcedureExpression (Expression ): def __init__ (self,exp ): self.args = exp[1 ] self.proc = exp[2 ] self.env = exp[3 ] def eval (self,evaluator,env ): return evaluator.eval(self.proc,env)
对于 If 表达式,我们先 eval 条件,然后根据 eval 结果再 eval 对应分支,而 cond 表达式则需要转化为嵌套的 if 表达式再进行 eval:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class IfExpression (Expression ): def __init__ (self,exp ): self.pred = exp[1 ] self.true_exp = exp[2 ] self.false_exp = exp[3 ] def eval (self,evaluator,env ): if evaluator.eval(self.pred,env): return evaluator.eval(self.true_exp,env) return evaluator.eval(self.false_exp,env) class CondExpression (Expression ): def __init__ (self,exp ): self.conditions = exp[1 :len(exp)-1 ] self.otherwise = exp[-1 ] def eval (self,evaluator,env ): exps = self._cond_to_if(self.conditions) return IfExpression(exps).eval(evaluator,env) def _cond_to_if (self,conditions ): if len(conditions) == 1 : return ["if" ] + conditions[0 ] + [self.otherwise[-1 ]] conditions[0 ] += [self._cond_to_if(conditions[1 :])] return ["if" ] + conditions[0 ]
对于 SequenceExpression,我们直接迭代执行里面的表达式即可:
1 2 3 4 5 6 7 8 class SequenceExpression (Expression ): def __init__ (self,exp ): self.exps = exp[1 :] def eval (self,evaluator,env ): result = None for exp in self.exps: result = evaluator.eval(exp,env) return result
对于 ApplicationExpression,我们需要先计算出参数的值,然后调用 evaluator 的 apply:
1 2 3 4 5 6 7 8 class ApplicationExpression (Expression ): def __init__ (self,exp ): self.operator = exp[1 ] self.args = exp[2 ] def eval (self,evaluator,env ): operator = evaluator.eval(self.operator,env) arg_values = map(lambda arg: evaluator.eval(arg,env),self.args) return evaluator.apply(operator,arg_values)