本文,我们将实现表达式里面的 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)