01
解释器是什么
解释器是一种计算机程序,它能够读取和执行其他程序的源代码,通常是在运行时逐行或逐句地执行 我们还是打个比方:
解释器:别人问你问题,你需要立马思考并给出答案
编译器:别人问你问题,但你早已将答案写于纸上,无需思考,只需找到此问题的对应答案即可
解释器工作原理
将源代码逐行解释为可让计算机执行的指令,并立即执行
解释器先要去接收源代码,接着进行词法分析,其过程中会将字符串分解成一个又一个Tokens
再接着就是进行语法分析和语义分析,产生词素流,同时构建一个抽象语法树,语义分析器将检查器每一个节点,以此来保证接收到的源代码符合这门语言的语义规则
进行中间代码生成,再对中间代码优化,将优化后的中间代码转化为目标代码;最后执行目标代码
在中途需要去处理错误,捕获+报告;以及内存管理
02
简单介绍下解释器,现在我们正式开始
需求-确定基本特性
首先我们需要去确定其基本特性;比如说:所支持的语法、数据类型、控制流结构
从语法上:变量的声明、函数的定义、类/对象
从数据类型上,比如:整数、浮点数、布尔值、字符串、字符以及复合数据类型:数组、列表、元组、字典、集合
从控制流结构上,比如:条件语句、循环、跳转...
关键字、标识符、字面量、运算符
环境管理
我们该如何去管理变量?如何存储?以及设置变量和获取变量的方法?
那么在这时我们就可以通过设置一个类来管理环境,并使其能对变量进行存储/操作
由于类具有封装性、重用性、维护性、扩展性...等诸多好处,因此其用来管理变量是非常结构化、灵活性很强的一种方式
类定义
首先我们定义一个类,class xxx:
这个类的方法将用来对变量进行管理/存储
class Environment:
初始化
在定义这个类后,我们需要对这个类进行初始化;
我们可以创建一个字典,用来存储变量名以及其值
def __init__(self):
self.variables = {}
__init__
是类的构造函数,它将初始化此类实例
变量的设置
光有能存储变量的容器怎么行?我们需要给这个类添加一个新方法:让它可以去设置一个变量(存储进字典);我们让这个方法能接收变量名以及其值
But!在存储进字典前,我们当然还需要对其变量的值进行一个判断,或者说是评估,若无误则存储进字典内。评估我们可以使用eval
函数。但别忘了使用try...except控制流,以支持处理多种异常
def set_variable(self, name, value):
self.variables[name] = self.evaluate_expression(value)
def evaluate_expression(self, expr):
try:
return eval(expr, {}, self.variables)
except NameError:
return expr
except SyntaxError:
return expr
except TypeError:
return eval(str(expr), {}, self.variables)
评估变量值的方法是evaluate_expression,我们让它能接收要被评估的变量值
首先它将try尝试用eval函数来评估参数expr;
注意:eval
参数1是表达式字符串,参数二三分别为全局字典和局部字典
如果遇到Namerror则表示expr的内容(包含)为未被定义的变量;若其表达式语法错误则将报错SyntaxError;若表达式类型错误,将报错TypeError
变量值的获取
当解释器在工作时,如果遇到一个变量,但却无法获取其值时,那么就会报错。
所以我们需要给其添加一个方法,让解释器能调用这个方法以此来获取到被遇到变量的值
那如何获取呢?当然是从字典里,所以我们要让这个方法能接受一个变量名,并在字典里返回这个变量的值,若不存在,我们当然就要让它返回None
def get_variable(self, name):
return self.variables.get(name)
看上去好像搞定了?但当解释器真正遇到变量的时候,它的判断标准是什么呢?(非定义)这里我说我的思路,我的思路是占位符里+标识符->{a},也就是模板字符串
所以解释器遇到的变量就是{x}这样的,所以靠上面的方法肯定是无法获取到其变量值的。于此我们就需要设置一种新的评估方法。
这个评估方法,可以先遍历字典所有项,接着我们把表达式({a}...)这种,去掉其占位符,并将内标识符替换成相应的值;but,但如果这个变量是字符串呢?那么我们就需要给它左右加上单引号。最后我们还是需要去评估,评估修改后的表达式,如果中途出现问题就返回false
def evaluate_expression2(self, expression):
for key, value in self.variables.items():
if isinstance(value, str):
expression = expression.replace('{' + key + '}', f"'{value}'")
else:
expression = expression.replace('{' + key + '}', str(value))
try:
return eval(expression)
except Exception as e:
return False
好了01~02在这里就先结束了,NEXT 03-04